Skip to content

Commit

Permalink
Add SonarCloud and Coverlet (#197)
Browse files Browse the repository at this point in the history
* Add SonarCloud step

Signed-off-by: Tomasz Maruszak <maruszaktomasz@gmail.com>
  • Loading branch information
zarusz authored Nov 1, 2023
1 parent c4cbbac commit ca8d6b7
Show file tree
Hide file tree
Showing 19 changed files with 117 additions and 79 deletions.
37 changes: 35 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,52 @@ jobs:

steps:
- uses: actions/checkout@v3

- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x

- name: Restore dependencies
run: dotnet restore $SOLUTION_NAME
working-directory: ./src

- name: Install Coverlet
run: find . -name "*.Test.csproj" | xargs -t -I {} dotnet add {} package coverlet.collector
working-directory: ./src

- name: SonarCloud - Setup Java17
uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: "17"

- name: SonarCloud - Install SonarCloud scanner
run: dotnet tool update dotnet-sonarscanner --tool-path ./.sonar/scanner

- name: SonarCloud - SonarScanner Begin
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ../.sonar/scanner/dotnet-sonarscanner begin /k:"zarusz_SlimMessageBus" /o:"zarusz" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.exclusions="Samples/**/*,Tests/**/*"
working-directory: ./src

- name: Build
run: dotnet build $SOLUTION_NAME --configuration $SOLUTION_CONFIGURATION --no-restore
working-directory: ./src
- name: Unit Tests
run: dotnet test $SOLUTION_NAME --configuration $SOLUTION_CONFIGURATION --no-build --verbosity normal --logger html --results-directory TestResults --filter Category!=Integration
run: dotnet test $SOLUTION_NAME --configuration $SOLUTION_CONFIGURATION --no-build --verbosity normal --logger html --results-directory TestResults --collect:"XPlat Code Coverage;Format=opencover" --filter Category!=Integration
working-directory: ./src

# - name: Dump GitHub context
# env:
# GITHUB_CONTEXT: ${{ toJson(github) }}
# run: echo "$GITHUB_CONTEXT"
# Run integration tests against the test infrastructure if secrets are provided

- name: Integrations Tests
if: "${{ env.azure_servicebus_key != '' }}"
run: dotnet test $SOLUTION_NAME --configuration $SOLUTION_CONFIGURATION --no-build --verbosity normal --logger html --results-directory TestResults --filter Category=Integration
run: dotnet test $SOLUTION_NAME --configuration $SOLUTION_CONFIGURATION --no-build --verbosity normal --logger html --results-directory TestResults --collect:"XPlat Code Coverage;Format=opencover" --filter Category=Integration
working-directory: ./src
env:
azure_servicebus_key: ${{ secrets.azure_servicebus_key }}
Expand All @@ -54,6 +79,14 @@ jobs:
redis_password: ${{ secrets.redis_password }}
mqtt_password: ${{ secrets.mqtt_password }}
rabbitmq_password: ${{ secrets.rabbitmq_password }}

- name: SonarCloud - SonarScanner End
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ../.sonar/scanner/dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
working-directory: ./src

- name: Upload test results
uses: actions/upload-artifact@v3
with:
Expand Down
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ SlimMessageBus is a client façade for message brokers for .NET. It comes with i
[![Gitter](https://badges.gitter.im/SlimMessageBus/community.svg)](https://gitter.im/SlimMessageBus/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![GitHub license](https://img.shields.io/github/license/zarusz/SlimMessageBus)](https://github.com/zarusz/SlimMessageBus/blob/master/LICENSE)
[![Build](https://github.com/zarusz/SlimMessageBus/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/zarusz/SlimMessageBus/actions/workflows/build.yml)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=zarusz_SlimMessageBus&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=zarusz_SlimMessageBus)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=zarusz_SlimMessageBus&metric=coverage)](https://sonarcloud.io/summary/new_code?id=zarusz_SlimMessageBus)
[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=zarusz_SlimMessageBus&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=zarusz_SlimMessageBus)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=zarusz_SlimMessageBus&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=zarusz_SlimMessageBus)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=zarusz_SlimMessageBus&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=zarusz_SlimMessageBus)

> The v2.0.0 major release is available.
> Please review the [release notes](https://github.com/zarusz/SlimMessageBus/releases/tag/Host.Transport-2.0.0).
> The 2.x.x major release is available.
> Please review the [migration guide](https://github.com/zarusz/SlimMessageBus/releases/tag/Host.Transport-2.0.0).
- [Key elements of SlimMessageBus](#key-elements-of-slimmessagebus)
- [Docs](#docs)
Expand Down Expand Up @@ -148,7 +153,7 @@ services.AddSlimMessageBus(mbb =>
{
mbb
// First child bus - in this example Kafka transport
.AddChildBus("Bus1", (builder) =>
.AddChildBus("Bus1", (builder) =>
{
builder
.Produce<SomeMessage>(x => x.DefaultTopic("some-topic"))
Expand All @@ -171,7 +176,7 @@ services.AddSlimMessageBus(mbb =>
// Use in-memory transport provider
//.WithProviderMemory(cfg => { ... }) // requires SlimMessageBus.Host.Memory package
})

// Add other bus transports (as child bus), if needed
//.AddChildBus("Bus2", (builder) => { })
Expand Down Expand Up @@ -264,7 +269,7 @@ The `SlimMessageBus` configuration for the in-memory provider looks like this:
//IServiceCollection services;
// Cofigure the message bus
services.AddSlimMessageBus(mbb =>
services.AddSlimMessageBus(mbb =>
{
mbb.WithProviderMemory();
// Find types that implement IConsumer<T> and IRequestHandler<T, R> and declare producers and consumers on the mbb
Expand All @@ -277,7 +282,7 @@ services.AddSlimMessageBus(mbb =>
For the ASP.NET project, set up the `MessageBus.Current` helper (if you want to use it, and pick up the current web-request scope):

```cs
services.AddSlimMessageBus(mbb =>
services.AddSlimMessageBus(mbb =>
{
// ...
mbb.AddAspNet(); // requires SlimMessageBus.Host.AspNetCore package
Expand Down Expand Up @@ -356,7 +361,7 @@ Run all tests:
dotnet test
```

Run all tests except integration tests that require local/cloud infrastructure:
Run all tests except integration tests that require local/cloud infrastructure:

```cmd
dotnet test --filter Category!=Integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public EhGroupConsumer(EventHubMessageBus messageBus, GroupPath groupPath, Func<
_groupPath = groupPath ?? throw new ArgumentNullException(nameof(groupPath));
if (partitionConsumerFactory == null) throw new ArgumentNullException(nameof(partitionConsumerFactory));

MessageBus = messageBus ?? throw new ArgumentNullException(nameof(messageBus));
MessageBus = messageBus;

_partitionConsumerByPartitionId = new SafeDictionaryWrapper<string, EhPartitionConsumer>(partitionId =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ public abstract class EhPartitionConsumer

protected EhPartitionConsumer(EventHubMessageBus messageBus, GroupPathPartitionId groupPathPartition)
{
_logger = messageBus.LoggerFactory.CreateLogger<EhPartitionConsumer>();
MessageBus = messageBus ?? throw new ArgumentNullException(nameof(messageBus));
GroupPathPartition = groupPathPartition ?? throw new ArgumentNullException(nameof(groupPathPartition));
_logger = messageBus.LoggerFactory.CreateLogger<EhPartitionConsumer>();
}

public Task OpenAsync()
Expand Down
6 changes: 3 additions & 3 deletions src/SlimMessageBus.Host.AzureEventHub/EventHubMessageBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ protected override void Build()
_logger.LogDebug(e, "Error creating EventHubClient for path {Path}", path);
throw;
}
});
}
});
}

protected override async Task CreateConsumers()
{
Expand Down Expand Up @@ -102,7 +102,7 @@ protected override async Task OnStart()
}
}

protected override async Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders, CancellationToken cancellationToken)
protected override async Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders = null, CancellationToken cancellationToken = default)
{
AssertActive();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ protected override async ValueTask DisposeAsyncCore()
}
}

protected override async Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders, CancellationToken cancellationToken)
protected override async Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders = null, CancellationToken cancellationToken = default)
{
var messageType = message?.GetType();

Expand Down Expand Up @@ -164,11 +164,11 @@ protected override async Task ProduceToTransport(object message, string path, by
}
}

public override Task ProduceRequest(object request, IDictionary<string, object> headers, string path, ProducerSettings producerSettings)
public override Task ProduceRequest(object request, IDictionary<string, object> requestHeaders, string path, ProducerSettings producerSettings)
{
if (headers is null) throw new ArgumentNullException(nameof(headers));
if (requestHeaders is null) throw new ArgumentNullException(nameof(requestHeaders));

return base.ProduceRequest(request, headers, path, producerSettings);
return base.ProduceRequest(request, requestHeaders, path, producerSettings);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ public ServiceBusTopologyService(ILogger<ServiceBusTopologyService> logger, Mess
[Flags]
private enum TopologyCreationStatus
{
NotExists = 0,
Exists = 1,
Created = 2
None = 0,
NotExists = 1,
Exists = 2,
Created = 4
}

private async Task<TopologyCreationStatus> SwallowExceptionIfEntityExists(Func<Task<TopologyCreationStatus>> task)
Expand Down Expand Up @@ -206,7 +207,7 @@ await TryCreateQueue(path, topologyProvisioning.CanConsumerCreateQueue, options
removeRuleTasks
.AddRange(rulesPage.Values
.Where(rule => !filters.Any(filter => filter.Name == rule.Name))
.Select(rule => SwallowExceptionIfMessagingEntityNotFound(() =>
.Select(rule => SwallowExceptionIfMessagingEntityNotFound(() =>
adminClient.DeleteRuleAsync(path, subscriptionName, rule.Name)))
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ public HandlerValidationInterceptor(IEnumerable<IValidator<T>> validators, IVali
{
}

public async Task<R> OnHandle(T message, Func<Task<R>> next, IConsumerContext context)
public async Task<R> OnHandle(T request, Func<Task<R>> next, IConsumerContext context)
{
await OnValidate(message, context.CancellationToken).ConfigureAwait(false);
await OnValidate(request, context.CancellationToken).ConfigureAwait(false);
return await next().ConfigureAwait(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class KafkaGroupConsumer : AbstractConsumer, IKafkaCommitController
public KafkaGroupConsumer(KafkaMessageBus messageBus, string group, IReadOnlyCollection<string> topics, Func<TopicPartition, IKafkaCommitController, IKafkaPartitionConsumer> processorFactory)
: base(messageBus.LoggerFactory.CreateLogger<KafkaGroupConsumer>())
{
MessageBus = messageBus ?? throw new ArgumentNullException(nameof(messageBus));
MessageBus = messageBus;
Group = group ?? throw new ArgumentNullException(nameof(group));
Topics = topics ?? throw new ArgumentNullException(nameof(topics));

Expand Down
2 changes: 1 addition & 1 deletion src/SlimMessageBus.Host.Kafka/KafkaMessageBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ protected override async ValueTask DisposeAsyncCore()
}
}

protected override async Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders, CancellationToken cancellationToken)
protected override async Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders = null, CancellationToken cancellationToken = default)
{
AssertActive();

Expand Down
4 changes: 2 additions & 2 deletions src/SlimMessageBus.Host.Outbox.Sql/SqlOutboxRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,13 +342,13 @@ protected async virtual ValueTask DisposeAsyncCore()
}
}

public async Task DeleteSent(DateTime timestampBefore, CancellationToken token)
public async Task DeleteSent(DateTime olderThan, CancellationToken token)
{
await EnsureConnection();

var affected = await ExecuteNonQuery(token, Settings.OperationRetry, _sqlTemplate.SqlOutboxMessageDeleteSent, cmd =>
{
cmd.Parameters.Add("@Timestamp", SqlDbType.DateTime2).Value = timestampBefore;
cmd.Parameters.Add("@Timestamp", SqlDbType.DateTime2).Value = olderThan;
});

_logger.Log(affected > 0 ? LogLevel.Information : LogLevel.Debug, "Removed {MessageCount} sent messages from outbox table", affected);
Expand Down
56 changes: 30 additions & 26 deletions src/SlimMessageBus.Host.RabbitMQ/RabbitMqMessageBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ public class RabbitMqMessageBus : MessageBusBase<RabbitMqMessageBusSettings>, IR
private readonly ILogger _logger;
private IConnection _connection;

private IModel _channel;
private readonly object _channelLock = new();
private IModel _channel;

#region IRabbitMqChannel

Expand Down Expand Up @@ -38,22 +38,22 @@ protected override async Task CreateConsumers()

foreach (var (queueName, consumers) in Settings.Consumers.GroupBy(x => x.GetQueueName()).ToDictionary(x => x.Key, x => x.ToList()))
{
AddConsumer(new RabbitMqConsumer(LoggerFactory,
channel: this,
queueName: queueName,
consumers,
Serializer,
messageBus: this,
AddConsumer(new RabbitMqConsumer(LoggerFactory,
channel: this,
queueName: queueName,
consumers,
Serializer,
messageBus: this,
ProviderSettings.HeaderValueConverter));
}

if (Settings.RequestResponse != null)
{
AddConsumer(new RabbitMqResponseConsumer(LoggerFactory,
channel: this,
queueName: Settings.RequestResponse.GetQueueName(),
Settings.RequestResponse,
this,
AddConsumer(new RabbitMqResponseConsumer(LoggerFactory,
channel: this,
queueName: Settings.RequestResponse.GetQueueName(),
Settings.RequestResponse,
this,
ProviderSettings.HeaderValueConverter));
}
}
Expand Down Expand Up @@ -83,28 +83,32 @@ private async Task CreateConnection()

lock (_channelLock)
{
_channel.CloseAndDispose();
_channel = _connection.CreateModel();

var topologyService = new RabbitMqTopologyService(LoggerFactory, _channel, Settings, ProviderSettings);
_channel?.CloseAndDispose();

var customAction = ProviderSettings.GetOrDefault<RabbitMqTopologyInitializer>(RabbitMqProperties.TopologyInitializer);
if (customAction != null)
if (_connection != null)
{
// Allow the user to specify its own initializer
customAction(_channel, () => topologyService.ProvisionTopology());
}
else
{
// Perform default topology setup
topologyService.ProvisionTopology();
_channel = _connection.CreateModel();

var topologyService = new RabbitMqTopologyService(LoggerFactory, _channel, Settings, ProviderSettings);

var customAction = ProviderSettings.GetOrDefault<RabbitMqTopologyInitializer>(RabbitMqProperties.TopologyInitializer);
if (customAction != null)
{
// Allow the user to specify its own initializer
customAction(_channel, () => topologyService.ProvisionTopology());
}
else
{
// Perform default topology setup
topologyService.ProvisionTopology();
}
}
}
}
catch (Exception e)
{
_logger.LogError(e, "Could not initialize RabbitMQ connection: {ErrorMessage}", e.Message);
}
}
}

protected override async ValueTask DisposeAsyncCore()
Expand Down
2 changes: 1 addition & 1 deletion src/SlimMessageBus.Host.Redis/RedisMessageBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void AddTopicConsumer(string topic, ISubscriber subscriber, IMessageProcessor<Me

#region Overrides of MessageBusBase

protected override Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders, CancellationToken cancellationToken)
protected override Task ProduceToTransport(object message, string path, byte[] messagePayload, IDictionary<string, object> messageHeaders = null, CancellationToken cancellationToken = default)
{
var messageType = message.GetType();

Expand Down
Loading

0 comments on commit ca8d6b7

Please sign in to comment.