diff --git a/.gitignore b/.gitignore index 53a131bd..975fee1d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ /Splitio.Redis/bin /Splitio.Redis/obj /src/Splitio/bin -/src/Splitio/obj \ No newline at end of file +/src/Splitio/obj +.DS_Store \ No newline at end of file diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/dotnetclientrepo/input_sets/dotnetclient.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/dotnetclientrepo/input_sets/dotnetclient.yaml new file mode 100644 index 00000000..14fb9b3c --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/dotnetclientrepo/input_sets/dotnetclient.yaml @@ -0,0 +1,14 @@ +inputSet: + name: dotnet-client + identifier: dotnetclient + orgIdentifier: PROD + projectIdentifier: Harness_Split + pipeline: + identifier: dotnetclientrepo + properties: + ci: + codebase: + build: + type: PR + spec: + number: <+trigger.prNumber> diff --git a/.harness/pipeline.yaml b/.harness/pipeline.yaml new file mode 100644 index 00000000..9e534720 --- /dev/null +++ b/.harness/pipeline.yaml @@ -0,0 +1,319 @@ +pipeline: + name: dotnet-client-repo + identifier: dotnetclientrepo + projectIdentifier: Harness_Split + orgIdentifier: PROD + tags: {} + properties: + ci: + codebase: + connectorRef: fmegithubharnessgitops + repoName: dotnet-client + build: <+input> + stages: + - stage: + name: Build and Test + identifier: Build_and_Test + description: "" + type: CI + spec: + cloneCodebase: true + caching: + enabled: true + override: true + platform: + os: Windows + arch: Amd64 + runtime: + type: Cloud + spec: + size: flex + execution: + steps: + - step: + type: Run + name: Setup NET SDK + identifier: Setup_NET_SDK + spec: + shell: Powershell + command: |- + # Install .NET SDK (adjust version as needed) + Invoke-WebRequest -Uri "https://dot.net/v1/dotnet-install.ps1" -OutFile "dotnet-install.ps1" + .\dotnet-install.ps1 -Channel 9.0 -InstallDir "C:\dotnet" + $env:PATH = "C:\dotnet;$env:PATH" + dotnet --version + nuget install redis-64 -excludeversion -source http://www.nuget.org/api/v2/ + Redis-64\tools\redis-server.exe --service-install + Redis-64\tools\redis-server.exe --service-start + - step: + type: Run + name: Restore Dependencies + identifier: Restore_Dependencies + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet restore + - step: + type: Run + name: Install SonarQube + identifier: Install_SonarQube + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet tool install --tool-path c:\dotnet -v diag dotnet-sonarscanner + dotnet tool list -g + - step: + type: Run + name: SonarQube Begin Analysis + identifier: SonarQube_Begin_Analysis + spec: + shell: Powershell + command: |- + ls C:\dotnet + $env:PATH = "C:\dotnet;C:\dotnet\tools;$env:PATH" + dotnet-sonarscanner begin ` + /k:"dotnet-client" ` + /d:sonar.host.url="https://sonar.harness.io/" ` + /d:sonar.token="<+secrets.getValue("sonarqube-token")>" ` + /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" ` + /d:sonar.coverage.exclusions="**/*Tests*/**,**/bin/**,**/obj/**" ` + /d:sonar.exclusions="**/bin/**,**/obj/**,**/*.dll,**/*.pdb" ` + /d:sonar.sourceEncoding="UTF-8" + - step: + type: Run + name: Build + identifier: Build + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet build --configuration Release --no-restore + - step: + type: Run + name: Run tests with coverage + identifier: Run_tests_with_coverage + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet test .\tests\Splitio-tests\Splitio-tests.csproj ` + -c Release ` + -f net9.0 ` + --no-build ` + --collect:"XPlat Code Coverage" ` + --results-directory:"./TestResults" ` + -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover + - step: + type: Run + name: SonarQube End Analysis + identifier: SonarQube_End_Analysis + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet sonarscanner end /d:sonar.token="<+secrets.getValue("sonarqube-token")>" + - step: + type: Run + name: Post Quality Gate + identifier: Post_Quality_Gate + spec: + shell: Powershell + command: |- + $scriptContent = @' + param( + [Parameter(Mandatory=$true)] + [string]$GitHubToken, + + [Parameter(Mandatory=$true)] + [string]$GitHubRepo, # Format: "owner/repo" + + [Parameter(Mandatory=$true)] + [string]$CommitSha, + + [Parameter(Mandatory=$true)] + [string]$SonarProjectKey, + + [Parameter(Mandatory=$true)] + [string]$SonarToken, + + [Parameter(Mandatory=$true)] + [string]$SonarUrl # e.g., "https://sonarcloud.io" or your SonarQube server + ) + + # Function to get SonarQube quality gate status + function Get-SonarQualityGate { + param($ProjectKey, $Token, $ServerUrl) + + $headers = @{ + 'Authorization' = "Bearer $Token" + 'Content-Type' = 'application/json' + } + + try { + # Get project status + $statusUrl = "$ServerUrl/api/qualitygates/project_status?projectKey=$ProjectKey" + $response = Invoke-RestMethod -Uri $statusUrl -Headers $headers -Method Get + + return $response.projectStatus + } + catch { + Write-Error "Failed to get SonarQube quality gate status: $($_.Exception.Message)" + return $null + } + } + + # Function to post status to GitHub + function Post-GitHubStatus { + param($Token, $Repo, $Sha, $State, $Description, $Context, $TargetUrl) + + $headers = @{ + 'Authorization' = "token $Token" + 'Accept' = 'application/vnd.github.v3+json' + 'Content-Type' = 'application/json' + } + + $body = @{ + state = $State + description = $Description + context = $Context + target_url = $TargetUrl + } | ConvertTo-Json + Write-Host $Sha + $url = "https://api.github.com/repos/splitio/$Repo/statuses/$Sha" + + try { + $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Body $body + Write-Host "✅ Successfully posted status to GitHub" -ForegroundColor Green + return $response + } + catch { + Write-Error "Failed to post status to GitHub: $($_.Exception.Message)" + return $null + } + } + + # Main execution + Write-Host "🔍 Fetching SonarQube quality gate status..." -ForegroundColor Blue + + $qualityGate = Get-SonarQualityGate -ProjectKey $SonarProjectKey -Token $SonarToken -ServerUrl $SonarUrl + + if ($null -eq $qualityGate) { + Write-Error "Failed to retrieve quality gate status" + exit 1 + } + + # Determine GitHub status based on SonarQube quality gate + $githubState = switch ($qualityGate.status) { + "OK" { "success" } + "ERROR" { "failure" } + "WARN" { "success" } # You might want to change this to "failure" based on your requirements + default { "pending" } + } + + $description = switch ($qualityGate.status) { + "OK" { "✅ Quality gate passed" } + "ERROR" { "❌ Quality gate failed" } + "WARN" { "⚠️ Quality gate passed with warnings" } + default { "🔄 Quality gate status unknown" } + } + + # Add conditions details if available + if ($qualityGate.conditions) { + $failedConditions = $qualityGate.conditions | Where-Object { $_.status -eq "ERROR" } + if ($failedConditions.Count -gt 0) { + $description += " ($($failedConditions.Count) condition(s) failed)" + } + } + + # Construct target URL + $targetUrl = "$SonarUrl/dashboard?id=$SonarProjectKey" + + Write-Host "📊 Quality Gate Status: $($qualityGate.status)" -ForegroundColor Yellow + Write-Host "🎯 GitHub State: $githubState" -ForegroundColor Yellow + Write-Host "📝 Description: $description" -ForegroundColor Yellow + + # Post status to GitHub + Write-Host "📤 Posting status to GitHub..." -ForegroundColor Blue + + $result = Post-GitHubStatus -Token $GitHubToken -Repo $GitHubRepo -Sha $CommitSha -State $githubState -Description $description -Context "sonarqube/quality-gate" -TargetUrl $targetUrl + + if ($null -eq $result) { + Write-Error "Failed to post status to GitHub" + exit 1 + } + + Write-Host "🎉 Successfully posted SonarQube quality gate status to GitHub!" -ForegroundColor Green + + # Optional: Create detailed comment with quality gate details + if ($qualityGate.conditions) { + Write-Host "📋 Quality Gate Conditions:" -ForegroundColor Cyan + foreach ($condition in $qualityGate.conditions) { + $status = switch ($condition.status) { + "OK" { "✅" } + "ERROR" { "❌" } + "WARN" { "⚠️" } + default { "❓" } + } + Write-Host " $status $($condition.metricKey): $($condition.actualValue) (threshold: $($condition.errorThreshold))" -ForegroundColor White + } + } + '@ + $scriptContent | Out-File -FilePath "sonar-github-status.ps1" -Encoding UTF8 + + .\sonar-github-status.ps1 ` + -GitHubToken "<+secrets.getValue('github-devops-token')>" ` + -GitHubRepo "dotnet-client" ` + -CommitSha "<+codebase.commitSha>" ` + -SonarProjectKey "dotnet-client" ` + -SonarToken "<+secrets.getValue('sonarqube-token')>" ` + -SonarUrl "https://sonar.harness.io/" + - step: + type: Run + name: Run Other Tests Net 9 + identifier: Run_Other_Tests_Net_9 + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet test .\tests\Splitio.Integration-tests\Splitio.Integration-tests.csproj -f net9.0 -c Release --no-build + dotnet test .\tests\Splitio.Integration-events-tests\Splitio.Integration-events-tests.csproj -f net9.0 -c Release --no-build + dotnet test .\tests\Splitio.Integration-redis-tests\Splitio.Integration-redis-tests.csproj -f net9.0 -c Release --no-build + dotnet test .\tests\Splitio.TestSupport\Splitio.TestSupport.csproj -c Release -f net9.0 --no-build + - step: + type: Run + name: Run unit tests Net 472 + identifier: Run_unit_tests_Net_8 + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet test .\tests\Splitio.Integration-tests\Splitio.Integration-tests.csproj -f net472 -c Release --no-build + dotnet test .\tests\Splitio.Integration-events-tests\Splitio.Integration-events-tests.csproj -f net472 -c Release --no-build + dotnet test .\tests\Splitio.Integration-redis-tests\Splitio.Integration-redis-tests.csproj -f net472 -c Release --no-build + dotnet test .\tests\Splitio.TestSupport\Splitio.TestSupport.csproj -c Release -f net472 --no-build + dotnet test .\tests\Splitio-tests\Splitio-tests.csproj -f net472 -c Release --no-build + contextType: Pipeline + - step: + type: Run + name: Create Nuget + identifier: Create_Nuget + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + if (!(Test-Path ".\nuget")) { mkdir .\nuget } + dotnet pack .\src\Splitio --configuration Release --output .\nuget + dotnet pack .\Splitio.Redis --configuration Release --output .\nuget + - step: + type: Run + name: Upload Nuget + identifier: Upload_Nuget + spec: + shell: Powershell + command: |- + $env:PATH = "C:\dotnet;$env:PATH" + dotnet nuget push '.\nuget\*.nupkg' -k $Env:API_KEY -s 'https://harness0.harness.io/pkg/l7B_kbSEQD2wjrM7PShm5w/fme-nuget/nuget/' + envVariables: + API_KEY: <+secrets.getValue("harness-ci-nuget-token")> diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 753988e8..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,43 +0,0 @@ -image: - - Visual Studio 2022 - -nuget: - account_feed: true - -version: 7.12.0 -dotnet_csproj: - patch: true - file: '**\*.csproj' - package_version: '{version}' - -skip_branch_with_pr: true - -configuration: Release - -before_build: - - choco install "sonarscanner-msbuild-net46" -y - - nuget install redis-64 -excludeversion -source http://www.nuget.org/api/v2/ - - Redis-64\tools\redis-server.exe --service-install - - dotnet restore -s https://www.nuget.org/api/v2/ - - cmd: set BUILD_VERSION=%APPVEYOR_BUILD_NUMBER% - -build_script: - - sonar-scanner.bat - - dotnet build -c Release - - Redis-64\tools\redis-server.exe --service-start - - dotnet test .\tests\Splitio-tests\Splitio-tests.csproj -c Release -f net9.0 --no-build --collect:"XPlat Code Coverage;Format=opencover" - - SonarScanner.MSBuild.exe end /d:sonar.login=%SONAR_LOGIN% - -test: on - -after_test: - - dotnet test .\tests\Splitio.Integration-tests\Splitio.Integration-tests.csproj -c Release -f net9.0 --no-build - - dotnet test .\tests\Splitio.Integration-events-tests\Splitio.Integration-events-tests.csproj -c Release -f net9.0 --no-build - - dotnet test .\tests\Splitio.Integration-redis-tests\Splitio.Integration-redis-tests.csproj -c Release -f net9.0 --no-build - - dotnet test .\tests\Splitio.TestSupport\Splitio.TestSupport.csproj -c Release -f net9.0 --no-build - - dotnet pack .\src\Splitio --configuration Release - - dotnet pack .\Splitio.Redis --configuration Release - -artifacts: - - path: '**\Splitio*.nupkg' - name: splitio-nuget diff --git a/sonar-scanner.bat b/sonar-scanner.bat deleted file mode 100644 index 5f3daf9b..00000000 --- a/sonar-scanner.bat +++ /dev/null @@ -1,50 +0,0 @@ -@echo off - -SET "JAVA_HOME=C:/Program Files/Java/jdk17" -setlocal EnableDelayedExpansion -GOTO :main - -:sonar_scanner -SonarScanner.MSBuild.exe begin ^ - /n:"dotnet-client" ^ - /k:"dotnet-client" ^ - /v:"%APPVEYOR_BUILD_VERSION%" ^ - /d:sonar.host.url="https://sonarqube.split-internal.com" ^ - /d:sonar.login="%SONAR_LOGIN%" ^ - /d:sonar.ws.timeout="300" ^ - /d:sonar.cs.opencover.reportsPaths="**\TestResults\*\*.xml" ^ - /d:sonar.coverage.exclusions="**-tests.cs" ^ - /d:sonar.links.ci="https://ci.appveyor.com/project/SplitDevOps/dotnet-client" ^ - /d:sonar.links.scm="https://github.com/splitio/dotnet-client" ^ - %* -EXIT /B 0 - -:main -IF NOT "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" ( - echo Pull Request number %APPVEYOR_PULL_REQUEST_NUMBER% - CALL :sonar_scanner ^ - "/d:sonar.pullrequest.provider="GitHub"" ^ - "/d:sonar.pullrequest.github.repository="splitio/dotnet-client"" ^ - "/d:sonar.pullrequest.key="%APPVEYOR_PULL_REQUEST_NUMBER%"" ^ - "/d:sonar.pullrequest.branch="%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"" ^ - "/d:sonar.pullrequest.base="%APPVEYOR_REPO_BRANCH%"" -) ELSE ( - IF "%APPVEYOR_REPO_BRANCH%"=="main" ( - echo "Main branch." - CALL :sonar_scanner ^ - "/d:sonar.branch.name="%APPVEYOR_REPO_BRANCH%"" - ) ELSE ( - IF "%APPVEYOR_REPO_BRANCH%"=="development" ( - echo "Development branch." - SET "TARGET_BRANCH=main" - ) ELSE ( - echo "Feature branch." - SET "TARGET_BRANCH=development" - ) - echo Branch Name is %APPVEYOR_REPO_BRANCH% - echo Target Branch is !TARGET_BRANCH! - CALL :sonar_scanner ^ - "/d:sonar.branch.name="%APPVEYOR_REPO_BRANCH%"" ^ - "/d:sonar.branch.target="!TARGET_BRANCH!"" - ) - )