Bump github/codeql-action/upload-sarif from 3.37.3 to 4.37.6 #1175
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Test | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - pre-main-integration | |
| pull_request: | |
| branches: | |
| - main | |
| - pre-main-integration | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| env: | |
| DOCFX_VERSION: 2.78.5 | |
| DOTNET_ILDASM_VERSION: 0.12.2 | |
| jobs: | |
| javascript-tests: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: npm | |
| cache-dependency-path: package-lock.json | |
| - name: Restore npm dependencies | |
| run: npm ci | |
| - name: Run JavaScript tests | |
| run: npm run test:js | |
| - name: Audit npm dependencies | |
| run: npm run audit:high | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore FolderDiffIL4DotNet.sln | |
| - name: Verify formatting | |
| run: dotnet format FolderDiffIL4DotNet.sln --verify-no-changes --no-restore --verbosity minimal | |
| - name: Test NuGet audit gate | |
| run: python3 -m unittest discover -s scripts/tests -p 'test_*.py' | |
| - name: Audit NuGet dependencies | |
| run: python3 scripts/nuget_audit_gate.py --solution FolderDiffIL4DotNet.sln | |
| - name: Build | |
| run: dotnet build FolderDiffIL4DotNet.sln --configuration Release --no-restore | |
| - name: Install DocFX | |
| run: dotnet tool update --global docfx --version "$DOCFX_VERSION" | |
| - name: Generate documentation site | |
| run: | | |
| export PATH="$PATH:$HOME/.dotnet/tools" | |
| docfx metadata docfx.json | |
| docfx build docfx.json | |
| - name: Install real disassembler for E2E tests | |
| if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }} | |
| run: | | |
| dotnet tool install --global dotnet-ildasm --version "$DOTNET_ILDASM_VERSION" | |
| echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH" | |
| DOTNET_ROLL_FORWARD=Major "$HOME/.dotnet/tools/dotnet-ildasm" --version | |
| - name: Restore local tools | |
| run: dotnet tool restore | |
| - name: Test with coverage | |
| if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }} | |
| env: | |
| DOTNET_ROLL_FORWARD: Major | |
| FOLDERDIFF_RUN_E2E: true | |
| run: dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj --configuration Release --no-build --nologo --settings coverlet.runsettings --logger "trx;LogFileName=test_results.trx" --collect:"XPlat Code Coverage" --results-directory ./TestResults | |
| - name: Generate coverage report | |
| if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }} | |
| run: | | |
| dotnet tool run reportgenerator \ | |
| -reports:"TestResults/**/coverage.cobertura.xml" \ | |
| -targetdir:"CoverageReport" \ | |
| -reporttypes:"MarkdownSummaryGithub;Cobertura;HtmlInline_AzurePipelines" | |
| if [ -f "CoverageReport/SummaryGithub.md" ]; then | |
| cat CoverageReport/SummaryGithub.md >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| - name: Enforce coverage thresholds | |
| if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }} | |
| run: | | |
| python3 - <<'PY' | |
| import glob | |
| import sys | |
| import xml.etree.ElementTree as ET | |
| line_threshold = 80.0 | |
| branch_threshold = 75.0 | |
| # Per-class baseline floors for core diff logic. | |
| # コア差分ロジックに対するクラス単位のベースライン下限。 | |
| core_class_line_threshold = 85.0 | |
| core_class_branch_threshold = 65.0 | |
| core_classes = [ | |
| "FolderDiffIL4DotNet.Services.FileDiffService", | |
| "FolderDiffIL4DotNet.Services.FolderDiffService", | |
| "FolderDiffIL4DotNet.Services.FileComparisonService", | |
| ] | |
| matches = glob.glob("TestResults/**/coverage.cobertura.xml", recursive=True) | |
| if not matches: | |
| print("coverage.cobertura.xml was not found.", file=sys.stderr) | |
| sys.exit(1) | |
| root = ET.parse(matches[0]).getroot() | |
| line_rate = float(root.attrib["line-rate"]) * 100.0 | |
| branch_rate = float(root.attrib["branch-rate"]) * 100.0 | |
| print(f"Total line coverage : {line_rate:.2f}% (threshold {line_threshold:.2f}%)") | |
| print(f"Total branch coverage: {branch_rate:.2f}% (threshold {branch_threshold:.2f}%)") | |
| failures = [] | |
| if line_rate < line_threshold: | |
| failures.append(f"line coverage {line_rate:.2f}% < {line_threshold:.2f}%") | |
| if branch_rate < branch_threshold: | |
| failures.append(f"branch coverage {branch_rate:.2f}% < {branch_threshold:.2f}%") | |
| # Check per-class thresholds for core diff classes. | |
| # Partial classes produce multiple <class> entries with the same name | |
| # but different filenames — aggregate line/branch hits across all entries. | |
| # コア差分クラスのクラス単位閾値をチェック。 | |
| # Partial class は同名で異なるファイルの複数 <class> エントリを生成するため、 | |
| # 全エントリの行数・ブランチ数を集約してから判定する。 | |
| print() | |
| print("--- Core class coverage ---") | |
| from collections import defaultdict | |
| agg = defaultdict(lambda: {"lines_covered": 0, "lines_total": 0, | |
| "branches_covered": 0, "branches_total": 0}) | |
| for pkg in root.findall(".//package"): | |
| for cls in pkg.findall(".//class"): | |
| cls_name = cls.attrib.get("name", "") | |
| if cls_name not in core_classes: | |
| continue | |
| for line in cls.findall(".//line"): | |
| agg[cls_name]["lines_total"] += 1 | |
| if int(line.attrib.get("hits", "0")) > 0: | |
| agg[cls_name]["lines_covered"] += 1 | |
| if line.attrib.get("branch", "false").lower() == "true": | |
| cc = line.attrib.get("condition-coverage", "") | |
| # Format: "X% (covered/total)" | |
| # 形式: "X% (covered/total)" | |
| if "(" in cc and "/" in cc: | |
| inner = cc.split("(")[1].rstrip(")") | |
| cov, tot = inner.split("/") | |
| agg[cls_name]["branches_covered"] += int(cov) | |
| agg[cls_name]["branches_total"] += int(tot) | |
| core_warnings = [] | |
| for cls_name in core_classes: | |
| d = agg[cls_name] | |
| if d["lines_total"] == 0: | |
| print(f" {cls_name}: no coverage data found [MISSING]") | |
| core_warnings.append(f"{cls_name} coverage data was not found") | |
| continue | |
| cls_line = d["lines_covered"] / d["lines_total"] * 100.0 | |
| cls_branch = (d["branches_covered"] / d["branches_total"] * 100.0 | |
| if d["branches_total"] > 0 else 100.0) | |
| status = "OK" | |
| if cls_line < core_class_line_threshold or cls_branch < core_class_branch_threshold: | |
| status = "BELOW TARGET" | |
| print(f" {cls_name}: line {cls_line:.2f}%, branch {cls_branch:.2f}% [{status}]") | |
| if cls_line < core_class_line_threshold: | |
| core_warnings.append( | |
| f"{cls_name} line coverage {cls_line:.2f}% < {core_class_line_threshold:.2f}%" | |
| ) | |
| if cls_branch < core_class_branch_threshold: | |
| core_warnings.append( | |
| f"{cls_name} branch coverage {cls_branch:.2f}% < {core_class_branch_threshold:.2f}%" | |
| ) | |
| if core_warnings: | |
| print("\nCore class coverage threshold check failed:", file=sys.stderr) | |
| for w in core_warnings: | |
| print(f" - {w}", file=sys.stderr) | |
| failures.extend(core_warnings) | |
| if failures: | |
| print("\nCoverage threshold check failed:", file=sys.stderr) | |
| for failure in failures: | |
| print(f" - {failure}", file=sys.stderr) | |
| sys.exit(1) | |
| PY | |
| - name: Validate test scope map | |
| if: ${{ hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }} | |
| continue-on-error: true | |
| run: python3 scripts/validate-test-scope-map.py | |
| - name: Upload test and coverage artifacts | |
| if: ${{ always() && hashFiles('FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj') != '' }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: TestAndCoverage | |
| if-no-files-found: warn | |
| path: | | |
| TestResults/**/*.trx | |
| TestResults/**/coverage.cobertura.xml | |
| CoverageReport/** | |
| - name: Upload documentation artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: DocumentationSite | |
| path: _site/** | |
| - name: Publish | |
| run: dotnet publish FolderDiffIL4DotNet.csproj --configuration Release --no-build --output publish | |
| - name: Remove debugging symbols | |
| run: find publish -name '*.pdb' -delete | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: FolderDiffIL4DotNet | |
| path: publish/** | |
| mutation-testing: | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore FolderDiffIL4DotNet.sln | |
| - name: Build | |
| run: dotnet build FolderDiffIL4DotNet.sln --configuration Release --no-restore | |
| - name: Restore local tools | |
| run: dotnet tool restore | |
| - name: Install real disassembler for E2E tests | |
| run: | | |
| dotnet tool install --global dotnet-ildasm --version "$DOTNET_ILDASM_VERSION" | |
| echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH" | |
| DOTNET_ROLL_FORWARD=Major "$HOME/.dotnet/tools/dotnet-ildasm" --version | |
| - name: Run Stryker mutation testing | |
| env: | |
| DOTNET_ROLL_FORWARD: Major | |
| run: dotnet tool run dotnet-stryker --config-file stryker-config.json --output StrykerOutput | |
| - name: Generate mutation visibility summary | |
| if: always() | |
| run: > | |
| python3 scripts/generate-mutation-summary.py | |
| --output-root StrykerOutput | |
| --run-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| --summary-artifact-name "StrykerSummary-${{ github.run_number }}-${{ github.run_attempt }}" | |
| --report-artifact-name "StrykerReport-${{ github.run_number }}-${{ github.run_attempt }}" | |
| - name: Post mutation summary to job summary | |
| if: always() | |
| run: cat StrykerOutput/mutation-summary.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload mutation visibility summary | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: StrykerSummary-${{ github.run_number }}-${{ github.run_attempt }} | |
| if-no-files-found: error | |
| path: | | |
| StrykerOutput/mutation-summary.md | |
| StrykerOutput/mutation-summary.json | |
| - name: Upload mutation testing report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: StrykerReport-${{ github.run_number }}-${{ github.run_attempt }} | |
| if-no-files-found: warn | |
| path: StrykerOutput/** | |
| mutation-comment: | |
| runs-on: ubuntu-latest | |
| needs: mutation-testing | |
| if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Download mutation visibility summary | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: StrykerSummary-${{ github.run_number }}-${{ github.run_attempt }} | |
| path: StrykerOutput | |
| - name: Post mutation summary to pull request | |
| continue-on-error: true | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | |
| with: | |
| script: | | |
| const { upsertMutationSummaryComment } = require('./scripts/update-mutation-pr-comment.js'); | |
| await upsertMutationSummaryComment({ | |
| github, | |
| context, | |
| summaryPath: 'StrykerOutput/mutation-summary.md', | |
| }); | |
| benchmark: | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'workflow_dispatch' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore FolderDiffIL4DotNet.Benchmarks/FolderDiffIL4DotNet.Benchmarks.csproj | |
| - name: Run benchmarks | |
| run: dotnet run --project FolderDiffIL4DotNet.Benchmarks/FolderDiffIL4DotNet.Benchmarks.csproj --configuration Release -- --exporters json github | |
| - name: Upload benchmark results | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: BenchmarkResults | |
| if-no-files-found: warn | |
| path: BenchmarkDotNet.Artifacts/** | |
| test-windows: | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~\AppData\Local\NuGet\packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore FolderDiffIL4DotNet.sln | |
| - name: Build | |
| run: dotnet build FolderDiffIL4DotNet.sln --configuration Release --no-restore | |
| - name: Install real disassembler for E2E tests | |
| shell: pwsh | |
| run: | | |
| dotnet tool install --global dotnet-ildasm --version $env:DOTNET_ILDASM_VERSION | |
| $toolPath = Join-Path $env:USERPROFILE ".dotnet\tools" | |
| $toolPath | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| & (Join-Path $toolPath "dotnet-ildasm.exe") --version | |
| env: | |
| DOTNET_ROLL_FORWARD: Major | |
| - name: Test | |
| run: dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj --configuration Release --no-build --nologo | |
| env: | |
| DOTNET_ROLL_FORWARD: Major | |
| FOLDERDIFF_RUN_E2E: true | |
| test-macos: | |
| name: macOS stable tests and CLI smoke | |
| runs-on: macos-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Cache NuGet packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| run: dotnet restore FolderDiffIL4DotNet.sln | |
| - name: Build | |
| run: dotnet build FolderDiffIL4DotNet.sln --configuration Release --no-restore | |
| - name: Run stable tests | |
| run: >- | |
| dotnet test FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj | |
| --configuration Release | |
| --no-build | |
| --nologo | |
| --filter "Category!=E2E&Category!=Performance" | |
| --logger "trx;LogFileName=macos_test_results.trx" | |
| --results-directory ./MacOsTestResults | |
| - name: Run non-interactive CLI smoke | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| smoke_root="$RUNNER_TEMP/nildiff-macos-smoke" | |
| old_dir="$smoke_root/old folder" | |
| new_dir="$smoke_root/new folder" | |
| report_root="$smoke_root/reports" | |
| cli_path="$GITHUB_WORKSPACE/bin/Release/net8.0/nildiff" | |
| mkdir -p "$old_dir" "$new_dir" "$report_root" | |
| printf 'old only\n' > "$old_dir/only-old.txt" | |
| printf 'before\n' > "$old_dir/CaseProbe.txt" | |
| printf 'after\n' > "$new_dir/caseprobe.txt" | |
| test -x "$cli_path" | |
| "$cli_path" --doctor --skip-il --no-banner --no-pause | |
| set +e | |
| "$cli_path" \ | |
| "$old_dir" \ | |
| "$new_dir" \ | |
| macos-smoke \ | |
| --output "$report_root" \ | |
| --skip-il \ | |
| --no-banner \ | |
| --no-pause \ | |
| --fail-on-diff | |
| smoke_exit=$? | |
| set -e | |
| if [ "$smoke_exit" -ne 5 ]; then | |
| echo "::error::Expected reportable-difference exit code 5, got $smoke_exit." | |
| exit 1 | |
| fi | |
| for artifact in diff_report.md diff_report.html audit_log.json; do | |
| test -s "$report_root/macos-smoke/$artifact" | |
| done | |
| grep -Fq "$old_dir" "$report_root/macos-smoke/diff_report.md" | |
| grep -Fq "$new_dir" "$report_root/macos-smoke/diff_report.md" | |
| grep -Fq '| `[ * ]` | CaseProbe.txt |' "$report_root/macos-smoke/diff_report.md" | |
| - name: Upload macOS test results | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: MacOsTestResults | |
| path: MacOsTestResults/*.trx |