name: Build # Every job builds the real plugin: the core library linked against the # pinned livekit/client-sdk-cpp release, and -- where libobs is available -- # the OBS adapter module itself. # # Linux gets libobs from Ubuntu's libobs-dev. macOS and Windows have no # equivalent system package, so they run obs-plugintemplate's buildspec # bootstrap (buildspec.json + cmake/common/buildspec_common.cmake), which # downloads the pinned obs-deps bundle and obs-studio source and builds just # `libobs`. That step is the slow one: several minutes on a cold runner. # # The actual per-platform dependency-install and configure/build/test/verify # commands live in .gitea/scripts/ and are shared with # .gitea/workflows/release.yml, so the two workflows can't drift apart -- # edit the scripts, not either workflow, to change how a platform builds. # # RELEASE GATE: this workflow only builds, tests, and uploads CI-internal # workflow artifacts (actions/upload-artifact, below) -- it does not create a # Gitea Release, push a tag-triggered publish, or otherwise distribute # binaries publicly, and it must not start doing so without explicit owner # sign-off on the WebRTC/OpenH264 attribution question tracked in # third_party/livekit/README.md and the README's top-level Status section. # (The separate GPLv2/Apache-2.0 license-compatibility question is resolved: # this project's own code is Apache-2.0.) If a real release/publish step is # ever added here, it must carry that same gate. # # (.gitea/workflows/release.yml is that publish step, gated on a pushed # version tag rather than on every push -- see the gate reminder baked into # its generated release notes.) on: push: # Excludes tag pushes -- a bare `push:` matches every ref push, tags # included, which meant tagging a release triggered THIS workflow's full # 3-platform build (Windows and all) at the same time as # release.yml's own -- two full Windows builds serialized behind the # runner's capacity:1, for one tag push. release.yml already covers # exactly this build (plus packaging) on every `v*` tag; this workflow's # job is ordinary commits. branches: - "**" pull_request: jobs: linux: name: Linux (ubuntu-24.04) # Pinned to 24.04 rather than ubuntu-latest, which this instance's two # Linux runners answer with different releases. 24.04's libobs-dev is # 30.0.2, exactly the OBS version buildspec.json pins for macOS/Windows, # so all three platforms build against the same libobs. On a 22.04 runner # libobs-dev is OBS 27, which is a different API surface entirely. runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Install build dependencies run: .gitea/scripts/linux-deps.sh - name: Configure, build, test, verify run: .gitea/scripts/linux-build.sh - name: Upload plugin continue-on-error: true uses: actions/upload-artifact@v3 with: name: streamer-tools-camera-linux-x64 path: build/package macos: name: macOS (macos-latest) runs-on: macos-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Install build dependencies run: .gitea/scripts/macos-deps.sh - name: Cache OBS SDK bootstrap deps # cmake/macos/buildspec.cmake downloads the pinned obs-deps bundle + # obs-studio source into .deps/ and already skips re-downloading via # SHA256 marker files -- but .deps/ lives inside the checkout, so a # fresh `actions/checkout` above wipes it every run regardless. This # cache step is what actually makes that existing skip-logic apply # across runs. The runner's built-in cache server is on by default # (cache.enabled: true), so this needs no runner-side config. uses: actions/cache@v4 with: path: .deps key: obs-deps-${{ runner.os }}-${{ hashFiles('cmake/macos/buildspec.cmake', 'cmake/common/buildspec_common.cmake', 'buildspec.json') }} - name: Configure, build, test, verify run: .gitea/scripts/macos-build.sh - name: Drop non-relocatable OBS build tree before caching # cmake/common/buildspec_common.cmake's obs-studio sub-build writes # an out-of-source CMakeCache.txt (.deps/obs-studio-*/build_*) that # bakes in this job's absolute checkout path. The next run's # checkout lands at a *different* absolute path, so restoring that # directory from the cache above makes CMake refuse to reconfigure # it ("CMakeCache.txt directory ... is different than the directory # ... where CMakeCache.txt was created"). Everything that actually # needs to survive between runs -- the extracted source, and the # already-installed libobs package under .deps/cmake, .deps/include, # .deps/lib -- has no such path baked in and is unaffected. Delete # only the intermediate build tree, after it has already done its # job (libobs is built and installed by this point), so the cache # saved at the end of this job contains nothing that requires the # path it was created under. if: always() continue-on-error: true run: rm -rf .deps/obs-studio-*/build_* - name: Upload plugin continue-on-error: true uses: actions/upload-artifact@v3 with: name: streamer-tools-camera-macos path: build/package windows: name: Windows (windows-latest) runs-on: windows-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Verify build dependencies # winvm-builder is a self-hosted act_runner labeled "windows-latest"; # it is NOT the GitHub-hosted image, so none of that image's # preinstalled tooling can be assumed present. This used to be # `uses: lukka/get-cmake@latest`, which re-downloaded and # re-extracted CMake + Ninja on every single run -- its own cache # (routed through this act_runner's cache server) reported a "cloud # cache miss" on every run even immediately after a successful save, # and separately the extraction step alone measured ~7.5 minutes on # this VM (consistent with Defender real-time scanning, not raw I/O) # -- together the dominant cost of every Windows CI run. CMake and # Ninja are now installed once, directly on winvm-builder's system # PATH (C:\BuildTools\cmake\bin, C:\BuildTools\ninja -- see the # README's "Windows runner: persistent build tools" section for # exactly what that machine has installed and how to redo it if the # VM is ever rebuilt). This step just fails loudly if that ever # stops being true, rather than silently falling back to a slow # re-download. shell: powershell run: | $ErrorActionPreference = "Stop" cmake --version ninja --version - name: Cache OBS SDK bootstrap deps # See the matching step in the macOS job above for why this is # needed: cmake/windows/buildspec.cmake's own download logic is # already idempotent, it just never gets the chance because .deps/ # lives inside the checkout and is wiped by every fresh clone. uses: actions/cache@v4 with: path: .deps key: obs-deps-${{ runner.os }}-${{ hashFiles('cmake/windows/buildspec.cmake', 'cmake/common/buildspec_common.cmake', 'buildspec.json') }} - name: Configure, build, test, verify # Windows PowerShell (powershell.exe), not PowerShell Core (pwsh) -- # this self-hosted runner does not have pwsh installed, only the # in-box Windows PowerShell 5.1 the original inline steps implicitly # ran under. shell: powershell run: ./.gitea/scripts/windows-build.ps1 - name: Drop non-relocatable OBS build tree before caching # See the matching step in the macOS job above. Confirmed live on # this runner: caching .deps/obs-studio-30.0.2/build_x86 as-is made # every run's first configure attempt fail with a path mismatch # against the job that populated the cache, falling back to # -DSTPLUGIN_BOOTSTRAP_OBS=OFF and only succeeding because the # already-installed libobs package (path-independent) was still # found. That fallback masked the problem behind a misleading # "::warning::OBS SDK bootstrap failed" every run instead of fixing # it. Deleting the build tree here, after libobs is already built # and installed, is the actual fix. if: always() continue-on-error: true shell: powershell run: Remove-Item -Recurse -Force .deps\obs-studio-*\build_* -ErrorAction SilentlyContinue - name: Upload plugin continue-on-error: true uses: actions/upload-artifact@v3 with: name: streamer-tools-camera-windows-x64 path: build/package