Instructions pas à pas pour la configuration et l'utilisation de Gitlab CI + Visual Studio pour créer une application .NET Framework

Par nature, de nombreux développeurs trop paresseuxn'aime pas refaire la même action encore et encore. Il est plus facile pour nous d'apprendre à un ordinateur à faire des actions monotones à notre place.







Dès qu'un membre de notre équipe apporte des modifications au code (lisez "fusionner une branche de fonctionnalité dans develop"), notre serveur de build:







  • Construit le code source et le programme d'installation de l'application

    • consigne le numéro d'assemblage, en augmentant à chaque fois le dernier chiffre. Par exemple, la version actuelle de notre logiciel 3.3.0.202 - partie 3.3.0 a été une fois introduite par le développeur (bonjour, SemVer ), et "202" est déposé pendant le processus d'assemblage.
    • Dans le processus, il analyse la qualité du code (à l'aide de SonarQube) - et envoie un rapport au SonarQube interne,
  • Immédiatement après l'assemblage, il lance des autotests (xUnit) et analyse la couverture des tests (OpenCover),


En outre, en fonction de la branche à laquelle les modifications ont été apportées, les opérations suivantes peuvent être effectuées:







  • envoyer un assemblage (avec un changelog) à un ou plusieurs canaux de télégramme (il est parfois plus pratique de prendre des assemblages à partir de là)
  • publier des fichiers sur le système de mise à jour automatique du logiciel.


Ci-dessous, vous trouverez comment nous avons appris à Gitlab CI à faire la plupart de ce travail morne pour nous.







Table des matières



  1. Installez et enregistrez Gitlab Runner .
  2. .gitlab-ci.yml .
  3. Developer PowerShell for VS.
  4. CI .
  5. SonarQube.
  6. «» xUnit + OpenCover.
  7. .




, , github , WPF unit-, . gitlab.com , .







Gitlab Runner



Gitlab CI - , Gitlab Runner , . .Net Framework Windows.







Gitlab Runner, :







  1. Git Windows git.
  2. Visual Studio Microsoft. Build Tools Visual Studio 2019. , Visual Studio 2019.
  3. C:\GitLab-Runner gitlab runner. [ Gitlab] (https://docs.gitlab.com/runner/install/windows.html) — : «Download the binary for x86 or amd64».
  4. cmd powershell , C:\GitLab-Runner install (Gitlab runner ).

        .\gitlab-runner.exe install
          
          



  5. Runner-. , Runner:

    • Settings > CI/CD Runners,
    • Settings > CI/CD Runners,
    • Gitlab- — , Overview > Runners.
  6. Runner-,

        .\gitlab-runner.exe register
          
          





Runner-:







  • coordinator URL — http https gitlab;
  • gitlab-ci token — , ;
  • gitlab-ci description — Runner-, Gitlab-;
  • gitlab-ci tags — Runner-. , — gitlab-. , Runner- (, Runner-, Windows, Runner- Linux);
  • enter the executorshell



    . , ; shell windows powershell, .


.gitlab-ci.yml



Gitlab CI , .gitlab-ci.yml



, .







.gitlab-ci.yml



.NET Framework : 1, 2. :







variables:
  #        ;     ,   
  MSBUILD_CONCURRENCY: 4
  #     ,     ,  
  NUGET_PATH: 'C:\Tools\Nuget\nuget.exe'
  MSBUILD_PATH: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\msbuild.exe'
  XUNIT_PATH: 'C:\Tools\xunit.runner.console.2.3.1\xunit.console.exe'
  TESTS_OUTPUT_FOLDER_PATH: '.\tests\CiCdExample.Tests\bin\Release\'

#    .      ,      : build, test  deploy.
#      .
stages:
  - build
  - test

#    (job-)

build_job:
  stage: build # ,     build
  # tags: windows #    ,      Runner-    
  only: #      
    - branches
  script: #  
    - '& "$env:NUGET_PATH" restore'
    - '& "$env:MSBUILD_PATH" /p:Configuration=Release /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly' # ;  clp:ErrorsOnly   ;  nr:false   msbuild 
  artifacts: #      ,     gitlab (.. )         
    expire_in: 2 days #   
    paths: #  ,      
      - '$env:TESTS_OUTPUT_FOLDER_PATH'

test_job:
  stage: test
  only:
    - branches
  script:
    - '& "$env:XUNIT_PATH" "$env:TESTS_OUTPUT_FOLDER_PATH\CiCdExample.Tests.dll"'
  dependencies: # ,          build_job
    - build_job
      
      





: , (, -), gitlab. ( ) Settings > CI/CD Variables. (key) SAMPLE_PARAMETER, .gitlab-ci.yml $env:SAMPLE_PARAMETER.







( Protected) / ( Masked).







Gitlab CI.







Developer PowerShell for VS



, , . , : Visual Studio. , - Visual Studio 2017 BuildTools, Visual Studio Professional 2019, .







, Visual Studio 2017 Visual Studio . vswhere, Visual Studio, . Visual Studio 2019 ( 16.1 ) , «» Powershell Developer Powershell, VS.













Variables:







variables:
  VSWHERE_PATH: '%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe'
      
      





before_msbuild enter_vsdevshell :







.before_msbuild: &enter_vsdevshell
  before_script:
    - '$vsWherePath = [System.Environment]::ExpandEnvironmentVariables($env:VSWHERE_PATH)'
    - '& $vsWherePath -latest -format value -property installationPath -products Microsoft.VisualStudio.Product.BuildTools | Tee-Object -Variable visualStudioPath'
    - 'Join-Path "$visualStudioPath" "\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" | Import-Module'
    - 'Enter-VsDevShell -VsInstallPath:"$visualStudioPath" -SkipAutomaticLocation'
      
      





, Visual Studio, . :







build_job:
  <<: *enter_vsdevshell
  stage: build
  only:
    - branches
  script:
    - 'msbuild /t:restore /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly'
    - 'msbuild /p:Configuration=Release /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly'
  artifacts:
    expire_in: 2 days
    paths:
      - '$env:TESTS_OUTPUT_FOLDER_PATH'
      
      





, .before_msbuild
  1. vswhere.exe Visual Studio. ( VSWHERE_PATH). %programfiles%



    , . .NET System.Environment.ExpandEnvironmentVariables.


: vswhere.







  1. vswhere Visual Studio.

    , vswhere.exe



    -help



    , :

    • -latest ( ),
    • -property installationPath ( ),
    • -format value ( , ),
    • -products < Visual Studio, > ( Visual Studio). , -products Microsoft.VisualStudio.Product.Community Microsoft.VisualStudio.Product.BuildTools



      Visual Studio Community BuildTools. https://aka.ms/vs/workloads.


: $visualStudioPath Visual Studio , Visual Studio ( ).







  1. Import-Module Microsoft.VisualStudio.DevShell.dll, Powershell Developer-. Join-Path Visual Studio.

    , Microsoft.VisualStudio.DevShell.dll Visual Studio — Import-Module , .


: Powershell .







  1. «» Developer Powershell. , Visual Studio ( -VsInstallPath



    ). SkipAutomaticLocation



    ( < >\source\repos



    ).


: Developer Powershell msbuild , .







CI



t4 : <major>.<minor>.<revision>



, Gitlab CI tt-, , , . — git tag



git describe



.







git tag



(). . , . , . git rebase git commit --amend, , . git book.







git describe



, , gitbook . : . — fatal: No tags can describe '< >'



. — , , .







: , gitflow - finish hotfix finish release. gitflow, ( ).







, gitflow, feature- develop , develop:







N'oubliez pas de recréer les branches de develop

( git : - 1.0.5, git describe



)







. gitflow ( rebase-), master feature- develop, merge- master develop .







msbuild :







build_job:
  <<: *enter_vsdevshell
  stage: build
  only:
    - branches
  script:
    - 'msbuild /t:restore /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly'
    - '$versionGroup = git describe --long | Select-String -Pattern "(?<major>[0-9]+)\.(?<minor>[0-9]*)\.(?<patch>[0-9]*)\-(?<commit>[0-9]+)\-g[0-9a-f]+" | Select-Object -First 1'
    - '[int]$major, [int]$minor, [int]$patch, [int]$commit = $versionGroup.Matches[0].Groups["major", "minor", "patch", "commit"].Value'
    - '[string]$version = "$major.$minor.$patch.$commit"'
    - 'msbuild /p:Configuration=Release /p:AssemblyVersionNumber=$version /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly'
  artifacts:
    expire_in: 2 days
    paths:
      - '$env:TESTS_OUTPUT_FOLDER_PATH'
      
      





:







  1. <major>.<minor>.<revision>



    .
  2. git describe --long



    , <major>.<minor>.<revision>-< >-g< >



    .
  3. , — $versionGroup



    .
  4. 4 $major



    , $minor



    , $patch



    , $commit



    , .
  5. msbuild .


: , gitflow, () master release hofix, : . , 3.4, release- 3.5. : , master, , 3.4.







SonarQube



SonarQube — .







SonarQube Community-, . , . (develop), (, SonarQube):







  1. SonarQube , .
  2. SonarScanner for MSBuild ( sonarqube.org)[https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-msbuild/] — .NET Framework 4.6+.
  3. . , C:\Tools\SonarScanner



    .

    : NuGet, - .
  4. CI/CD Gitlab :

    • SONARQUBE_PROJECT_KEY — ,
    • SONARQUBE_AUTH_TOKEN — .



      ( ). ( Masked) , .
  5. Variables:

        variables:
          SONARSCANNER_MSBUILD_PATH: 'C:\Tools\SonarScanner\SonarScanner.MSBuild.exe'
          SONARQUBE_HOST_URL: 'url   SonarQube'
          
          



  6. (test_job) build_job:

        test_job:
          stage: test
          only:
            - /^develop$/
          <<: *enter_vsdevshell
          script:
            - '$versionGroup = git describe --long | Select-String -Pattern "(?<major>[0-9]+)\.(?<minor>[0-9]*)\.(?<patch>[0-9]*)\-(?<commit>[0-9]+)\-g[0-9a-f]+" | Select-Object -First 1'
            - '[int]$major, [int]$minor, [int]$patch, [int]$commit = $versionGroup.Matches[0].Groups["major", "minor", "patch", "commit"].Value'
            - '[string]$version = "$major.$minor.$patch.$commit"'
            - '& "$env:SONARSCANNER_MSBUILD_PATH" begin /key:$env:SONARQUBE_PROJECT_KEY /d:sonar.host.url=$env:SONARQUBE_HOST_URL /d:sonar.login=$env:SONARQUBE_AUTH_TOKEN /d:sonar.gitlab.project_id=$CI_PROJECT_PATH /d:sonar.gitlab.ref_name=develop /v:$version /d:sonar.dotnet.excludeGeneratedCode=true'
            - 'msbuild /t:rebuild /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly'
            - '& "$env:SONARSCANNER_MSBUILD_PATH" end /d:sonar.login=$env:SONARQUBE_AUTH_TOKEN'
            - '& "$env:XUNIT_PATH" "$env:TESTS_OUTPUT_FOLDER_PATH\CiCdExample.Tests.dll"'
          
          





develop SonarQube .







: msbuild /t:rebuild



. , . .







:







  • key — SonarQube,
  • v — . ,
  • sonar.gitlab.project_id — ID Gitlab,
  • sonar.gitlab.ref_name — , SonarQube ,
  • sonar.dotnet.excludeGeneratedCode — , System.CodeDom.Compiler.GeneratedCode ( ).


«» xUnit + OpenCover



- — . , :







  • ,
  • xUnit,
  • OpenConver,
  • SonarQube.


: OpenCover ReportGenerator, SonarQube .







:







  1. OpenCover zip- github.
  2. . , C:\Tools\OpenCover



    .

    : NuGet, - .
  3. Variables:

        variables:
          OBJECTS_TO_TEST_REGEX: '^Rt[^\n]*\.(dll|exe)$'
          OPENCOVER_PATH: 'C:\Tools\opencover-4.7.922\xunit.console.exe'
          OPENCOVER_FILTER: '+[Rt.*]* -[*UnitTests]* -[*AssemblyInfo]*'
          OPENCOVER_REPORT_FILE_PATH: '.\cover.xml'
          
          



  4. (test_job), OpenCover:

        test_job:
          stage: test
          only:
            - /^develop$/
          <<: *enter_vsdevshell
          script:
            - '$versionGroup = git describe --long | Select-String -Pattern "(?<major>[0-9]+)\.(?<minor>[0-9]*)\.(?<patch>[0-9]*)\-(?<commit>[0-9]+)\-g[0-9a-f]+" | Select-Object -First 1'
            - '[int]$major, [int]$minor, [int]$patch, [int]$commit = $versionGroup.Matches[0].Groups["major", "minor", "patch", "commit"].Value'
            - '[string]$version = "$major.$minor.$patch.$commit"'
            - '& "$env:SONARSCANNER_MSBUILD_PATH" begin /key:$env:SONARQUBE_PROJECT_KEY /d:sonar.host.url=$env:SONARQUBE_HOST_URL /d:sonar.login=$env:SONARQUBE_AUTH_TOKEN /d:sonar.gitlab.project_id=$CI_PROJECT_PATH /d:sonar.gitlab.ref_name=develop /v:$version /d:sonar.cs.opencover.reportsPaths="$env:OPENCOVER_REPORT_FILE_PATH" /d:sonar.dotnet.excludeGeneratedCode=true'
            - 'msbuild /t:rebuild /m:$env:MSBUILD_CONCURRENCY /nr:false /clp:ErrorsOnly'
            - '$dllsToRunUnitTesting = @(Get-ChildItem "$env:TESTS_OUTPUT_FOLDER_PATH" -Recurse) | Where-Object {$_.Name -match $env:OBJECTS_TO_TEST_REGEX} | ForEach-Object { """""$_""""" } | Join-String -Separator " "'
            - '& "$env:OPENCOVER_PATH" -register -target:"$env:XUNIT_PATH" -targetargs:"$dllsToRunUnitTesting -noshadow" -filter:"$env:OPENCOVER_FILTER" -output:"$env:OPENCOVER_REPORT_FILE_PATH" | Write-Host'
            - 'if ($?) {'
            - '[xml]$coverXml = Get-Content "$env:OPENCOVER_REPORT_FILE_PATH"'
            - '$sequenceCoverage = $coverXml.CoverageSession.Summary.sequenceCoverage'
            - '$branchCoverage = $coverXml.CoverageSession.Summary.branchCoverage'
            - 'Write-Host "Total Sequence Coverage <!<$sequenceCoverage>!>"'
            - 'Write-Host "Total Branch Coverage [![$branchCoverage]!]"'
            - '} else {'
            - 'Write-Host "One or more tests failed!"'
            - 'Throw'
            - '}'
            - '& "$env:SONARSCANNER_MSBUILD_PATH" end /d:sonar.login=$env:SONARQUBE_AUTH_TOKEN'
          
          





    : begin- sonar scanner- — /d:sonar.cs.opencover.reportsPaths



    .







    ( ) Gitlab, Settings > CI/CD Test coverage parsing



    . , Gitlab- :

    • ( Sequence Coverage Statement Coverage), <!<([^>]+)>!>



      ,
    • ( Decision Coverage Branch Coverage), \[!\[([^>]+)\]!\]



      .





All Articles