نسخه بروزرسانی خودکار – جامعه dev

به عنوان توسعه دهندگان ، ما نمی خواهیم وقت خود را در نسخه ها هدر دهیم و یکی از چالش ها با انتشار خودکار ، به روزرسانی شماره نسخه است.
تعهدات متعارف
در چندین شرکت من وب سایت متعهد متعارف را معرفی کرده ام. این به ما امکان می دهد تا به راحتی نوع تغییر در عنوان تعهد خود را اضافه کنیم.
اگر هر توسعه دهنده از این کنوانسیون ها استفاده می کند ، می توانید نسخه سازی را در خط لوله خودکار کنید ، و این همان کاری است که من حدود دو سال پیش انجام دادم. من به شما نشان خواهم داد که چگونه
اول از همه ، باید اعتراف کنم که من یک گورو PowerShell نیستم ، بنابراین اگر این پست به شما کمک کرده است ، اسکریپت ها را بهبود بخشید.
اکنون اجازه می دهیم با تمام مراحل مورد نیاز ما شروع کنیم و پس از استفاده از یک خط لوله نمونه چه راهی بهتر.
منطق شماره پچ
ما نام پیش فرض خط لوله را روی $ (تاریخ: yyymmmdd) $ (Rev: RR) تنظیم کردیم ، بنابراین می توانیم از این به عنوان شماره پچ استفاده کنیم. این چند مزیت به ما می دهد:
- بدون نیاز به 1+ یا تنظیم مجدد به 0 منطق
- ما همیشه می دانیم چه زمانی نسخه ای منتشر می شود
اکنون محدودیت هایی در این مورد وجود دارد ، حداقل در صورت ایجاد یک بسته NUGET:
- قطعات نسخه در Nuget عدد صحیح هستند ، بنابراین نسخه حداکثر 2147483647 است
- محدودیت 99 نسخه در روز است
- این منطق از سال 2148 شکست خواهد خورد. این اشکال جدید Y2K خواهد بود!
# 2147483647
# yyyyMMddrr
name: $(date:yyyyMMdd)$(rev:rr)
variables:
system_accesstoken: $(System.AccessToken)
projectName: 'name'
isMaster: $[eq(variables['Build.SourceBranch'], 'refs/heads/master')]
trigger:
- master
استفاده مجدد از اسکریپت ها
پس از نوشتن و آزمایش اسکریپت ها (جزئیات بعداً در وبلاگ) اسکریپت ها را در یک مخزن دیگر قرار دادیم ، بنابراین آنها قابل استفاده مجدد هستند
resources:
repositories:
- repository: repoName
type: git
name: TeamProjectName/repoName
هیچ کس کامل نیست
گاهی اوقات یک توسعه دهنده (جدید) فراموش می کند که کنوانسیون را اضافه کند. بنابراین ما دو پارامتر اضافی اضافه کردیم تا هنگام اجرای یک خط لوله به صورت دستی ، نوع انتشار را تنظیم کنیم.
parameters:
- name: buildConfiguration
type: string
default: 'Release'
version
- name: releaseNewVersion
type: boolean
default: false
- name: newVersionType
type: string
default: 'patch'
values:
- patch
- minor
- major
به این ترتیب هنگام شروع کار به صورت دستی به نظر می رسد
برچسب verion در git
اسکریپت های ما نسخه جدید را به عنوان برچسب برای git می نویسند. این بدان معنی است که خط لوله برای فشار به مخزن به مجوز نیاز دارد.
steps:
- checkout: self
displayName: "Git checkout with allow scripts to access the system token for pushing"
persistCredentials: true
clean: true
fetchDepth: 0
جریان اسکریپت ها
در اینجا می توانید تمام اسکریپت هایی را که ما ساخته ایم و نحوه تماس با آنها در خط لوله مشاهده کنید.
- template: scriptsFolderName/set-latest-version-in-variables.yml@repoName
- template: scriptsFolderName/update-version-variables.yml@repoName
parameters:
overruleNewVersion: ${{ parameters.ReleaseNewVersion }}
newVersionType: ${{ parameters.newVersionType }}
- template: scriptsFolderName/create-git-tag.yml@repoName
- template: scriptsFolderName/update-version-in-project-file.yml@repoName
parameters:
buildConfiguration: ${{ parameters.buildConfiguration }}
- template: scriptsFolderName/default-build.yml@repoName
parameters:
buildConfiguration: ${{ parameters.buildConfiguration }}
- template: scriptsFolderName/push-new-version.yml@repoName
parameters:
buildConfiguration: ${{ parameters.buildConfiguration }}
- powershell: |
$newVersion = "$($(Major)).$($(Minor)).$($(Patch))"
Write-Host "##vso[build.updatebuildnumber]$newVersion"
displayName: 'Rename pipeline to new version'
condition: and(succeeded(), eq(variables.isRelease, 'true'))
تنظیم آخرین نسخه
برای تنظیم آخرین نسخه ، آخرین برچسب را دریافت می کنیم. وقتی هیچ برچسب در دسترس نیست ، از نسخه 0.0.0 استفاده می کنیم.
وقتی این اسکریپت را پیاده سازی می کنید اما می خواهید با نسخه بالاتر شروع کنید ، اگر قبلاً در دسترس نیست ، آن برچسب را ایجاد کنید.
پس از تنظیم نسخه کامل ، آن را به متغیرهای اصلی ، جزئی و پچ تقسیم کردیم که می توانیم بعداً در خط لوله به روز شویم.
#set-latest-version-in-variables.yml
steps:
- powershell: |
$latestVersion = git describe --tags --abbrev=0 2>$null
if ($latestVersion) {
echo "Current version: $($latestVersion)"
} else {
$latestVersion = "0.0.0"
echo "No tag was found. Using version 0.0.0 as a base."
}
$versionArray = $latestVersion -split "\."
$major = [int]$versionArray[0]
$minor = [int]$versionArray[1]
$patch = [int]$versionArray[2]
Write-Host "##vso[task.setvariable variable=Major]$major"
Write-Host "##vso[task.setvariable variable=Minor]$minor"
Write-Host "##vso[task.setvariable variable=Patch]$patch"
displayName: 'Get latest version and set variables'
condition: and(succeeded(), eq(variables.isMaster, 'true'))
افزایش شماره نسخه
جریان عادی این خواهد بود که اجرای به طور خودکار شروع شده و از کنوانسیون استفاده شده است ، به این معنی که عنوان تعهد با:
- رفع = پچ
- feat = جزئی
- Anytype! = عمده
ما این کار را با Regex انجام می دهیم و همچنین بخش های دیگری از پیام متعهد را می گیریم. چه کسی می داند ، شاید ما بتوانیم در آینده از آنها استفاده کنیم. برخی از نمونه هایی از نحوه بازگشت REGEX نتایج.
پس از این ، ما فقط نوع تغییر را بررسی می کنیم و نوع نسخه مربوطه را به روز می کنیم ، جایی که پچ همیشه به روز می شود.
ما برخی از چک های اضافی را برای قسمت اجرای دستی اضافه کردیم که منطق پیش فرض را برطرف می کند.
#update-version-variables.yml
parameters:
overruleNewVersion: false
newVersionType: ''
steps:
- powershell: |
$latestCommitTitle = git log -n 1 --pretty=format:"%s"
#Normalize title
$pattern = "^merged pr \d+:\s*(.*)"
$normalizedTitle = $latestCommitTitle.ToLower()
if($latestCommitTitle.ToLower() -match $pattern) {
$normalizedTitle = $matches[1]
}
$pattern = "(?\w+)(?(?:\([^()\r\n]*\)|\()?(?!)?)(?:.*)?"
$normalizedTitle -match $pattern
echo "type: $($matches["type"])"
echo "scope: $($matches["scope"])"
echo "breaking: $($matches["breaking"])"
echo "subject: $($matches["subject"])"
$major = [int]$(Major)
$minor = [int]$(Minor)
$patch = $(Patch)
$changed = $false
if('${{ parameters.overruleNewVersion }}' -eq "true") {
echo '${{ parameters.newVersionType }}'
$changed = $true
if('${{ parameters.newVersionType }}' -eq "major") {
echo "breaking change"
$major += 1
$minor = 0
}
elseif('${{ parameters.newVersionType }}' -eq "minor"){
echo "minor change"
$minor += 1
}
else{
echo "patch change"
}
}
else {
if($matches["breaking"] -ne $null) {
echo "breaking change"
$major += 1
$minor = 0
$changed = $true
}
elseif($matches["type"] -eq "feat"){
echo "minor change"
$minor += 1
$changed = $true
}
elseif($matches["type"] -eq "fix"){
echo "patch change"
$changed = $true
}
}
echo "Changed: $($changed)"
if($changed) {
Write-Host "##vso[task.setvariable variable=Major]$major"
Write-Host "##vso[task.setvariable variable=Minor]$minor"
Write-Host "##vso[task.setvariable variable=Patch]$(Build.BuildNumber)"
Write-Host "##vso[task.setvariable variable=IsRelease]true"
}
displayName: 'Check change type and update version'
condition: and(succeeded(), eq(variables.isMaster, 'true'))
ایجاد برچسب GIT
هنگامی که تغییری وجود داشت که نیاز به انتشار داشت ، متغیر ISReLease در آخرین اسکریپت تنظیم می شود و وقتی که هست ، ما فقط یک برچسب GIT جدید ایجاد می کنیم.
این تنها درصورتی کار خواهد کرد که مجوز GIT را در خط لوله تنظیم کنید persistCredentials: true
#create-git-tag.yml
steps:
- powershell: |
git tag "$($(Major)).$($(Minor)).$($(Patch))"
displayName: 'Create git tag'
condition: and(succeeded(), eq(variables.IsRelease, 'true'))
اختیاری: به روزرسانی پرونده پروژه
ما بسته های کتابخانه/NUGET را در .NET توسعه می دهیم ، بنابراین آخرین مرحله برای ما به روزرسانی پرونده .csproj خواهد بود. این اطمینان حاصل می کند که هنگام ساخت ، نسخه بسته Nuget صحیح خواهد بود.
همانطور که قبلاً نوشتم ، NUGET از یک عدد صحیح در هر نوع نسخه استفاده می کند. اما اگر عمیق تر به نظر برسیم ، چیز جالبی پیدا می کنیم. نوع در هر برچسب متفاوت است:
- بسته بندی: int32
- نسخه: int16 = 32.767
#update-version-in-project-file.yml
parameters:
projectName: ''
steps:
- powershell: |
$newVersionTag = git describe --tags --abbrev=0
echo "New version tag: $($newVersionTag)"
$projectName="$(projectName)"
$pattern = '^(.*?(|).*?)([0-9].[0-9]{1,2}.)(([0-9]{1,2})(-rc([0-9]{2}))?)(.*?)$'
$path = if (Test-Path -Path $projectName) {'{0}\*' -f $projectName } else { '*' }
$ProjectFileName="{0}.csproj" -f $projectName
$ProjectFiles = Get-ChildItem -Path $path -Include $ProjectFileName -Recurse
foreach ($file in $ProjectFiles)
{
echo "file: $($file)"
echo "file path $($file.PSPath)"
(Get-Content $file.PSPath) | ForEach-Object{
if($_ -match $pattern){
'{0}{1}{2}' -f $matches[1],$newVersionTag,$matches[8]
} else {
# Output line as is
$_
}
} | Set-Content $file.PSPath
}
displayName: 'Update version in project file'
condition: and(succeeded(), eq(variables.IsRelease, 'true'))
من امیدوارم که این به شما کمک کند تا بچه ها بتوانید روند نسخه سازی خود را خودکار کنید و نسخه های خود را ساده کنید. اگر سؤال دارید یا به کمک بیشتری نیاز دارید ، احساس راحتی کنید. برنامه نویسی مبارک! 😊