Skip to content

Commit

Permalink
Create tests that verifies the Dockerfiles and templates are in sync
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelSimons committed Jul 22, 2020
1 parent 63d1a3a commit 3c4653d
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 84 deletions.
4 changes: 4 additions & 0 deletions build-and-test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ param(
[string[]]$TestCategories = @("runtime", "runtime-deps", "aspnet", "sdk", "sample", "image-size")
)

if ($Mode -eq "BuildAndTest" -or $Mode -eq "Test") {
& ./tests/run-tests.ps1 -TestCategories "pre-build"
}

if ($Mode -eq "BuildAndTest" -or $Mode -eq "Build") {
# Build the product images
& ./eng/common/build.ps1 `
Expand Down
4 changes: 3 additions & 1 deletion eng/common/templates/jobs/build-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ parameters:
jobs:
- job: ${{ parameters.name }}
condition: and(succeeded(), ${{ parameters.matrix }})
dependsOn: GenerateBuildMatrix
dependsOn:
- PreBuildValidation
- GenerateBuildMatrix
pool: ${{ parameters.pool }}
strategy:
matrix: $[ ${{ parameters.matrix }} ]
Expand Down
13 changes: 7 additions & 6 deletions eng/common/templates/jobs/test-images-linux-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ parameters:
pool: {}
matrix: {}
testJobTimeout: 60
preBuildValidation: false
jobs:
- job: ${{ parameters.name }}
condition: and(succeeded(), ${{ parameters.matrix }})
dependsOn: GenerateTestMatrix
${{ if eq(parameters.preBuildValidation, 'false') }}:
condition: and(succeeded(), ${{ parameters.matrix }})
dependsOn: GenerateTestMatrix
strategy:
matrix: $[ ${{ parameters.matrix }} ]
pool: ${{ parameters.pool }}
strategy:
matrix: $[ ${{ parameters.matrix }} ]
timeoutInMinutes: ${{ parameters.testJobTimeout }}
steps:
- template: ../steps/test-images-linux-client.yml
parameters:
setupImageBuilder: false
setupTestRunner: true
preBuildValidation: ${{ parameters.preBuildValidation }}
8 changes: 8 additions & 0 deletions eng/common/templates/stages/build-test-publish-repo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ stages:
- stage: Build
condition: and(succeeded(), contains(variables['stages'], 'build'))
jobs:
- template: ../jobs/test-images-linux-client.yml
parameters:
name: PreBuildValidation
pool:
vmImage: $(defaultLinuxAmd64PoolImage)
testJobTimeout: ${{ parameters.linuxAmdTestJobTimeout }}
preBuildValidation: true

- template: ../jobs/generate-matrix.yml
parameters:
matrixType: ${{ parameters.buildMatrixType }}
Expand Down
29 changes: 20 additions & 9 deletions eng/common/templates/steps/test-images-linux-client.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
parameters:
preBuildValidation: false

steps:
- template: init-docker-linux.yml
parameters:
Expand All @@ -8,11 +11,15 @@ steps:
echo "##vso[task.setvariable variable=testRunner.container]testrunner-$(Build.BuildId)-$(System.JobId)"
optionalTestArgs=""
if [ "${{ eq(variables['System.TeamProject'], 'public') }}" == "False" ]; then
optionalTestArgs="$optionalTestArgs -PullImages -Registry $(acr.server) -RepoPrefix $(stagingRepoPrefix) -ImageInfoPath $(artifactsPath)/image-info/image-info.json"
fi
if [ "$REPOTESTARGS" != "" ]; then
optionalTestArgs="$optionalTestArgs $REPOTESTARGS"
if [ "${{ parameters.preBuildValidation }}" == "true" ]; then
optionalTestArgs="$optionalTestArgs -TestCategories pre-build"
else
if [ "${{ eq(variables['System.TeamProject'], 'public') }}" == "False" ]; then
optionalTestArgs="$optionalTestArgs -PullImages -Registry $(acr.server) -RepoPrefix $(stagingRepoPrefix) -ImageInfoPath $(artifactsPath)/image-info/image-info.json"
fi
if [ "$REPOTESTARGS" != "" ]; then
optionalTestArgs="$optionalTestArgs $REPOTESTARGS"
fi
fi
echo "##vso[task.setvariable variable=optionalTestArgs]$optionalTestArgs"
displayName: Set Test Variables
Expand All @@ -30,9 +37,10 @@ steps:
-File $(engCommonRelativePath)/Invoke-WithRetry.ps1
"docker login -u $(acr.userName) -p $(BotAccount-dotnet-docker-acr-bot-password) $(acr.server)"
displayName: Docker login
- template: ../steps/download-build-artifact.yml
parameters:
targetPath: $(Build.ArtifactStagingDirectory)
- ${{ if eq(parameters.preBuildValidation, 'false') }}:
- template: ../steps/download-build-artifact.yml
parameters:
targetPath: $(Build.ArtifactStagingDirectory)
- script: >
docker exec $(testRunner.container) pwsh
-File $(testScriptPath)
Expand Down Expand Up @@ -63,7 +71,10 @@ steps:
searchFolder: $(Common.TestResultsDirectory)
mergeTestResults: true
publishRunAttachments: true
testRunTitle: $(dotnetVersion) $(osVariant) $(architecture)
${{ if eq(parameters.preBuildValidation, 'false') }}:
testRunTitle: $(dotnetVersion) $(osVariant) $(architecture)
${{ if eq(parameters.preBuildValidation, 'true') }}:
testRunTitle: Pre-Build Validation
- script: docker rm -f $(testRunner.container)
displayName: Cleanup TestRunner Container
condition: always()
Expand Down
14 changes: 8 additions & 6 deletions eng/dockerfile-templates/Get-GeneratedDockerfiles.ps1
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
#!/usr/bin/env pwsh
param(
# Paths to the Dockerfiles to generate.
[string[]]$Paths
[switch]$Validate
)

if ($Paths) {
$pathArgs = " --path " + ($Paths -join " --path ")
if ($Validate) {
$customImageBuilderArgs = " --validate"
}

$repoRoot = (Get-Item "$PSScriptRoot").Parent.Parent.FullName

$onDockerfilesGenerated = {
param($ContainerName)
Exec "docker cp ${ContainerName}:/repo/src $repoRoot"

if (-Not $Validate) {
Exec "docker cp ${ContainerName}:/repo/src $repoRoot"
}
}

& $PSScriptRoot/../common/Invoke-ImageBuilder.ps1 `
-ImageBuilderArgs "generateDockerfiles --architecture * --os-type *$pathArgs" `
-ImageBuilderArgs "generateDockerfiles --architecture '*' --os-type '*'$customImageBuilderArgs" `
-OnCommandExecuted $onDockerfilesGenerated
13 changes: 10 additions & 3 deletions eng/update-dependencies/ScriptRunnerUpdater.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.DotNet.VersionTools.Dependencies;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.DotNet.VersionTools.Dependencies;

namespace Dotnet.Docker
{
Expand Down Expand Up @@ -53,16 +54,22 @@ private void ExecuteScript()
Trace.TraceInformation($"Executing '{_scriptPath}'");

// Support both execution within Windows 10, Nano Server and Linux environments.
Process process;
try
{
Process process = Process.Start("pwsh", _scriptPath);
process = Process.Start("pwsh", _scriptPath);
process.WaitForExit();
}
catch (Win32Exception)
{
Process process = Process.Start("powershell", _scriptPath);
process = Process.Start("powershell", _scriptPath);
process.WaitForExit();
}

if (process.ExitCode != 0)
{
throw new InvalidOperationException($"Unable to successfully execute '{_scriptPath}'");
}
}
}
}
22 changes: 12 additions & 10 deletions tests/Microsoft.DotNet.Docker.Tests/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,30 @@ namespace Microsoft.DotNet.Docker.Tests
{
public static class Config
{
private static Lazy<JObject> Manifest { get; } = new Lazy<JObject>(() => LoadManifest());

public static string SourceRepoRoot { get; } = Environment.GetEnvironmentVariable("SOURCE_REPO_ROOT") ?? string.Empty;
public static bool IsHttpVerificationDisabled { get; } =
Environment.GetEnvironmentVariable("DISABLE_HTTP_VERIFICATION") != null;
public static bool PullImages { get; } = Environment.GetEnvironmentVariable("PULL_IMAGES") != null;
public static bool IsNightlyRepo { get; } = GetIsNightlyRepo();
public static bool IsRunningInContainer { get; } =
Environment.GetEnvironmentVariable("RUNNING_TESTS_IN_CONTAINER") != null;
public static string RepoPrefix { get; } = Environment.GetEnvironmentVariable("REPO_PREFIX") ?? string.Empty;
public static string Registry { get; } = Environment.GetEnvironmentVariable("REGISTRY") ?? GetManifestRegistry();
public static string Registry { get; } =
Environment.GetEnvironmentVariable("REGISTRY") ?? (string)Manifest.Value["registry"];

private static string GetManifestRegistry()
private static bool GetIsNightlyRepo()
{
string manifestJson = File.ReadAllText("manifest.json");
JObject manifest = JObject.Parse(manifestJson);
return (string)manifest["registry"];
string repo = (string)Manifest.Value["repos"][0]["name"];
return repo.Contains("-nightly");
}

private static bool GetIsNightlyRepo()
private static JObject LoadManifest()
{
string manifestJson = File.ReadAllText("manifest.json");
JObject manifest = JObject.Parse(manifestJson);
string repo = (string)manifest["repos"][0]["name"];
return repo.Contains("-nightly");
string manifestPath = Path.Combine(SourceRepoRoot, "manifest.json");
string manifestJson = File.ReadAllText(manifestPath);
return JObject.Parse(manifestJson);
}
}
}
40 changes: 1 addition & 39 deletions tests/Microsoft.DotNet.Docker.Tests/DockerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,45 +99,7 @@ private static string Execute(
}

private static (Process Process, string StdOut, string StdErr) ExecuteProcess(
string args, ITestOutputHelper outputHelper)
{
Process process = new Process
{
EnableRaisingEvents = true,
StartInfo =
{
FileName = "docker",
Arguments = args,
RedirectStandardOutput = true,
RedirectStandardError = true,
}
};

StringBuilder stdOutput = new StringBuilder();
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) => stdOutput.AppendLine(e.Data));

StringBuilder stdError = new StringBuilder();
process.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => stdError.AppendLine(e.Data));

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();

string output = stdOutput.ToString().Trim();
if (outputHelper != null && !string.IsNullOrWhiteSpace(output))
{
outputHelper.WriteLine(output);
}

string error = stdError.ToString().Trim();
if (outputHelper != null && !string.IsNullOrWhiteSpace(error))
{
outputHelper.WriteLine(error);
}

return (process, output, error);
}
string args, ITestOutputHelper outputHelper) => ExecuteHelper.ExecuteProcess("docker", args, outputHelper);

private string ExecuteWithLogging(string args, bool ignoreErrors = false, bool autoRetry = false)
{
Expand Down
54 changes: 54 additions & 0 deletions tests/Microsoft.DotNet.Docker.Tests/ExecuteHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Text;
using Xunit.Abstractions;

namespace Microsoft.DotNet.Docker.Tests
{
public static class ExecuteHelper
{
public static (Process Process, string StdOut, string StdErr) ExecuteProcess(
string fileName, string args, ITestOutputHelper outputHelper)
{
Process process = new Process
{
EnableRaisingEvents = true,
StartInfo =
{
FileName = fileName,
Arguments = args,
RedirectStandardOutput = true,
RedirectStandardError = true,
}
};

StringBuilder stdOutput = new StringBuilder();
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) => stdOutput.AppendLine(e.Data));

StringBuilder stdError = new StringBuilder();
process.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => stdError.AppendLine(e.Data));

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();

string output = stdOutput.ToString().Trim();
if (outputHelper != null && !string.IsNullOrWhiteSpace(output))
{
outputHelper.WriteLine(output);
}

string error = stdError.ToString().Trim();
if (outputHelper != null && !string.IsNullOrWhiteSpace(error))
{
outputHelper.WriteLine(error);
}

return (process, output, error);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@
<Content Include="TestAppArtifacts/*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="../../manifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="../../samples/**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>samples/%(RecursiveDir)%(Filename)%(Extension)</Link>
</Content>
</ItemGroup>

</Project>
6 changes: 4 additions & 2 deletions tests/Microsoft.DotNet.Docker.Tests/SampleImageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace Microsoft.DotNet.Docker.Tests
[Trait("Category", "sample")]
public class SampleImageTests
{
private static readonly string s_samplesPath = Path.Combine(Config.SourceRepoRoot, "samples");

public SampleImageTests(ITestOutputHelper outputHelper)
{
OutputHelper = outputHelper;
Expand Down Expand Up @@ -80,7 +82,7 @@ public void VerifyComplexAppSample()
{
string appTag = SampleImageData.GetImageName("complexapp-local-app");
string testTag = SampleImageData.GetImageName("complexapp-local-test");
string sampleFolder = $"samples/complexapp";
string sampleFolder = Path.Combine(s_samplesPath, "complexapp");
string dockerfilePath = $"{sampleFolder}/Dockerfile";
string testContainerName = ImageData.GenerateContainerName("sample-complex-test");
string tempDir = null;
Expand Down Expand Up @@ -141,7 +143,7 @@ private async Task VerifySampleAsync(
{
if (!imageData.IsPublished)
{
string sampleFolder = $"samples/{imageType}";
string sampleFolder = Path.Combine(s_samplesPath, imageType);
string dockerfilePath = $"{sampleFolder}/Dockerfile.{imageData.DockerfileSuffix}";

DockerHelper.Build(image, dockerfilePath, contextDir: sampleFolder, pull: Config.PullImages);
Expand Down
Loading

0 comments on commit 3c4653d

Please sign in to comment.