-
Notifications
You must be signed in to change notification settings - Fork 0
Add automatic release CI with patch version bumping and MSVC optimization #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
c032081
Initial plan
Copilot 6e7a9b7
Add automatic release CI workflow with patch version bumping
Copilot 94e6c2a
Update release workflow to use modern GitHub release action
Copilot fcbfb0c
fix: improve semantic version sorting and commit message escaping
Copilot 6242eda
docs: add documentation about automatic release workflow
Copilot 51b2b5b
refactor: optimize git operations and improve tag pattern matching
Copilot 0f33994
fix: only release on PR merge with source changes and successful build
Copilot e74b1c4
fix: improve PR file detection and revert README changes
Copilot 316a424
fix: fail workflow on version parse error, mark releases as prereleasβ¦
Copilot a81a265
fix: add concurrency control to prevent duplicate release tag collisions
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| name: Release Build | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [closed] | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| build-and-release: | ||
| # Only run if PR was merged (not just closed) and source files changed | ||
| if: github.event.pull_request.merged == true | ||
| runs-on: windows-latest | ||
| concurrency: | ||
| group: 'release-${{ github.ref }}' | ||
| cancel-in-progress: false | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Fetch all history for proper versioning | ||
|
|
||
| - name: Check if source files changed | ||
| id: check_files | ||
| shell: pwsh | ||
| run: | | ||
| # Get list of changed files in the merged PR | ||
| $changedFiles = git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | ||
| Write-Output "Changed files:" | ||
| Write-Output $changedFiles | ||
|
|
||
| # Check if any C++ source files changed | ||
| $sourceChanged = $false | ||
| foreach ($file in $changedFiles) { | ||
| if ($file -match '\.(cpp|h|hpp|c|cc|cxx)$') { | ||
| $sourceChanged = $true | ||
| Write-Output "Source file changed: $file" | ||
| break | ||
| } | ||
| } | ||
|
|
||
| if ($sourceChanged) { | ||
| Write-Output "should_release=true" >> $env:GITHUB_OUTPUT | ||
| Write-Output "Source files changed - will proceed with release" | ||
| } else { | ||
| Write-Output "should_release=false" >> $env:GITHUB_OUTPUT | ||
| Write-Output "No source files changed - skipping release" | ||
| } | ||
supervoidcoder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| - name: Setup MSVC | ||
| if: steps.check_files.outputs.should_release == 'true' | ||
| uses: ilammy/msvc-dev-cmd@v1 | ||
|
|
||
| - name: Get latest release tag | ||
| if: steps.check_files.outputs.should_release == 'true' | ||
| id: get_latest_tag | ||
| shell: pwsh | ||
| run: | | ||
| # Get the latest tag that matches semantic versioning pattern | ||
| $tags = git tag -l "v[0-9]*.[0-9]*.[0-9]*" | ||
| if ($tags) { | ||
| # Parse and sort tags by semantic version | ||
| $sortedTags = $tags | ForEach-Object { | ||
| if ($_ -match 'v?(\d+)\.(\d+)\.(\d+)') { | ||
| [PSCustomObject]@{ | ||
| Tag = $_ | ||
| Major = [int]$Matches[1] | ||
| Minor = [int]$Matches[2] | ||
| Patch = [int]$Matches[3] | ||
| } | ||
| } | ||
| } | Sort-Object -Property Major, Minor, Patch -Descending | ||
| $latestTag = $sortedTags[0].Tag | ||
| Write-Output "Latest tag: $latestTag" | ||
| Write-Output "latest_tag=$latestTag" >> $env:GITHUB_OUTPUT | ||
| } else { | ||
| Write-Output "No existing tags found, starting from v0.0.0" | ||
| Write-Output "latest_tag=v0.0.0" >> $env:GITHUB_OUTPUT | ||
| } | ||
|
|
||
| - name: Determine next version | ||
| if: steps.check_files.outputs.should_release == 'true' | ||
| id: next_version | ||
| shell: pwsh | ||
| run: | | ||
| $latestTag = "${{ steps.get_latest_tag.outputs.latest_tag }}" | ||
|
|
||
| # Parse version (remove 'v' prefix) | ||
| if ($latestTag -match 'v?(\d+)\.(\d+)\.(\d+)') { | ||
| $major = [int]$Matches[1] | ||
| $minor = [int]$Matches[2] | ||
| $patch = [int]$Matches[3] | ||
|
|
||
| # Increment patch version | ||
| $patch = $patch + 1 | ||
|
|
||
| $newVersion = "v$major.$minor.$patch" | ||
| Write-Output "Next version: $newVersion" | ||
| Write-Output "version=$newVersion" >> $env:GITHUB_OUTPUT | ||
| Write-Output "version_number=$major.$minor.$patch" >> $env:GITHUB_OUTPUT | ||
| } else { | ||
| Write-Error "Could not parse version from tag: $latestTag" | ||
| exit 1 | ||
| } | ||
|
|
||
| - name: Parse commit message for release notes | ||
| if: steps.check_files.outputs.should_release == 'true' | ||
| id: parse_commit | ||
| shell: pwsh | ||
| run: | | ||
| # Get commit information in a single call | ||
| $commitMsg = git log -1 --pretty=%B | ||
| $commitSubject = $commitMsg.Split("`n")[0] | ||
| $commitBodyLines = $commitMsg.Split("`n") | Select-Object -Skip 1 | ||
| $commitBody = ($commitBodyLines -join "`n").Trim() | ||
|
|
||
| # Create release notes | ||
| $releaseNotes = "## Changes`n`n" | ||
|
|
||
| # Parse commit type (fix, feat, docs, etc.) | ||
| if ($commitSubject -match '^(fix|feat|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?:\s*(.+)$') { | ||
| $type = $Matches[1] | ||
| $description = $Matches[3] | ||
|
|
||
| $typeLabel = switch ($type) { | ||
| 'fix' { 'π Fix' } | ||
| 'feat' { 'β¨ Feature' } | ||
| 'docs' { 'π Documentation' } | ||
| 'style' { 'π Style' } | ||
| 'refactor' { 'β»οΈ Refactor' } | ||
| 'test' { 'β Test' } | ||
| 'chore' { 'π§ Chore' } | ||
| 'perf' { 'β‘ Performance' } | ||
| 'ci' { 'π· CI' } | ||
| 'build' { 'π¦ Build' } | ||
| 'revert' { 'βͺ Revert' } | ||
| default { 'π Update' } | ||
| } | ||
|
|
||
| $releaseNotes += "**$typeLabel**: $description`n" | ||
| } else { | ||
| # If not following conventional commits, just use the subject | ||
| $releaseNotes += "$commitSubject`n" | ||
| } | ||
|
|
||
| # Add commit body if present (with length limit) | ||
| if ($commitBody -ne "") { | ||
| $maxBodyLength = 1000 | ||
| if ($commitBody.Length -gt $maxBodyLength) { | ||
| $commitBody = $commitBody.Substring(0, $maxBodyLength) + "..." | ||
| } | ||
| $releaseNotes += "`n$commitBody`n" | ||
| } | ||
|
|
||
| # Add commit SHA | ||
| $commitSha = git rev-parse --short HEAD | ||
| $releaseNotes += "`n---`n*Commit: $commitSha*" | ||
|
|
||
| # Save to output using multiline string with proper escaping | ||
| $delimiter = "EOF_$(Get-Random)" | ||
| Write-Output "notes<<$delimiter" >> $env:GITHUB_OUTPUT | ||
| Write-Output $releaseNotes >> $env:GITHUB_OUTPUT | ||
| Write-Output $delimiter >> $env:GITHUB_OUTPUT | ||
|
|
||
| - name: Compile with MSVC | ||
| if: steps.check_files.outputs.should_release == 'true' | ||
| id: compile | ||
| shell: pwsh | ||
| run: | | ||
| # Compile and capture exit code | ||
| cl /O2 /Ot /GL /std:c++20 /EHsc main.cpp /DUNICODE /D_UNICODE /Fe:win-witr.exe | ||
| $exitCode = $LASTEXITCODE | ||
|
|
||
| if ($exitCode -eq 0) { | ||
| Write-Output "Compilation successful" | ||
| Write-Output "compile_success=true" >> $env:GITHUB_OUTPUT | ||
| } else { | ||
| Write-Output "Compilation failed with exit code: $exitCode" | ||
| Write-Output "compile_success=false" >> $env:GITHUB_OUTPUT | ||
| Write-Error "Build failed - release will be skipped" | ||
| exit 1 | ||
| } | ||
|
|
||
| - name: Create Release and Upload Asset | ||
| if: steps.check_files.outputs.should_release == 'true' && steps.compile.outputs.compile_success == 'true' | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| tag_name: ${{ steps.next_version.outputs.version }} | ||
| name: Release win-witr ${{ steps.next_version.outputs.version }} | ||
| body: ${{ steps.parse_commit.outputs.notes }} | ||
| files: win-witr.exe | ||
| draft: false | ||
| prerelease: true | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.