Skip to content
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
9 changes: 8 additions & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
"dotnet-inspect"
],
"rollForward": false
},
"purview.build": {
"version": "0.5.3",
"commands": [
"purview-build"
],
"rollForward": false
}
}
}
}
6 changes: 5 additions & 1 deletion .config/purview-build.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"TestFilter": "/*/*/*/*[Category=Unit]"
},
"PackValidation": {
// Explicit because Purview.Build 0.5.3 defaults RequiredCompilerFlags to empty. Earlier
// versions forced this check on and could not be configured off, so these packages have
// always been validated against it; declaring it keeps that behaviour.
"RequiredCompilerFlags": ["optimization=release"],
"RequireSymbolPackage": true,
"RequireSymbolFiles": true,
// RequireExplicitContent defaults to true, so this is the exhaustive declaration of what each
Expand Down Expand Up @@ -110,4 +114,4 @@
"Policy": "TrunkReservesMinor"
}
}
}
}
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<PackageVersion Include="Testcontainers" Version="4.15.0" />
<PackageVersion Include="Microsoft.Extensions.Telemetry.Abstractions" Version="10.10.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.401" />
<PackageVersion Include="Purview.Telemetry.SourceGenerator" Version="5.0.1" />
<PackageVersion Include="Purview.Telemetry.SourceGenerator" Version="5.0.3" />
<PackageVersion Include="TUnit" Version="1.72.4" />
<PackageVersion Include="TUnit.Core" Version="1.72.4" />
<PackageVersion Include="TUnit.Mocks" Version="1.72.4" />
Expand Down
21 changes: 9 additions & 12 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ solution_file := root_folder + "Containers.slnx"
test_solution := solution_file
build_configuration := "Debug"

pipeline_feed := "https://api.nuget.org/v3/index.json"
pipeline_tool := ".tools/purview-build/purview-build"
pipeline_tool := "dotnet purview-build"

artifact_folder := "./artifacts/"

Expand All @@ -21,33 +20,31 @@ artifact_folder := "./artifacts/"
default:
just --list

# Install the shared Purview.Build tool (authenticated to the Purview-Dev feed) if not present
# Restore the repository's .NET local tools (.config/dotnet-tools.json)
[private]
ensure-pipeline-tool:
if [ ! -x "{{ pipeline_tool }}" ]; then \
dotnet tool install Purview.Build --tool-path .tools/purview-build --add-source "{{ pipeline_feed }}"; \
fi
dotnet tool restore

# Run the PR pipeline (restore, build, lint, tests, pack, validate)
[group('Pipeline')]
pipeline-pr *args:
just ensure-pipeline-tool
echo "Running PR pipeline..."
"{{ pipeline_tool }}" {{ args }}
{{ pipeline_tool }} {{ args }}

# Run the build pipeline (restore, build, lint)
[group('Pipeline')]
pipeline-build *args:
just ensure-pipeline-tool
echo "Running build pipeline..."
"{{ pipeline_tool }}" --Build:RunTests=false --Release:Mode=None {{ args }}
{{ pipeline_tool }} --Build:RunTests=false --Release:Mode=None {{ args }}

# Run the release pipeline (restore, build, lint, tests, pack, publish, GitHub release)
[group('Pipeline')]
pipeline-release *args:
just ensure-pipeline-tool
echo "Running release pipeline..."
"{{ pipeline_tool }}" --Release:Mode=NuGet {{ args }}
{{ pipeline_tool }} --Release:Mode=NuGet {{ args }}

# Run the release pipeline (restore, build, lint, tests, pack, local nuget publish)
# Note: `just` runs recipes through the shell, which strips backslashes from unquoted arguments.
Expand All @@ -57,21 +54,21 @@ pipeline-release *args:
pipeline-local-release *args:
just ensure-pipeline-tool
echo "Running local release pipeline..."
"{{ pipeline_tool }}" --Release:Mode=LocalNuGet {{ args }}
{{ pipeline_tool }} --Release:Mode=LocalNuGet {{ args }}

# Run the pipeline with tests enabled
[group('Pipeline')]
pipeline-tests *args:
just ensure-pipeline-tool
echo "Running tests pipeline..."
"{{ pipeline_tool }}" --Build:RunTests=true --Release:Mode=None {{ args }}
{{ pipeline_tool }} --Build:RunTests=true --Release:Mode=None {{ args }}

# Run the pipeline through pack + validate (restore, build, lint, tests, pack, validate pack contents) without publishing/releasing
[group('Pipeline')]
pipeline-pack-validate *args:
just ensure-pipeline-tool
echo "Running pack + validate pipeline..."
"{{ pipeline_tool }}" --Build:RunPack=true --Build:ValidatePack=true --Release:Mode=None {{ args }}
{{ pipeline_tool }} --Build:RunPack=true --Build:ValidatePack=true --Release:Mode=None {{ args }}

# -----------------------------------------------------------------------------
# Build and Test
Expand Down
4 changes: 2 additions & 2 deletions docs/wiki/Release-Flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ The `Justfile` wraps the common steps:

## The shared pipeline

All pipeline recipes first install the `Purview.Build` tool into `.tools/purview-build` and then run it
against `purview-build.json`:
All pipeline recipes first run `dotnet tool restore` (installing the pinned `Purview.Build` from
`.config/dotnet-tools.json`) and then run it against `purview-build.json`:

| Recipe | Pipeline arguments |
| --- | --- |
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"allowPrerelease": true
},
"msbuild-sdks": {
"Purview.BuildSdk": "1.0.4"
"Purview.BuildSdk": "1.0.5"
},
"test": {
"runner": "Microsoft.Testing.Platform"
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "purview-containers",
"name": "containers",
"version": "1.0.0-prerelease.6",
"description": "Testcontainers-style library for .NET that runs throwaway Linux containers for integration testing, on Microsoft WSL Containers or Docker.",
"license": "MIT",
"author": {
"name": "Kieron Lanning",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace Purview.Containers.Docker;

/// <summary>
/// Covers <see cref="DockerContainerBackend.CreateContainer(IContainerConfiguration)"/> against a real
/// daemon. Creating a container builds the underlying Testcontainers container, which connects to the
/// daemon, so this is an integration concern: with no daemon reachable the call throws
/// <c>DockerUnavailableException</c> rather than returning a container. The daemon-free surface of the
/// backend (its name and <c>Create</c>) stays in <c>Docker.UnitTests</c>.
/// </summary>
public class DockerContainerBackendFactoryTests
{
static Task SkipIfUnavailableAsync() => DockerTest.SkipIfUnavailableAsync();

[Test]
public async Task CreateContainer_AdaptsTheConfiguredImageAndName()
{
await SkipIfUnavailableAsync();

ContainerConfiguration configuration = new() { Image = "alpine:3.19", Name = "purview-unit-test" };

var container = new DockerContainerBackend().CreateContainer(configuration);

await Assert.That(container).IsTypeOf<DockerContainer>();
await Assert.That(container.Image).IsEqualTo("alpine:3.19");
await Assert.That(container.Name).IsEqualTo("purview-unit-test");
}

[Test]
public async Task CreateContainer_GeneratesNoName_WhenTheConfigurationDoesNotSetOne()
{
await SkipIfUnavailableAsync();

ContainerConfiguration configuration = new() { Image = "alpine:3.19" };

var container = new DockerContainerBackend().CreateContainer(configuration);

await Assert.That(container.Name).IsNotEmpty();
}
}
27 changes: 3 additions & 24 deletions src/tests/Docker.UnitTests/DockerContainerBackendTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
namespace Purview.Containers.Docker;

/// <summary>
/// Unit coverage for the Docker backend that needs no daemon: identity, registration metadata and the
/// configuration translation. Anything that talks to a daemon lives in <c>Docker.IntegrationTests</c>.
/// Unit coverage for the Docker backend that needs no daemon: identity and registration metadata.
/// Anything that talks to a daemon lives in <c>Docker.IntegrationTests</c> — including
/// <c>CreateContainer</c>, which builds the underlying Testcontainers container and therefore connects.
/// </summary>
public class DockerContainerBackendTests
{
Expand All @@ -17,26 +18,4 @@ public async Task Create_ReturnsANewBackend()
{
await Assert.That(DockerContainerBackend.Create()).IsNotNull();
}

[Test]
public async Task CreateContainer_AdaptsTheConfiguredImageAndName()
{
ContainerConfiguration configuration = new() { Image = "alpine:3.19", Name = "purview-unit-test" };

var container = new DockerContainerBackend().CreateContainer(configuration);

await Assert.That(container).IsTypeOf<DockerContainer>();
await Assert.That(container.Image).IsEqualTo("alpine:3.19");
await Assert.That(container.Name).IsEqualTo("purview-unit-test");
}

[Test]
public async Task CreateContainer_GeneratesNoName_WhenTheConfigurationDoesNotSetOne()
{
ContainerConfiguration configuration = new() { Image = "alpine:3.19" };

var container = new DockerContainerBackend().CreateContainer(configuration);

await Assert.That(container.Name).IsNotEmpty();
}
}
Loading