build: add pinned on-demand Rayforge preparation
This commit is contained in:
parent
6a7ba8a6e4
commit
71067308d7
5 changed files with 154 additions and 4 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,6 +3,7 @@ __pycache__/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.venv/
|
.venv/
|
||||||
.uv-cache/
|
.uv-cache/
|
||||||
|
/.build/
|
||||||
|
|
||||||
# Sensitive/raw acquisition data belongs in ThePirateRay-PrivateStash.
|
# Sensitive/raw acquisition data belongs in ThePirateRay-PrivateStash.
|
||||||
/raw/
|
/raw/
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,22 @@ toolchain is a separate, reviewable action: upstream's setup includes MSYS2,
|
||||||
GTK, compiler/build packages and network downloads, so it should not be an
|
GTK, compiler/build packages and network downloads, so it should not be an
|
||||||
implicit side effect of a workflow test.
|
implicit side effect of a workflow test.
|
||||||
|
|
||||||
|
## On-demand source and build policy
|
||||||
|
|
||||||
|
The public repository records the upstream URL and exact commit in
|
||||||
|
`upstreams/rayforge.json`. `scripts/prepare_rayforge_build.ps1` fetches that
|
||||||
|
revision into the ignored `.build/upstreams/` cache only when explicitly
|
||||||
|
invoked. Its default action prepares source only; it neither installs the
|
||||||
|
Windows toolchain nor starts a build.
|
||||||
|
|
||||||
|
Windows dependencies and bundle creation require separate
|
||||||
|
`-InstallWindowsDependencies` and `-BuildWindowsBundle` switches. This keeps a
|
||||||
|
multi-gigabyte MSYS2/UCRT64 toolchain out of normal clone, test and documentation
|
||||||
|
workflows and makes a CI-produced bundle the preferred interaction-test input.
|
||||||
|
|
||||||
## Next action
|
## Next action
|
||||||
|
|
||||||
Provide an already reviewed Rayforge Windows build/runtime, or explicitly
|
Produce or obtain an artifact for the pinned revision through the explicit
|
||||||
approve installation of the pinned checkout's MSYS2/UCRT64 dependencies. Then
|
on-demand build path, then rerun the preflight and perform the packaged
|
||||||
rerun the preflight and perform the packaged no-device interaction checklist
|
no-device interaction checklist from `rayforge-graphical-workflow-spike.md`.
|
||||||
from `rayforge-graphical-workflow-spike.md`.
|
Do not make the Windows build toolchain an implicit project dependency.
|
||||||
|
|
|
||||||
94
scripts/prepare_rayforge_build.ps1
Normal file
94
scripts/prepare_rayforge_build.ps1
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
[CmdletBinding(SupportsShouldProcess)]
|
||||||
|
param(
|
||||||
|
[string]$CacheRoot,
|
||||||
|
[switch]$InstallWindowsDependencies,
|
||||||
|
[switch]$BuildWindowsBundle
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$repositoryRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
$manifestPath = Join-Path $repositoryRoot "upstreams\rayforge.json"
|
||||||
|
$manifest = Get-Content -Raw -LiteralPath $manifestPath | ConvertFrom-Json
|
||||||
|
|
||||||
|
if (-not $CacheRoot) {
|
||||||
|
$CacheRoot = Join-Path $repositoryRoot ".build\upstreams"
|
||||||
|
}
|
||||||
|
|
||||||
|
$shortCommit = $manifest.commit.Substring(0, 12)
|
||||||
|
$checkout = Join-Path $CacheRoot "rayforge-$shortCommit"
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $checkout)) {
|
||||||
|
if (-not $PSCmdlet.ShouldProcess($checkout, "Clone pinned Rayforge source")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $CacheRoot | Out-Null
|
||||||
|
& git clone --filter=blob:none --no-checkout $manifest.repository $checkout
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Rayforge clone failed with exit code $LASTEXITCODE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath (Join-Path $checkout ".git"))) {
|
||||||
|
throw "Existing cache path is not a Git checkout: $checkout"
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentCommit = (& git -C $checkout rev-parse HEAD 2>$null)
|
||||||
|
if ($LASTEXITCODE -ne 0 -or $currentCommit -ne $manifest.commit) {
|
||||||
|
if (-not $PSCmdlet.ShouldProcess($checkout, "Fetch and check out pinned commit $($manifest.commit)")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
& git -C $checkout fetch --depth 1 origin $manifest.commit
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Rayforge fetch failed with exit code $LASTEXITCODE"
|
||||||
|
}
|
||||||
|
& git -C $checkout checkout --detach $manifest.commit
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Rayforge checkout failed with exit code $LASTEXITCODE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$verifiedCommit = (& git -C $checkout rev-parse HEAD).Trim()
|
||||||
|
if ($verifiedCommit -ne $manifest.commit) {
|
||||||
|
throw "Rayforge pin mismatch: expected $($manifest.commit), got $verifiedCommit"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Output "Rayforge source ready at $checkout"
|
||||||
|
Write-Output "Verified commit: $verifiedCommit"
|
||||||
|
|
||||||
|
if (-not $InstallWindowsDependencies -and -not $BuildWindowsBundle) {
|
||||||
|
Write-Output "No dependencies were installed and no build was started."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$bash = "C:\msys64\usr\bin\bash.exe"
|
||||||
|
if (-not (Test-Path -LiteralPath $bash)) {
|
||||||
|
throw "MSYS2 is required for the upstream Windows build. Install it explicitly before using build flags."
|
||||||
|
}
|
||||||
|
|
||||||
|
$msysCheckout = (& $bash -lc "cygpath -u '$checkout'").Trim()
|
||||||
|
|
||||||
|
if ($InstallWindowsDependencies) {
|
||||||
|
if ($PSCmdlet.ShouldProcess("C:\msys64", "Install Rayforge Windows build dependencies")) {
|
||||||
|
& $bash -lc "cd '$msysCheckout' && bash scripts/win/win_setup.sh"
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Rayforge Windows dependency setup failed with exit code $LASTEXITCODE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($BuildWindowsBundle) {
|
||||||
|
$environmentFile = Join-Path $checkout ".msys2_env"
|
||||||
|
if (-not (Test-Path -LiteralPath $environmentFile)) {
|
||||||
|
throw "Windows dependencies are not prepared. Re-run with -InstallWindowsDependencies."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSCmdlet.ShouldProcess($checkout, "Build pinned Rayforge Windows bundle")) {
|
||||||
|
& $bash -lc "cd '$msysCheckout' && bash scripts/win/win_build.sh 'pirateray-$shortCommit'"
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Rayforge Windows build failed with exit code $LASTEXITCODE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
tests/test_upstream_build_reference.py
Normal file
35
tests/test_upstream_build_reference.py
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import json
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
MANIFEST = ROOT / "upstreams" / "rayforge.json"
|
||||||
|
PREPARE = ROOT / "scripts" / "prepare_rayforge_build.ps1"
|
||||||
|
PIN = "c28918c87f8273dd1d244f5a057addc192807fa5"
|
||||||
|
|
||||||
|
|
||||||
|
class UpstreamBuildReferenceTests(unittest.TestCase):
|
||||||
|
def test_rayforge_reference_is_exact_and_https(self):
|
||||||
|
data = json.loads(MANIFEST.read_text(encoding="utf-8"))
|
||||||
|
self.assertEqual(data["commit"], PIN)
|
||||||
|
self.assertEqual(
|
||||||
|
data["repository"], "https://github.com/barebaric/rayforge.git"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_prepare_script_is_on_demand_and_uses_ignored_cache(self):
|
||||||
|
script = PREPARE.read_text(encoding="utf-8")
|
||||||
|
self.assertIn('".build\\upstreams"', script)
|
||||||
|
self.assertIn("SupportsShouldProcess", script)
|
||||||
|
self.assertIn("InstallWindowsDependencies", script)
|
||||||
|
self.assertIn("BuildWindowsBundle", script)
|
||||||
|
self.assertIn("No dependencies were installed", script)
|
||||||
|
|
||||||
|
def test_prepare_script_has_no_hardware_path(self):
|
||||||
|
script = PREPARE.read_text(encoding="utf-8").lower()
|
||||||
|
for forbidden in ("pyusb", "usb.core", "9588", "9899", "frame", "mark"):
|
||||||
|
self.assertNotIn(forbidden, script)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
7
upstreams/rayforge.json
Normal file
7
upstreams/rayforge.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "Rayforge",
|
||||||
|
"repository": "https://github.com/barebaric/rayforge.git",
|
||||||
|
"commit": "c28918c87f8273dd1d244f5a057addc192807fa5",
|
||||||
|
"license": "MIT",
|
||||||
|
"purpose": "Pinned host application for offline reuse and JCZ addon validation"
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue