Skip to content
Closed

Dev #13460

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/scripts/.package.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,16 @@ package() {
local commit_hash

if [[ -d ${project_root}/.git ]] {
local git_description="$(git describe --tags --long)"
# `|| true` keeps ERR_RETURN/TRAPZERR from firing (and leaking the
# callstack into the variable) when the fork has no tags reachable.
local git_description="$(git describe --tags --long 2>/dev/null || true)"
if [[ -z ${git_description} ]] {
# obs-studio-plus fork fallback: synthesize <version>-<distance>-g<sha>
# from the commit count and short HEAD hash so packaging proceeds.
local _short_hash="$(git rev-parse --short=9 HEAD)"
local _commit_count="$(git rev-list --count HEAD)"
git_description="0.0.1-${_commit_count}-g${_short_hash}"
}
commit_version="${${git_description%-*}%-*}"
commit_hash="${git_description##*-g}"
commit_distance="${${git_description%-*}##*-}"
Expand Down
10 changes: 9 additions & 1 deletion .github/scripts/Package-Windows.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ function Package {

Install-BuildDependencies -WingetFile "${ScriptHome}/.Wingetfile"

$GitDescription = Invoke-External git describe --tags --long
# obs-studio-plus fork: tolerate missing tags (git describe --tags fails
# when no tag is reachable). Fall back to <version>-<commit-count>-g<sha>.
$GitDescription = $null
try { $GitDescription = Invoke-External git describe --tags --long } catch { }
if ( -not $GitDescription ) {
$ShortHash = (Invoke-External git rev-parse --short=9 HEAD).Trim()
$CommitCount = (Invoke-External git rev-list --count HEAD).Trim()
$GitDescription = "0.0.1-${CommitCount}-g${ShortHash}"
}
$Tokens = ($GitDescription -split '-')
$CommitVersion = $Tokens[0..$($Tokens.Count - 3)] -join '-'
$CommitHash = $($Tokens[-1]).SubString(1)
Expand Down
99 changes: 99 additions & 0 deletions .github/workflows/no-core-changes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: No Core Changes
# Enforces the Mosaic fork rule: libobs/, plugins/, deps/, and the C++/Qt
# parts of frontend/ track upstream OBS Studio untouched. Only files under
# engine/, CI infrastructure, and explicitly-allowlisted fork-specific
# build fixes may diverge.
#
# See CONTRIBUTING.md for the full policy.

on:
push:
branches:
- dev
- 'engine/**'
pull_request:
branches:
- dev
- master

permissions:
contents: read

jobs:
diff-against-upstream:
name: Diff Against Upstream OBS
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 0

- name: Add upstream remote
run: |
git remote add upstream https://github.com/obsproject/obs-studio.git
git fetch --depth=200 upstream master

- name: Check off-limits paths
run: |
set -euo pipefail

# Off-limits paths (see CONTRIBUTING.md).
OFF_LIMITS=(
'libobs/'
'libobs-d3d11/'
'libobs-opengl/'
'libobs-winrt/'
'plugins/'
'deps/'
)

# Frontend is special: only the C++/Qt code is off-limits. The
# frontend/cmake/os-linux.cmake flatpak fix is allowlisted below.
# We restrict to actual source files, not cmake.
OFF_LIMITS+=(
'frontend/*.cpp'
'frontend/*.hpp'
'frontend/*.h'
'frontend/*.mm'
'frontend/*.swift'
'frontend/data/'
'frontend/dialogs/'
'frontend/docks/'
'frontend/forms/'
'frontend/idian/'
'frontend/menu/'
'frontend/models/'
'frontend/oauth/'
'frontend/plugins/'
'frontend/settings/'
'frontend/utility/'
'frontend/widgets/'
'frontend/window-basic-main.*'
)

MERGE_BASE=$(git merge-base upstream/master HEAD)
echo "Merge base with upstream/master: ${MERGE_BASE}"

# Find any diff in off-limits paths.
CHANGED=$(git diff --name-only "${MERGE_BASE}" HEAD -- "${OFF_LIMITS[@]}" || true)

if [[ -z "${CHANGED}" ]]; then
echo '✅ No core changes detected. Fork rule respected.'
exit 0
fi

echo '❌ The following files were modified in off-limits paths:'
echo '---'
echo "${CHANGED}"
echo '---'
echo ''
echo 'See CONTRIBUTING.md ("Mosaic — Fork Contribution Rules").'
echo 'OBS core (libobs, plugins, frontend C++) tracks upstream untouched.'
echo ''
echo 'Options:'
echo ' 1. Move the change into engine/ (preferred)'
echo ' 2. File the change upstream first (obsproject/obs-studio)'
echo ' 3. If the change is genuinely fork-specific build/CI infrastructure'
echo ' and would be accepted upstream as a robustness fix, update'
echo ' CONTRIBUTING.md to allowlist it explicitly.'
exit 1
9 changes: 8 additions & 1 deletion .github/workflows/push.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
name: Push
# Mosaic fork: triggers on dev and engine/** branches
run-name: ${{ github.ref_name }} push run 🚀
on:
push:
paths-ignore:
- '**.md'
- '**.rst'
- 'AUTHORS'
- 'COPYING'
branches:
- master
- 'release/**'
- dev
- 'feature/**'
tags:
- '*'
workflow_dispatch:
permissions:
contents: write
jobs:
check-format:
name: Format 🔍
if: github.ref_name == 'master'
if: github.ref_name == 'master' || github.ref_name == 'dev' || startsWith(github.ref_name, 'feature/')
uses: ./.github/workflows/check-format.yaml
permissions:
contents: read
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
!COPYING
!INSTALL
!README.rst
!ROADMAP.md
!MOSAIC_PLAN.md
!/engine

# Exclude lock files
*.lock.json
Expand Down
125 changes: 125 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,128 @@
Mosaic — Fork Contribution Rules
================================

> The section below is **specific to this fork** (`OgBops/mosaic`).
> Upstream OBS Studio's full contribution guide follows further down and
> applies to any code that is intended to be submitted upstream.

This repository hosts `mosaic-host`, the engine for the Mosaic desktop
app. Mosaic is a separate user-facing product (separate repository,
future). This fork exists for one reason: produce a headless
`mosaic-host` binary that runs the upstream broadcasting engine in a
sidecar process and exposes its functionality over IPC.

## The hard rule: upstream broadcasting code is read-only

We do **not** modify the upstream broadcasting engine, its plugins, or
any code that ships as part of upstream OBS Studio. The fork's value is
in keeping the upstream code unmodified so upstream changes merge cleanly
forever.

### Off-limits paths

| Path | What it is |
|------|-----------|
| `libobs/` | The upstream broadcasting engine |
| `libobs-d3d11/`, `libobs-opengl/`, `libobs-winrt/` | Engine GPU backends |
| `plugins/` | Every upstream encoder, capture source, filter, output |
| `frontend/` (C++/Qt code) | Upstream Qt UI. We don't link it; we also don't modify it. |
| `deps/` | Third-party dependencies as upstream ships them |

### Allowed playgrounds

| Path | Purpose |
|------|---------|
| `engine/` | All Mosaic engine code (IPC server, host wrapper). New code lives here. |
| `.github/workflows/`, `.github/scripts/`, `.github/actions/` | CI infrastructure |
| `cmake/common/versionconfig.cmake` | Already-shipped fork-specific build robustness fix |
| `frontend/cmake/os-linux.cmake` | Already-shipped flatpak metadata fix |
| `*.md`, `*.rst`, `AUTHORS`, `COPYING` | Documentation and licensing |
| `build-aux/` | Project tooling |

### Smell test

Before any commit outside `engine/`:

> "Would this change still be correct if we deleted the entire fork tomorrow
> and submitted it upstream as a PR?"

If yes, fine. If no, you're modifying upstream code. Stop.

## What if the upstream engine is genuinely missing what we need?

We file the change **upstream first**.

1. Search [obsproject/obs-studio issues](https://github.com/obsproject/obs-studio/issues)
for prior discussion.
2. Open an upstream PR or issue with the API change request.
3. Wait for upstream review.
4. Once accepted upstream, sync via `master`.

We do not carry local core patches. The discipline is the point.

## Where Mosaic engine code goes

```
engine/
├─ host/ # mosaic-host binary: links the upstream engine, runs IPC server
│ ├─ ipc/ # newline-JSON IPC protocol implementation
│ ├─ methods/ # IPC method handlers (capture, output, scenes...)
│ └─ main.cpp # entry point
├─ protocol/ # IPC protocol schema (shared definitions)
└─ spike/ # Phase 0 throwaway code (deleted at end of phase 0)
```

## CI enforcement

The workflow `.github/workflows/no-core-changes.yaml` runs on every push to
`dev` and `engine/**`. It diffs against `upstream/master` and fails the
build if any off-limits path has changed beyond explicitly-allowlisted
commits.

To intentionally update the allowlist (rare — only for upstream-able
fork-specific build/CI fixes), edit the allowlist in the workflow itself
and reference the upstream issue or PR.

## Branding separation (trademark)

"OBS" and "OBS Studio" are trademarks of the OBS Project. Mosaic is an
independent project and does not redistribute upstream-branded binaries.
Specifically:

- The Mosaic desktop app, when it exists, has its own name, icon, and
bundle identifier — it never ships as "OBS.app" or
`com.obsproject.obs-studio`.
- This repository's `master` branch carries upstream code with its
original branding, but `master` is never tagged or released from this
repository.
- The CI artifacts produced from `dev` are for our own development
verification only and are not redistributed publicly.
- Any release artifact from this repository must be built from
`engine/`-only code, or from a `dev` HEAD where the build has been
explicitly re-branded.

## Branching

| Branch | Purpose |
|--------|---------|
| `master` | Tracks upstream OBS Studio. Untouched. |
| `dev` | Integration branch. Mosaic docs, CI, the engine entry points land here. |
| `engine/<name>` | Active engine work. Branch off `dev`. |
| `engine/spike` | Phase 0 spike. Temporary; deleted after the spike retro. |

Open work-in-progress PRs against `dev`, never `master`.

## License

Files in `engine/` are licensed under the GPL v2 or later, same as the
upstream broadcasting source, because they link the upstream engine.

The Mosaic app (separate repository) does **not** link the upstream
engine — it communicates with `mosaic-host` over IPC — and is therefore
not subject to GPL. That separation is load-bearing. Keep it that way.

---

OBS Studio Contribution Guidelines
============

Expand Down
Loading
Loading