Skip to content

Commit b59a708

Browse files
authored
Merge pull request #35 from ntoskrnl7/codex/add-release-version-script
[codex] add release preparation helper
2 parents 8e4c65c + e8dbdf1 commit b59a708

4 files changed

Lines changed: 238 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: Release version, for example 0.1.13
8+
required: true
9+
type: string
10+
publish:
11+
description: Publish the generated package to nuget.org
12+
required: true
13+
type: boolean
14+
default: true
15+
github_release:
16+
description: Upload release assets to GitHub Releases
17+
required: true
18+
type: boolean
19+
default: true
20+
21+
permissions:
22+
contents: write
23+
actions: write
24+
25+
jobs:
26+
release:
27+
name: Prepare release and dispatch package workflow
28+
runs-on: windows-2022
29+
30+
steps:
31+
- uses: actions/checkout@v5
32+
with:
33+
ref: main
34+
fetch-depth: 0
35+
36+
- name: Configure release checkout
37+
shell: pwsh
38+
run: |
39+
git config user.name 'github-actions[bot]'
40+
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
41+
git fetch origin main --tags
42+
git checkout -B main origin/main
43+
44+
- name: Create version commit and tag
45+
shell: pwsh
46+
run: ./scripts/release/Prepare-CrtSysRelease.ps1 -Version '${{ inputs.version }}' -Push
47+
48+
- name: Dispatch Package workflow
49+
shell: pwsh
50+
env:
51+
GH_TOKEN: ${{ github.token }}
52+
run: |
53+
$version = '${{ inputs.version }}'
54+
$publish = '${{ inputs.publish }}'.ToLowerInvariant()
55+
$githubRelease = '${{ inputs.github_release }}'.ToLowerInvariant()
56+
$tagName = "v$version"
57+
58+
for ($attempt = 1; $attempt -le 6; $attempt++) {
59+
Write-Host "Dispatching Package workflow for $tagName (attempt $attempt)"
60+
& gh workflow run package.yml `
61+
--repo '${{ github.repository }}' `
62+
--ref $tagName `
63+
-f publish=$publish `
64+
-f github_release=$githubRelease
65+
66+
if ($LASTEXITCODE -eq 0) {
67+
Write-Host "Package workflow dispatch requested for $tagName."
68+
exit 0
69+
}
70+
71+
Start-Sleep -Seconds 10
72+
}
73+
74+
throw "Package workflow dispatch failed for $tagName."

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,23 @@ repository `crtsys`, workflow file `package.yml`, and no environment
269269
restriction. Set the GitHub Actions repository variable
270270
`NUGET_TRUSTED_PUBLISHING_USER` to the nuget.org user that created the policy.
271271

272+
To prepare a release without manually editing `include/.internal/version`, run
273+
the release helper from an up-to-date `main` branch:
274+
275+
```powershell
276+
.\scripts\release\Prepare-CrtSysRelease.ps1 -Version 0.1.13 -Push
277+
```
278+
279+
The helper updates `include/.internal/version`, commits the version bump,
280+
creates the matching `v0.1.13` tag, and pushes both the commit and tag. The tag
281+
push starts the `Package` workflow.
282+
283+
The same flow is also available from the GitHub UI: open **Actions**,
284+
select **Release**, choose **Run workflow**, and enter the release version. The
285+
workflow creates the version bump commit and tag, then dispatches the `Package`
286+
workflow for that tag. If branch protection blocks direct pushes to `main`, use
287+
the local helper or adjust the release rule first.
288+
272289
## Building This Repository
273290

274291
Clone the repository and build the test app and driver for the host

docs/ko-kr.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,23 @@ repository `crtsys`, workflow file `package.yml`, environment 제한 없음으
272272
`NUGET_TRUSTED_PUBLISHING_USER`에는 policy를 생성한 nuget.org 사용자를
273273
설정합니다.
274274

275+
`include/.internal/version`을 직접 수정하지 않고 release를 준비하려면 최신
276+
`main` branch에서 release helper를 실행합니다.
277+
278+
```powershell
279+
.\scripts\release\Prepare-CrtSysRelease.ps1 -Version 0.1.13 -Push
280+
```
281+
282+
이 helper는 `include/.internal/version`을 수정하고, version bump commit을
283+
만든 뒤, 대응되는 `v0.1.13` tag를 만들고 commit과 tag를 push합니다. tag
284+
push가 `Package` workflow를 시작합니다.
285+
286+
같은 흐름은 GitHub UI에서도 사용할 수 있습니다. **Actions**에서
287+
**Release**를 선택하고 **Run workflow**를 눌러 release version을 입력하면
288+
workflow가 version bump commit과 tag를 만들고, 그 tag 기준으로 `Package`
289+
workflow를 실행합니다. branch protection이 `main` 직접 push를 막는 경우에는
290+
로컬 helper를 사용하거나 release 규칙을 먼저 조정해야 합니다.
291+
275292
## 이 저장소 빌드
276293

277294
저장소를 clone한 뒤, 현재 호스트 아키텍처 기준으로 테스트 앱과 드라이버를
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
param(
2+
[Parameter(Mandatory = $true)]
3+
[ValidatePattern('^\d+\.\d+\.\d+$')]
4+
[string] $Version,
5+
6+
[string] $Branch = 'main',
7+
8+
[switch] $Push,
9+
10+
[switch] $AllowNonMainBranch
11+
)
12+
13+
Set-StrictMode -Version Latest
14+
$ErrorActionPreference = 'Stop'
15+
16+
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
17+
$versionHeader = Join-Path $repoRoot 'include\.internal\version'
18+
$tagName = "v$Version"
19+
20+
function Invoke-Git {
21+
param(
22+
[Parameter(ValueFromRemainingArguments = $true)]
23+
[string[]] $Arguments
24+
)
25+
26+
& git @Arguments
27+
if ($LASTEXITCODE -ne 0) {
28+
throw "git $($Arguments -join ' ') failed with exit code $LASTEXITCODE."
29+
}
30+
}
31+
32+
function Test-GitRefExists {
33+
param([string] $Ref)
34+
35+
& git rev-parse --verify --quiet $Ref *> $null
36+
return $LASTEXITCODE -eq 0
37+
}
38+
39+
Push-Location $repoRoot
40+
try {
41+
Invoke-Git rev-parse --show-toplevel *> $null
42+
43+
$currentBranch = (& git branch --show-current).Trim()
44+
if (-not $AllowNonMainBranch -and $currentBranch -ne $Branch) {
45+
throw "Release preparation must run on '$Branch'. Current branch is '$currentBranch'."
46+
}
47+
48+
Invoke-Git fetch origin $Branch --tags
49+
if (-not $AllowNonMainBranch) {
50+
$localHead = (& git rev-parse HEAD).Trim()
51+
$remoteHead = (& git rev-parse "origin/$Branch").Trim()
52+
if ($localHead -ne $remoteHead) {
53+
throw "Local '$Branch' must match origin/$Branch before preparing a release."
54+
}
55+
}
56+
57+
$status = (& git status --porcelain).Trim()
58+
if (-not [string]::IsNullOrWhiteSpace($status)) {
59+
throw "Working tree must be clean before preparing a release."
60+
}
61+
62+
if (Test-GitRefExists "refs/tags/$tagName") {
63+
throw "Local tag already exists: $tagName"
64+
}
65+
66+
& git ls-remote --exit-code --tags origin $tagName *> $null
67+
if ($LASTEXITCODE -eq 0) {
68+
throw "Remote tag already exists on origin: $tagName"
69+
}
70+
if ($LASTEXITCODE -ne 2) {
71+
throw "Could not check whether remote tag exists on origin: $tagName"
72+
}
73+
74+
$parts = $Version.Split('.')
75+
$major = $parts[0]
76+
$minor = $parts[1]
77+
$patch = $parts[2]
78+
79+
if (-not (Test-Path $versionHeader)) {
80+
throw "Version header was not found: $versionHeader"
81+
}
82+
83+
$currentVersion = (& (Join-Path $repoRoot 'scripts\nuget\Get-CrtSysVersion.ps1')).Trim()
84+
if ($currentVersion -eq $Version) {
85+
throw "Version header is already $Version."
86+
}
87+
88+
$content = Get-Content -LiteralPath $versionHeader -Raw
89+
$content = [regex]::Replace(
90+
$content,
91+
'(?m)^(#define\s+CRTSYS_VERSION_MAJOR\s+)\d+(\s*)$',
92+
{ param($match) "$($match.Groups[1].Value)$major$($match.Groups[2].Value)" })
93+
$content = [regex]::Replace(
94+
$content,
95+
'(?m)^(#define\s+CRTSYS_VERSION_MINOR\s+)\d+(\s*)$',
96+
{ param($match) "$($match.Groups[1].Value)$minor$($match.Groups[2].Value)" })
97+
$content = [regex]::Replace(
98+
$content,
99+
'(?m)^(#define\s+CRTSYS_VERSION_PATCH\s+)\d+(\s*)$',
100+
{ param($match) "$($match.Groups[1].Value)$patch$($match.Groups[2].Value)" })
101+
102+
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
103+
[System.IO.File]::WriteAllText($versionHeader, $content, $utf8NoBom)
104+
105+
$resolvedVersion = (& (Join-Path $repoRoot 'scripts\nuget\Get-CrtSysVersion.ps1')).Trim()
106+
if ($resolvedVersion -ne $Version) {
107+
throw "Version header update failed. Expected $Version, got $resolvedVersion."
108+
}
109+
110+
Invoke-Git diff --check
111+
Invoke-Git add -- include/.internal/version
112+
Invoke-Git commit -m "release crtsys $Version"
113+
Invoke-Git tag -a $tagName -m "crtsys $Version"
114+
115+
if ($Push) {
116+
Invoke-Git push origin $currentBranch
117+
Invoke-Git push origin $tagName
118+
Write-Host "Pushed $currentBranch and $tagName. The Package workflow should start from the tag."
119+
} else {
120+
Write-Host "Prepared release commit and tag locally."
121+
Write-Host "Push with:"
122+
Write-Host " git push origin $currentBranch"
123+
Write-Host " git push origin $tagName"
124+
}
125+
} catch {
126+
Write-Error $_
127+
exit 1
128+
} finally {
129+
Pop-Location
130+
}

0 commit comments

Comments
 (0)