рдпрд╛ рдЖрд░рд╛рдо рдХреЛрдбрд┐рдВрдЧ рдХреА рдПрдХ рд╢рд╛рдо рдореЗрдВ рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рд╕реБрдВрджрд░ рдмреИрдЬ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
рд╢рд╛рдпрдж рд╣рд░ рдбреЗрд╡рд▓рдкрд░ рдЬрд┐рд╕рдХреЗ рдкрд╛рд╕ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдкрд╛рд▓рддреВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╣реИ, рдХрд┐рд╕реА рд╕рдордп рд╕реНрдЯреЗрдЯрд╕, рдХреЛрдб рдХрд╡рд░реЗрдЬ, рдирдЧреЗрдЯ рдореЗрдВ рдкреИрдХреЗрдЬ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╕реБрдВрджрд░ рдмреИрдЬ рдХреА рдереАрдо рдкрд░ рдПрдХ рдЦреБрдЬрд▓реА рд╣реИ ... рдФрд░ рдЗрд╕ рдЦреБрдЬрд▓реА рдиреЗ рдореБрдЭреЗ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛ред рдЗрд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреА рддреИрдпрд╛рд░реА рдореЗрдВ, рдореБрдЭреЗ рдЕрдкрдиреА рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдРрд╕реА рд╕реБрдВрджрд░рддрд╛ рдорд┐рд▓реА:

рдпрд╣ рдЖрд▓реЗрдЦ GitLab рдореЗрдВ рдПрдХ .Net рдХреЛрд░ рдХреНрд▓рд╛рд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдирд┐рд░рдВрддрд░ рдПрдХреАрдХрд░рдг рдФрд░ рд╡рд┐рддрд░рдг рдХреЗ рдореВрд▓ рд╕реЗрдЯрдЕрдк рдХреЛ рдХрд╡рд░ рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ GitLab рдкреЗрдЬ рдореЗрдВ рдкреНрд░рд▓реЗрдЦрди рдХрд╛ рдкреНрд░рдХрд╛рд╢рди рд╣реЛрдЧрд╛ рдФрд░ рдПрдХрддреНрд░ рдХрд┐рдП рдЧрдП рдкреИрдХреЗрдЬ рдХреЛ Azure DevOps рдореЗрдВ рдПрдХ рдирд┐рдЬреА рдлреАрдб рдкрд░ рднреЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╡реАрдПрд╕ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧреАрддрд╛рд▓рд╛рдм рд╡рд░реНрдХрдлрд╝реНрд▓реЛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди (рд╡рд┐рдХрд╛рд╕ рдкрд░реНрдпрд╛рд╡рд░рдг рд╕реЗ рд╕реАрдзреЗ рд╕реЗрдЯрд┐рдВрдЧ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП) рдХреЗ рд╕рд╛рде рд╡рд┐рдХрд╛рд╕ рдХреЗ рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред
рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдкрд░рд┐рдЪрдп
рд╕реАрдбреА - рдпрд╣ рддрдм рд╣реИ рдЬрдм рдЖрдк рдмрд╕ рдзрдХреНрдХрд╛ рджрд┐рдпрд╛ рд╣реИ, рдФрд░ рдЧреНрд░рд╛рд╣рдХ рд╕рдм рдХреБрдЫ рдЧрд┐рд░ рдЧрдпрд╛ рд╣реИ?
CI / CD рдХреНрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдЧреВрдЧрд▓ рдХрд░рдирд╛ рдХреНрдпреЛрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реИред GitLab рдореЗрдВ рдкрд╛рдЗрдкрд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЗрд╕ рдкрд░ рдкреВрд░реНрдг рдкреНрд░рд▓реЗрдЦрди рднреА рдЖрд╕рд╛рди рд╣реИ ред рдпрд╣рд╛рдБ рдореИрдВ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдФрд░ рдЬрд╣рд╛рдБ рддрдХ рд╕рдВрднрд╡ рд╣реЛ рджреЛрд╖реЛрдВ рдХреЗ рдмрд┐рдирд╛ рдкрдХреНрд╖реА рдХреА рдирдЬрд╝рд░ рд╕реЗ рдкреНрд░рдгрд╛рд▓реА рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддрд╛ рд╣реВрдБ:
- , merge request , - ,
- , ,
- ,
- тАФ .. ,
- (.. ) тАФ ( ),
- , .
, :
- тАФ , , , , , , .,
- (stage) тАФ , 1+ ,
- (job) тАФ . (), , / .
, CI/CD , , , .
: ?, -, GitHub'e , тАФ . , GitHub.
тАФ . git тАФ , SSH- тАФ , .
:
:
:
- merge request,
- merge request ,
- Azure DevOps,
- GitLab Pages,
- !11
:
- 1 тАФ
- 2 тАФ
- 3 тАФ
- 1 тАФ nuget- Azure DevOps
- 2 тАФ xmldoc GitLab Pages
!
Microsoft Azure
Azure DevOps
- тАФ
- тАФ

Create , . , ( -> Overview -> Azure DevOps Services)

Atrifacts, Create feed
- Include packages from common public sources,
nuget

Connect to feed, Visual Studio, Machine Setup Source

, Personal Access Token

- тАФ
- тАФ
- тАФ 1
- (scope) тАФ Packaging/Read & Write

тАФ
GitLab, CI/CD

Variables,
- тАФ ( )
- тАФ . 9
- Mask variable

.
, CI/CD GitLab .gitlab-ci.yml
. , .
, YAML
. , , .
docker-, . .Net Core Docker Hub. GitHub , . .Net Core 3.1,
image: mcr.microsoft.com/dotnet/core/sdk:3.1
Microsoft , .
тАФ stage'. GitLab 5 :
.pre
тАФ ,.post
тАФ ,build
тАФ .pre
,test
тАФ ,deploy
тАФ .
, . , , , . , :
stages:
- build
- test
- deploy
, . , , before_script
:
before_script:
- $PSVersionTable.PSVersion
- dotnet --version
- nuget help | select-string Version
, . :
dummy job:
script:
- echo ok
, , , , , тАж тАФ bash: .PSVersion: command not found
. WTF?
тАФ runner' ( , GitLab') bash
. , , :
dummy job on windows:
script:
- echo ok
tags:
- windows
! .
, , , test
, . , test
.
, , :
build job:
script:
- echo "building..."
tags:
- windows
stage: build
test and cover job:
script:
- echo "running tests and coverage analysis..."
tags:
- windows
stage: test
pack and deploy job:
script:
- echo "packing and pushing to nuget..."
tags:
- windows
stage: deploy
pages:
script:
- echo "creating docs..."
tags:
- windows
stage: deploy
, .
- , , . , .
: only/except rules. , only/except
(merge_request
, тАФ , ) ( .. ); rules
, , (when
GitLab CI/CD).
тАФ merge request, Azure DevOps тАФ merge request , тАФ .
, merge request:
build job:
# snip
only:
- merge_request
merge request :
pack and deploy job:
# snip
only:
- merge_request
- master
, .
merge request :
rules:
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
; rules
only/except
.
build job
, . , , artifacts
:
build job:
# snip
artifacts:
paths:
- path/to/build/artifacts
- another/path
- MyCoolLib.*/bin/Release/*
wildcards, .
, тАФ , . .
, ( ) , .
, - , - , ( .net) . , 3 :
dotnet build
dotnet test
dotnet pack
, , - .
- , ,
-c Release
- , :
coverlet.msbuild
: dotnet add package coverlet.msbuild
/p:CollectCoverage=true
- (. )
- nuget- :
-o .
Coverlet :
Calculating coverage result...
Generating report 'C:\Users\xxx\source\repos\my-project\myProject.tests\coverage.json'
+-------------+--------+--------+--------+
| Module | Line | Branch | Method |
+-------------+--------+--------+--------+
| project 1 | 83,24% | 66,66% | 92,1% |
+-------------+--------+--------+--------+
| project 2 | 87,5% | 50% | 100% |
+-------------+--------+--------+--------+
| project 3 | 100% | 83,33% | 100% |
+-------------+--------+--------+--------+
+---------+--------+--------+--------+
| | Line | Branch | Method |
+---------+--------+--------+--------+
| Total | 84,27% | 65,76% | 92,94% |
+---------+--------+--------+--------+
| Average | 90,24% | 66,66% | 97,36% |
+---------+--------+--------+--------+
GitLab , . coverage
; capture-, :
test and cover job:
# snip
coverage: /\|\s*Total\s*\|\s*(\d+[,.]\d+%)/
.
тАФ , .
:
nuget (nuget.config
), : dotnet new nugetconfig
: ( ) . , .
- :
nuget sources add -name <name> -source <url> -username <organization> -password <gitlab variable> -configfile nuget.config -StorePasswordInClearText
name
тАФ ,url
тАФ URL " ", . 6organization
тАФ Azure DevOpsgitlab variable
тАФ , GitLab (" ", . 11). , $variableName
-StorePasswordInClearText
тАФ ( )-verbosity detailed
- :
nuget push -source <name> -skipduplicate -apikey <key> *.nupkg
- ,
*.nupkg
. name
тАФ .key
тАФ . Azure DevOps Connect to feed az
.-skipduplicate
тАФ 409 Conflict
; .
:
- , , master, docfx.
docfx init
. .
..\public
тАФ GitLab public Pages. .. тАФ .
- GitLab.
pages
( GitLab Pages):
- :
nuget install docfx.console -version 2.51.0
тАФ docfx; ..\docfx.console.2.51.0\tools\docfx.exe .\docfx_project\docfx.json
тАФ
- artifacts:
pages:
# snip
artifacts:
paths:
- public
docfx
. тАФ . , , metadata.src
:
{
"metadata": [
{
"src": [
{
"src": "../",
"files": [
"**/*.csproj"
],
"exclude":[
"*.tests*/**"
]
}
],
},
],
}
metadata.src.src: "../"
тАФ docfx.json
, .. .metadata.src.files: ["**/*.csproj"]
тАФ , C# .metadata.src.exclude: ["*.tests*/**"]
тАФ , .tests
, , , , README .
.gitlab-ci.ymlimage: mcr.microsoft.com/dotnet/core/sdk:3.1
before_script:
- $PSVersionTable.PSVersion
- dotnet --version
- nuget help | select-string Version
stages:
- build
- test
- deploy
build job:
stage: build
script:
- dotnet build -c Release
tags:
- windows
only:
- merge_requests
- master
artifacts:
paths:
- your/path/to/binaries
test and cover job:
stage: test
tags:
- windows
script:
- dotnet test -c Release /p:CollectCoverage=true
coverage: /\|\s*Total\s*\|\s*(\d+[,.]\d+%)/
only:
- merge_requests
- master
pack and deploy job:
stage: deploy
tags:
- windows
script:
- dotnet pack -c Release -o .
- dotnet new nugetconfig
- nuget sources add -name feedName -source https://pkgs.dev.azure.com/your-organization/_packaging/your-feed/nuget/v3/index.json -username your-organization -password $nugetFeedToken -configfile nuget.config -StorePasswordInClearText
- nuget push -source feedName -skipduplicate -apikey az *.nupkg
only:
- master
pages:
tags:
- windows
stage: deploy
script:
- nuget install docfx.console -version 2.51.0
- $env:path = "$env:path;$($(get-location).Path)"
- .\docfx.console.2.51.0\tools\docfx.exe .\docfx\docfx.json
artifacts:
paths:
- public
only:
- master
!
GitLab CI/CD Gtntral pipelines:

Shields.io тАФ , .


Azure DevOps Artifacts . Azure DevOps Create badge markdown-:


, YAML тАФ .
, windows
, / ( ). , :
.common_tags: &common_tags
tags:
- windows
.common_only: &common_only
only:
- merge_requests
- master
:
build job:
<<: *common_tags
<<: *common_only
, .
, тАФ ; Version, . , , , .
тАФ , . , тАФ , .
, release (v./ver./version) <version number> (rev./revision <revision>)?
, , dotnet pack
. тАФ .
:
$rx = "release\s+(v\.?|ver\.?|version)\s*(?<maj>\d+)(?<min>\.\d+)?(?<rel>\.\d+)?\s*((rev\.?|revision)?\s+(?<rev>[a-zA-Z0-9-_]+))?"
$found = $env:CI_COMMIT_MESSAGE -match $rx
if (!$found) { Write-Output "no release info found, aborting"; exit }
$maj = $matches['maj']
$min = $matches['min']
if ($matches.ContainsKey('rel')) { $rel = $matches['rel'] } else { $rel = ".$(get-date -format "yyyy")" }
$bld = $(get-date -format "MMdd")
if ($matches.ContainsKey('rev')) { $rev = "-$($matches['rev'])" } else { $rev = '' }
$version = "$maj$min$rel.$bld$rev"
dotnet pack -c Release -o . /p:Version=$version
pack and deploy job
.
- , powershell , , , .
рдмреЗрд╢рдХ, GitLab CI / CD рдЗрд╕ рдЧрд╛рдЗрдб рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж рд╢рд╛рдпрдж рдЕрдзрд┐рдХ рд╡реНрдпрд╛рдкрдХ рдФрд░ рдмрд╣реБрдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рд╣реИ - рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдРрд╕рд╛ рд╣реИ ред рд╡рд╣рд╛рдБ рднреА рдСрдЯреЛ DevOps рд╣реИ , рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ
рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрдиреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдВ, рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВ, рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ, рддреИрдирд╛рддреА рдХрд░реЗрдВ рдФрд░ рдЙрдирдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░реЗрдВ
рдЕрдм рдореИрдВ рдкреБрд▓рдореА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдЬрд╝реНрдпреЛрд░ рдореЗрдВ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рддреИрдирд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд▓рдХреНрд╖реНрдп рд╡рд╛рддрд╛рд╡рд░рдг рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реВрдВ, рдЬреЛ рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред