Beispiel #1
0
        public async Task BasicRepoBuild()
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BasicRepoBuild), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                builder.AddProject(ProjectCreator
                                   .Create()
                                   .PropertyGroup()
                                   .Property("AllowEmptySignList", "true"), "eng/Signing.props");

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"))
                .Should().NotThrow();
            }
        }
Beispiel #2
0
        public async Task BuildShouldUseDotNetCertifcateIfSet(bool?useDotNetCert)
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BuildShouldUseDotNetCertifcateIfSet), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                // Always put in the AllowEmptySignList
                var signingProps = ProjectCreator.Create().PropertyGroup();
                signingProps.Property("AllowEmptySignList", "true");

                if (useDotNetCert.HasValue)
                {
                    signingProps.Property("UseDotNetCertificate", useDotNetCert.Value.ToString());
                }

                // Clear out ItemsToSignPostBuild
                signingProps.ItemGroup()
                .ItemRemove("ItemsToSignPostBuild", "@(ItemsToSignPostBuild)");

                builder.AddProject(signingProps, "eng/Signing.props");

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true")
                                   .Property("EnableSourceLink", "false"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("pack"),
                    TestRepoUtils.BuildArg("publish"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"),
                    "/p:AutoGenerateSymbolPackages=false")
                .Should().NotThrow();

                // Now, go find the Round0 signing project and ensure that the certificate names were set properly.
                // The arcade default for an exe is Microsoft400
                string round0FilePath    = Path.Combine(builder.TestRepoRoot, "artifacts", "tmp", "Release", "Signing", "Round0.proj");
                string round0ProjectText = File.ReadAllText(round0FilePath);
                string expectedCert      = useDotNetCert.GetValueOrDefault() ? DotNetCertificate : MicrosoftCertificate;

                Regex authenticodeRegex = new Regex("<Authenticode>(.*)</Authenticode>");
                var   matches           = authenticodeRegex.Matches(round0ProjectText);
                matches.Count.Should().Be(1);
                matches[0].Groups[1].Value.Should().Be(expectedCert);
            }
        }
Beispiel #3
0
        public async Task BuildShouldNotChangeNonMicrosoft400CertsWhenPostBuildSigning()
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BuildShouldNotChangeNonMicrosoft400CertsWhenSigning), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                // Always put in the AllowEmptySignList
                var signingProps = ProjectCreator.Create().PropertyGroup();
                signingProps.Property("AllowEmptySignList", "true");
                signingProps.Property("UseDotNetCertificate", "true");

                // Update the .exe extension with a new cert.
                const string certOverride = "Microsoft401";

                signingProps.ItemGroup()
                .ItemUpdate("StrongNameSignInfo", update: "MsSharedLib72",
                            metadata: new Dictionary <string, string> {
                    { "PublicKeyToken", "31bf3856ad364e35" }, { "CertificateName", certOverride }
                });

                builder.AddProject(signingProps, "eng/Signing.props");

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true")
                                   .Property("EnableSourceLink", "false"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("pack"),
                    TestRepoUtils.BuildArg("publish"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"),
                    "/p:AutoGenerateSymbolPackages=false",
                    "/p:PostBuildSign=true",
                    "/p:DotNetPublishUsingPipelines=true")
                .Should().NotThrow();

                string assetManifestText = GetAssetManifest(builder);
                // Should find Microsoft401, MicrosoftDotNet500, but not Microsoft400
                assetManifestText.IndexOf(DotNetCertificate).Should().NotBe(-1);
                assetManifestText.IndexOf(certOverride).Should().NotBe(-1);
                assetManifestText.IndexOf(MicrosoftCertificate).Should().Be(-1);
            }
        }
Beispiel #4
0
        public async Task BuildShouldUseDotNetCertifcateIfSetWithPostBuildSigning(bool?useDotNetCert)
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BuildShouldUseDotNetCertifcateIfSet), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                // Always put in the AllowEmptySignList
                var signingProps = ProjectCreator.Create().PropertyGroup();
                signingProps.Property("AllowEmptySignList", "true");

                if (useDotNetCert.HasValue)
                {
                    signingProps.Property("UseDotNetCertificate", useDotNetCert.Value.ToString());
                }

                builder.AddProject(signingProps, "eng/Signing.props");

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true")
                                   .Property("EnableSourceLink", "false"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("pack"),
                    TestRepoUtils.BuildArg("publish"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"),
                    "/p:AutoGenerateSymbolPackages=false",
                    "/p:PostBuildSign=true",
                    "/p:DotNetPublishUsingPipelines=true")
                .Should().NotThrow();
                string assetManifestText = GetAssetManifest(builder);
                string expectedCert      = useDotNetCert.GetValueOrDefault() ? DotNetCertificate : MicrosoftCertificate;
                string unexpectedCert    = useDotNetCert.GetValueOrDefault() ? MicrosoftCertificate : DotNetCertificate;

                // Ensure that we see the expected cert.
                assetManifestText.IndexOf(unexpectedCert).Should().Be(-1);
                assetManifestText.IndexOf(expectedCert).Should().NotBe(-1);
            }
        }
Beispiel #5
0
        public async Task BuildShouldErrorIfNoItemsToSignAndNonEmptySignPostBuildList(bool propertyIsSet)
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BuildShouldErrorIfNoItemsToSignAndNonEmptySignPostBuildList), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                // Always put in the AllowEmptySignList
                var signingProps = ProjectCreator.Create().PropertyGroup();
                signingProps.Property("AllowEmptySignList", "true");

                if (propertyIsSet)
                {
                    signingProps.Property("AllowEmptySignPostBuildList", "false");
                }

                // Clear out ItemsToSignPostBuild
                signingProps.ItemGroup()
                .ItemRemove("ItemsToSignPostBuild", "@(ItemsToSignPostBuild)");

                builder.AddProject(signingProps, "eng/Signing.props");

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true")
                                   .Property("EnableSourceLink", "false"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("pack"),
                    TestRepoUtils.BuildArg("publish"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"),
                    "/p:AutoGenerateSymbolPackages=false",
                    "/p:PostBuildSign=true")
                .Should().Throw <Exception>($"build of repo {builder.TestRepoRoot} is post build signed")
                .WithMessage("*error : List of files to sign post-build is empty. Make sure that ItemsToSignPostBuild is configured correctly.*");
            }
        }
Beispiel #6
0
        /// <summary>
        /// Retrieve the text from the asset manifest file. Checks that there is only a single asset manifest.
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        private static string GetAssetManifest(TestRepoBuilder builder)
        {
            // Now, go find the asset manifest. Since we don't know exactly where it will be and what it will
            // be named (configuration and OS names end up influencing the path), just find an asset manifest under
            // artifacts/log/**/AssetManifests/*. There should only be one.
            string logsDirectory = Path.Combine(builder.TestRepoRoot, "artifacts", "log");

            string[] logFiles            = Directory.GetFiles(logsDirectory, "*.xml", SearchOption.AllDirectories);
            string   escapedDirSeperator = Regex.Escape($"{Path.DirectorySeparatorChar}");
            Regex    assetManifestRegex  = new Regex(@$ ".*{escapedDirSeperator}AssetManifest{escapedDirSeperator}.*\.xml");
            var      assetManifests      = logFiles.Where(am => assetManifestRegex.IsMatch(am)).ToArray();

            assetManifests.Length.Should().Be(1);
            string assetManifestText = File.ReadAllText(assetManifests[0]);

            return(assetManifestText);
        }
Beispiel #7
0
        public async Task BuildShouldErrorIfNoItemsToSignAndNonEmptySignList(bool propertyIsSet)
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BuildShouldErrorIfNoItemsToSignAndNonEmptySignList), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                if (propertyIsSet)
                {
                    builder.AddProject(ProjectCreator
                                       .Create()
                                       .PropertyGroup()
                                       .Property("AllowEmptySignList", "false"), "eng/Signing.props");
                }

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"))
                .Should().Throw <Exception>().WithMessage("*error : List of files to sign is empty. Make sure that ItemsToSign is configured correctly*");
            }
        }
Beispiel #8
0
        public async Task BuildShouldNotChangeNonMicrosoft400CertsWhenSigning()
        {
            var envVars = Environment.GetEnvironmentVariables();

            using (var builder = new TestRepoBuilder(nameof(BuildShouldNotChangeNonMicrosoft400CertsWhenSigning), _commonRepoResourcesFixture.CommonResources))
            {
                await builder.AddDefaultRepoSetupAsync();

                // Always put in the AllowEmptySignList
                var signingProps = ProjectCreator.Create().PropertyGroup();
                signingProps.Property("AllowEmptySignList", "true");

                // Clear out ItemsToSignPostBuild
                signingProps.ItemGroup()
                .ItemRemove("ItemsToSignPostBuild", "@(ItemsToSignPostBuild)");

                // Update the .exe extension with a new cert.
                // <StrongNameSignInfo Include="MsSharedLib72" PublicKeyToken="31bf3856ad364e35" CertificateName="Microsoft400" />
                const string certOverride = "Microsoft401";

                signingProps.ItemGroup()
                .ItemUpdate("StrongNameSignInfo", update: "MsSharedLib72",
                            metadata: new Dictionary <string, string> {
                    { "PublicKeyToken", "31bf3856ad364e35" }, { "CertificateName", certOverride }
                });

                builder.AddProject(signingProps, "eng/Signing.props");

                // Create a simple project
                builder.AddProject(ProjectCreator
                                   .Templates
                                   .SdkCsproj(
                                       targetFramework: "net6.0",
                                       outputType: "Exe")
                                   .PropertyGroup()
                                   .Property("IsPackable", "true")
                                   .Property("EnableSourceLink", "false"),
                                   "./src/FooPackage/FooPackage.csproj");
                await builder.AddSimpleCSFile("src/FooPackage/Program.cs");

                builder.Build(
                    TestRepoUtils.BuildArg("configuration"),
                    "Release",
                    TestRepoUtils.BuildArg("restore"),
                    TestRepoUtils.BuildArg("pack"),
                    TestRepoUtils.BuildArg("publish"),
                    TestRepoUtils.BuildArg("sign"),
                    TestRepoUtils.BuildArg("projects"),
                    Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"),
                    "/p:AutoGenerateSymbolPackages=false")
                .Should().NotThrow();

                // Now, go find the Round0 signing project and ensure that the certificate names were set properly.
                // The arcade default for an exe is Microsoft400
                string round0FilePath    = Path.Combine(builder.TestRepoRoot, "artifacts", "tmp", "Release", "Signing", "Round0.proj");
                string round0ProjectText = File.ReadAllText(round0FilePath);

                Regex authenticodeRegex = new Regex("<Authenticode>(.*)</Authenticode>");
                var   matches           = authenticodeRegex.Matches(round0ProjectText);
                matches.Count.Should().Be(1);
                matches[0].Groups[1].Value.Should().Be(certOverride);
            }
        }
        /// <summary>
        /// Create a set of repo resources.
        /// </summary>
        /// <param name="useIsolatedRoots">
        ///     Should isolated .dotnet and .packages locations
        ///     be used? If false, then to share a dotnet root, a simple repo is created
        ///     and restored. Then the resulting .dotnet and .packages directories are
        ///     </param>
        /// <returns></returns>
        public static async Task <RepoResources> Create(bool useIsolatedRoots)
        {
            string dotnetVersion;
            string arcadeVersion;
            string dotnetRoot   = null;
            string packagesRoot = null;
            string commonRoot   = null;

            var globalJsonLocation = TestRepoBuilder.GetTestInputPath("global.json");

            using (var reader = new StreamReader(globalJsonLocation))
                using (JsonDocument doc = JsonDocument.Parse(reader.BaseStream))
                {
                    dotnetVersion = doc.RootElement.GetProperty("tools").GetProperty("dotnet").GetString();
                    arcadeVersion = doc.RootElement.GetProperty("msbuild-sdks").GetProperty("Microsoft.DotNet.Arcade.Sdk").GetString();
                }

            // If not using isolated roots, create a quick test repo builder
            // to restore things.
            if (!useIsolatedRoots)
            {
                // Common repo resources for constructing a simple repo. The
                // repo's test dir is set to not be deleted, and the .dotnet and .packages paths are extracted.
                // During the disposal of the returned set of resources, the common dir is deleted.
                var commonRepoResources = new RepoResources()
                {
                    ArcadeVersion = arcadeVersion, DotNetVersion = dotnetVersion
                };
                using (var builder = new TestRepoBuilder("common", commonRepoResources, deleteOnDispose: false))
                {
                    await builder.AddDefaultRepoSetupAsync();

                    // Create a simple project
                    builder.AddProject(ProjectCreator
                                       .Templates
                                       .SdkCsproj(
                                           targetFramework: "net5.0",
                                           outputType: "Exe"),
                                       "./src/FooPackage/FooPackage.csproj");
                    await builder.AddSimpleCSFile("./src/FooPackage/Program.cs");

                    builder.Build(
                        TestRepoUtils.BuildArg("restore"),
                        TestRepoUtils.BuildArg("ci"),
                        TestRepoUtils.BuildArg("projects"),
                        Path.Combine(builder.TestRepoRoot, "src/FooPackage/FooPackage.csproj"))();

                    commonRoot = builder.TestRepoRoot;
                    dotnetRoot = Path.Combine(builder.TestRepoRoot, ".dotnet");
                    if (!Directory.Exists(dotnetRoot))
                    {
                        // Coming from the machine
                        dotnetRoot = null;
                    }
                    packagesRoot = Path.Combine(builder.TestRepoRoot, ".packages");
                    if (!Directory.Exists(packagesRoot))
                    {
                        packagesRoot = null;
                    }
                }
            }

            RepoResources repoResources = new RepoResources()
            {
                ArcadeVersion      = arcadeVersion,
                DotNetVersion      = dotnetVersion,
                CommonPackagesRoot = packagesRoot,
                CommonDotnetRoot   = dotnetRoot,
                CommonRoot         = commonRoot
            };

            return(repoResources);
        }