Skip to content

test: Set ConfigureAwait #597

test: Set ConfigureAwait

test: Set ConfigureAwait #597

Workflow file for this run

# Copyright (c) Omar Boukli-Hacene. All rights reserved.
# Distributed under an MIT-style license that can be
# found in the LICENSE file.
# SPDX-License-Identifier: MIT
name: Build and test
on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:
permissions: {}
env:
INTEGRATION_TEST_RESULTS_DIR_NAME: integration_test_results
UNIT_TEST_RESULTS_DIR_NAME: unit_test_results
jobs:
build:
name: Solution build
runs-on: ubuntu-latest
env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Build release
uses: ./.github/workflows/composite/dotnet-build
with:
configuration: Release
integration_test:
name: Integration test
runs-on: ubuntu-latest
env:
AKTABOOK_ENVIRONMENT: Test
AKTABOOK_INTEGRATION_TEST_ENVIRONMENT: Test
BUS_HOST_PID_FILE: src/Aktabook.Bus/bin/Release/net6.0/aktabook-bus.pid
DOTNET_CLI_TELEMETRY_OPTOUT: true
RequesterServiceBus__RabbitMQConnectionOptions__HostName: localhost
RequesterServiceBus__RabbitMQConnectionOptions__Password: ${{ secrets.RABBITMQ_INTEGRATION_TEST_PASSWORD }}
RequesterServiceBus__RabbitMQConnectionOptions__PortNumber: 5672
RequesterServiceBus__RabbitMQConnectionOptions__UserName: ${{ secrets.RABBITMQ_INTEGRATION_TEST_USERNAME }}
RequesterServiceBus__RabbitMQConnectionOptions__VirtualHost: aktabook_vhost
RequesterServiceDbContext__SqlServerConfig__DataSource: 127.0.0.1
RequesterServiceDbContext__SqlServerConfig__TrustServerCertificate: true
RequesterServiceDbContext__SqlServerConfig__InitialCatalog: aktabook_common
RequesterServiceDbContext__SqlServerConfig__Password: ${{ secrets.SQLSERVER_INTEGRATION_TEST_SA_PASSWORD }}
RequesterServiceDbContext__SqlServerConfig__UserID: sa
SQLSERVER_CLIENT_NUGET_VERSION: "5.1.0"
outputs:
artifact_name: ${{ steps.get_artifact_name.outputs.artifact_name }}
services:
sql_server:
image: mcr.microsoft.com/mssql/server:2022-latest
env:
ACCEPT_EULA: Y
SA_PASSWORD: ${{ secrets.SQLSERVER_INTEGRATION_TEST_SA_PASSWORD }}
SQLCMDUSER: sa
SQLCMDPASSWORD: ${{ secrets.SQLSERVER_INTEGRATION_TEST_SA_PASSWORD }}
ports:
- 1433:1433
options: >-
--health-cmd "
/opt/mssql-tools/bin/sqlcmd
-h -1
-Q 'SET NOCOUNT ON; SELECT 1'
-S 127.0.0.1
-W
> /dev/null
"
--health-interval 7s
--health-retries 5
--health-timeout 3s
rabbitmq:
image: rabbitmq:management
env:
RABBITMQ_DEFAULT_PASS: ${{ secrets.RABBITMQ_INTEGRATION_TEST_PASSWORD }}
RABBITMQ_DEFAULT_USER: ${{ secrets.RABBITMQ_INTEGRATION_TEST_USERNAME }}
RABBITMQ_DEFAULT_VHOST: aktabook_vhost
ports:
- 5672:5672
- 15672:15672
options: >-
--health-cmd "rabbitmq-diagnostics ping"
--health-interval 7s
--health-retries 5
--health-timeout 3s
--hostname aktabook-queue
steps:
- name: Mask escaped values
run: >-
printf "::add-mask::%q\n"
$RequesterServiceDbContext__SqlServerConfig__Password
echo "::add-mask::$(jq
--raw-input
--raw-output
@uri <<<"$RequesterServiceBus__RabbitMQConnectionOptions__Password")"
- name: Check out repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Build release
uses: ./.github/workflows/composite/dotnet-build
with:
configuration: Release
- name: Restore .NET tools
run: dotnet tool restore
- name: Create RabbitMQ virtual host
env:
BUS_USERNAME: ${{ secrets.RABBITMQ_INTEGRATION_TEST_USERNAME }}
BUS_PASSWORD: ${{ secrets.RABBITMQ_INTEGRATION_TEST_PASSWORD }}
run: >-
curl
--data-urlencode
--request PUT
--silent
--netrc-file <(cat <<< "login $BUS_USERNAME password $BUS_PASSWORD")
http://localhost:15672/api/vhosts/$RequesterServiceBus__RabbitMQConnectionOptions__VirtualHost
- name: Create AMQP connection URL
run: >-
echo "RABBITMQ_CONNECTION_STRING="$(
dotnet script eval --
$RequesterServiceBus__RabbitMQConnectionOptions__HostName
$RequesterServiceBus__RabbitMQConnectionOptions__PortNumber
$RequesterServiceBus__RabbitMQConnectionOptions__VirtualHost
$RequesterServiceBus__RabbitMQConnectionOptions__UserName
$RequesterServiceBus__RabbitMQConnectionOptions__Password
<<<
'Console.WriteLine((new UriBuilder("amqp",
Args[0],
int.Parse(Args[1]),
Uri.EscapeDataString(Args[2]))
{ UserName = Uri.EscapeDataString(Args[3]),
Password = Uri.EscapeDataString(Args[4])
}).Uri.ToString());'
)""
>> $GITHUB_ENV
- name: Create NServiceBus delays
env:
BUS_USERNAME: ${{ secrets.RABBITMQ_INTEGRATION_TEST_USERNAME }}
BUS_PASSWORD: ${{ secrets.RABBITMQ_INTEGRATION_TEST_PASSWORD }}
run: >-
dotnet rabbitmq-transport
delays create
--connectionStringEnv RABBITMQ_CONNECTION_STRING
dotnet rabbitmq-transport
delays verify
--url http://localhost:15672
--username $BUS_USERNAME
--password $BUS_PASSWORD
- name: Create NServiceBus BookInfoRequestEndpoint
run: >-
dotnet rabbitmq-transport
endpoint create BookInfoRequestEndpoint
--auditQueueName AuditQueue
--connectionStringEnv RABBITMQ_CONNECTION_STRING
--errorQueueName ErrorQueue
--queueType Quorum
--routingTopology Conventional
--useDurableEntities
- name: Start code coverage collection server
run: >-
dotnet coverage collect
--background
--session-id coverage_session
--server-mode
--output ${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}/coverage_session/coverage.coverage
--output-format coverage
- name: Create SQL Server connection string
run: >-
echo "SQLSERVER_CONNECTION_STRING="$(
dotnet script eval --
$RequesterServiceDbContext__SqlServerConfig__DataSource
$RequesterServiceDbContext__SqlServerConfig__TrustServerCertificate
$RequesterServiceDbContext__SqlServerConfig__UserID
$RequesterServiceDbContext__SqlServerConfig__Password
$RequesterServiceDbContext__SqlServerConfig__InitialCatalog
<<<
'#r "nuget: Microsoft.Data.SqlClient, ${{ env.SQLSERVER_CLIENT_NUGET_VERSION }}"
using Microsoft.Data.SqlClient;
Console.WriteLine((new SqlConnectionStringBuilder
{
DataSource = Args[0],
TrustServerCertificate = bool.Parse(Args[1]),
UserID = Args[2],
Password = Args[3],
InitialCatalog = Args[4]
}).ConnectionString);'
)""
>> $GITHUB_ENV
- name: Create database objects
run: >-
dotnet coverage connect
coverage_session
dotnet ef database update
--configuration Release
--connection "$SQLSERVER_CONNECTION_STRING"
--no-build
--project src/Aktabook.Data.Migrations
- name: Run bus endpoint host
run: >-
dotnet coverage connect
--background
coverage_session
./Aktabook.Bus
working-directory: src/Aktabook.Bus/bin/Release/net6.0/
- name: Wait for bus readiness check
env:
PORT: 23514
run: >-
x=1;
while [[ $x -le 30 && ! -f "$BUS_HOST_PID_FILE" ]];
do sleep $(( x++ ));
done
nc -4 -d -i 1 -n -v -w 10 -z
127.0.0.1 ${{ env.PORT }}
- name: Wait for bus liveness first check
env:
PORT: 23515
run: >-
nc -4 -d -i 1 -n -v -w 10 -z
127.0.0.1 ${{ env.PORT }}
- name: Run integration tests with ephemeral database
env:
RequesterServiceDbContext__SqlServerConfig__InitialCatalog: aktabook_ephemeral
run: >-
dotnet test
--collect 'Code Coverage'
--configuration Release
--filter 'FullyQualifiedName~IntegrationTest&Category=Ephemeral'
--no-build
--no-restore
--results-directory ${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}
- name: Run integration tests with long-lived database
run: >-
dotnet test
--collect 'Code Coverage'
--configuration Release
--filter 'FullyQualifiedName~IntegrationTest&Category!=Ephemeral'
--no-build
--no-restore
--results-directory ${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}
- name: Wait for bus liveness last check
env:
PORT: 23515
run: >-
nc -4 -d -i 1 -n -v -w 10 -z
127.0.0.1 ${{ env.PORT }}
- name: Stop bus endpoint host
run: >-
pkill
--pidfile $BUS_HOST_PID_FILE
--signal SIGTERM
- name: Stop code coverage collection server
run: >-
dotnet coverage
shutdown
coverage_session
- name: Create merged test coverage report directory
run: mkdir --parents ${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}/merged/
- name: Merge test coverage reports
run: >-
dotnet coverage merge
--remove-input-files
--recursive
--output ${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}/merged/merged.xml
--output-format xml
${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}/*/*.*
- name: Archive test coverage results
run: >-
7z a -bb0 -bd -m0=lzma2 -mx=3
${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}.7z
${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}/merged/
- name: Get artifact name
id: get_artifact_name
run: >-
echo "artifact_name="${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}-$(git rev-parse --short "$GITHUB_SHA")""
>> $GITHUB_OUTPUT
- name: Upload test results archive
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: ${{ steps.get_artifact_name.outputs.artifact_name }}
path: ${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}.7z
- name: Upload bus logs
if: ${{ always() }}
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: bus-logs
path: src/Aktabook.Bus/bin/Release/net6.0/Logs
- name: Upload public API logs
if: ${{ always() }}
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: public-api-logs
path: src/Aktabook.Bus/bin/Release/net6.0/Logs
unit_test:
name: Unit test
runs-on: ubuntu-latest
outputs:
artifact_name: ${{ steps.get_artifact_name.outputs.artifact_name }}
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Build release
uses: ./.github/workflows/composite/dotnet-build
with:
configuration: Release
- name: Restore .NET tools
run: dotnet tool restore
- name: Run unit tests
run: >-
dotnet test
--collect 'Code Coverage'
--configuration Release
--filter 'FullyQualifiedName~UnitTest'
--no-build
--no-restore
--results-directory ${{ env.UNIT_TEST_RESULTS_DIR_NAME }}
- name: Create merged test coverage report directory
run: mkdir --parents ${{ env.UNIT_TEST_RESULTS_DIR_NAME }}/merged/
- name: Merge test coverage reports
run: >-
dotnet coverage merge
--remove-input-files
--recursive
--output ${{ env.UNIT_TEST_RESULTS_DIR_NAME }}/merged/merged.xml
--output-format xml
${{ env.UNIT_TEST_RESULTS_DIR_NAME }}/*/*.*
- name: Archive test coverage results
run: >-
7z a -bb0 -bd -m0=lzma2 -mx=3
${{ env.UNIT_TEST_RESULTS_DIR_NAME }}.7z
${{ env.UNIT_TEST_RESULTS_DIR_NAME }}/merged/
- name: Get artifact name
id: get_artifact_name
run: >-
echo "artifact_name="${{ env.UNIT_TEST_RESULTS_DIR_NAME }}-$(git rev-parse --short "$GITHUB_SHA")""
>> $GITHUB_OUTPUT
- name: Upload test results archive
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: ${{ steps.get_artifact_name.outputs.artifact_name }}
path: ${{ env.UNIT_TEST_RESULTS_DIR_NAME }}.7z
quality_gate:
name: Quality gate
runs-on: ubuntu-latest
needs:
- unit_test
- integration_test
env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false
- name: Download integration test results
uses: actions/download-artifact@v3
with:
name: ${{ needs.integration_test.outputs.artifact_name }}
- name: Download unit test results
uses: actions/download-artifact@v3
with:
name: ${{ needs.unit_test.outputs.artifact_name }}
- name: Unarchive integration test results
run: >-
7z x
-o"${{ github.workspace }}"
${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}.7z
- name: Unarchive unit test results
run: >-
7z x
-o"${{ github.workspace }}"
${{ env.UNIT_TEST_RESULTS_DIR_NAME }}.7z
- name: Cache NuGet packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: >-
${{ runner.os }}-nuget-${{
hashFiles('**/packages.lock.json',
'.config/dotnet-tools.json')
}}
restore-keys: |
${{ runner.os }}-nuget-
- name: Set up .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
- name: Restore .NET tools
run: dotnet tool restore
- name: Merge test coverage reports
run: >-
dotnet coverage merge
--remove-input-files
--recursive
--output merged.xml
--output-format xml
${{ env.UNIT_TEST_RESULTS_DIR_NAME }}/merged.xml
${{ env.INTEGRATION_TEST_RESULTS_DIR_NAME }}/merged.xml
- name: Restores dependencies
env:
DOTNET_NUGET_SIGNATURE_VERIFICATION: true
run: dotnet restore --locked-mode
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
DOTNET_CLI_TELEMETRY_OPTOUT: true
run: >-
JAVA_HOME=$JAVA_HOME_17_X64
dotnet sonarscanner begin
/k:'oboukli_aktabook'
/o:'oboukli'
/d:'sonar.host.url=https://sonarcloud.io'
/d:'sonar.sourceEncoding=UTF-8'
/d:'sonar.login=${{ secrets.SONAR_TOKEN }}'
/d:'sonar.cs.vscoveragexml.reportsPaths=merged.xml'
dotnet build
--no-incremental
--no-restore
dotnet sonarscanner end
/d:'sonar.login=${{ secrets.SONAR_TOKEN }}'