Files
Toastconcern--FrameStudio/.github/workflows/build.yml
T

204 lines
8.3 KiB
YAML

# Builds Frame Studio for every computer it runs on, plus a same-commit Frame Home payload, on branch pushes,
# pull requests, and by hand (Actions > build > Run workflow). A push to main replaces the Studio "latest" pre-release
# and includes the Frame Home installer. A tag "v*" publishes a versioned release containing both products.
name: build
on:
push:
branches: ['**']
tags: ['v*']
pull_request:
workflow_dispatch:
permissions:
contents: read
# A newer push to the same branch replaces a run still going (its builds would be out of date anyway).
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true
# Every Studio build knows the commit it's from (studio/updater.h compares it with the latest release's).
env:
FRAME_BUILD: ${{ github.sha }}
FRAME_HOME_PAYLOAD_DIR: ${{ github.workspace }}/build/frame-home/payload
jobs:
linux:
name: Linux ${{ matrix.arch }}
needs: [frame-home]
strategy:
fail-fast: false
matrix:
include:
- { arch: x64, runner: ubuntu-24.04, extra: "" }
- { arch: x86, runner: ubuntu-24.04, i386: true,
extra: "gcc-multilib g++-multilib libx11-dev:i386 libxrandr-dev:i386 libxinerama-dev:i386 libxcursor-dev:i386 libxi-dev:i386" }
- { arch: arm64, runner: ubuntu-24.04-arm, extra: "" }
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: FrameHome-payload
path: build/frame-home/payload
- name: Tools and X11 headers
run: |
# x86 links against 32-bit X11, so apt needs the i386 packages too
if [ "${{ matrix.i386 }}" = "true" ]; then sudo dpkg --add-architecture i386; fi
sudo apt-get update
sudo apt-get install -y ninja-build cmake libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxkbcommon-dev ${{ matrix.extra }}
- name: Build
run: sh scripts/build-studio.sh linux-${{ matrix.arch }}
- uses: actions/upload-artifact@v4
with:
name: FrameStudio-linux-${{ matrix.arch }}
path: dist/FrameStudio-linux-${{ matrix.arch }}.tar.gz
windows:
name: Windows ${{ matrix.arch }}
needs: [frame-home]
strategy:
fail-fast: false
matrix:
arch: [x64, x86, arm64]
runs-on: windows-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: FrameHome-payload
path: build/frame-home/payload
- name: Build (MSVC)
shell: cmd
run: studio\build_windows.bat ${{ matrix.arch }} "%GITHUB_WORKSPACE%\build\windows-${{ matrix.arch }}"
- name: Package
shell: pwsh
run: |
$name = "FrameStudio-windows-${{ matrix.arch }}"
$stage = "build/stage/$name"
New-Item -ItemType Directory -Force $stage | Out-Null
Copy-Item "build/windows-${{ matrix.arch }}/Frame Studio.exe" $stage
Copy-Item -Recurse "build/windows-${{ matrix.arch }}/frame" "$stage/frame"
Copy-Item LICENSE "$stage/LICENSE.txt"
New-Item -ItemType Directory -Force dist | Out-Null
Compress-Archive -Path $stage -DestinationPath "dist/$name.zip" -Force
- uses: actions/upload-artifact@v4
with:
name: FrameStudio-windows-${{ matrix.arch }}
path: dist/FrameStudio-windows-${{ matrix.arch }}.zip
macos:
name: macOS ${{ matrix.arch }}
needs: [frame-home]
strategy:
fail-fast: false
matrix:
include:
- { arch: arm64, runner: macos-14 }
# Intel: macos-13 was retired (Dec 2025); macos-15-intel is GitHub's last Intel Mac runner (until Aug 2027).
# Not cross-built on an ARM Mac because Homebrew's MoltenVK, bundled into the app, is the runner's own arch.
- { arch: x64, runner: macos-15-intel }
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: FrameHome-payload
path: build/frame-home/payload
- name: Tools and MoltenVK (Vulkan on Metal, bundled into the app)
run: brew install ninja molten-vk
- name: Build
run: sh scripts/build-studio.sh macos-${{ matrix.arch }}
- uses: actions/upload-artifact@v4
with:
name: FrameStudio-macos-${{ matrix.arch }}
path: dist/FrameStudio-macos-${{ matrix.arch }}.zip
frame-home:
name: Build Frame Home payload
runs-on: ubuntu-24.04-arm
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- name: Install Frame Home build dependencies
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y cmake ninja-build gcc-13 g++-13 glslc zip
- name: Build payload and installer
run: sh scripts/build-frame-home.sh --ci
- uses: actions/upload-artifact@v4
with:
name: FrameHome-payload
path: build/frame-home/payload
- uses: actions/upload-artifact@v4
with:
name: FrameHome-installer
path: build/frame-home/FrameHome-installer.zip
if-no-files-found: error
- uses: actions/upload-artifact@v4
with:
name: FrameHome-build-info
path: build/frame-home/build-info.txt
if-no-files-found: error
release:
name: Publish
# "latest" gets every build that finished (a failed or still-slow platform just isn't in it); a version release
# needs them all. We don't wait on macOS: its runners can sit in GitHub's queue for hours, and since a push
# cancels the previous run, waiting meant no run ever reached this job. Both Mac builds still upload and are
# attached whenever they finish in time.
if: ${{ !cancelled() && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') }}
needs: [linux, windows, frame-home]
runs-on: ubuntu-24.04
timeout-minutes: 20
permissions:
contents: write
id-token: write
attestations: write
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
steps:
- uses: actions/download-artifact@v4
with:
pattern: FrameStudio-*
path: dist
merge-multiple: true
- uses: actions/download-artifact@v4
with:
name: FrameHome-payload
path: ${{ runner.temp }}/frame-home-payload
- uses: actions/download-artifact@v4
with:
name: FrameHome-installer
path: dist
# What Frame Studio (studio/updater.h) and the headset's Environments panel check for updates: this commit,
# Frame Home's identity (a hash of the headset programs, the same one the panel works out for what's installed)
# and the files in this release.
- name: latest.json
run: |
home=$(cd "$RUNNER_TEMP/frame-home-payload" && sha256sum bin/frame-home bin/frame-switcher bin/fenv-tool layer/libframe_home_layer.so layer/env_ps.spv | cut -c1-64 | sha256sum | cut -c1-64)
files=$(ls dist | python3 -c 'import json, sys; print(json.dumps([l.strip() for l in sys.stdin if l.strip()]))')
printf '{"build": "%s", "home": "%s", "date": "%s", "files": %s}\n' "$GITHUB_SHA" "$home" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$files" > dist/latest.json
cat dist/latest.json
- uses: actions/attest-build-provenance@v2
with:
subject-path: dist/FrameStudio-*
- uses: actions/attest-build-provenance@v2
with:
subject-path: dist/FrameHome-installer.zip
- name: Version release (tag v*)
if: ${{ startsWith(github.ref, 'refs/tags/v') && !contains(needs.*.result, 'failure') }}
run: gh release create "${{ github.ref_name }}" dist/* --repo "$REPO" --title "Frame Studio ${{ github.ref_name }}" --generate-notes
- name: Latest build (push to main)
if: github.ref == 'refs/heads/main'
run: |
gh release delete latest --repo "$REPO" --yes --cleanup-tag 2>/dev/null || true
gh release create latest dist/* --repo "$REPO" --prerelease --target "${{ github.sha }}" \
--title "Latest build (${GITHUB_SHA::7})" \
--notes "Built automatically from ${{ github.sha }} on $(date -u '+%Y-%m-%d %H:%M UTC'). Replaced by every push to main."