diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc38da9f39..5c7db60d2d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,9 +9,9 @@ name: Build on: - push: - branches: [ 'master', 'release/**' ] + workflow_dispatch: pull_request: + push: branches: [ 'master', 'release/**' ] release: types: [published] @@ -57,17 +57,15 @@ jobs: - name: Git checkout uses: actions/checkout@v4 - name: Restore tools - run: | - dotnet tool restore + run: dotnet tool restore - name: Restore packages - run: | - dotnet restore + run: dotnet restore - name: Calculate version suffix shell: pwsh run: | if ($env:GITHUB_REF_TYPE -eq 'tag') { # Get the version prefix/suffix from the git tag. For example: 'v1.0.0-preview1-final' => '1.0.0' and 'preview1-final' - $segments = $env:GITHUB_REF_NAME -split "-" + $segments = $env:GITHUB_REF_NAME -split '-' $versionPrefix = $segments[0].TrimStart('v') $versionSuffix = $segments.Length -eq 1 ? '' : $segments[1..$($segments.Length - 1)] -join '-' @@ -93,9 +91,7 @@ jobs: Write-Output "Using version suffix: $versionSuffix" Write-Output "PACKAGE_VERSION_SUFFIX=$versionSuffix" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Build - shell: pwsh - run: | - dotnet build --no-restore --configuration Release /p:VersionSuffix=$env:PACKAGE_VERSION_SUFFIX + run: dotnet build --no-restore --configuration Release /p:VersionSuffix=${{ env.PACKAGE_VERSION_SUFFIX }} - name: Test env: # Override log levels, to reduce logging output when running tests in ci-build. @@ -104,10 +100,9 @@ jobs: Logging__LogLevel__Microsoft.Extensions.Hosting.Internal.Host: 'None' Logging__LogLevel__Microsoft.EntityFrameworkCore.Database.Command: 'None' Logging__LogLevel__JsonApiDotNetCore: 'None' - run: | - dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" + run: dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" - name: Upload coverage to codecov.io - if: matrix.os == 'ubuntu-latest' + if: ${{ matrix.os == 'ubuntu-latest' }} env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} uses: codecov/codecov-action@v5 @@ -115,11 +110,9 @@ jobs: fail_ci_if_error: true verbose: true - name: Generate packages - shell: pwsh - run: | - dotnet pack --no-build --configuration Release --output $env:GITHUB_WORKSPACE/artifacts/packages /p:VersionSuffix=$env:PACKAGE_VERSION_SUFFIX + run: dotnet pack --no-build --configuration Release --output ${{ github.workspace }}/artifacts/packages /p:VersionSuffix=${{ env.PACKAGE_VERSION_SUFFIX }} - name: Upload packages to artifacts - if: matrix.os == 'ubuntu-latest' + if: ${{ matrix.os == 'ubuntu-latest' }} uses: actions/upload-artifact@v4 with: name: packages @@ -127,7 +120,7 @@ jobs: - name: Generate documentation shell: pwsh env: - # This contains the git tag name on release; in that case we build the docs without publishing them. + # This contains the git tag name on release; in that case, we build the docs without publishing them. DOCFX_SOURCE_BRANCH_NAME: ${{ github.base_ref || github.ref_name }} run: | cd docs @@ -142,7 +135,7 @@ jobs: New-Item -Force _site/styles -ItemType Directory | Out-Null Copy-Item -Recurse home/assets/* _site/styles/ - name: Upload documentation to artifacts - if: matrix.os == 'ubuntu-latest' + if: ${{ matrix.os == 'ubuntu-latest' }} uses: actions/upload-artifact@v4 with: name: documentation @@ -169,8 +162,7 @@ jobs: - name: Git checkout uses: actions/checkout@v4 - name: Restore tools - run: | - dotnet tool restore + run: dotnet tool restore - name: InspectCode shell: pwsh run: | @@ -199,7 +191,7 @@ jobs: } if ($failed) { - Write-Error "One or more projects failed code inspection." + Write-Error 'One or more projects failed code inspection.' } } @@ -226,13 +218,11 @@ jobs: with: fetch-depth: 2 - name: Restore tools - run: | - dotnet tool restore + run: dotnet tool restore - name: Restore packages - run: | - dotnet restore + run: dotnet restore - name: CleanupCode (on PR diff) - if: github.event_name == 'pull_request' + if: ${{ github.event_name == 'pull_request' }} shell: pwsh run: | # Not using the environment variables for SHAs, because they may be outdated. This may happen on force-push after the build is queued, but before it starts. @@ -243,10 +233,10 @@ jobs: Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff - name: CleanupCode (on branch) - if: github.event_name == 'push' || github.event_name == 'release' + if: ${{ github.event_name == 'push' || github.event_name == 'release' }} shell: pwsh run: | - Write-Output "Running code cleanup on all files." + Write-Output 'Running code cleanup on all files.' dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff publish: @@ -263,23 +253,17 @@ jobs: - name: Download artifacts uses: actions/download-artifact@v4 - name: Publish to GitHub Packages - if: github.event_name == 'push' || github.event_name == 'release' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: pwsh + if: ${{ github.event_name == 'push' || github.event_name == 'release' }} run: | - dotnet nuget add source --username 'json-api-dotnet' --password "$env:GITHUB_TOKEN" --store-password-in-clear-text --name 'github' 'https://nuget.pkg.github.com/json-api-dotnet/index.json' - dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:GITHUB_TOKEN" --source 'github' + dotnet nuget add source --username 'json-api-dotnet' --password '${{ secrets.GITHUB_TOKEN }}' --store-password-in-clear-text --name 'github' 'https://nuget.pkg.github.com/json-api-dotnet/index.json' + dotnet nuget push '${{ github.workspace }}/packages/*.nupkg' --api-key '${{ secrets.GITHUB_TOKEN }}' --source 'github' - name: Publish to feedz.io - if: github.event_name == 'push' || github.event_name == 'release' - env: - FEEDZ_IO_API_KEY: ${{ secrets.FEEDZ_IO_API_KEY }} - shell: pwsh + if: ${{ github.event_name == 'push' || github.event_name == 'release' }} run: | dotnet nuget add source --name 'feedz-io' 'https://f.feedz.io/json-api-dotnet/jsonapidotnetcore/nuget/index.json' - dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:FEEDZ_IO_API_KEY" --source 'feedz-io' + dotnet nuget push '${{ github.workspace }}/packages/*.nupkg' --api-key '${{ secrets.FEEDZ_IO_API_KEY }}' --source 'feedz-io' - name: Publish documentation - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} @@ -287,9 +271,5 @@ jobs: publish_dir: ./documentation commit_message: 'Auto-generated documentation from' - name: Publish to NuGet - if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/v') - env: - NUGET_ORG_API_KEY: ${{ secrets.NUGET_ORG_API_KEY }} - shell: pwsh - run: | - dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:NUGET_ORG_API_KEY" --source 'nuget.org' --skip-duplicate + if: ${{ github.event_name == 'release' && startsWith(github.ref, 'refs/tags/v') }} + run: dotnet nuget push '${{ github.workspace }}/packages/*.nupkg' --api-key '${{ secrets.NUGET_ORG_API_KEY }}' --source 'nuget.org' --skip-duplicate diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 508d210158..705d75d68c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,10 +1,9 @@ name: "CodeQL" on: - push: - branches: [ 'master', 'release/**' ] + workflow_dispatch: pull_request: - # The branches below must be a subset of the branches above + push: branches: [ 'master', 'release/**' ] schedule: - cron: '0 0 * * 5' diff --git a/.github/workflows/qodana.yml b/.github/workflows/qodana.yml index 8ce0acd5db..0f88a90f3f 100644 --- a/.github/workflows/qodana.yml +++ b/.github/workflows/qodana.yml @@ -1,13 +1,17 @@ -# https://www.jetbrains.com/help/qodana/cloud-forward-reports.html#cloud-forward-reports-github-actions - name: Qodana on: workflow_dispatch: pull_request: push: - branches: - - master - - 'release/*' + branches: [ 'master', 'release/**' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true jobs: qodana: @@ -17,17 +21,32 @@ jobs: pull-requests: write checks: write steps: - - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 8.0.* + 9.0.* + - name: Git checkout + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2024.1 + - name: Restore tools + run: dotnet tool restore + - name: Restore packages + run: dotnet restore + - name: Build + run: dotnet build --no-restore --configuration Release + - name: Qodana scan + uses: JetBrains/qodana-action@v2025.1 + with: + args: --ide,QDNET,--profile-name,qodana.recommended,--configuration,Release,--apply-fixes + push-fixes: pull-request + upload-result: true env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} - - name: Upload results to artifacts on failure - if: failure() - uses: actions/upload-artifact@v4 + - name: Upload SARIF report + uses: github/codeql-action/upload-sarif@v3 with: - name: qodana_results - path: ${{ runner.temp }}/qodana/results + sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json diff --git a/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs b/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs index 82790819fe..715310e04f 100644 --- a/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs +++ b/src/Examples/DapperExample/AtomicOperations/AmbientTransactionFactory.cs @@ -26,7 +26,7 @@ public AmbientTransactionFactory(IJsonApiOptions options, IDataModelService data internal async Task BeginTransactionAsync(CancellationToken cancellationToken) { - var instance = (IOperationsTransactionFactory)this; + IOperationsTransactionFactory instance = this; IOperationsTransaction transaction = await instance.BeginTransactionAsync(cancellationToken); return (AmbientTransaction)transaction; diff --git a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs index b7f200dd48..df712d6eec 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/LinkBuilder.cs @@ -219,7 +219,7 @@ private string GetLinkForPagination(int pageOffset, string? pageSizeValue) private string GetQueryStringInPaginationLink(int pageOffset, string? pageSizeValue) { - Dictionary parameters = HttpContext.Request.Query.ToDictionary(pair => pair.Key, pair => (string?)pair.Value.ToString()); + Dictionary parameters = HttpContext.Request.Query.ToDictionary(pair => pair.Key, string? (pair) => pair.Value.ToString()); if (pageSizeValue == null) {