├── .editorconfig
├── .gitattributes
├── .github
├── dependabot.yml
├── release.yml
└── workflows
│ ├── build.yml
│ ├── changelog.config
│ ├── changelog.yml
│ ├── dotnet-file.yml
│ ├── includes.yml
│ ├── publish.yml
│ └── triage.yml
├── .gitignore
├── .netconfig
├── Directory.Build.rsp
├── _config.yml
├── assets
├── 32.png
├── css
│ └── style.scss
├── icon.png
├── icon.svg
└── img
│ ├── ciretry.png
│ ├── comment.png
│ ├── progress.png
│ └── timings.png
├── changelog.md
├── dotnet-retest.sln
├── license.txt
├── readme.md
└── src
├── Directory.Build.props
├── Directory.Build.targets
├── Sample
├── Sample.csproj
└── UnitTest1.cs
├── dotnet-retest
├── DotnetMuxer.cs
├── Extensions.cs
├── Process.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── RetestCommand.cs
├── TrxCommand.cs
├── dotnet-retest.csproj
├── help.md
├── icon.png
└── readme.md
└── nuget.config
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome:http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Don't use tabs for indentation.
7 | [*]
8 | indent_style = space
9 | # (Please don't specify an indent_size here; that has too many unintended consequences.)
10 |
11 | # Code files
12 | [*.{cs,csx,vb,vbx}]
13 | indent_size = 4
14 |
15 | # Xml project files
16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj,msbuildproj,props,targets}]
17 | indent_size = 2
18 |
19 | # Xml config files
20 | [*.{ruleset,config,nuspec,resx,vsixmanifest,vsct}]
21 | indent_size = 2
22 |
23 | # YAML files
24 | [*.{yaml,yml}]
25 | indent_size = 2
26 |
27 | # JSON files
28 | [*.json]
29 | indent_size = 2
30 |
31 | # Dotnet code style settings:
32 | [*.{cs,vb}]
33 | # Sort using and Import directives with System.* appearing first
34 | dotnet_sort_system_directives_first = true
35 | # Avoid "this." and "Me." if not necessary
36 | dotnet_style_qualification_for_field = false:suggestion
37 | dotnet_style_qualification_for_property = false:suggestion
38 | dotnet_style_qualification_for_method = false:suggestion
39 | dotnet_style_qualification_for_event = false:suggestion
40 |
41 | # Use language keywords instead of framework type names for type references
42 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
43 | dotnet_style_predefined_type_for_member_access = true:suggestion
44 |
45 | # Suggest more modern language features when available
46 | dotnet_style_object_initializer = true:suggestion
47 | dotnet_style_collection_initializer = true:suggestion
48 | dotnet_style_coalesce_expression = true:suggestion
49 | dotnet_style_null_propagation = true:suggestion
50 | dotnet_style_explicit_tuple_names = true:suggestion
51 |
52 | # CSharp code style settings:
53 |
54 | # IDE0040: Add accessibility modifiers
55 | dotnet_style_require_accessibility_modifiers = omit_if_default:error
56 |
57 | # IDE0040: Add accessibility modifiers
58 | dotnet_diagnostic.IDE0040.severity = error
59 |
60 | [*.cs]
61 | # Top-level files are definitely OK
62 | csharp_using_directive_placement = outside_namespace:silent
63 | csharp_style_namespace_declarations = block_scoped:silent
64 | csharp_prefer_simple_using_statement = true:suggestion
65 | csharp_prefer_braces = true:silent
66 |
67 | # Prefer "var" everywhere
68 | csharp_style_var_for_built_in_types = true:suggestion
69 | csharp_style_var_when_type_is_apparent = true:suggestion
70 | csharp_style_var_elsewhere = true:suggestion
71 |
72 | # Prefer method-like constructs to have an expression-body
73 | csharp_style_expression_bodied_methods = true:none
74 | csharp_style_expression_bodied_constructors = true:none
75 | csharp_style_expression_bodied_operators = true:none
76 |
77 | # Prefer property-like constructs to have an expression-body
78 | csharp_style_expression_bodied_properties = true:none
79 | csharp_style_expression_bodied_indexers = true:none
80 | csharp_style_expression_bodied_accessors = true:none
81 |
82 | # Suggest more modern language features when available
83 | csharp_style_pattern_matching_over_is_with_cast_check = true:error
84 | csharp_style_pattern_matching_over_as_with_null_check = true:error
85 | csharp_style_inlined_variable_declaration = true:suggestion
86 | csharp_style_throw_expression = true:suggestion
87 | csharp_style_conditional_delegate_call = true:suggestion
88 |
89 | # Newline settings
90 | csharp_new_line_before_open_brace = all
91 | csharp_new_line_before_else = true
92 | csharp_new_line_before_catch = true
93 | csharp_new_line_before_finally = true
94 | csharp_new_line_before_members_in_object_initializers = true
95 | csharp_new_line_before_members_in_anonymous_types = true
96 |
97 | # Test settings
98 | [**/*Tests*/**{.cs,.vb}]
99 | # xUnit1013: Public method should be marked as test. Allows using records as test classes
100 | dotnet_diagnostic.xUnit1013.severity = none
101 |
102 | # CS9113: Parameter is unread (usually, ITestOutputHelper)
103 | dotnet_diagnostic.CS9113.severity = none
104 |
105 | # Default severity for analyzer diagnostics with category 'Style'
106 | dotnet_analyzer_diagnostic.category-Style.severity = none
107 |
108 | # VSTHRD200: Use "Async" suffix for async methods
109 | dotnet_diagnostic.VSTHRD200.severity = none
110 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # normalize by default
2 | * text=auto encoding=UTF-8
3 | *.sh text eol=lf
4 |
5 | # These are windows specific files which we may as well ensure are
6 | # always crlf on checkout
7 | *.bat text eol=crlf
8 | *.cmd text eol=crlf
9 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Please see the documentation for all configuration options:
2 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: nuget
7 | directory: /
8 | schedule:
9 | interval: daily
10 | groups:
11 | Azure:
12 | patterns:
13 | - "Azure*"
14 | - "Microsoft.Azure*"
15 | Identity:
16 | patterns:
17 | - "System.IdentityModel*"
18 | - "Microsoft.IdentityModel*"
19 | System:
20 | patterns:
21 | - "System*"
22 | exclude-patterns:
23 | - "System.IdentityModel*"
24 | Extensions:
25 | patterns:
26 | - "Microsoft.Extensions*"
27 | Web:
28 | patterns:
29 | - "Microsoft.AspNetCore*"
30 | Tests:
31 | patterns:
32 | - "Microsoft.NET.Test*"
33 | - "xunit*"
34 | - "coverlet*"
35 | ThisAssembly:
36 | patterns:
37 | - "ThisAssembly*"
38 | ProtoBuf:
39 | patterns:
40 | - "protobuf-*"
41 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | labels:
4 | - bydesign
5 | - dependencies
6 | - duplicate
7 | - question
8 | - invalid
9 | - wontfix
10 | - need info
11 | - techdebt
12 | authors:
13 | - devlooped-bot
14 | - dependabot
15 | - github-actions
16 | categories:
17 | - title: ✨ Implemented enhancements
18 | labels:
19 | - enhancement
20 | - title: 🐛 Fixed bugs
21 | labels:
22 | - bug
23 | - title: 📝 Documentation updates
24 | labels:
25 | - docs
26 | - documentation
27 | - title: 🔨 Other
28 | labels:
29 | - '*'
30 | exclude:
31 | labels:
32 | - dependencies
33 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # Builds and runs tests in all three supported OSes
2 | # Pushes CI feed if secrets.SLEET_CONNECTION is provided
3 |
4 | name: build
5 | on:
6 | workflow_dispatch:
7 | inputs:
8 | configuration:
9 | type: choice
10 | description: Configuration
11 | options:
12 | - Release
13 | - Debug
14 | push:
15 | branches: [ main, dev, 'dev/*', 'feature/*', 'rel/*' ]
16 | paths-ignore:
17 | - changelog.md
18 | - readme.md
19 | pull_request:
20 | types: [opened, synchronize, reopened]
21 |
22 | env:
23 | DOTNET_NOLOGO: true
24 | PackOnBuild: true
25 | GeneratePackageOnBuild: true
26 | VersionPrefix: 42.42.${{ github.run_number }}
27 | VersionLabel: ${{ github.ref }}
28 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
29 | MSBUILDTERMINALLOGGER: auto
30 | Configuration: ${{ github.event.inputs.configuration || 'Release' }}
31 |
32 | defaults:
33 | run:
34 | shell: bash
35 |
36 | jobs:
37 | build:
38 | name: build-${{ matrix.os }}
39 | runs-on: ${{ matrix.os }}
40 | strategy:
41 | matrix:
42 | os: [ 'windows-latest', 'ubuntu-latest', 'macOS-latest' ]
43 | steps:
44 | - name: 🤘 checkout
45 | uses: actions/checkout@v4
46 |
47 | - name: 🙏 build
48 | run: dotnet build -m:1 -bl:build.binlog
49 |
50 | - name: ⚙ install
51 | working-directory: bin
52 | run: dotnet tool update -g dotnet-retest --prerelease --add-source .
53 |
54 | - name: 🧪 test
55 | run: dotnet retest -- ./src/Sample/
56 |
57 | - name: 🐛 logs
58 | uses: actions/upload-artifact@v4
59 | if: runner.debug && always()
60 | with:
61 | name: logs
62 | path: '*.binlog'
63 |
64 | # Only push CI package to sleet feed if building on ubuntu (fastest)
65 | - name: 🚀 sleet
66 | env:
67 | SLEET_CONNECTION: ${{ secrets.SLEET_CONNECTION }}
68 | if: env.SLEET_CONNECTION != '' && matrix.os == 'ubuntu-latest'
69 | run: |
70 | dotnet tool install -g --version 4.0.18 sleet
71 | sleet push bin --config none -f --verbose -p "SLEET_FEED_CONTAINER=nuget" -p "SLEET_FEED_CONNECTIONSTRING=${{ secrets.SLEET_CONNECTION }}" -p "SLEET_FEED_TYPE=azure" || echo "No packages found"
72 |
73 | dotnet-format:
74 | runs-on: ubuntu-latest
75 | steps:
76 | - name: 🤘 checkout
77 | uses: actions/checkout@v4
78 | with:
79 | submodules: recursive
80 | fetch-depth: 0
81 |
82 | - name: ✓ ensure format
83 | run: |
84 | dotnet format whitespace --verify-no-changes -v:diag --exclude ~/.nuget
85 | dotnet format style --verify-no-changes -v:diag --exclude ~/.nuget
86 |
--------------------------------------------------------------------------------
/.github/workflows/changelog.config:
--------------------------------------------------------------------------------
1 | usernames-as-github-logins=true
2 | issues_wo_labels=true
3 | pr_wo_labels=true
4 | exclude-labels=bydesign,dependencies,duplicate,discussion,question,invalid,wontfix,need info,docs
5 | enhancement-label=:sparkles: Implemented enhancements:
6 | bugs-label=:bug: Fixed bugs:
7 | issues-label=:hammer: Other:
8 | pr-label=:twisted_rightwards_arrows: Merged:
9 | unreleased=false
10 |
--------------------------------------------------------------------------------
/.github/workflows/changelog.yml:
--------------------------------------------------------------------------------
1 | name: changelog
2 | on:
3 | workflow_dispatch:
4 | release:
5 | types: [released]
6 |
7 | jobs:
8 | changelog:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: 🤖 defaults
12 | uses: devlooped/actions-bot@v1
13 | with:
14 | name: ${{ secrets.BOT_NAME }}
15 | email: ${{ secrets.BOT_EMAIL }}
16 | gh_token: ${{ secrets.GH_TOKEN }}
17 | github_token: ${{ secrets.GITHUB_TOKEN }}
18 |
19 | - name: 🤘 checkout
20 | uses: actions/checkout@v4
21 | with:
22 | fetch-depth: 0
23 | ref: main
24 | token: ${{ env.GH_TOKEN }}
25 |
26 | - name: ⚙ ruby
27 | uses: ruby/setup-ruby@v1
28 | with:
29 | ruby-version: 3.0.3
30 |
31 | - name: ⚙ changelog
32 | run: |
33 | gem install github_changelog_generator
34 | github_changelog_generator --user ${GITHUB_REPOSITORY%/*} --project ${GITHUB_REPOSITORY##*/} --token $GH_TOKEN --o changelog.md --config-file .github/workflows/changelog.config
35 |
36 | - name: 🚀 changelog
37 | run: |
38 | git add changelog.md
39 | (git commit -m "🖉 Update changelog with ${GITHUB_REF#refs/*/}" && git push) || echo "Done"
--------------------------------------------------------------------------------
/.github/workflows/dotnet-file.yml:
--------------------------------------------------------------------------------
1 | # Synchronizes .netconfig-configured files with dotnet-file
2 | name: dotnet-file
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | - cron: "0 0 * * *"
7 | push:
8 | branches: [ 'dotnet-file' ]
9 |
10 | env:
11 | DOTNET_NOLOGO: true
12 |
13 | jobs:
14 | run:
15 | permissions:
16 | contents: write
17 | uses: devlooped/oss/.github/workflows/dotnet-file-core.yml@main
18 | secrets:
19 | BOT_NAME: ${{ secrets.BOT_NAME }}
20 | BOT_EMAIL: ${{ secrets.BOT_EMAIL }}
21 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
--------------------------------------------------------------------------------
/.github/workflows/includes.yml:
--------------------------------------------------------------------------------
1 | name: +Mᐁ includes
2 | on:
3 | workflow_dispatch:
4 | push:
5 | branches:
6 | - 'main'
7 | paths:
8 | - '**.md'
9 | - '!changelog.md'
10 |
11 | jobs:
12 | includes:
13 | runs-on: ubuntu-latest
14 | permissions:
15 | contents: write
16 | pull-requests: write
17 | steps:
18 | - name: 🤖 defaults
19 | uses: devlooped/actions-bot@v1
20 | with:
21 | name: ${{ secrets.BOT_NAME }}
22 | email: ${{ secrets.BOT_EMAIL }}
23 | gh_token: ${{ secrets.GH_TOKEN }}
24 | github_token: ${{ secrets.GITHUB_TOKEN }}
25 |
26 | - name: 🤘 checkout
27 | uses: actions/checkout@v4
28 | with:
29 | token: ${{ env.GH_TOKEN }}
30 |
31 | - name: +Mᐁ includes
32 | uses: devlooped/actions-includes@v1
33 |
34 | - name: ✍ pull request
35 | uses: peter-evans/create-pull-request@v6
36 | with:
37 | add-paths: '**.md'
38 | base: main
39 | branch: markdown-includes
40 | delete-branch: true
41 | labels: docs
42 | author: ${{ env.BOT_AUTHOR }}
43 | committer: ${{ env.BOT_AUTHOR }}
44 | commit-message: +Mᐁ includes
45 | title: +Mᐁ includes
46 | body: +Mᐁ includes
47 | token: ${{ env.GH_TOKEN }}
48 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | # Builds a final release version and pushes to nuget.org
2 | # whenever a release is published.
3 | # Requires: secrets.NUGET_API_KEY
4 |
5 | name: publish
6 | on:
7 | release:
8 | types: [prereleased, released]
9 |
10 | env:
11 | DOTNET_NOLOGO: true
12 | Configuration: Release
13 | PackOnBuild: true
14 | GeneratePackageOnBuild: true
15 | VersionLabel: ${{ github.ref }}
16 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
17 | MSBUILDTERMINALLOGGER: auto
18 |
19 | jobs:
20 | publish:
21 | runs-on: ubuntu-latest
22 | steps:
23 | - name: 🤘 checkout
24 | uses: actions/checkout@v4
25 | with:
26 | submodules: recursive
27 | fetch-depth: 0
28 |
29 | - name: 🙏 build
30 | run: dotnet build -m:1 -bl:build.binlog
31 |
32 | - name: ⚙ install
33 | working-directory: bin
34 | run: dotnet tool update -g dotnet-retest --prerelease --add-source .
35 |
36 | - name: 🧪 test
37 | run: dotnet retest -- ./src/Sample/
38 |
39 | - name: 🐛 logs
40 | uses: actions/upload-artifact@v4
41 | if: runner.debug && always()
42 | with:
43 | name: logs
44 | path: '*.binlog'
45 |
46 | - name: ⬆️ upload
47 | if: success()
48 | uses: actions/upload-artifact@v4
49 | with:
50 | name: pkg
51 | path: bin/*
52 |
53 | - name: 🚀 sleet
54 | env:
55 | SLEET_CONNECTION: ${{ secrets.SLEET_CONNECTION }}
56 | if: env.SLEET_CONNECTION != ''
57 | run: |
58 | dotnet tool install -g --version 4.0.18 sleet
59 | sleet push bin --config none -f --verbose -p "SLEET_FEED_CONTAINER=nuget" -p "SLEET_FEED_CONNECTIONSTRING=${{ secrets.SLEET_CONNECTION }}" -p "SLEET_FEED_TYPE=azure" || echo "No packages found"
60 |
61 | - name: 🚀 nuget
62 | env:
63 | NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
64 | if: env.NUGET_API_KEY != ''
65 | run: dotnet nuget push ./bin/**/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{secrets.NUGET_API_KEY}} --skip-duplicate
66 |
--------------------------------------------------------------------------------
/.github/workflows/triage.yml:
--------------------------------------------------------------------------------
1 | name: 'triage'
2 | on:
3 | schedule:
4 | - cron: '42 0 * * *'
5 |
6 | workflow_dispatch:
7 | # Manual triggering through the GitHub UI, API, or CLI
8 | inputs:
9 | daysBeforeClose:
10 | description: "Days before closing stale or need info issues"
11 | required: true
12 | default: "30"
13 | daysBeforeStale:
14 | description: "Days before labeling stale"
15 | required: true
16 | default: "180"
17 | daysSinceClose:
18 | description: "Days since close to lock"
19 | required: true
20 | default: "30"
21 | daysSinceUpdate:
22 | description: "Days since update to lock"
23 | required: true
24 | default: "30"
25 |
26 | permissions:
27 | actions: write # For managing the operation state cache
28 | issues: write
29 | contents: read
30 |
31 | jobs:
32 | stale:
33 | # Do not run on forks
34 | if: github.repository_owner == 'devlooped'
35 | runs-on: ubuntu-latest
36 | steps:
37 | - name: ⌛ rate
38 | shell: pwsh
39 | if: github.event_name != 'workflow_dispatch'
40 | env:
41 | GH_TOKEN: ${{ secrets.DEVLOOPED_TOKEN }}
42 | run: |
43 | # add random sleep since we run on fixed schedule
44 | $wait = get-random -max 180
45 | echo "Waiting random $wait seconds to start"
46 | sleep $wait
47 | # get currently authenticated user rate limit info
48 | $rate = gh api rate_limit | convertfrom-json | select -expandproperty rate
49 | # if we don't have at least 100 requests left, wait until reset
50 | if ($rate.remaining -lt 100) {
51 | $wait = ($rate.reset - (Get-Date (Get-Date).ToUniversalTime() -UFormat %s))
52 | echo "Rate limit remaining is $($rate.remaining), waiting for $($wait / 1000) seconds to reset"
53 | sleep $wait
54 | $rate = gh api rate_limit | convertfrom-json | select -expandproperty rate
55 | echo "Rate limit has reset to $($rate.remaining) requests"
56 | }
57 |
58 | - name: ✏️ stale labeler
59 | # pending merge: https://github.com/actions/stale/pull/1176
60 | uses: kzu/stale@c8450312ba97b204bf37545cb249742144d6ca69
61 | with:
62 | ascending: true # Process the oldest issues first
63 | stale-issue-label: 'stale'
64 | stale-issue-message: |
65 | Due to lack of recent activity, this issue has been labeled as 'stale'.
66 | It will be closed if no further activity occurs within ${{ fromJson(inputs.daysBeforeClose || 30 ) }} more days.
67 | Any new comment will remove the label.
68 | close-issue-message: |
69 | This issue will now be closed since it has been labeled 'stale' without activity for ${{ fromJson(inputs.daysBeforeClose || 30 ) }} days.
70 | days-before-stale: ${{ fromJson(inputs.daysBeforeStale || 180) }}
71 | days-before-close: ${{ fromJson(inputs.daysBeforeClose || 30 ) }}
72 | days-before-pr-close: -1 # Do not close PRs labeled as 'stale'
73 | exempt-all-milestones: true
74 | exempt-all-assignees: true
75 | exempt-issue-labels: priority,sponsor,backed
76 | exempt-authors: kzu
77 |
78 | - name: 🤘 checkout actions
79 | uses: actions/checkout@v4
80 | with:
81 | repository: 'microsoft/vscode-github-triage-actions'
82 | ref: v42
83 |
84 | - name: ⚙ install actions
85 | run: npm install --production
86 |
87 | - name: 🔒 issues locker
88 | uses: ./locker
89 | with:
90 | token: ${{ secrets.DEVLOOPED_TOKEN }}
91 | ignoredLabel: priority
92 | daysSinceClose: ${{ fromJson(inputs.daysSinceClose || 30) }}
93 | daysSinceUpdate: ${{ fromJson(inputs.daysSinceUpdate || 30) }}
94 |
95 | - name: 🔒 need info closer
96 | uses: ./needs-more-info-closer
97 | with:
98 | token: ${{ secrets.DEVLOOPED_TOKEN }}
99 | label: 'need info'
100 | closeDays: ${{ fromJson(inputs.daysBeforeClose || 30) }}
101 | closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity.\n\nHappy Coding!"
102 | pingDays: 80
103 | pingComment: "Hey @${assignee}, this issue might need further attention.\n\n@${author}, you can help us out by closing this issue if the problem no longer exists, or adding more information."
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | obj
3 | artifacts
4 | pack
5 | TestResults
6 | results
7 | BenchmarkDotNet.Artifacts
8 | /app
9 | .vs
10 | .vscode
11 | .genaiscript
12 | .idea
13 | local.settings.json
14 |
15 | *.suo
16 | *.sdf
17 | *.userprefs
18 | *.user
19 | *.nupkg
20 | *.metaproj
21 | *.tmp
22 | *.log
23 | *.cache
24 | *.binlog
25 | *.zip
26 | __azurite*.*
27 | __*__
28 |
29 | .nuget
30 | *.lock.json
31 | *.nuget.props
32 | *.nuget.targets
33 |
34 | node_modules
35 | _site
36 | .jekyll-metadata
37 | .jekyll-cache
38 | .sass-cache
39 | Gemfile.lock
40 | package-lock.json
41 |
--------------------------------------------------------------------------------
/.netconfig:
--------------------------------------------------------------------------------
1 | [file]
2 | url = https://github.com/devlooped/oss
3 | [file ".netconfig"]
4 | url = https://github.com/devlooped/oss/blob/main/.netconfig
5 | skip
6 | [file "readme.md"]
7 | url = https://github.com/devlooped/oss/blob/main/readme.md
8 | skip
9 | [file ".github/workflows/combine-prs.yml"]
10 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/combine-prs.yml
11 | skip
12 | [file "src/kzu.snk"]
13 | url = https://github.com/devlooped/oss/blob/main/src/kzu.snk
14 | skip
15 | [file ".editorconfig"]
16 | url = https://github.com/devlooped/oss/blob/main/.editorconfig
17 | sha = e81ab754b366d52d92bd69b24bef1d5b1c610634
18 | etag = 7298c6450967975a8782b5c74f3071e1910fc59686e48f9c9d5cd7c68213cf59
19 | weak
20 | [file ".gitattributes"]
21 | url = https://github.com/devlooped/oss/blob/main/.gitattributes
22 | sha = 5f92a68e302bae675b394ef343114139c075993e
23 | etag = 338ba6d92c8d1774363396739c2be4257bfc58026f4b0fe92cb0ae4460e1eff7
24 | weak
25 | [file ".github/dependabot.yml"]
26 | url = https://github.com/devlooped/oss/blob/main/.github/dependabot.yml
27 | sha = 49661dbf0720cde93eb5569be7523b5912351560
28 | etag = c147ea2f3431ca0338c315c4a45b56ee233c4d30f8d6ab698d0e1980a257fd6a
29 | weak
30 | [file ".github/release.yml"]
31 | url = https://github.com/devlooped/oss/blob/main/.github/release.yml
32 | sha = 0c23e24704625cf75b2cb1fdc566cef7e20af313
33 | etag = 310df162242c95ed19ed12e3c96a65f77e558b46dced676ad5255eb12caafe75
34 | weak
35 | [file ".github/workflows/build.yml"]
36 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/build.yml
37 | skip
38 | [file ".github/workflows/changelog.config"]
39 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/changelog.config
40 | sha = 08d83cb510732f861416760d37702f9f55bd7f9e
41 | etag = 556a28914eeeae78ca924b1105726cdaa211af365671831887aec81f5f4301b4
42 | weak
43 | [file ".github/workflows/changelog.yml"]
44 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/changelog.yml
45 | sha = 5fb172362c767bef7c36478f1a6bdc264723f8f9
46 | etag = ad1efa56d6024ee1add2bcda81a7e4e38d0e9069473c6ff70374d5ce06af1f5a
47 | weak
48 | [file ".github/workflows/dotnet-file.yml"]
49 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/dotnet-file.yml
50 | sha = 8fa147d4799d73819040736c399d0b1db2c2d86c
51 | etag = 1ca805a23656e99c03f9d478dba8ccef6e571f5de2ac0e9bb7e3c5216c99a694
52 | weak
53 | [file ".github/workflows/includes.yml"]
54 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/includes.yml
55 | sha = 85829f2510f335f4a411867f3dbaaa116c3ab3de
56 | etag = 086f6b6316cc6ea7089c0dcc6980be519e6ed6e6201e65042ef41b82634ec0ee
57 | weak
58 | [file ".github/workflows/publish.yml"]
59 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/publish.yml
60 | skip
61 | [file ".gitignore"]
62 | url = https://github.com/devlooped/oss/blob/main/.gitignore
63 | sha = e0be248fff1d39133345283b8227372b36574b75
64 | etag = c449ec6f76803e1891357ca2b8b4fcb5b2e5deeff8311622fd92ca9fbf1e6575
65 | weak
66 | [file "Directory.Build.rsp"]
67 | url = https://github.com/devlooped/oss/blob/main/Directory.Build.rsp
68 | sha = 0f7f7f7e8a29de9b535676f75fe7c67e629a5e8c
69 | etag = 0ccae83fc51f400bfd7058170bfec7aba11455e24a46a0d7e6a358da6486e255
70 | weak
71 | [file "_config.yml"]
72 | url = https://github.com/devlooped/oss/blob/main/_config.yml
73 | sha = fa83a5161ba52bc5d510ce0ba75ee0b1f8d4bc63
74 | etag = 9139148f845adf503fd3c3c140eb64421fc476a1f9c027fc50825c0efb05f557
75 | weak
76 | [file "assets/css/style.scss"]
77 | url = https://github.com/devlooped/oss/blob/main/assets/css/style.scss
78 | sha = 9db26e2710b084d219d6355339d822f159bf5780
79 | etag = f710d8919abfd5a8d00050b74ba7d0bb05c6d02e40842a3012eb96555c208504
80 | weak
81 | [file "license.txt"]
82 | url = https://github.com/devlooped/oss/blob/main/license.txt
83 | sha = 0683ee777d7d878d4bf013d7deea352685135a05
84 | etag = 2c6335b37e4ae05eea7c01f5d0c9d82b49c488f868a8b5ba7bff7c6ff01f3994
85 | weak
86 | [file "src/Directory.Build.props"]
87 | url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.props
88 | sha = 2fff747a9673b499c99f2da183cdd5263fdc9333
89 | etag = 0fccddf04f282fe98122ab2610dc2972c205a521254559bf013655c6271b0017
90 | weak
91 | [file "src/Directory.Build.targets"]
92 | url = https://github.com/devlooped/oss/blob/main/src/Directory.Build.targets
93 | sha = a8b208093599263b7f2d1fe3854634c588ea5199
94 | etag = 19087699f05396205e6b050d999a43b175bd242f6e8fac86f6df936310178b03
95 | weak
96 | [file "src/dotnet-retest/TrxCommand.cs"]
97 | url = https://github.com/devlooped/dotnet-trx/blob/main/src/dotnet-trx/TrxCommand.cs
98 | sha = cf6a9a0eb401157bbd9d877575a49f98af515db8
99 | etag = f83f144e7ef6f5e28d22baf938a70f8e39ec50b6e8427d88fa9f8db302695e48
100 | weak
101 | [file "src/dotnet-retest/Process.cs"]
102 | url = https://github.com/devlooped/dotnet-trx/blob/main/src/dotnet-trx/Process.cs
103 | sha = 8385c4a7355e472f4a94939a5da5ea47cc43b4a3
104 | etag = d36430441b9b7d4f444707afb6434665c4a38204da5fab6ca298cd8382b9d684
105 | weak
106 | [file "src/dotnet-retest/Extensions.cs"]
107 | url = https://github.com/devlooped/dotnet-trx/blob/main/src/dotnet-trx/Extensions.cs
108 | sha = 59102327ff8db52de1d7487d53e6bfef5891b5cd
109 | etag = 422d00a9218315f8f53d34a3a16d4cd1001fe71042bc9e04cd5439f62f3cce0b
110 | weak
111 | [file ".github/workflows/dotnet-file-core.yml"]
112 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/dotnet-file-core.yml
113 | skip
114 | [file ".github/workflows/triage.yml"]
115 | url = https://github.com/devlooped/oss/blob/main/.github/workflows/triage.yml
116 | sha = 33000c0c4ab4eb4e0e142fa54515b811a189d55c
117 | etag = 013a47739e348f06891f37c45164478cca149854e6cd5c5158e6f073f852b61a
118 | weak
119 | [file "src/nuget.config"]
120 | url = https://github.com/devlooped/oss/blob/main/src/nuget.config
121 | sha = 032439dbf180fca0539a5bd3a019f18ab3484b76
122 | etag = da7c0104131bd474b52fc9bc9f9bda6470e24ae38d4fb9f5c4f719bc01370ab5
123 | weak
124 |
--------------------------------------------------------------------------------
/Directory.Build.rsp:
--------------------------------------------------------------------------------
1 | # See https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-response-files
2 | -nr:false
3 | -m:1
4 | -v:m
5 | -clp:Summary;ForceNoAlign
6 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
2 |
3 | exclude: [ 'src/', '*.sln', 'Gemfile*', '*.rsp' ]
--------------------------------------------------------------------------------
/assets/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devlooped/dotnet-retest/2c7c276e888a5a4a37adce3c8ba2896b0d83f627/assets/32.png
--------------------------------------------------------------------------------
/assets/css/style.scss:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | @import "jekyll-theme-slate";
5 |
6 | .inner {
7 | max-width: 960px;
8 | }
9 |
10 | pre, code {
11 | background-color: unset;
12 | font-size: unset;
13 | }
14 |
15 | code {
16 | font-size: 0.80em;
17 | }
18 |
19 | h1 > img {
20 | border: unset;
21 | box-shadow: unset;
22 | vertical-align: middle;
23 | -moz-box-shadow: unset;
24 | -o-box-shadow: unset;
25 | -ms-box-shadow: unset;
26 | }
27 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devlooped/dotnet-retest/2c7c276e888a5a4a37adce3c8ba2896b0d83f627/assets/icon.png
--------------------------------------------------------------------------------
/assets/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/assets/img/ciretry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devlooped/dotnet-retest/2c7c276e888a5a4a37adce3c8ba2896b0d83f627/assets/img/ciretry.png
--------------------------------------------------------------------------------
/assets/img/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devlooped/dotnet-retest/2c7c276e888a5a4a37adce3c8ba2896b0d83f627/assets/img/comment.png
--------------------------------------------------------------------------------
/assets/img/progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devlooped/dotnet-retest/2c7c276e888a5a4a37adce3c8ba2896b0d83f627/assets/img/progress.png
--------------------------------------------------------------------------------
/assets/img/timings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devlooped/dotnet-retest/2c7c276e888a5a4a37adce3c8ba2896b0d83f627/assets/img/timings.png
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [v0.7.1](https://github.com/devlooped/dotnet-retest/tree/v0.7.1) (2025-03-02)
4 |
5 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.7.0...v0.7.1)
6 |
7 | :bug: Fixed bugs:
8 |
9 | - Include standard error in the result to make it easier to find errors. [\#56](https://github.com/devlooped/dotnet-retest/issues/56)
10 |
11 | ## [v0.7.0](https://github.com/devlooped/dotnet-retest/tree/v0.7.0) (2025-02-25)
12 |
13 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.6.5...v0.7.0)
14 |
15 | :bug: Fixed bugs:
16 |
17 | - Error on output when projects contain more than 1000 unit tests [\#47](https://github.com/devlooped/dotnet-retest/issues/47)
18 |
19 | :twisted_rightwards_arrows: Merged:
20 |
21 | - Include messages to standard error, this to make the log complete [\#57](https://github.com/devlooped/dotnet-retest/pull/57) (@Tasteful)
22 |
23 | ## [v0.6.5](https://github.com/devlooped/dotnet-retest/tree/v0.6.5) (2025-02-18)
24 |
25 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.6.4...v0.6.5)
26 |
27 | :sparkles: Implemented enhancements:
28 |
29 | - Bring changes from trx new verbosity levels [\#64](https://github.com/devlooped/dotnet-retest/pull/64) (@kzu)
30 |
31 | :bug: Fixed bugs:
32 |
33 | - Fix broken verbose reporting of successful tests [\#70](https://github.com/devlooped/dotnet-retest/pull/70) (@kzu)
34 |
35 | :twisted_rightwards_arrows: Merged:
36 |
37 | - Showcase that we can run/render 1k+ tests [\#71](https://github.com/devlooped/dotnet-retest/pull/71) (@kzu)
38 | - Remove confusing and duplicate -v for version [\#67](https://github.com/devlooped/dotnet-retest/pull/67) (@kzu)
39 |
40 | ## [v0.6.4](https://github.com/devlooped/dotnet-retest/tree/v0.6.4) (2025-02-18)
41 |
42 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.6.3...v0.6.4)
43 |
44 | :bug: Fixed bugs:
45 |
46 | - Avoid extra noise in log for CI builds [\#58](https://github.com/devlooped/dotnet-retest/issues/58)
47 | - Column width inside Azure DevOps pipeline [\#54](https://github.com/devlooped/dotnet-retest/issues/54)
48 | - Retry attempts are not working anymore in 0.6.X [\#48](https://github.com/devlooped/dotnet-retest/issues/48)
49 | - Make retry logic more resilient to changes in xunit/vstest output [\#62](https://github.com/devlooped/dotnet-retest/pull/62) (@kzu)
50 |
51 | :twisted_rightwards_arrows: Merged:
52 |
53 | - Avoid noise in auto-update of progress [\#59](https://github.com/devlooped/dotnet-retest/pull/59) (@Tasteful)
54 | - Send output directly to System.Console to avoid line breaks [\#55](https://github.com/devlooped/dotnet-retest/pull/55) (@Tasteful)
55 |
56 | ## [v0.6.3](https://github.com/devlooped/dotnet-retest/tree/v0.6.3) (2024-09-02)
57 |
58 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.6.2...v0.6.3)
59 |
60 | :sparkles: Implemented enhancements:
61 |
62 | - Add a way to opt-out of the summary [\#31](https://github.com/devlooped/dotnet-retest/pull/31) (@kzu)
63 |
64 | :hammer: Other:
65 |
66 | - Command option to disable trx output [\#29](https://github.com/devlooped/dotnet-retest/issues/29)
67 |
68 | :twisted_rightwards_arrows: Merged:
69 |
70 | - Ensure readme is encoded in UTF-8 [\#33](https://github.com/devlooped/dotnet-retest/pull/33) (@kzu)
71 | - Improve style disable when NO\_COLOR [\#30](https://github.com/devlooped/dotnet-retest/pull/30) (@kzu)
72 |
73 | ## [v0.6.2](https://github.com/devlooped/dotnet-retest/tree/v0.6.2) (2024-08-24)
74 |
75 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.6.1...v0.6.2)
76 |
77 | :bug: Fixed bugs:
78 |
79 | - Fix issue when filename has \[ or \] characters [\#27](https://github.com/devlooped/dotnet-retest/pull/27) (@kzu)
80 |
81 | ## [v0.6.1](https://github.com/devlooped/dotnet-retest/tree/v0.6.1) (2024-08-08)
82 |
83 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.6.0...v0.6.1)
84 |
85 | ## [v0.6.0](https://github.com/devlooped/dotnet-retest/tree/v0.6.0) (2024-08-07)
86 |
87 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.5.0...v0.6.0)
88 |
89 | :sparkles: Implemented enhancements:
90 |
91 | - Rename attempts to retries [\#19](https://github.com/devlooped/dotnet-retest/pull/19) (@kzu)
92 |
93 | ## [v0.5.0](https://github.com/devlooped/dotnet-retest/tree/v0.5.0) (2024-08-07)
94 |
95 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.4.1...v0.5.0)
96 |
97 | :sparkles: Implemented enhancements:
98 |
99 | - Add ouctome column and screenshots [\#18](https://github.com/devlooped/dotnet-retest/pull/18) (@kzu)
100 |
101 | ## [v0.4.1](https://github.com/devlooped/dotnet-retest/tree/v0.4.1) (2024-08-07)
102 |
103 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.4.0...v0.4.1)
104 |
105 | :sparkles: Implemented enhancements:
106 |
107 | - Don't allow non-trx logger on non-Windows OS [\#17](https://github.com/devlooped/dotnet-retest/pull/17) (@kzu)
108 | - Make progress description column multiline [\#16](https://github.com/devlooped/dotnet-retest/pull/16) (@kzu)
109 | - Increase console verbosity to get better progress [\#15](https://github.com/devlooped/dotnet-retest/pull/15) (@kzu)
110 |
111 | ## [v0.4.0](https://github.com/devlooped/dotnet-retest/tree/v0.4.0) (2024-08-06)
112 |
113 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.3.0...v0.4.0)
114 |
115 | :sparkles: Implemented enhancements:
116 |
117 | - Allow for extra loggers in addition to trx [\#14](https://github.com/devlooped/dotnet-retest/pull/14) (@kzu)
118 | - Improve progress reporting by showing output [\#13](https://github.com/devlooped/dotnet-retest/pull/13) (@kzu)
119 |
120 | ## [v0.3.0](https://github.com/devlooped/dotnet-retest/tree/v0.3.0) (2024-07-31)
121 |
122 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.2.3...v0.3.0)
123 |
124 | ## [v0.2.3](https://github.com/devlooped/dotnet-retest/tree/v0.2.3) (2024-07-29)
125 |
126 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.2.2...v0.2.3)
127 |
128 | ## [v0.2.2](https://github.com/devlooped/dotnet-retest/tree/v0.2.2) (2024-07-29)
129 |
130 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.2.1...v0.2.2)
131 |
132 | :sparkles: Implemented enhancements:
133 |
134 | - Bring fix for test error markup rendering [\#10](https://github.com/devlooped/dotnet-retest/pull/10) (@kzu)
135 |
136 | ## [v0.2.1](https://github.com/devlooped/dotnet-retest/tree/v0.2.1) (2024-07-29)
137 |
138 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.2.0...v0.2.1)
139 |
140 | ## [v0.2.0](https://github.com/devlooped/dotnet-retest/tree/v0.2.0) (2024-07-21)
141 |
142 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/v0.1.0...v0.2.0)
143 |
144 | :sparkles: Implemented enhancements:
145 |
146 | - Take into account duplicate FQN from theories [\#6](https://github.com/devlooped/dotnet-retest/pull/6) (@kzu)
147 |
148 | ## [v0.1.0](https://github.com/devlooped/dotnet-retest/tree/v0.1.0) (2024-07-21)
149 |
150 | [Full Changelog](https://github.com/devlooped/dotnet-retest/compare/cc678481a604157a20545f0a37a4fe7e119a77b3...v0.1.0)
151 |
152 | :sparkles: Implemented enhancements:
153 |
154 | - Don't prefix trx report options unnecessarily [\#5](https://github.com/devlooped/dotnet-retest/pull/5) (@kzu)
155 | - Run retest with sample on all platforms [\#3](https://github.com/devlooped/dotnet-retest/pull/3) (@kzu)
156 |
157 | :twisted_rightwards_arrows: Merged:
158 |
159 | - Showcase CI runs [\#4](https://github.com/devlooped/dotnet-retest/pull/4) (@kzu)
160 |
161 |
162 |
163 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
164 |
--------------------------------------------------------------------------------
/dotnet-retest.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.11.35005.142
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-retest", "src\dotnet-retest\dotnet-retest.csproj", "{30849648-147D-41B7-ACBE-D54AD360E0C8}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "src\Sample\Sample.csproj", "{5A647D73-B3A8-49E8-A8A3-AC3CAD00DF48}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {30849648-147D-41B7-ACBE-D54AD360E0C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {30849648-147D-41B7-ACBE-D54AD360E0C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {30849648-147D-41B7-ACBE-D54AD360E0C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {30849648-147D-41B7-ACBE-D54AD360E0C8}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {5A647D73-B3A8-49E8-A8A3-AC3CAD00DF48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {5A647D73-B3A8-49E8-A8A3-AC3CAD00DF48}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {5A647D73-B3A8-49E8-A8A3-AC3CAD00DF48}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {5A647D73-B3A8-49E8-A8A3-AC3CAD00DF48}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {36DBDAFF-AF65-47FF-847A-A2BBD8AB8A95}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Daniel Cazzulino and Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |  dotnet retest
2 | ============
3 |
4 | [](https://www.nuget.org/packages/dotnet-retest)
5 | [](https://www.nuget.org/packages/dotnet-retest)
6 | [](https://github.com//devlooped/dotnet-retest/blob/main/license.txt)
7 | [](https://github.com/devlooped/dotnet-retest/actions)
8 |
9 |
10 | Runs `dotnet test` with retries for failed tests automatically, and pretty-prints aggregated
11 | test results, integrating also with GitHub PR comments just like [dotnet-trx](https://github.com/devlooped/dotnet-trx).
12 |
13 | 
14 |
15 | When running locally, it provides live progress on each run:
16 |
17 | 
18 |
19 | and timing and outcome for each attempt:
20 |
21 | 
22 |
23 | Typical usage: `dotnet retest [OPTIONS] [-- [dotnet test options]]` (with optional `--attempts` which defaults to `3`):
24 |
25 | ```yml
26 | - name: 🧪 test
27 | run: |
28 | dotnet tool update -g dotnet-retest
29 | dotnet retest -- --no-build [other test options and args]
30 | ```
31 |
32 | PR comment integration:
33 |
34 | 
35 |
36 | > NOTE: this behavior is triggered by the presence of the `GITHUB_REF_NAME` and `CI` environment variables.
37 |
38 |
39 | ```shell
40 | USAGE:
41 | dotnet retest [OPTIONS] [-- [dotnet test options]]
42 |
43 | OPTIONS:
44 | DEFAULT
45 | -h, --help Prints help information
46 | --version Prints version information
47 | --retries 3 Maximum retries when re-running failed tests
48 | --no-summary Whether to emit a summary to console/GitHub
49 | --output Include test output in report
50 | -v, --verbosity Quiet Output display verbosity:
51 | - quiet: only failed tests are displayed
52 | - normal: failed and skipped tests are
53 | displayed
54 | - verbose: failed, skipped and passed tests
55 | are displayed
56 | --gh-comment True Report as GitHub PR comment
57 | --gh-summary True Report as GitHub step summary
58 | ```
59 |
60 |
61 |
62 | > NOTE: rendering the passed tests requires `verbose` verbosity, since typically
63 | > you'll just want to see the failed tests in the report, especially in projects with
64 | > large number of tests.
65 |
66 | Install:
67 |
68 | ```shell
69 | dotnet tool install -g dotnet-retest
70 | ```
71 |
72 | Update:
73 |
74 | ```shell
75 | dotnet tool update -g dotnet-retest
76 | ```
77 |
78 |
79 |
80 | # Sponsors
81 |
82 |
83 | [](https://github.com/clarius)
84 | [](https://github.com/MFB-Technologies-Inc)
85 | [](https://github.com/torutek-gh)
86 | [](https://github.com/drivenet)
87 | [](https://github.com/Keflon)
88 | [](https://github.com/tbolon)
89 | [](https://github.com/kfrancis)
90 | [](https://github.com/twenzel)
91 | [](https://github.com/unoplatform)
92 | [](https://github.com/dansiegel)
93 | [](https://github.com/rbnswartz)
94 | [](https://github.com/jfoshee)
95 | [](https://github.com/Mrxx99)
96 | [](https://github.com/eajhnsn1)
97 | [](https://github.com/IxTechnologies)
98 | [](https://github.com/davidjenni)
99 | [](https://github.com/Jonathan-Hickey)
100 | [](https://github.com/akunzai)
101 | [](https://github.com/jakobt)
102 | [](https://github.com/tinohager)
103 | [](https://github.com/KenBonny)
104 | [](https://github.com/SimonCropp)
105 | [](https://github.com/agileworks-eu)
106 | [](https://github.com/sorahex)
107 | [](https://github.com/arsdragonfly)
108 | [](https://github.com/vezel-dev)
109 | [](https://github.com/ChilliCream)
110 | [](https://github.com/4OTC)
111 | [](https://github.com/v-limo)
112 | [](https://github.com/jordansjones)
113 | [](https://github.com/DominicSchell)
114 | [](https://github.com/jkingry)
115 |
116 |
117 |
118 |
119 | [](https://github.com/sponsors/devlooped)
120 |
121 |
122 | [Learn more about GitHub Sponsors](https://github.com/sponsors)
123 |
124 |
125 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 |
7 | true
14 |
15 |
16 |
17 |
18 | $(CI)
19 |
20 |
21 |
22 | Daniel Cazzulino
23 | Copyright (C) Daniel Cazzulino and Contributors. All rights reserved.
24 | false
25 | MIT
26 |
27 |
28 | icon.png
29 | readme.md
30 |
31 | icon.png
32 | readme.md
33 |
34 | true
35 | true
36 |
37 | $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\bin'))
38 |
39 |
40 | true
41 | true
42 |
43 |
44 | true
45 |
46 |
47 |
48 | Release
49 | Latest
50 |
51 |
52 | false
53 |
54 | embedded
55 | true
56 | enable
57 |
58 | strict
59 |
60 |
61 | $(MSBuildProjectName)
62 | $(MSBuildProjectName.IndexOf('.'))
63 | $(MSBuildProjectName.Substring(0, $(RootNamespaceDot)))
64 |
65 |
66 | $(DefaultItemExcludes);*.binlog;*.zip;*.rsp;*.items;**/TestResults/**/*.*
67 |
68 | true
69 | true
70 | true
71 | true
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | NU5105;$(NoWarn)
81 |
82 | true
83 |
84 |
85 | true
86 |
87 |
88 | LatestMinor
89 |
90 |
91 |
92 |
93 | $(MSBuildThisFileDirectory)kzu.snk
94 |
100 | 002400000480000094000000060200000024000052534131000400000100010051155fd0ee280be78d81cc979423f1129ec5dd28edce9cd94fd679890639cad54c121ebdb606f8659659cd313d3b3db7fa41e2271158dd602bb0039a142717117fa1f63d93a2d288a1c2f920ec05c4858d344a45d48ebd31c1368ab783596b382b611d8c92f9c1b3d338296aa21b12f3bc9f34de87756100c172c52a24bad2db
101 | 00352124762f2aa5
102 | true
103 |
104 |
105 |
106 |
114 | 42.42.42
115 |
116 |
117 |
118 | <_VersionLabel>$(VersionLabel.Replace('refs/heads/', ''))
119 | <_VersionLabel>$(_VersionLabel.Replace('refs/tags/v', ''))
120 |
121 |
122 | <_VersionLabel Condition="$(_VersionLabel.Contains('refs/pull/'))">$(VersionLabel.TrimEnd('.0123456789'))
123 |
124 | <_VersionLabel>$(_VersionLabel.Replace('refs/pull/', 'pr'))
125 |
126 | <_VersionLabel>$(_VersionLabel.Replace('/merge', ''))
127 |
128 | <_VersionLabel>$(_VersionLabel.Replace('/', '-'))
129 |
130 |
131 | $(_VersionLabel)
132 |
133 | $(_VersionLabel)
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
162 |
163 | 1.0.0
164 | $(VersionPrefix)-$(VersionSuffix)
165 | $(VersionPrefix)
166 |
167 |
168 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CI;$(DefineConstants)
6 |
7 |
8 |
9 |
10 | false
11 | false
12 | true
13 |
14 |
15 |
16 | true
17 | true
18 |
19 |
20 |
21 |
31 | false
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
44 |
45 |
49 |
50 |
51 |
55 |
56 |
60 |
61 |
62 |
64 |
65 | 1.0.0
66 | $(VersionPrefix)-$(VersionSuffix)
67 | $(VersionPrefix)
68 |
69 |
70 |
71 |
72 | $(PackFolder)
73 | $(PackFolderPath.Replace('\$(TargetFramework)', ''))
74 | $(IntermediateOutputPath)$(PackFolderPath)\
75 | $(OutputPath)$(PackFolderPath)\
76 | $(OutputPath)
77 |
78 |
79 |
80 |
81 | pr$(GITHUB_REF.Replace('refs/pull/', '').Replace('/merge', ''))
82 | $(GITHUB_REF.Replace('refs/heads/', '').Replace('refs/tags/', ''))
83 |
84 | $(BUILD_SOURCEBRANCH.Replace('refs/heads/', '').Replace('refs/tags/', ''))
85 |
86 | pr$(APPVEYOR_PULL_REQUEST_NUMBER)
87 | $(APPVEYOR_REPO_TAG_NAME)
88 | $(APPVEYOR_REPO_BRANCH)
89 |
90 | $(TEAMCITY_BUILD_BRANCH)
91 |
92 | pr$(TRAVIS_PULL_REQUEST)
93 | $(TRAVIS_BRANCH)
94 |
95 | pr$(CIRCLE_PR_NUMBER)
96 | $(CIRCLE_TAG)
97 | $(CIRCLE_BRANCH)
98 |
99 | $(CI_COMMIT_TAG)
100 | pr$(CI_MERGE_REQUEST_IID)
101 | pr$(CI_EXTERNAL_PULL_REQUEST_IID)
102 | $(CI_COMMIT_BRANCH)
103 |
104 | pr$(BUDDY_EXECUTION_PULL_REQUEST_NO)
105 | $(BUDDY_EXECUTION_TAG)
106 | $(BUDDY_EXECUTION_BRANCH)
107 |
108 |
109 |
110 |
111 | CoreResGen;$(CoreCompileDependsOn)
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | $(IntermediateOutputPath)\$([MSBuild]::ValueOrDefault('%(RelativeDir)', '').Replace('\', '.').Replace('/', '.'))%(Filename).g$(DefaultLanguageSourceExtension)
121 | $(Language)
122 | $(RootNamespace)
123 | $(RootNamespace).$([MSBuild]::ValueOrDefault('%(RelativeDir)', '').Replace('\', '.').Replace('/', '.').TrimEnd('.'))
124 | %(Filename)
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
148 |
149 |
150 |
151 | $(PrivateRepositoryUrl)
152 |
153 |
154 |
155 | $(SourceRevisionId)
156 | $(SourceRevisionId.Substring(0, 9))
157 |
158 | $(RepositorySha)
159 |
160 |
161 |
162 |
163 | <_GitSourceRoot Include="@(SourceRoot -> WithMetadataValue('SourceControl', 'git'))" />
164 |
165 |
166 |
167 | @(_GitSourceRoot)
168 |
169 |
170 |
171 |
172 |
177 |
178 | $(RepositoryUrl)
179 | $(Description)
180 | $(RepositoryUrl)/blob/main/changelog.md
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/src/Sample/Sample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 | false
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Sample/UnitTest1.cs:
--------------------------------------------------------------------------------
1 | namespace Sample;
2 |
3 | public class UnitTest1
4 | {
5 | [Theory]
6 | [InlineData(1)]
7 | [InlineData(2)]
8 | public void Test1(int value)
9 | {
10 | Assert.True(value > 0);
11 | }
12 |
13 | [Fact]
14 | public void FailsOnce()
15 | {
16 | if (!File.Exists("failsonce.txt"))
17 | {
18 | File.WriteAllText("failsonce.txt", "");
19 | Assert.Fail("Fails once");
20 | }
21 |
22 | File.Delete("failsonce.txt");
23 | }
24 |
25 | [Fact]
26 | public void FailsTwice()
27 | {
28 | // Add random delay to simulate actual test execution
29 | Thread.Sleep(Random.Shared.Next(1000, 5000));
30 |
31 | var attempt = int.Parse(
32 | File.Exists("failstwice.txt") ?
33 | File.ReadAllText("failstwice.txt") :
34 | "0");
35 |
36 | if (attempt < 2)
37 | {
38 | File.WriteAllText("failstwice.txt", (attempt + 1).ToString());
39 | Assert.Fail("Fails twice");
40 | }
41 |
42 | // Succeeds
43 | File.Delete("failstwice.txt");
44 | }
45 |
46 | public static IEnumerable