diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml
new file mode 100644
index 0000000..a22b4d2
--- /dev/null
+++ b/.azure/pipelines/ci.yml
@@ -0,0 +1,47 @@
+variables:
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
+ DOTNET_CLI_TELEMETRY_OPTOUT: 1
+ CI_BUILD_NUMBER: $(Build.BuildId)
+ BRANCH_NAME: $(Build.SourceBranchName)
+ TAG_NAME: $(Build.SourceBranchName)
+
+trigger:
+ - master
+ - ci-*
+ - refs/tags/v*
+
+pr:
+ branches:
+ include:
+ - master
+
+#schedules:
+# - cron: "0 0 * * *"
+# displayName: "Daily midnight build"
+# branches:
+# include:
+# - master
+
+stages:
+ - stage: Build_Test
+ jobs:
+ - template: jobs/build_and_test.yml
+
+ - stage: E2E_Tests
+ dependsOn:
+ - Build_Test
+ jobs:
+ - template: jobs/e2e_tests.yml
+
+ - stage: Code_Coverage
+ dependsOn:
+ - Build_Test
+ jobs:
+ - template: jobs/coverage.yml
+
+ - stage: Deploy
+ dependsOn:
+ - E2E_Tests
+ condition: and( succeeded(), startsWith( variables['Build.SourceBranch'], 'refs/tags' ) )
+ jobs:
+ - template: jobs/deploy_nuget.yml
diff --git a/.azure/pipelines/jobs/build_and_test.yml b/.azure/pipelines/jobs/build_and_test.yml
new file mode 100644
index 0000000..d53632f
--- /dev/null
+++ b/.azure/pipelines/jobs/build_and_test.yml
@@ -0,0 +1,70 @@
+jobs:
+ - job: build_test
+ displayName: build and test
+ pool:
+ vmImage: 'ubuntu-18.04'
+ strategy:
+ matrix:
+ debug-build:
+ BUILD_CONFIG: Debug
+ release-build:
+ BUILD_CONFIG: Release
+ steps:
+ - bash: |
+ echo 'installed sdks:'
+ dotnet --list-sdks
+ echo "-------------------------------------------------"
+ echo 'environment variables:'
+ env | sort
+
+ chmod u+x ./build.sh
+ displayName: init
+
+ - bash: ./build.sh build
+ displayName: build
+
+ # coverlet.msbuild must be added as package to the tests
+ - bash: ./build.sh test-coverage
+ displayName: test
+
+ - task: PublishTestResults@2
+ condition: always()
+ inputs:
+ testRunner: VSTest
+ # no global glob, because of trx-test-files used in the project
+ testResultsFiles: 'tests/trx2junit.Tests/TestResults/*.trx'
+
+ - bash: |
+ cd tests/Coverage
+
+ workDir="$(System.DefaultWorkingDirectory)"
+
+ if [[ "$AGENT_OS" == "Windows_NT" ]]; then
+ # Windows needs special treetment for the substitution due the \
+ workDir="${workDir//\\/\\\\}\\\\"
+ else
+ workDir+="/"
+ fi
+
+ # Mac has a different sed, so special case it (hooray for standars ;-))
+ if [[ "$AGENT_OS" != "Darwin" ]]; then
+ sed -i 's|[^<]*|/|g' "Cobertura.xml"
+ sed -i "s|${workDir}||g" "Cobertura.xml"
+ else
+ sed -i '' 's|[^<]+|/|g' "Cobertura.xml"
+ sed -i '' "s|${workDir}||g" "Cobertura.xml"
+ fi
+ displayName: make Cobertura-paths relative
+
+ # shortcut for PublishPipelineArtifact
+ # Coverage report will be created later in a different stage
+ - publish: tests/Coverage/Cobertura.xml
+ artifact: 'Coverage-${{ parameters.name }}-$(BUILD_CONFIG)'
+
+ - bash: ./build.sh pack
+ displayName: pack
+ condition: and(succeeded(), eq(variables['BUILD_CONFIG'], 'Release'))
+
+ - publish: 'NuGet-Packed'
+ artifact: 'NuGet-Packed'
+ condition: and(succeeded(), eq(variables['BUILD_CONFIG'], 'Release'))
diff --git a/.azure/pipelines/jobs/coverage.yml b/.azure/pipelines/jobs/coverage.yml
new file mode 100644
index 0000000..f72bd8c
--- /dev/null
+++ b/.azure/pipelines/jobs/coverage.yml
@@ -0,0 +1,28 @@
+jobs:
+ - job: coverage_report_quality
+ pool:
+ vmImage: 'ubuntu-18.04'
+ steps:
+ # checkout is needed for file-references
+ #- checkout: none
+
+ - task: DownloadPipelineArtifact@2
+ inputs:
+ targetPath: './coverage'
+
+ - task: PublishCodeCoverageResults@1
+ inputs:
+ codeCoverageTool: Cobertura
+ summaryFileLocation: 'coverage/**/Cobertura.xml'
+ pathToSources: $(System.DefaultWorkingDirectory)
+
+ # extension from Marketplace https://marketplace.visualstudio.com/acquisition?itemName=mspremier.BuildQualityChecks
+ - task: BuildQualityChecks@6
+ displayName: 'Check build quality'
+ inputs:
+ checkCoverage: true
+ coverageFailOption: 'build'
+ coverageType: 'lines'
+ allowCoverageVariance: true
+ coverageVariance: '0.5'
+ baseBranchRef: 'master'
diff --git a/.azure/pipelines/jobs/deploy_nuget.yml b/.azure/pipelines/jobs/deploy_nuget.yml
new file mode 100644
index 0000000..98eb18a
--- /dev/null
+++ b/.azure/pipelines/jobs/deploy_nuget.yml
@@ -0,0 +1,66 @@
+jobs:
+ - job: deploy_nuget
+ pool:
+ vmImage: 'ubuntu-18.04'
+ steps:
+ - checkout: none
+
+ - task: DownloadPipelineArtifact@2
+ inputs:
+ artifactName: 'NuGet-Packed'
+ targetPath: './'
+
+ - bash: |
+ echo "NuGet-Packed:"
+ ls -la .
+
+ if [[ "$TAG_NAME" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)(-(preview-[0-9]+))$ ]]; then
+ mkdir deploy_custom
+
+ for package in ./*.nupkg; do
+ mv $package deploy_custom
+ done
+
+ echo "##vso[task.setvariable variable=deploy_custom;]1"
+ elif [[ "$TAG_NAME" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
+ mkdir deploy_nuget
+
+ for package in ./*.nupkg; do
+ mv $package deploy_nuget
+ done
+
+ echo "##vso[task.setvariable variable=deploy_nuget;]1"
+ else
+ echo "no deploy, as $TAG_NAME does not match"
+ echo ##vso[task.complete result=Skipped;]tag does not match for deploy
+ fi
+
+ echo "-------------------------------------------------"
+ echo "custom:"
+ ls -la deploy_custom
+ echo "-------------------------------------------------"
+ echo "nuget:"
+ ls -la deploy_nuget
+ echo "-------------------------------------------------"
+ displayName: 'deploy to nuget / custom'
+
+ - task: NuGetAuthenticate@0
+ condition: eq(variables['deploy_custom'], '1')
+
+ - task: NuGetCommand@2
+ condition: eq(variables['deploy_custom'], '1')
+ inputs:
+ command: push
+ packagesToPush: deploy_custom/*.nupkg
+ nuGetFeedType: 'internal'
+ publishVstsFeed: 'github-Projects/gfoidl-public'
+ displayName: deploy to custom feed
+
+ - task: NuGetCommand@2
+ condition: eq(variables['deploy_nuget'], '1')
+ inputs:
+ command: push
+ packagesToPush: deploy_nuget/*.nupkg
+ nuGetFeedType: external
+ publishFeedCredentials: 'nuget - gfoidl'
+ displayName: deploy to nuget
diff --git a/.azure/pipelines/jobs/e2e_tests.yml b/.azure/pipelines/jobs/e2e_tests.yml
new file mode 100644
index 0000000..5ce2d68
--- /dev/null
+++ b/.azure/pipelines/jobs/e2e_tests.yml
@@ -0,0 +1,82 @@
+jobs:
+ - job: e2e_tests
+ displayName: e2e tests
+ pool:
+ vmImage: 'ubuntu-18.04'
+ steps:
+ - bash: |
+ sudo apt update
+ sudo apt install -y libxml2-utils
+ displayName: install xml-lint
+
+ - task: DownloadPipelineArtifact@2
+ inputs:
+ artifactName: 'NuGet-Packed'
+ targetPath: './NuGet-Packed'
+
+ - bash: |
+ chmod ugo+x -R *.sh
+ chmod ugo+x ./tests/scripts/*.sh
+ displayName: init
+
+ - bash: |
+ # copied from build.sh (but modified)
+ if [[ -n "$TAG_NAME" ]]; then
+ if [[ "$TAG_NAME" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)(-(preview-[0-9]+))?$ ]]; then
+ export VersionMajor="${BASH_REMATCH[1]}"
+ export VersionMinor="${BASH_REMATCH[2]}"
+ export VersionPatch="${BASH_REMATCH[3]}"
+ export VersionSuffix="${BASH_REMATCH[5]}"
+
+ ToolVersion="$VersionMajor.$VersionMinor.$VersionPatch-$VersionSuffix"
+ fi
+ fi
+
+ # special handling for pre-releases (is a constraint by .NET Core global tools)
+ # and also to prevent installation from NuGet-feed (which may have higher version than the
+ # built tool)
+ if [[ -z "$ToolVersion" ]]; then
+ dotnet tool install --tool-path $(pwd)/tool --configfile=ci-nuget.config trx2junit
+ else
+ dotnet tool install --tool-path $(pwd)/tool --version="$ToolVersion" --configfile=ci-nuget.config trx2junit
+ fi
+
+ echo "##vso[task.prependpath]$(pwd)/tool"
+ displayName: install built trx2junit-tool
+
+ - bash: |
+ echo $PATH
+ echo "-------------------------------------------------"
+ dotnet tool list --tool-path $(pwd)/tool
+ echo "-------------------------------------------------"
+ trx2junit
+
+ if [[ $? != 1 ]]; then
+ echo "hm, something strange"
+ exit 1
+ fi
+ displayName: check tool installation
+
+ - bash: ./build.sh build
+ displayName: build
+
+ - bash: ./tests/scripts/run-samples.sh
+ displayName: samples
+
+ - bash: ./tests/scripts/run-single-arg.sh
+ displayName: single-arg
+
+ - bash: ./tests/scripts/run-multiple-args.sh
+ displayName: multiple-args
+
+ - bash: ./tests/scripts/run-globbing.sh
+ displayName: globbing
+
+ - bash: ./tests/scripts/run-no-globbing.sh
+ displayName: no-globbing
+
+ - bash: ./tests/scripts/run-different-output-location.sh
+ displayName: different-output-location
+
+ - bash: ./tests/scripts/run-junit2trx.sh
+ displayName: junit2trx
diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 7cb85b0..0000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,196 +0,0 @@
-version: 2.1
-
-executors:
- build-executor:
- docker:
- - image: gfoidl/dotnet-xmllint:3.0
- environment:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
-
- deploy-executor:
- docker:
- - image: mcr.microsoft.com/dotnet/core/sdk:3.0
- environment:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
-
-commands:
- set_env:
- description: "Sets the build environment variables"
- steps:
- - run:
- name: "set build environment"
- command: |
- if [[ -z "$CI_BUILD_NUMBER" ]]; then
- echo 'export CI_BUILD_NUMBER="$CIRCLE_BUILD_NUM"' >> "$BASH_ENV"
- echo 'export BRANCH_NAME="$CIRCLE_BRANCH"' >> "$BASH_ENV"
- echo 'export TAG_NAME="$CIRCLE_TAG"' >> "$BASH_ENV"
- fi
-
- # Exporting / sourcing the path before installing the tool prevents the message about the PATH
- echo 'export PATH="$PATH:/root/.dotnet/tools"' >> "$BASH_ENV"
-
- build_test:
- description: "Builds and tests"
- parameters:
- debug-build:
- type: boolean
- default: false
- steps:
- - checkout
- - set_env
- - run:
- name: init
- command: |
- chmod ugo+x ./*.sh
- chmod ugo+x ./tests/scripts/*.sh
-
- # Use v1.4.1 as this supports .NET Core 2.1. Version 1.5.0 is for .NET Core 2.2.
- dotnet tool install -g --version=1.4.1 coverlet.console
- - run:
- # build has to be from the build.sh in order to pick the correct version numbers, etc.
- name: build
- command: ./build.sh build
- - run:
- name: test
- command: ./build.sh test
- - unless:
- condition: << parameters.debug-build >>
- steps:
- - run:
- name: pack
- command: ./build.sh pack
- - run:
- name: global tool install (trx2junit)
- command: |
- # copied from build.sh (but modified)
- if [[ -n "$CIRCLE_TAG" ]]; then
- if [[ "$CIRCLE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)(-(preview-[0-9]+))$ ]]; then
- VersionMajor="${BASH_REMATCH[1]}"
- VersionMinor="${BASH_REMATCH[2]}"
- VersionPatch="${BASH_REMATCH[3]}"
- VersionSuffix="${BASH_REMATCH[5]}"
-
- ToolVersion="$VersionMajor.$VersionMinor.$VersionPatch-$VersionSuffix"
- fi
- fi
-
- # special handling for pre-releases (is a constraint by .net Core global tools)
- # and also to prevent installation from NuGet-feed (which may have higher version than the
- # built tool)
- if [[ -z "$ToolVersion" ]]; then
- dotnet tool install -g --configfile=ci-nuget.config trx2junit
- else
- dotnet tool install -g --version="$ToolVersion" --configfile=ci-nuget.config trx2junit
- fi
- - run:
- name: global tool install (trx2junit)
- when: on_fail
- command: |
- echo "Previous job failed, so use trx2junit from NuGet instead of local copy"
- echo ""
- dotnet tool install -g trx2junit
- - run:
- name: project test results
- when: always
- command: |
- if [[ -d "tests/TestResults" ]]; then
- trx2junit tests/TestResults/*.trx
- #rm tests/TestResults/*.trx
- fi
- - run:
- name: code coverage
- command: |
- if [[ -z "$CODECOV_TOKEN" ]]; then
- echo "codecov token not set -- skipping code coverage"
- else
- ./build.sh coverage
- fi
- - run: ./tests/scripts/run-samples.sh
- - run: ./tests/scripts/run-single-arg.sh
- - run: ./tests/scripts/run-multiple-args.sh
- - run: ./tests/scripts/run-globbing.sh
- - run: ./tests/scripts/run-no-globbing.sh
- - run: ./tests/scripts/run-different-output-location.sh
- - run: ./tests/scripts/run-junit2trx.sh
- - persist_to_workspace:
- root: .
- paths:
- - build.sh
- - NuGet-Packed
- - store_test_results:
- path: tests/TestResults
- - store_artifacts:
- path: tests/TestResults
- destination: TestResults
-
-jobs:
- release_build_test_job:
- executor: build-executor
- steps:
- - build_test
-
- debug_build_test_job:
- executor: build-executor
- environment:
- BUILD_CONFIG: Debug
- steps:
- - build_test:
- debug-build: true
-
- deploy_job:
- executor: deploy-executor
- parameters:
- target:
- type: string
- steps:
- - set_env
- - attach_workspace:
- at: .
- - run:
- name: deploy to << parameters.target >>
- command: |
- chmod ugo+x ./build.sh
- ./build.sh deploy << parameters.target >>
-
-workflows:
- version: 2
- build_test_deploy:
- jobs:
- - release_build_test_job:
- filters:
- tags:
- only: /^v[0-9]+\.[0-9]+\.[0-9]+(-preview-[0-9]+)?$/
-
- - debug_build_test_job:
- filters:
- tags:
- only: /^v[0-9]+\.[0-9]+\.[0-9]+(-preview-[0-9]+)?$/
-
- - deploy_job:
- name: deploy-nuget
- target: nuget # parameter
- requires:
- - release_build_test_job
- - debug_build_test_job
- filters:
- branches:
- ignore: /.*/
- tags:
- only: /^v[0-9]+\.[0-9]+\.[0-9]+$/
- context: org-global
-
- - deploy_job:
- name: deploy-myget
- target: myget # parameter
- requires:
- - release_build_test_job
- - debug_build_test_job
- filters:
- branches:
- #only: master
- ignore: /.*/
- tags:
- only: /^v[0-9]+\.[0-9]+\.[0-9]+(-preview-[0-9]+)?$/
- context: org-global
diff --git a/.editorconfig b/.editorconfig
index 8b9b676..305ac90 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,14 +4,17 @@ root = true
# all files
[*]
+charset = utf-8
+
# Indentation and spacing
-indent_size = 4
indent_style = space
+indent_size = 4
tab_width = 4
# New line preferences
end_of_line = lf
insert_final_newline = true
+trim_trailing_whitespace = true
# C# files
[*.cs]
@@ -179,11 +182,19 @@ dotnet_naming_rule.private_or_internal_static_field_should_be_static_field.sever
dotnet_naming_rule.private_or_internal_static_field_should_be_static_field.symbols = private_or_internal_static_field
dotnet_naming_rule.private_or_internal_static_field_should_be_static_field.style = static_field
+dotnet_naming_rule.private_or_internal_field_should_be_instance_field.severity = suggestion
+dotnet_naming_rule.private_or_internal_field_should_be_instance_field.symbols = private_or_internal_field
+dotnet_naming_rule.private_or_internal_field_should_be_instance_field.style = instance_field
+
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.interface.required_modifiers =
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
+dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
+dotnet_naming_symbols.private_or_internal_field.required_modifiers =
dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected
@@ -191,11 +202,11 @@ dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = stat
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.types.required_modifiers =
+dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.non_field_members.required_modifiers =
+dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.constant.applicable_kinds = field
dotnet_naming_symbols.constant.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
@@ -203,17 +214,22 @@ dotnet_naming_symbols.constant.required_modifiers = const
# Naming styles
-dotnet_naming_style.pascal_case.required_prefix =
-dotnet_naming_style.pascal_case.required_suffix =
-dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
-dotnet_naming_style.begins_with_i.required_suffix =
-dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.static_field.required_prefix = s_
-dotnet_naming_style.static_field.required_suffix =
-dotnet_naming_style.static_field.word_separator =
+dotnet_naming_style.static_field.required_suffix =
+dotnet_naming_style.static_field.word_separator =
dotnet_naming_style.static_field.capitalization = camel_case
+
+dotnet_naming_style.instance_field.required_prefix = _
+dotnet_naming_style.instance_field.required_suffix =
+dotnet_naming_style.instance_field.word_separator =
+dotnet_naming_style.instance_field.capitalization = camel_case
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..2a0c8a1
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @gfoidl
diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml
new file mode 100644
index 0000000..3774ed3
--- /dev/null
+++ b/.github/workflows/automerge.yml
@@ -0,0 +1,42 @@
+# Reminder:
+# =========
+# branch protection rules must be set, otherwise the automerge will happen as soon as the label
+# is applied and not when CI is readay.
+
+name: automerge
+on:
+ pull_request:
+ types:
+ - labeled
+ - unlabeled
+ - synchronize
+ - opened
+ - edited
+ - ready_for_review
+ - reopened
+ - unlocked
+
+ pull_request_review:
+ types:
+ - submitted
+
+ check_suite:
+ types:
+ - completed
+
+ status: {}
+
+jobs:
+ automerge:
+ runs-on: ubuntu-latest
+ steps:
+ - name: automerge
+ uses: "pascalgn/automerge-action@v0.8.0"
+ #with:
+ # args: "--trace"
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ MERGE_LABELS: "automerge"
+ #MERGE_REMOVE_LABELS: "automerge" # https://github.com/pascalgn/automerge-action/issues/56
+ MERGE_METHOD: "squash"
+ MERGE_DELETE_BRANCH: "true"
diff --git a/.gitignore b/.gitignore
index d5e8c75..920f539 100644
--- a/.gitignore
+++ b/.gitignore
@@ -220,3 +220,5 @@ _Pvt_Extensions
/source/packages
/NuGet-Packed
/tests/*.playlist
+/tests/Coverage
+/tests/trx2junit.Tests/coverage.*.cobertura.xml
diff --git a/ReadMe.md b/ReadMe.md
index b14bce9..c6c603f 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -1,6 +1,6 @@
-| CircleCI | Code Coverage | NuGet |
-| -- | -- | -- |
-| [](https://circleci.com/gh/gfoidl/trx2junit/tree/master)| [](https://codecov.io/gh/gfoidl/trx2junit) | [](https://www.nuget.org/packages/trx2junit/) |
+| CI | NuGet |
+| -- | -- |
+| [](https://dev.azure.com/gh-gfoidl/github-Projects/_build/latest?definitionId=35&branchName=master) | [](https://www.nuget.org/packages/trx2junit/) |
# trx2junit (.NET Core global tool)
diff --git a/build.sh b/build.sh
index 10b62cb..02613c5 100644
--- a/build.sh
+++ b/build.sh
@@ -1,13 +1,14 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
## CI build script for projects based on gfoidl's schema.
#
# Arguments:
# build builds the solution
# test runs all tests under ./tests
+# test-coverage test + determines code coverage with coverlet.msbuild
# coverage determines code coverage with coverlet and uploads to codecov
# pack creates the NuGet-package
-# deploy deploys to $2, which must be either nuget or myget
+# deploy deploys to $2, which must be either nuget or custom
# * when CI_SKIP_DEPLOY is set, no deploy is done
# * when DEBUG is set, the action is echoed and not done
#
@@ -18,24 +19,27 @@
# TAG_NAME tag the commit is on
# CI_SKIP_DEPLOY when set no deploy is done, even if deploy is called
# DEBUG when set deploy is simulted by echoing the action
+# TEST_DIR directory in which to search for test-assemblies
# TEST_FRAMEWORK when set only the specified test-framework (dotnet test -f) will be used
# TESTS_TO_SKIP a list of test-projects to skip / ignore, separated by ;
# CODECOV_TOKEN the token for codecov to uploads the opencover-xml
+# MOVE_TRX moves the test-results (trx) to tests/TestResults
#
# Functions (sorted alphabetically):
# build builds the solution
# coverage code coverage
-# deploy deploys the solution either to nuget or myget
+# deploy deploys the solution either to nuget or custom
# main entry-point
# pack creates the NuGet-package
# setBuildEnv sets the environment variables regarding the build-environment
# test runs tests for projects in ./tests
+# test-coverage runs tests for projects in ./tests and collects code-coverage
# _coverageCore helper -- used by coverage
# _deployCore helper -- used by deploy
# _testCore helper -- used by test
#
# Exit-codes:
-# 101 deploy target is neither 'nuget' nor 'myget', so it is unknown
+# 101 deploy target is neither 'nuget' nor 'custom', so it is unknown
# 102 no args given for script, help is displayed and exited
# $? exit-code for build-step is returned unmodified
#------------------------------------------------------------------------------
@@ -46,13 +50,14 @@ help() {
echo "Arguments:"
echo " build builds the solution"
echo " test runs all tests under ./tests"
+ echo " test-coverage test + determines code coverage with coverlet.msbuild"
echo " coverage determines code coverage with coverlet and uploads to codecov"
echo " pack creates the NuGet-package"
- echo " deploy [nuget|myget] deploys to the destination"
+ echo " deploy [nuget|custom] deploys to the destination"
}
#------------------------------------------------------------------------------
setBuildEnv() {
- export BUILD_CONFIG=${BUILD_CONFIG-Release}
+ export BUILD_CONFIG=${BUILD_CONFIG:-Release}
# BuildNumber is used by MsBuild for version information.
# ci tools clone usually to depth 50, so this is not good
@@ -78,7 +83,7 @@ setBuildEnv() {
#------------------------------------------------------------------------------
build() {
dotnet restore
- dotnet build -c $BUILD_CONFIG --no-restore
+ dotnet build -c "$BUILD_CONFIG" --no-restore
}
#------------------------------------------------------------------------------
_testCore() {
@@ -89,7 +94,7 @@ _testCore() {
local testDir
local testNameWOExtension
local testName
- local testResultName
+ #local testResultName
local dotnetTestArgs
local testsToSkip
@@ -97,8 +102,10 @@ _testCore() {
testDir=$(dirname "$testFullName")
testNameWOExtension=$(basename "$testDir")
testName=$(basename "$testFullName")
- testResultName="$testNameWOExtension-$(date +%s)"
- dotnetTestArgs="-c $BUILD_CONFIG --no-build --verbosity quiet --logger \"trx;LogFileName=$testResultName.trx\" $testFullName"
+ #testResultName="$testNameWOExtension-$(date +%Y%m%d-%H%M%S_%N)"
+
+ #dotnetTestArgs=("-c ${BUILD_CONFIG}" "--no-build" "--verbosity normal" "--logger \"trx;LogFileName=${testResultName}.trx\"")
+ dotnetTestArgs=("-c ${BUILD_CONFIG}" "--no-build" "--verbosity normal" "--logger \"trx\"")
if [[ -n "$TESTS_TO_SKIP" ]]; then
testsToSkip=(${TESTS_TO_SKIP//;/ })
@@ -112,22 +119,38 @@ _testCore() {
fi
echo ""
- echo "test framework: ${TEST_FRAMEWORK-not specified}"
+ echo "test framework: ${TEST_FRAMEWORK:-not specified}"
echo "test fullname: $testFullName"
echo "testing: $testName..."
- echo "test result name: $testResultName"
+ #echo "test result name: $testResultName"
echo ""
if [[ -n "$TEST_FRAMEWORK" ]]; then
- dotnetTestArgs="-f $TEST_FRAMEWORK $dotnetTestArgs"
+ dotnetTestArgs+=("-f ${TEST_FRAMEWORK}")
fi
- dotnet test $dotnetTestArgs
+ if [[ -n "$collectCoverage" ]]; then
+ echo "running tests and collecting code coverage"
+ echo ""
+
+ # Strange but git-bash (Windows) needs double-escapes, so //p:CollectCoverage=true
+ # whereas non-Windows just needs /p:CollectCoverage=true
+ # To avoid platform detection like [[ $(uname | grep mingw -i | wc -l) -ge 0 ]]
+ # use -p instead to be on the safe side.
+ dotnetTestArgs+=("-p:CollectCoverage=true" "-p:CoverletOutputFormat=cobertura")
+ fi
+
+ dotnetTestArgs+=("${testFullName}")
+ dotnet test ${dotnetTestArgs[@]}
local result=$?
- mkdir -p "./tests/TestResults"
- mv $testDir/TestResults/$testResultName*.trx ./tests/TestResults
+ if [[ -n "$MOVE_TRX" ]]; then
+ mkdir -p "./tests/TestResults"
+ mv "$testDir"/TestResults/*.trx ./tests/TestResults
+
+ echo "moved test-results (trx) to tests/TestResults"
+ fi
if [[ $result != 0 ]]; then
exit $result
@@ -139,7 +162,7 @@ _testCore() {
#------------------------------------------------------------------------------
test() {
local testDir
- testDir="./tests"
+ testDir="${TEST_DIR:-./tests}"
if [[ ! -d "$testDir" ]]; then
echo "test-directory not existing -> no test need to run"
@@ -152,6 +175,27 @@ test() {
done
}
#------------------------------------------------------------------------------
+test_coverage() {
+ collectCoverage=1
+ test
+
+ # Each test-project has it's coverage report, so merge them to one report
+
+ echo "check if dotnet-reportgenerator-globaltool is installed..."
+
+ if [[ $(dotnet tool list -g | grep dotnet-reportgenerator-globaltool | wc -l) -eq 0 ]]; then
+ echo "not installed -> will install it"
+ export PATH="$PATH:$HOME/.dotnet/tools"
+ dotnet tool install -g dotnet-reportgenerator-globaltool
+ else
+ echo "already installed"
+ fi
+
+ echo ""
+
+ reportgenerator -reports:tests/**/*.cobertura.xml -targetdir:tests/Coverage -reporttypes:"Cobertura;HtmlInline_AzurePipelines"
+}
+#------------------------------------------------------------------------------
_coverageCore() {
local testFullName
local testDir
@@ -180,6 +224,15 @@ coverage() {
return
fi
+ echo "check if coverlet.console is installed..."
+ if [[ $(dotnet tool list -g | grep coverlet.console | wc -l) -eq 0 ]]; then
+ echo "not installed -> will install it"
+ export PATH="$PATH:$HOME/.dotnet/tools"
+ dotnet tool install -g coverlet.console
+ else
+ echo "already installed"
+ fi
+
for testProject in "$testDir"/**/*.csproj; do
_coverageCore "$testProject"
done
@@ -193,7 +246,7 @@ coverage() {
fi
# a cool script, does quite a lot without any args :-)
- ./codecov.sh
+ ./codecov.sh -Z
else
echo "CODECOV_TOKEN not set -- skipping upload"
fi
@@ -223,8 +276,8 @@ deploy() {
if [[ "$1" == "nuget" ]]; then
_deployCore "$NUGET_FEED" "$NUGET_KEY"
- elif [[ "$1" == "myget" ]]; then
- _deployCore "$MYGET_FEED" "$MYGET_KEY"
+ elif [[ "$1" == "custom" ]]; then
+ _deployCore "$CUSTOM_FEED" "$CUSTOM_KEY"
elif [[ "$1" == "local" ]]; then
echo "Skipping deploy because 'local'"
else
@@ -237,22 +290,29 @@ main() {
setBuildEnv
case "$1" in
- build) build
- ;;
- test) test
- ;;
- coverage) coverage
- ;;
- pack) pack
- ;;
+ build)
+ build
+ ;;
+ test)
+ test
+ ;;
+ test-coverage)
+ test_coverage
+ ;;
+ coverage)
+ coverage
+ ;;
+ pack)
+ pack
+ ;;
deploy)
- shift
- deploy "$1"
- ;;
+ shift
+ deploy "$1"
+ ;;
*)
- help
- exit
- ;;
+ help
+ exit
+ ;;
esac
}
#------------------------------------------------------------------------------
diff --git a/source/trx2junit/Program.cs b/source/trx2junit/Program.cs
index 344b802..1a3e8a3 100644
--- a/source/trx2junit/Program.cs
+++ b/source/trx2junit/Program.cs
@@ -1,9 +1,11 @@
-using System;
+using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
namespace trx2junit
{
+ [ExcludeFromCodeCoverage]
static class Program
{
static async Task Main(string[] args)
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index d1dfb59..8e10d5b 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -1,4 +1,4 @@
-
+
@@ -8,7 +8,7 @@
-
+
diff --git a/tests/trx2junit.Tests/trx2junit.Tests.csproj b/tests/trx2junit.Tests/trx2junit.Tests.csproj
index c165c44..27cb175 100644
--- a/tests/trx2junit.Tests/trx2junit.Tests.csproj
+++ b/tests/trx2junit.Tests/trx2junit.Tests.csproj
@@ -1,4 +1,4 @@
-
+
$(TestTfm)
@@ -9,9 +9,16 @@
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/trx2junit.sln b/trx2junit.sln
index 589780d..a2b935e 100644
--- a/trx2junit.sln
+++ b/trx2junit.sln
@@ -25,11 +25,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{292C2B9E
verify-xml.sh = verify-xml.sh
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".circleci", ".circleci", "{148DD984-1D1C-4A97-A5F5-907812DCA662}"
- ProjectSection(SolutionItems) = preProject
- .circleci\config.yml = .circleci\config.yml
- EndProjectSection
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{15D1FCD7-8027-4DD0-BF1A-BFC295C99332}"
ProjectSection(SolutionItems) = preProject
samples\Directory.Build.props = samples\Directory.Build.props
@@ -66,6 +61,38 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{3531
tests\scripts\run-single-arg.sh = tests\scripts\run-single-arg.sh
EndProjectSection
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{BA2AD413-4251-4C08-9BE5-402DCA7CAA41}"
+ ProjectSection(SolutionItems) = preProject
+ .github\CODEOWNERS = .github\CODEOWNERS
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{9F873D32-DF04-4453-9604-716F5598AC7E}"
+ ProjectSection(SolutionItems) = preProject
+ .github\ISSUE_TEMPLATE\bug_report.md = .github\ISSUE_TEMPLATE\bug_report.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{8819C279-C1A2-420B-A1FD-28F4097EC41C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{A21A387B-90BB-45B0-AD48-240B86DA1FE9}"
+ ProjectSection(SolutionItems) = preProject
+ .github\workflows\automerge.yml = .github\workflows\automerge.yml
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".azure", ".azure", "{5101A9AB-5CCE-4A20-AEA5-432BD2E4D9D2}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{8A80B7B0-F9B3-45C9-8796-C8049C43CD7E}"
+ ProjectSection(SolutionItems) = preProject
+ .azure\pipelines\ci.yml = .azure\pipelines\ci.yml
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "jobs", "jobs", "{BF2D34D4-5549-4098-994B-FACDBD730C56}"
+ ProjectSection(SolutionItems) = preProject
+ .azure\pipelines\jobs\build_and_test.yml = .azure\pipelines\jobs\build_and_test.yml
+ .azure\pipelines\jobs\coverage.yml = .azure\pipelines\jobs\coverage.yml
+ .azure\pipelines\jobs\deploy_nuget.yml = .azure\pipelines\jobs\deploy_nuget.yml
+ .azure\pipelines\jobs\e2e_tests.yml = .azure\pipelines\jobs\e2e_tests.yml
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -98,12 +125,18 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FD8336E3-655B-430A-A72F-377E83D54C63} = {49823B21-7C47-43DF-B3C1-4F48E2237EAD}
- {148DD984-1D1C-4A97-A5F5-907812DCA662} = {292C2B9E-E093-4476-AE17-A08F144AC27A}
{AB4EB02B-E16A-40B7-8524-A4F752FDFBBA} = {15D1FCD7-8027-4DD0-BF1A-BFC295C99332}
{BA191F72-A499-4D5B-972C-66EF3BD24B99} = {15D1FCD7-8027-4DD0-BF1A-BFC295C99332}
{27B8F9C6-B0D5-4E66-8AB7-12A23D4EEFB9} = {B42081F2-652A-46C6-8E10-D727A3C360A1}
{CE59E4DA-EB17-49A6-A6E8-1484A3413C46} = {15D1FCD7-8027-4DD0-BF1A-BFC295C99332}
{3531998A-0501-4259-A130-D982412978AC} = {B42081F2-652A-46C6-8E10-D727A3C360A1}
+ {BA2AD413-4251-4C08-9BE5-402DCA7CAA41} = {B5D05395-4D8B-40A2-A03E-BFF4E76D7F7B}
+ {9F873D32-DF04-4453-9604-716F5598AC7E} = {BA2AD413-4251-4C08-9BE5-402DCA7CAA41}
+ {8819C279-C1A2-420B-A1FD-28F4097EC41C} = {292C2B9E-E093-4476-AE17-A08F144AC27A}
+ {A21A387B-90BB-45B0-AD48-240B86DA1FE9} = {8819C279-C1A2-420B-A1FD-28F4097EC41C}
+ {5101A9AB-5CCE-4A20-AEA5-432BD2E4D9D2} = {292C2B9E-E093-4476-AE17-A08F144AC27A}
+ {8A80B7B0-F9B3-45C9-8796-C8049C43CD7E} = {5101A9AB-5CCE-4A20-AEA5-432BD2E4D9D2}
+ {BF2D34D4-5549-4098-994B-FACDBD730C56} = {8A80B7B0-F9B3-45C9-8796-C8049C43CD7E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4A779269-CD77-4716-9E1A-DF4AE5817A41}