Skip to content

GitHub Release (Run ID: latest build) #6

GitHub Release (Run ID: latest build)

GitHub Release (Run ID: latest build) #6

name: Publish GitHub Release
run-name: "GitHub Release (Run ID: ${{ inputs.run_id || 'latest build' }})"
on:
workflow_dispatch:
inputs:
run_id:
description: "Build workflow run ID (leave empty to use latest)"
required: false
type: string
use_local_storage:
description: "Use local artifact storage"
required: false
type: boolean
default: true
use_self_hosted_runners:
description: "Use self-hosted runners"
required: false
type: boolean
default: true
workflow_call:
inputs:
run_id:
description: "Build workflow run ID (leave empty to use latest)"
required: false
type: string
use_local_storage:
description: "Use local artifact storage"
required: false
type: boolean
default: true
use_self_hosted_runners:
description: "Use self-hosted runners"
required: false
type: boolean
default: true
permissions:
contents: write
actions: read
jobs:
release:
name: Create GitHub Release
runs-on: ${{ inputs.use_self_hosted_runners && fromJson('["self-hosted","Linux"]') || fromJson('["ubuntu-latest"]') }}
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.BBB_CLIENT_ID }}
private-key: ${{ secrets.BBB_PRIVATE_KEY }}
- name: Validate local storage configuration
uses: ./.github/actions/validate-local-storage
with:
use_local_storage: ${{ inputs.use_local_storage }}
artifact_host: ${{ vars.ARTIFACT_HOST }}
artifact_base_path: ${{ vars.ARTIFACT_BASE_PATH }}
- name: Get Latest Build Run ID
id: get-run-id
uses: ./.github/actions/get-latest-build-run-id
with:
run_id: ${{ inputs.run_id }}
github_token: ${{ github.token }}
- name: Download Server Artifact
uses: ./.github/actions/download-artifact
with:
name: Server
path: ./server-publish
github-token: ${{ github.token }}
artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }}
artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }}
run-id: ${{ steps.get-run-id.outputs.run_id }}
- name: Download docker-compose file
uses: ./.github/actions/download-artifact
with:
name: DockerCompose
path: ./docker-compose-download
github-token: ${{ github.token }}
artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }}
artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }}
run-id: ${{ steps.get-run-id.outputs.run_id }}
- name: Verify Server Payload
uses: ./.github/actions/verify-server-payload
with:
path: ./server-publish
- name: Get Build Metadata
id: metadata
uses: ./.github/actions/get-build-metadata
with:
run-id: ${{ steps.get-run-id.outputs.run_id }}
github-token: ${{ github.token }}
artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }}
artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }}
# The build metadata lists the runtimes the build produced, so the archive set is
# decided by the build rather than by whatever happens to be on disk. Only the
# runtimes that have a release archive are zipped; the rest are reported and skipped.
- name: Prepare Release Artifacts
shell: pwsh
env:
SERVER_RIDS: ${{ steps.metadata.outputs.server_rids }}
PRIMARY_RID: ${{ steps.metadata.outputs.primary_rid }}
RELEASE_VERSION: ${{ steps.metadata.outputs.release_version }}
PRERELEASE: ${{ steps.metadata.outputs.prerelease }}
run: |
$RidLabels = [ordered]@{
'linux-x64' = 'linux-amd64'
'linux-arm64' = 'linux-arm64'
'win-x64' = 'win-x64'
}
$ArchiveCount = 0
$Archived = [System.Collections.Generic.List[string]]::new()
foreach ($Rid in $env:SERVER_RIDS.Split(',')) {
if (-not $RidLabels.Contains($Rid)) {
Write-Host "No release archive for '$Rid'; skipping."
continue
}
$RidDirectory = "./server-publish/$Rid"
if (-not (Test-Path -PathType Container $RidDirectory)) {
Write-Warning "'$RidDirectory' is missing from the Server artifact; skipping its archive."
continue
}
$Label = $RidLabels[$Rid]
$Archive = "server-$Label.zip"
Remove-Item -Path $Archive -Force -ErrorAction SilentlyContinue
# Zip from inside the runtime directory so the archive root is the payload root.
Push-Location -Path $RidDirectory
try {
zip -qr "../../$Archive" .
if ($LASTEXITCODE -ne 0) {
throw "zip failed for $Rid with exit code $LASTEXITCODE."
}
}
finally {
Pop-Location
}
$Archived.Add("- ``$Rid`` -> ``$Archive``")
Write-Host "$Archive <- $Rid"
$ArchiveCount++
}
if ($ArchiveCount -eq 0) {
throw "The Server artifact contains no payload for the runtimes in the build metadata ($env:SERVER_RIDS)."
}
# The primary runtime supplies the release notes and API schemas for the release.
Copy-Item -Path "./server-publish/$env:PRIMARY_RID/ControlR.Web.Server_internal.json" -Destination . -Force
Copy-Item -Path "./server-publish/$env:PRIMARY_RID/ControlR.Web.Server_v1.json" -Destination . -Force
Copy-Item -Path "docker-compose-download/docker-compose.yml" -Destination . -Force
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "## Release Summary"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "**Version:** v$env:RELEASE_VERSION"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "**Server Runtimes:**"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value $Archived
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "**Status:** Draft"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "**Pre-release:** $env:PRERELEASE"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value ""
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "⚠️ Release is in DRAFT mode - review and publish when ready"
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
name: v${{ steps.metadata.outputs.release_version }} Release
tag_name: v${{ steps.metadata.outputs.release_version }}
draft: true
prerelease: ${{ steps.metadata.outputs.prerelease == 'true' }}
generate_release_notes: false
body_path: ./server-publish/${{ steps.metadata.outputs.primary_rid }}/wwwroot/downloads/release-notes.md
files: |
server-*.zip
ControlR.Web.Server_internal.json
ControlR.Web.Server_v1.json
docker-compose.yml
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Archive Release Notes
if: ${{ steps.metadata.outputs.prerelease == 'false' }}
shell: pwsh
env:
PRIMARY_RID: ${{ steps.metadata.outputs.primary_rid }}
RELEASE_VERSION: ${{ steps.metadata.outputs.release_version }}
run: |
Copy-Item -Path "./server-publish/$env:PRIMARY_RID/wwwroot/downloads/release-notes.md" `
-Destination ".release-notes/v$env:RELEASE_VERSION.md" -Force
@'
## Breaking Changes
None.
## Enhancements
None.
## Fixes
None.
## Removals
None.
## Internal
None.
'@ | Set-Content -Path .release-notes/current.md -Encoding utf8
git config user.name "bitbound-bot[bot]"
git config user.email "bitbound-bot[bot]@users.noreply.github.com"
git add .release-notes/
$Changes = git status --porcelain -- .release-notes/
if (-not $Changes) {
Write-Host "Release notes are already up to date; nothing to commit."
}
else {
git commit -m "chore: archive release notes for v$env:RELEASE_VERSION"
if ($LASTEXITCODE -ne 0) {
throw "Failed to commit the archived release notes."
}
git push "https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git"
if ($LASTEXITCODE -ne 0) {
throw "Failed to push the archived release notes."
}
}