Add configurable color themes (default/light/dark/monochrome) #445
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: Validate And Package | |
| on: | |
| # Trigger when manually run | |
| workflow_dispatch: | |
| # Trigger on pushes to `main`, `rel/*`, or `dev/**` | |
| push: | |
| branches: | |
| - main | |
| - rel/* | |
| - dev/** | |
| # Trigger on pull requests to `main`, `rel/*`, or `dev/**` | |
| pull_request: | |
| branches: | |
| - main | |
| - rel/* | |
| - dev/** | |
| permissions: | |
| contents: read | |
| env: | |
| BUILD_CONFIGURATION: Release | |
| jobs: | |
| build-test-package: | |
| runs-on: windows-latest | |
| # A push to a branch with an open PR fires both `push` and `pull_request` | |
| # events. Rather than cancelling one of them (a cancelled run reports | |
| # as a failed required check on the PR's head SHA and blocks merge), | |
| # we skip the `pull_request` run for same-repo PRs only when the PR | |
| # head branch is also covered by this workflow's `push.branches` | |
| # filters, because only those branches already get a `push` run in | |
| # this repo. For PRs from forks, or same-repo PRs from other head | |
| # branches such as `feature/*`, we still let `pull_request` run. | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name != github.repository || | |
| (github.head_ref != 'main' && | |
| !startsWith(github.head_ref, 'rel/') && | |
| !startsWith(github.head_ref, 'dev/')) | |
| # Concurrency only dedupes runs for the SAME branch across DIFFERENT | |
| # commits (e.g. rapid pushes during a rebase). The cancelled older run | |
| # is on a stale SHA that is no longer the PR head, so it does not | |
| # block the PR. Push and pull_request events for the same SHA are | |
| # already deduped by the `if` above, so they never collide here. | |
| # For `pull_request` events, scope the group by PR number and head | |
| # repo so that two forks pushing branches with the same name do not | |
| # cancel each other. | |
| concurrency: | |
| group: build-${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('{0}-{1}', github.event.pull_request.head.repo.full_name, github.event.pull_request.number) || github.ref_name }} | |
| cancel-in-progress: true | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| # GitVersion needs full history to compute commit counts. | |
| fetch-depth: 0 | |
| - name: Setup .NET SDK | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| global-json-file: global.json | |
| cache: true | |
| cache-dependency-path: | | |
| global.json | |
| Directory.Packages.props | |
| **/*.csproj | |
| - name: Restore GitVersion tool | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| dotnet tool restore | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "Failed to restore the local GitVersion tool." | |
| } | |
| - name: Compute version properties | |
| id: version | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| # GitVersion.yml supplies Major.Minor via next-version and counts | |
| # commits since it was last bumped. We build the final version | |
| # string ourselves so it follows the Major.Minor.<commits>-preview | |
| # format consistently across pipelines. | |
| $gitVersionJson = dotnet tool run dotnet-gitversion /output json /nofetch /nonormalize | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "Failed to compute version metadata with dotnet-gitversion." | |
| } | |
| $gv = $gitVersionJson | ConvertFrom-Json | |
| $commitsSinceVersionSource = [int]$gv.CommitsSinceVersionSource | |
| if ($commitsSinceVersionSource -gt 65535) { | |
| throw "CommitsSinceVersionSource ($commitsSinceVersionSource) exceeds the maximum .NET assembly version segment value of 65535. Bump next-version before generating assembly and file versions." | |
| } | |
| $assemblyVersion = "$($gv.Major).$($gv.Minor).$commitsSinceVersionSource" | |
| $packageVersion = "$assemblyVersion-preview" | |
| $fileVersion = "$assemblyVersion.0" | |
| $infoVersion = "$packageVersion+${{ github.sha }}" | |
| Write-Host "AssemblyVersion: $assemblyVersion" | |
| Write-Host "PackageVersion: $packageVersion" | |
| "assembly_version=$assemblyVersion" >> $env:GITHUB_OUTPUT | |
| "package_version=$packageVersion" >> $env:GITHUB_OUTPUT | |
| "file_version=$fileVersion" >> $env:GITHUB_OUTPUT | |
| "informational_version=$infoVersion" >> $env:GITHUB_OUTPUT | |
| $branchName = "${{ github.ref_name }}" | |
| $branchLabel = $branchName.ToLowerInvariant() | |
| $branchLabel = $branchLabel -replace '[^0-9a-z-]', '-' | |
| $branchLabel = $branchLabel -replace '-+', '-' | |
| $branchLabel = $branchLabel.Trim('-') | |
| if ([string]::IsNullOrWhiteSpace($branchLabel)) { | |
| $branchLabel = 'branch' | |
| } | |
| if ($branchLabel.Length -gt 40) { | |
| $branchLabel = $branchLabel.Substring(0, 40).Trim('-') | |
| } | |
| "branch_label=$branchLabel" >> $env:GITHUB_OUTPUT | |
| "artifact_suffix=$branchLabel-${{ github.run_number }}" >> $env:GITHUB_OUTPUT | |
| - name: Restore | |
| run: dotnet restore CosmosDBShell.sln | |
| - name: Build solution | |
| run: >- | |
| dotnet build CosmosDBShell.sln | |
| --configuration $env:BUILD_CONFIGURATION | |
| --no-restore | |
| /p:Version=${{ steps.version.outputs.assembly_version }} | |
| /p:FileVersion=${{ steps.version.outputs.file_version }} | |
| /p:InformationalVersion=${{ steps.version.outputs.informational_version }} | |
| shell: pwsh | |
| - name: Test solution | |
| run: >- | |
| dotnet test CosmosDBShell.sln | |
| --configuration $env:BUILD_CONFIGURATION | |
| --no-build | |
| --no-restore | |
| --logger "trx;LogFileName=test-results.trx" | |
| --results-directory TestResults | |
| --collect "Code coverage" | |
| shell: pwsh | |
| - name: Run fuzzer smoke test | |
| working-directory: CosmosDBShell.Fuzzer | |
| run: dotnet run --configuration $env:BUILD_CONFIGURATION --no-build --no-restore -- --all | |
| shell: pwsh | |
| - name: Fail if fuzzer crash findings exist | |
| shell: pwsh | |
| run: | | |
| $crashes = Get-ChildItem -Path CosmosDBShell.Fuzzer/findings -Filter 'crash_*.txt' -ErrorAction SilentlyContinue | |
| if ($crashes -and $crashes.Count -gt 0) { | |
| Write-Error "Fuzzer recorded $($crashes.Count) crash(es). See the 'fuzz-findings' artifact for details." | |
| exit 1 | |
| } | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results | |
| path: TestResults | |
| if-no-files-found: ignore | |
| - name: Upload fuzzer findings | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: fuzz-findings | |
| path: CosmosDBShell.Fuzzer/findings | |
| if-no-files-found: ignore | |
| - name: Publish runtime artifacts | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $rids = @('win-x64', 'win-arm64', 'linux-x64', 'linux-arm64', 'osx-x64', 'osx-arm64') | |
| foreach ($rid in $rids) { | |
| dotnet restore CosmosDBShell/CosmosDBShell.csproj ` | |
| -r $rid | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "RID restore failed for $rid with exit code $LASTEXITCODE." | |
| } | |
| dotnet publish CosmosDBShell/CosmosDBShell.csproj ` | |
| --configuration $env:BUILD_CONFIGURATION ` | |
| --no-restore ` | |
| -r $rid ` | |
| --output "out/$rid" ` | |
| /p:Version=${{ steps.version.outputs.assembly_version }} ` | |
| /p:FileVersion=${{ steps.version.outputs.file_version }} ` | |
| /p:InformationalVersion=${{ steps.version.outputs.informational_version }} | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "RID publish failed for $rid with exit code $LASTEXITCODE." | |
| } | |
| } | |
| - name: Pack NuGet artifacts | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Path out/nupkg -Force | Out-Null | |
| # Restore for all RIDs so pack can build packages for each | |
| dotnet restore CosmosDBShell/CosmosDBShell.csproj | |
| dotnet pack CosmosDBShell/CosmosDBShell.csproj ` | |
| --configuration $env:BUILD_CONFIGURATION ` | |
| --no-restore ` | |
| --output out/nupkg ` | |
| /p:PackageVersion=${{ steps.version.outputs.package_version }} ` | |
| /p:Version=${{ steps.version.outputs.assembly_version }} ` | |
| /p:FileVersion=${{ steps.version.outputs.file_version }} ` | |
| /p:InformationalVersion=${{ steps.version.outputs.informational_version }} ` | |
| /p:ContinuousIntegrationBuild=true | |
| - name: Validate NuGet package set | |
| shell: pwsh | |
| run: | | |
| $pkgDir = Join-Path $pwd 'out/nupkg' | |
| $ridPatterns = @( | |
| 'CosmosDBShell.win-x64.*.nupkg', | |
| 'CosmosDBShell.win-arm64.*.nupkg', | |
| 'CosmosDBShell.linux-x64.*.nupkg', | |
| 'CosmosDBShell.linux-arm64.*.nupkg', | |
| 'CosmosDBShell.osx-x64.*.nupkg', | |
| 'CosmosDBShell.osx-arm64.*.nupkg' | |
| ) | |
| foreach ($pattern in $ridPatterns) { | |
| $matches = Get-ChildItem -Path (Join-Path $pkgDir $pattern) -ErrorAction SilentlyContinue | |
| if (-not $matches -or $matches.Count -eq 0) { | |
| Write-Error "Expected package was not generated: $pattern" | |
| exit 1 | |
| } | |
| } | |
| $allPackages = Get-ChildItem -Path (Join-Path $pkgDir 'CosmosDBShell.*.nupkg') -ErrorAction SilentlyContinue | |
| $pointerPackages = $allPackages | Where-Object { | |
| $_.Name -notmatch '^CosmosDBShell\.(win-x64|win-arm64|linux-x64|linux-arm64|osx-x64|osx-arm64)\..+\.nupkg$' | |
| } | |
| if (-not $pointerPackages -or $pointerPackages.Count -ne 1) { | |
| $names = @($pointerPackages | ForEach-Object { $_.Name }) | |
| Write-Error "Expected exactly one pointer package (non-RID). Found: $($names -join ', ')" | |
| exit 1 | |
| } | |
| $anyMatches = Get-ChildItem -Path (Join-Path $pkgDir 'CosmosDBShell.any.*.nupkg') -ErrorAction SilentlyContinue | |
| if ($anyMatches -and $anyMatches.Count -gt 0) { | |
| $names = $anyMatches | ForEach-Object { $_.Name } | Sort-Object | |
| Write-Error "Unexpected any-RID package(s) found: $($names -join ', ')" | |
| exit 1 | |
| } | |
| - name: List packaged NuGet files | |
| shell: pwsh | |
| run: | | |
| Get-ChildItem -Path out/nupkg -Filter *.nupkg -File | Sort-Object Name | ForEach-Object { | |
| Write-Host " - $($_.Name) [$($_.Length) bytes]" | |
| } | |
| - name: Write package install summary | |
| shell: pwsh | |
| run: | | |
| $summary = $env:GITHUB_STEP_SUMMARY | |
| $version = '${{ steps.version.outputs.package_version }}' | |
| $artifactSuffix = '${{ steps.version.outputs.artifact_suffix }}' | |
| $branchName = '${{ github.ref_name }}' | |
| $lines = @( | |
| '## NuGet packages', | |
| '', | |
| ('- Branch: `' + $branchName + '`'), | |
| ('- Preview version: `' + $version + '`'), | |
| '', | |
| 'Artifacts:', | |
| ('- `CosmosDBShell-pointer-' + $artifactSuffix + '`'), | |
| ('- `CosmosDBShell-win-x64-' + $artifactSuffix + '`'), | |
| ('- `CosmosDBShell-win-arm64-' + $artifactSuffix + '`'), | |
| ('- `CosmosDBShell-linux-x64-' + $artifactSuffix + '`'), | |
| ('- `CosmosDBShell-linux-arm64-' + $artifactSuffix + '`'), | |
| ('- `CosmosDBShell-osx-x64-' + $artifactSuffix + '`'), | |
| ('- `CosmosDBShell-osx-arm64-' + $artifactSuffix + '`'), | |
| '', | |
| 'Download the pointer package artifact and the artifact for your runtime, extract both `.nupkg` files to the same local folder, then install the base package:', | |
| '', | |
| '```powershell', | |
| 'dotnet tool install --global CosmosDBShell --add-source C:\path\to\nupkgs --version ' + $version, | |
| '```' | |
| ) | |
| $lines -join "`n" | Out-File -FilePath $summary -Encoding utf8 -Append | |
| - name: Upload pointer package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-pointer-${{ steps.version.outputs.artifact_suffix }} | |
| path: | | |
| out/nupkg/CosmosDBShell.*.nupkg | |
| !out/nupkg/CosmosDBShell.win-x64.*.nupkg | |
| !out/nupkg/CosmosDBShell.win-arm64.*.nupkg | |
| !out/nupkg/CosmosDBShell.linux-x64.*.nupkg | |
| !out/nupkg/CosmosDBShell.linux-arm64.*.nupkg | |
| !out/nupkg/CosmosDBShell.osx-x64.*.nupkg | |
| !out/nupkg/CosmosDBShell.osx-arm64.*.nupkg | |
| if-no-files-found: error | |
| - name: Upload win-x64 package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-win-x64-${{ steps.version.outputs.artifact_suffix }} | |
| path: out/nupkg/CosmosDBShell.win-x64.*.nupkg | |
| if-no-files-found: error | |
| - name: Upload win-arm64 package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-win-arm64-${{ steps.version.outputs.artifact_suffix }} | |
| path: out/nupkg/CosmosDBShell.win-arm64.*.nupkg | |
| if-no-files-found: error | |
| - name: Upload linux-x64 package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-linux-x64-${{ steps.version.outputs.artifact_suffix }} | |
| path: out/nupkg/CosmosDBShell.linux-x64.*.nupkg | |
| if-no-files-found: error | |
| - name: Upload linux-arm64 package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-linux-arm64-${{ steps.version.outputs.artifact_suffix }} | |
| path: out/nupkg/CosmosDBShell.linux-arm64.*.nupkg | |
| if-no-files-found: error | |
| - name: Upload osx-x64 package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-osx-x64-${{ steps.version.outputs.artifact_suffix }} | |
| path: out/nupkg/CosmosDBShell.osx-x64.*.nupkg | |
| if-no-files-found: error | |
| - name: Upload osx-arm64 package | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CosmosDBShell-osx-arm64-${{ steps.version.outputs.artifact_suffix }} | |
| path: out/nupkg/CosmosDBShell.osx-arm64.*.nupkg | |
| if-no-files-found: error |