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
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ root = true

[*.cs]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
44 changes: 44 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: .NET Build

on:
push:
branches: [ "**" ]
pull_request:
branches: [ "main" ]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that if I push changes to a branch while a build is already running, then the current build will be aborted and a new one started.

cancel-in-progress: true

permissions:
contents: read

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Safeguard against... shenanigans.


env:
SOLUTION_FILE: src/Ninject.Web.AspNetCore.slnx

jobs:
build:
runs-on: ubuntu-latest
name: Build and Test
steps:
# Checkout the repository
- name: Checkout code
uses: actions/checkout@v5

# Setup .NET Core SDK
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Restore dependencies
run: dotnet restore $SOLUTION_FILE

- name: Verify formatting
run: dotnet format $SOLUTION_FILE --verify-no-changes

- name: Build
run: dotnet build --no-restore $SOLUTION_FILE

- name: Test
run: dotnet test --no-build $SOLUTION_FILE
19 changes: 0 additions & 19 deletions .github/workflows/ci.yml

This file was deleted.

64 changes: 64 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: NuGet Package Release

on:
push:
tags:
- 'v*.*.*'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read

env:
SOLUTION_FILE: src/Ninject.Web.AspNetCore.slnx

jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write # required so the job can request a GitHub OIDC token for NuGet Trusted Publishing

steps:
# Checkout the repository
- name: Checkout code
uses: actions/checkout@v5

# Setup .NET Core SDK
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Restore dependencies
run: dotnet restore $SOLUTION_FILE

- name: Verify formatting
run: dotnet format $SOLUTION_FILE --verify-no-changes

- name: Build
run: dotnet build --no-restore $SOLUTION_FILE

- name: Test
run: dotnet test --no-build $SOLUTION_FILE

# Derive the package version from the pushed tag, e.g. refs/tags/v10.0.1 -> 10.0.1

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this also works for SemVer pre-release versions like "v10.2.0-beta.1" where the derived version will be "10.2.0-beta.1".

- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"

- name: Pack Ninject.Web.AspNetCore
run: dotnet pack $SOLUTION_FILE -c Release --include-symbols -p:SymbolPackageFormat=snupkg -p:Version=${{ steps.version.outputs.version }} --output ./artifacts

# Exchange the GitHub OIDC token for a short-lived (1 hour) NuGet API key
- name: NuGet login (OIDC -> temp API key)
uses: NuGet/login@v1
id: login
with:
user: ${{ secrets.NUGET_USER }}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly a secret since it's really just my NuGet username 😄. But apparently that's how it is done.


# Push the packages to NuGet
- name: Push to NuGet
run: dotnet nuget push ./artifacts/*.nupkg --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/lord-executor/Ninject.Web.AspNetCore/blob/master/LICENSE) [![.NET 8 CI](https://github.com/lord-executor/Ninject.Web.AspNetCore/actions/workflows/ci.yml/badge.svg)](https://github.com/lord-executor/Ninject.Web.AspNetCore/actions/workflows/ci.yml)
[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/lord-executor/Ninject.Web.AspNetCore/blob/master/LICENSE) [![.NET Build](https://github.com/lord-executor/Ninject.Web.AspNetCore/actions/workflows/build.yml/badge.svg)](https://github.com/lord-executor/Ninject.Web.AspNetCore/actions/workflows/build.yml)


# Overview
Expand Down
16 changes: 0 additions & 16 deletions doc/publish.ps1

This file was deleted.

21 changes: 9 additions & 12 deletions doc/release-process.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
# Release Process
Build and package the project with the _Release_ configuration.
Releases are built, packed and published automatically by the [`NuGet Package Release`](../.github/publish.yml) GitHub Actions workflow.

To ship a release, push a tag matching `v*.*.*` (e.g. `v10.0.1`):
```
$version = "5.1.x"
dotnet build .\src\Ninject.Web.AspNetCore.sln -c Release -p:Version="$version"
dotnet pack .\src\Ninject.Web.AspNetCore.sln -c Release --include-symbols -p:SymbolPackageFormat=snupkg -p:Version="$version"
git tag v10.0.1
git push origin v10.0.1
```

Publish all three packages with the `publish.ps1` script, replacing the API key and versions as needed.
```
.\doc\publish.ps1 -apiKey "NuGet APIKey" -version "$version"
```
The workflow then:
1. Restores, builds and tests the solution.
2. Derives the package version from the tag name (stripping the leading `v`, e.g. `v10.0.1` -> `10.0.1`) and packs all three packages with that version via `-p:Version`.
3. Exchanges the workflow's GitHub OIDC token for a short-lived NuGet API key ([NuGet Trusted Publishing](https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing)) and pushes the packages to nuget.org.

With the NuGet API key stored in the Windows credential manager, we can do
```
.\doc\publish.ps1 -apiKey $((Read-CredentialsStore -Target "NuGet:Ninject.Web.AspNetCore:APIKey").GetNetworkCredential().Password) -version "$version"
```
No manual build, pack or publish steps are required.
11 changes: 11 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project>

<PropertyGroup>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>Recommended</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<NoWarn>CA1805,CA1822</NoWarn>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Ninject.Planning.Bindings.Resolvers;
using Xunit;
namespace Ninject.Web.AspNetCore.ComplianceTest;
/// <summary>
/// See https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src - the dotnet/runtime
/// project which contains the dependency injection library code also contains a set of "compliance tests" that can be run against a potential alternative
/// implementation to check if it is compliant. This class is running the dedicated specification tests for KEYED services.
/// </summary>
public class KeyedDependencyInjectionComplianceTests : Microsoft.Extensions.DependencyInjection.Specification.KeyedDependencyInjectionSpecificationTests
{
protected override IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection)
{
var kernel = new AspNetCoreKernel();
// remove autobinding as CreateServiceWithKeyedParameter e.g. tests that no autobinding happens.
kernel.Components.Remove<IMissingBindingResolver, SelfBindingResolver>();
var factory = new NinjectServiceProviderFactory(kernel);
return factory.CreateBuilder(serviceCollection).Build();
}
#pragma warning disable xUnit1024, xUnit1026
[Theory(Skip = "Wrong implementation of the test, should use Assert.Equal and not Assert.Same")]
[InlineData(true)]
[InlineData(false)]
public new void ResolveWithAnyKeyQuery_Constructor(bool anyKeyQueryBeforeSingletonQueries)
{
}
[Theory(Skip = "Wrong implementation, should use Assert.Equal and not Assert.Same")]
[InlineData(true)]
[InlineData(false)]
public new void ResolveWithAnyKeyQuery_Constructor_Duplicates(bool anyKeyQueryBeforeSingletonQueries)
{
}
#pragma warning restore xUnit1024, xUnit1026
}
using System;
using Microsoft.Extensions.DependencyInjection;
using Ninject.Planning.Bindings.Resolvers;
using Xunit;

namespace Ninject.Web.AspNetCore.ComplianceTest;

/// <summary>
/// See https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src - the dotnet/runtime
/// project which contains the dependency injection library code also contains a set of "compliance tests" that can be run against a potential alternative
/// implementation to check if it is compliant. This class is running the dedicated specification tests for KEYED services.
/// </summary>
public class KeyedDependencyInjectionComplianceTests : Microsoft.Extensions.DependencyInjection.Specification.KeyedDependencyInjectionSpecificationTests
{
protected override IServiceProvider CreateServiceProvider(IServiceCollection collection)
{
var kernel = new AspNetCoreKernel();
// remove autobinding as CreateServiceWithKeyedParameter e.g. tests that no autobinding happens.
kernel.Components.Remove<IMissingBindingResolver, SelfBindingResolver>();
var factory = new NinjectServiceProviderFactory(kernel);

return factory.CreateBuilder(collection).Build();
}

#pragma warning disable xUnit1024, xUnit1026

[Theory(Skip = "Wrong implementation of the test, should use Assert.Equal and not Assert.Same")]
[InlineData(true)]
[InlineData(false)]
public new void ResolveWithAnyKeyQuery_Constructor(bool anyKeyQueryBeforeSingletonQueries)
{
}

[Theory(Skip = "Wrong implementation, should use Assert.Equal and not Assert.Same")]
[InlineData(true)]
[InlineData(false)]
public new void ResolveWithAnyKeyQuery_Constructor_Duplicates(bool anyKeyQueryBeforeSingletonQueries)
{
}
#pragma warning restore xUnit1024, xUnit1026
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
<!-- underscore test method names are this project's convention -->
<NoWarn>CA1707,CA1822,CA2263</NoWarn>

</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Hosting;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many files have a BOM which always annoys the living F out of me. An UTF-8 BOM makes no F-ing sense.

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.HttpSys;
using System;
using System.Runtime.Versioning;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting;

namespace Ninject.Web.AspNetCore.Hosting
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Ninject.Activation.Caching;
using Ninject.Activation.Caching;
using Ninject.Web.AspNetCore.Components;
using System;
using System.Collections.Generic;
Expand All @@ -7,7 +7,7 @@

namespace Ninject.Web.AspNetCore.Test.Fakes
{
public class FakeActivationCacheAccessor : IActivationCache, IActivationCacheAccessor
public sealed class FakeActivationCacheAccessor : IActivationCache, IActivationCacheAccessor

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This avoids the warning for calling GC.whatever... in the Dispose method which is one of the analyzer checks.

{
private readonly ConditionalWeakTable<object, ActivationEntry> _trackedInstances = new ConditionalWeakTable<object, ActivationEntry>();

Expand Down
6 changes: 3 additions & 3 deletions src/Ninject.Web.AspNetCore.Test/Fakes/IKeyedWeaponStorage.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
namespace Ninject.Web.AspNetCore.Test.Fakes
{
#if NET8_0_OR_GREATER
#if NET8_0_OR_GREATER
public interface IKeyedWeaponStorage
{
IWeapon Weapon { get; }
}
#endif
}
#endif
}
2 changes: 1 addition & 1 deletion src/Ninject.Web.AspNetCore.Test/Fakes/IWarrior.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Ninject.Web.AspNetCore.Test.Fakes
namespace Ninject.Web.AspNetCore.Test.Fakes
{
public interface IWarrior
{
Expand Down
4 changes: 2 additions & 2 deletions src/Ninject.Web.AspNetCore.Test/Fakes/KeyedNinja.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Ninject.Web.AspNetCore.Test.Fakes
#if NET8_0_OR_GREATER
public class KeyedNinja : IWarrior
{
public object Key {get; private set;}
public object Key { get; private set; }

public KeyedNinja([ServiceKey] object key)
{
Expand All @@ -15,4 +15,4 @@ public KeyedNinja([ServiceKey] object key)
public string Name => nameof(KeyedNinja);
}
#endif
}
}
6 changes: 3 additions & 3 deletions src/Ninject.Web.AspNetCore.Test/Fakes/KeyedWeaponStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Ninject.Web.AspNetCore.Test.Fakes
{
#if NET8_0_OR_GREATER
#if NET8_0_OR_GREATER
public class KeyedWeaponStorage : IKeyedWeaponStorage
{
public IWeapon Weapon { get; private set; }
Expand All @@ -11,5 +11,5 @@ public KeyedWeaponStorage([FromKeyedServices("Lance")] IWeapon lance)
Weapon = lance;
}
}
#endif
}
#endif
}
2 changes: 1 addition & 1 deletion src/Ninject.Web.AspNetCore.Test/Fakes/Knight.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Ninject.Web.AspNetCore.Test.Fakes
namespace Ninject.Web.AspNetCore.Test.Fakes
{
public class Knight : IWarrior
{
Expand Down
2 changes: 1 addition & 1 deletion src/Ninject.Web.AspNetCore.Test/Fakes/Lance.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Ninject.Web.AspNetCore.Test.Fakes
namespace Ninject.Web.AspNetCore.Test.Fakes
{
public class Lance : IWeapon
{
Expand Down
2 changes: 1 addition & 1 deletion src/Ninject.Web.AspNetCore.Test/Fakes/Longsword.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Ninject.Web.AspNetCore.Test.Fakes
namespace Ninject.Web.AspNetCore.Test.Fakes
{
public class Longsword : IWeapon
{
Expand Down
2 changes: 1 addition & 1 deletion src/Ninject.Web.AspNetCore.Test/Fakes/MobileInfantry.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Ninject.Web.AspNetCore.Test.Fakes
namespace Ninject.Web.AspNetCore.Test.Fakes
{
public class MobileInfantry : IWarrior
{
Expand Down
Loading