Create Release Candidate #194
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
| name: Create Release Candidate | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_type: | |
| description: 'Type of release increment (patch, minor, major)' | |
| required: true | |
| default: 'patch' | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| jobs: | |
| build: | |
| runs-on: windows-latest | |
| permissions: | |
| contents: write | |
| outputs: | |
| new_version: ${{ steps.get_version.outputs.new_version }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Get Latest Tag and Git Log | |
| shell: bash | |
| run: | | |
| LATEST_TAG=$(git tag | grep -v '\-rc\.' | sort -V | tail -n 1) | |
| echo "Latest Tag: $LATEST_TAG" | |
| GIT_LOG=$(git log "${LATEST_TAG}..HEAD" --no-merges --oneline) | |
| echo "Git Log:" | |
| echo "$GIT_LOG" | |
| echo "GIT_LOG<<EOF" >> $GITHUB_ENV | |
| echo "$GIT_LOG" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-${{ runner.os }}-${{ hashFiles('Frontend/bun.lock') }} | |
| restore-keys: bun-${{ runner.os }}- | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '**/packages.lock.json') }} | |
| restore-keys: nuget-${{ runner.os }}- | |
| - name: Display Git Log | |
| shell: bash | |
| run: | | |
| echo "Git Log since last tag:" | |
| echo "$GIT_LOG" | |
| - name: Generate Release Notes | |
| id: generate_release_notes | |
| shell: bash | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| run: | | |
| # --- Debug: Show jq info --- | |
| echo "ℹ️ Using jq from path: $(which jq)" | |
| echo "ℹ️ jq version: $(jq --version)" | |
| # --- Debug: Show raw input --- | |
| echo "📜 Raw GIT_LOG:" | |
| echo "$GIT_LOG" | |
| echo "" | |
| # Use pre-installed Chocolatey jq | |
| export PATH="/c/ProgramData/Chocolatey/bin:$PATH" | |
| # Define system prompt | |
| SYSTEM_PROMPT="You are a helpful assistant who creates user-friendly release notes for open-source applications such as games and clip recorders. Your task is to transform raw update logs into concise and easy-to-understand release notes. Use a casual, direct tone and avoid overly technical language and details that are not important for the end user. Please merge changes if you think they are the same method/function that changed. Avoid wrapping the final release notes in a Markdown code block. Non techy and do not include things like chore or refactor if it doesn't do anything for the user! Do not include the text Release Notes in the beginning. Do not say thanks in the end. Also, " | |
| # --- Debug: Show escaped content --- | |
| echo "🔧 Escaping content..." | |
| ESCAPED_SYSTEM=$(jq -Rs . <<< "$SYSTEM_PROMPT") | |
| ESCAPED_LOG=$(jq -Rs . <<< "$GIT_LOG") | |
| echo "🔒 Escaped System Prompt:" | |
| echo "$ESCAPED_SYSTEM" | |
| echo "" | |
| echo "🔒 Escaped Git Log:" | |
| echo "$ESCAPED_LOG" | |
| echo "" | |
| # Build JSON payload | |
| JSON_PAYLOAD=$(jq -n \ | |
| --arg model "gpt-4o" \ | |
| --argjson system "$ESCAPED_SYSTEM" \ | |
| --argjson log "$ESCAPED_LOG" \ | |
| '{ | |
| "model": $model, | |
| "messages": [ | |
| {"role": "system", "content": $system}, | |
| {"role": "user", "content": $log} | |
| ] | |
| }') | |
| # --- Debug: Show final payload --- | |
| echo "📦 JSON Payload:" | |
| echo "$JSON_PAYLOAD" | |
| echo "" | |
| # Make API call | |
| echo "📡 Making API request to OpenAI..." | |
| RESPONSE=$(curl -s -X POST "https://api.openai.com/v1/chat/completions" \ | |
| -H "Content-Type: application/json" \ | |
| -H "Authorization: Bearer $OPENAI_API_KEY" \ | |
| -d "$JSON_PAYLOAD") | |
| # --- Debug: Show raw response --- | |
| echo "📨 Raw API Response:" | |
| echo "$RESPONSE" | |
| echo "" | |
| # Extract release notes | |
| RELEASE_NOTES=$(echo "$RESPONSE" | jq -r '.choices[0].message.content') | |
| # --- Debug: Show final output --- | |
| echo "🎉 Generated Release Notes:" | |
| echo "$RELEASE_NOTES" | |
| echo "" | |
| - name: Determine Version | |
| id: get_version | |
| shell: pwsh | |
| run: | | |
| # Get the highest final release version (exclude RCs, sort by semver) | |
| $latestFinalTag = (git tag | Where-Object { $_ -notmatch '-rc\.' } | Sort-Object { [version]($_ -replace '^v', '') } | Select-Object -Last 1) -replace '^v', '' | |
| if (-not $latestFinalTag) { | |
| $latestFinalTag = "0.0.0" | |
| } | |
| Write-Host "Latest final release: $latestFinalTag" | |
| $releaseType = "${{ github.event.inputs.release_type }}" | |
| # Calculate what the next version would be based on release type | |
| $versionParts = $latestFinalTag.Split('.') | |
| $major = [int]$versionParts[0] | |
| $minor = [int]$versionParts[1] | |
| $patch = [int]$versionParts[2] | |
| switch ($releaseType) { | |
| "major" { $major++; $minor=0; $patch=0 } | |
| "minor" { $minor++; $patch=0 } | |
| "patch" { $patch++ } | |
| } | |
| $nextBaseVersion = "$major.$minor.$patch" | |
| Write-Host "Next base version would be: $nextBaseVersion" | |
| # Check if there are existing RCs for this next version | |
| $existingRCs = git tag | Where-Object { $_ -match "^v$([regex]::Escape($nextBaseVersion))-rc\.(\d+)$" } | |
| if ($existingRCs) { | |
| # Find the highest RC number | |
| $highestRC = $existingRCs | ForEach-Object { | |
| if ($_ -match '-rc\.(\d+)$') { [int]$Matches[1] } | |
| } | Sort-Object | Select-Object -Last 1 | |
| $rcNumber = $highestRC + 1 | |
| Write-Host "Found existing RCs, highest is rc.$highestRC, creating rc.$rcNumber" | |
| } else { | |
| $rcNumber = 1 | |
| Write-Host "No existing RCs for $nextBaseVersion, starting at rc.1" | |
| } | |
| $newVersion = "$nextBaseVersion-rc.$rcNumber" | |
| Write-Host "New version: $newVersion" | |
| echo "new_version=$newVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 | |
| echo "new_version=$newVersion" >> $env:GITHUB_OUTPUT | |
| - name: Configure Git User | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| shell: pwsh | |
| - name: Install vpk as .NET Global Tool | |
| run: | | |
| dotnet tool install -g vpk | |
| $env:PATH += ";$env:USERPROFILE\.dotnet\tools" | |
| shell: pwsh | |
| - name: Update Frontend version | |
| working-directory: ./Frontend | |
| shell: pwsh | |
| run: | | |
| $content = Get-Content package.json -Raw | |
| $packageJson = Get-Content package.json -Raw | ConvertFrom-Json | |
| $packageJson.version = $env:new_version | |
| $packageJson | ConvertTo-Json -Depth 100 | Set-Content package.json -NoNewline | |
| Write-Host "Updated version: $(Select-String -Path package.json -Pattern 'version')" | |
| - name: Install Frontend dependencies | |
| working-directory: ./Frontend | |
| run: bun install --frozen-lockfile | |
| - name: Build Frontend | |
| working-directory: ./Frontend | |
| run: bun run build | |
| - name: Move Frontend Build to Resources/wwwroot | |
| run: | | |
| $source = "./Frontend/dist" | |
| $destination = "./Resources/wwwroot" | |
| if (-Not (Test-Path -Path $destination)) { New-Item -ItemType Directory -Path $destination -Force } | |
| Remove-Item -Path "$destination\*" -Recurse -Force | |
| Copy-Item -Path "$source\*" -Destination $destination -Recurse -Force | |
| shell: pwsh | |
| - name: Publish the App | |
| run: dotnet publish -c Release --self-contained -r win-x64 -o publish | |
| shell: pwsh | |
| - name: Package with vpk | |
| run: vpk pack -u Segra -v ${{ env.new_version }} -p ./publish -e Segra.exe -o ./output --packTitle "Segra" --noPortable | |
| shell: pwsh | |
| - name: Create a Git Tag | |
| run: | | |
| git tag v${{ env.new_version }} | |
| git push origin v${{ env.new_version }} | |
| shell: pwsh | |
| - name: Upload Release Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Segra | |
| path: ./output | |
| retention-days: 1 | |
| pre-release: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download Build Artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: Segra | |
| - name: Create GitHub Release (Pre-Release) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ needs.build.outputs.new_version }} | |
| name: "Release v${{ needs.build.outputs.new_version }}" | |
| prerelease: true | |
| files: | | |
| ./Segra-win-Setup.exe | |
| ./RELEASES | |
| ./releases.win.json | |
| ./assets.win.json | |
| ./Segra-${{ needs.build.outputs.new_version }}-full.nupkg |