Skip to content

Commit 81c796d

Browse files
Replace brittle release workflow with upstream source builds
1 parent dc5e1ef commit 81c796d

7 files changed

Lines changed: 362 additions & 2396 deletions

File tree

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
name: Build Upstream OptiScaler
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
mode:
7+
description: Build mode (master or latest-any)
8+
required: true
9+
type: string
10+
publish_release:
11+
description: Publish a GitHub prerelease after a successful build
12+
required: false
13+
default: false
14+
type: boolean
15+
16+
permissions:
17+
contents: write
18+
19+
jobs:
20+
build:
21+
runs-on: windows-latest
22+
23+
steps:
24+
- name: Resolve upstream target
25+
id: resolve
26+
shell: pwsh
27+
env:
28+
GH_TOKEN: ${{ github.token }}
29+
MODE: ${{ inputs.mode }}
30+
PUBLISH_RELEASE: ${{ inputs.publish_release }}
31+
run: |
32+
$repo = 'optiscaler/OptiScaler'
33+
$headers = @{
34+
'Accept' = 'application/vnd.github+json'
35+
'X-GitHub-Api-Version' = '2022-11-28'
36+
}
37+
38+
if ($env:GH_TOKEN) {
39+
$headers['Authorization'] = "Bearer $env:GH_TOKEN"
40+
}
41+
42+
function Get-Json([string]$url) {
43+
Invoke-RestMethod -Headers $headers -Uri $url
44+
}
45+
46+
function Get-BranchHead([string]$branchName) {
47+
$encodedBranch = [System.Uri]::EscapeDataString($branchName)
48+
Get-Json "https://api.github.com/repos/$repo/branches/$encodedBranch"
49+
}
50+
51+
function Get-Commit([string]$sha) {
52+
Get-Json "https://api.github.com/repos/$repo/commits/$sha"
53+
}
54+
55+
function Slugify([string]$value) {
56+
$slug = $value.ToLowerInvariant() -replace '[^a-z0-9._-]+', '-'
57+
$slug = $slug.Trim('-')
58+
if ([string]::IsNullOrWhiteSpace($slug)) {
59+
throw "Could not slugify value: $value"
60+
}
61+
return $slug
62+
}
63+
64+
$mode = $env:MODE
65+
$publishRelease = $env:PUBLISH_RELEASE -eq 'true'
66+
67+
if ($mode -eq 'master') {
68+
$branchName = 'master'
69+
$branch = Get-BranchHead $branchName
70+
$sha = $branch.commit.sha
71+
$commit = Get-Commit $sha
72+
$commitDate = $commit.commit.committer.date
73+
}
74+
elseif ($mode -eq 'latest-any') {
75+
$branches = Get-Json "https://api.github.com/repos/$repo/branches?per_page=100"
76+
if (-not $branches) {
77+
throw 'No upstream branches found.'
78+
}
79+
80+
$candidates = foreach ($branch in $branches) {
81+
$sha = $branch.commit.sha
82+
$commit = Get-Commit $sha
83+
[PSCustomObject]@{
84+
BranchName = $branch.name
85+
Sha = $sha
86+
CommitDate = [DateTimeOffset]::Parse($commit.commit.committer.date)
87+
}
88+
}
89+
90+
$latest = $candidates | Sort-Object CommitDate -Descending | Select-Object -First 1
91+
$branchName = $latest.BranchName
92+
$sha = $latest.Sha
93+
$commitDate = $latest.CommitDate.ToString('o')
94+
}
95+
else {
96+
throw "Unsupported mode: $mode"
97+
}
98+
99+
$branchSlug = Slugify $branchName
100+
$shortSha = $sha.Substring(0, 8)
101+
$commitUrl = "https://github.com/$repo/commit/$sha"
102+
103+
switch ($mode) {
104+
'master' {
105+
$tagName = "master-$shortSha"
106+
$releaseName = "master @ $shortSha"
107+
$assetName = "OptiScaler_master_${shortSha}.7z"
108+
}
109+
'latest-any' {
110+
$tagName = "any-$branchSlug-$shortSha"
111+
$releaseName = "latest-any: $branchName @ $shortSha"
112+
$assetName = "OptiScaler_any_${branchSlug}_${shortSha}.7z"
113+
}
114+
}
115+
116+
$releaseBody = $commitUrl
117+
$metadataName = "$tagName.json"
118+
119+
"upstream_repo=$repo" >> $env:GITHUB_OUTPUT
120+
"mode=$mode" >> $env:GITHUB_OUTPUT
121+
"branch_name=$branchName" >> $env:GITHUB_OUTPUT
122+
"branch_slug=$branchSlug" >> $env:GITHUB_OUTPUT
123+
"sha=$sha" >> $env:GITHUB_OUTPUT
124+
"short_sha=$shortSha" >> $env:GITHUB_OUTPUT
125+
"commit_date=$commitDate" >> $env:GITHUB_OUTPUT
126+
"commit_url=$commitUrl" >> $env:GITHUB_OUTPUT
127+
"tag_name=$tagName" >> $env:GITHUB_OUTPUT
128+
"release_name=$releaseName" >> $env:GITHUB_OUTPUT
129+
"asset_name=$assetName" >> $env:GITHUB_OUTPUT
130+
"metadata_name=$metadataName" >> $env:GITHUB_OUTPUT
131+
"release_body=$releaseBody" >> $env:GITHUB_OUTPUT
132+
"publish_release=$($publishRelease.ToString().ToLowerInvariant())" >> $env:GITHUB_OUTPUT
133+
134+
- name: Check for existing release
135+
id: release_check
136+
if: steps.resolve.outputs.publish_release == 'true'
137+
shell: pwsh
138+
env:
139+
GH_TOKEN: ${{ github.token }}
140+
TAG_NAME: ${{ steps.resolve.outputs.tag_name }}
141+
run: |
142+
$headers = @{
143+
'Accept' = 'application/vnd.github+json'
144+
'X-GitHub-Api-Version' = '2022-11-28'
145+
}
146+
147+
if ($env:GH_TOKEN) {
148+
$headers['Authorization'] = "Bearer $env:GH_TOKEN"
149+
}
150+
151+
$url = "https://api.github.com/repos/${{ github.repository }}/releases/tags/$env:TAG_NAME"
152+
$exists = $false
153+
154+
try {
155+
Invoke-WebRequest -Headers $headers -Uri $url | Out-Null
156+
$exists = $true
157+
}
158+
catch {
159+
$statusCode = $_.Exception.Response.StatusCode.value__
160+
if ($statusCode -ne 404) {
161+
throw
162+
}
163+
}
164+
165+
$existsString = $exists.ToString().ToLowerInvariant()
166+
"release_exists=$existsString" >> $env:GITHUB_OUTPUT
167+
168+
- name: Skip because release already exists
169+
if: steps.resolve.outputs.publish_release == 'true' && steps.release_check.outputs.release_exists == 'true'
170+
shell: pwsh
171+
run: |
172+
Write-Host "Release tag ${{ steps.resolve.outputs.tag_name }} already exists. Skipping build."
173+
174+
- name: Checkout upstream source
175+
if: steps.resolve.outputs.publish_release != 'true' || steps.release_check.outputs.release_exists != 'true'
176+
uses: actions/checkout@v4
177+
with:
178+
repository: optiscaler/OptiScaler
179+
ref: ${{ steps.resolve.outputs.sha }}
180+
submodules: recursive
181+
fetch-depth: 1
182+
path: upstream
183+
184+
- name: Add MSBuild to PATH
185+
if: steps.resolve.outputs.publish_release != 'true' || steps.release_check.outputs.release_exists != 'true'
186+
uses: microsoft/setup-msbuild@v2
187+
188+
- name: Build upstream
189+
if: steps.resolve.outputs.publish_release != 'true' || steps.release_check.outputs.release_exists != 'true'
190+
shell: pwsh
191+
working-directory: ${{ github.workspace }}\upstream
192+
run: |
193+
msbuild /m /p:Configuration=Release . /verbosity:minimal
194+
195+
- name: Package build output
196+
id: package
197+
if: steps.resolve.outputs.publish_release != 'true' || steps.release_check.outputs.release_exists != 'true'
198+
shell: pwsh
199+
env:
200+
ASSET_NAME: ${{ steps.resolve.outputs.asset_name }}
201+
run: |
202+
$artifactDir = "${{ github.workspace }}\upstream\x64\Release\a"
203+
if (-not (Test-Path $artifactDir)) {
204+
throw "Expected build output directory not found: $artifactDir"
205+
}
206+
207+
$packagePath = "${{ runner.temp }}\$env:ASSET_NAME"
208+
if (Test-Path $packagePath) {
209+
Remove-Item -Force $packagePath
210+
}
211+
212+
& 7z a -r $packagePath "$artifactDir\*.*"
213+
if ($LASTEXITCODE -ne 0) {
214+
throw "7z packaging failed with exit code $LASTEXITCODE"
215+
}
216+
217+
"package_path=$packagePath" >> $env:GITHUB_OUTPUT
218+
219+
- name: Write metadata
220+
id: metadata
221+
if: steps.resolve.outputs.publish_release != 'true' || steps.release_check.outputs.release_exists != 'true'
222+
shell: pwsh
223+
env:
224+
METADATA_NAME: ${{ steps.resolve.outputs.metadata_name }}
225+
UPSTREAM_REPO: ${{ steps.resolve.outputs.upstream_repo }}
226+
MODE: ${{ steps.resolve.outputs.mode }}
227+
BRANCH_NAME: ${{ steps.resolve.outputs.branch_name }}
228+
BRANCH_SLUG: ${{ steps.resolve.outputs.branch_slug }}
229+
SHA: ${{ steps.resolve.outputs.sha }}
230+
SHORT_SHA: ${{ steps.resolve.outputs.short_sha }}
231+
COMMIT_DATE: ${{ steps.resolve.outputs.commit_date }}
232+
COMMIT_URL: ${{ steps.resolve.outputs.commit_url }}
233+
TAG_NAME: ${{ steps.resolve.outputs.tag_name }}
234+
RELEASE_NAME: ${{ steps.resolve.outputs.release_name }}
235+
ASSET_NAME: ${{ steps.resolve.outputs.asset_name }}
236+
PUBLISH_RELEASE: ${{ steps.resolve.outputs.publish_release }}
237+
run: |
238+
$metadata = [ordered]@{
239+
upstream_repo = $env:UPSTREAM_REPO
240+
mode = $env:MODE
241+
branch = $env:BRANCH_NAME
242+
branch_slug = $env:BRANCH_SLUG
243+
sha = $env:SHA
244+
short_sha = $env:SHORT_SHA
245+
commit_date = $env:COMMIT_DATE
246+
commit_url = $env:COMMIT_URL
247+
tag_name = $env:TAG_NAME
248+
release_name = $env:RELEASE_NAME
249+
asset_name = $env:ASSET_NAME
250+
publish_release = ($env:PUBLISH_RELEASE -eq 'true')
251+
built_at = (Get-Date).ToUniversalTime().ToString('o')
252+
}
253+
254+
$metadataPath = "${{ runner.temp }}\$env:METADATA_NAME"
255+
$metadata | ConvertTo-Json -Depth 4 | Out-File -FilePath $metadataPath -Encoding utf8
256+
257+
"metadata_path=$metadataPath" >> $env:GITHUB_OUTPUT
258+
259+
- name: Upload workflow artifacts
260+
if: steps.resolve.outputs.publish_release != 'true' || steps.release_check.outputs.release_exists != 'true'
261+
uses: actions/upload-artifact@v4
262+
with:
263+
name: ${{ steps.resolve.outputs.tag_name }}
264+
retention-days: 14
265+
path: |
266+
${{ steps.package.outputs.package_path }}
267+
${{ steps.metadata.outputs.metadata_path }}
268+
269+
- name: Create prerelease
270+
if: steps.resolve.outputs.publish_release == 'true' && steps.release_check.outputs.release_exists != 'true'
271+
uses: softprops/action-gh-release@v2
272+
with:
273+
tag_name: ${{ steps.resolve.outputs.tag_name }}
274+
name: ${{ steps.resolve.outputs.release_name }}
275+
body: ${{ steps.resolve.outputs.release_body }}
276+
prerelease: true
277+
files: |
278+
${{ steps.package.outputs.package_path }}
279+
${{ steps.metadata.outputs.metadata_path }}

0 commit comments

Comments
 (0)