Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
cce5c7f
Initial plan
Copilot Mar 21, 2026
517e229
Add game_state module and WebSocket game broadcasting support
Copilot Mar 21, 2026
77867ee
Fix misleading comment in json_append_field buffer check
Copilot Mar 21, 2026
a42d6df
Refactor RetroAchievements integration: centralize WebSocket state up…
kzryzstof Mar 21, 2026
a86209f
Add WebSocket support for broadcasting RetroAchievements data
kzryzstof Mar 21, 2026
2cd683f
Refactor WebSocket server: simplify message queuing, unify game state…
kzryzstof Mar 21, 2026
56dc0d3
Add WebSocket broadcast support for RetroAchievements user information
kzryzstof Mar 21, 2026
1581db9
Add support for serializing achievement descriptions in game state JS…
kzryzstof Mar 22, 2026
6125d05
Filter core achievements by subset in game state JSON serialization
kzryzstof Mar 22, 2026
4926f2e
Filter core achievements by subset in game state JSON serialization
kzryzstof Mar 22, 2026
1bda13f
Add playlist-based cover URL generation in game state updates
kzryzstof Mar 23, 2026
c39f482
Ensure WebSocket notifications are properly sent on game unload and a…
kzryzstof Mar 25, 2026
85257b8
Merge branch 'main' into copilot/add-game-info-in-memory
kzryzstof Apr 4, 2026
57ab935
Include game_state.c in WebSocket server build for MSVC
kzryzstof Apr 4, 2026
34dcc9c
Restrict GitHub Actions workflows to trigger only on 'main' branch pu…
kzryzstof Apr 4, 2026
9e5c80f
Add workflow to automate builds and release creation across platforms
kzryzstof Apr 4, 2026
d04c08e
Fix workflow syntax issues in 'Build.yml' for run-name and checksum g…
kzryzstof Apr 4, 2026
e4617b4
Remove 'pull_request' trigger from 'Build.yml' workflow
kzryzstof Apr 4, 2026
4b65730
Update GitHub Actions workflows to use latest action versions
kzryzstof Apr 4, 2026
445c619
Add binary caching and staging for upload jobs in GitHub Actions work…
kzryzstof Apr 5, 2026
fd21cbc
Remove binary caching and staging steps; update action versions in wo…
kzryzstof Apr 5, 2026
fdcaa4a
Update Linux CI workflow to x86_64, improve build steps, and disable …
kzryzstof Apr 5, 2026
4bf9478
Disable Windows build jobs in GitHub Actions workflow
kzryzstof Apr 5, 2026
9505ef8
Disable 'pull_request' triggers in all GitHub Actions workflows
kzryzstof Apr 5, 2026
93505d3
Simplify Linux CI workflow build configuration and consolidate build …
kzryzstof Apr 5, 2026
d16d42f
Update Linux CI to adjust build flags for D-Bus configuration
kzryzstof Apr 5, 2026
f64051f
Add `libx11-xcb-dev` to dependencies in Linux CI workflow
kzryzstof Apr 5, 2026
ec13ace
Update MacOS CI workflow to bundle release with assets and adjust art…
kzryzstof Apr 5, 2026
72db017
Enable auto-generated release notes and remove unused MacOS release a…
kzryzstof Apr 5, 2026
2e3e055
Add Windows ARM64 release bundling and installer generation steps to …
kzryzstof Apr 5, 2026
937ca8a
Add Windows x64 release bundling, asset inclusion, and installer gene…
kzryzstof Apr 5, 2026
377194f
Update CI workflows to switch Windows x64 to MinGW and streamline Win…
kzryzstof Apr 6, 2026
39cb120
Enable `pull_request` triggers in all GitHub Actions workflows
kzryzstof Apr 6, 2026
f7c78c5
For now, deactivate the assets.
kzryzstof Apr 6, 2026
e479b26
Disable `pull_request` triggers in all workflows and add MacOS releas…
kzryzstof Apr 6, 2026
4d0bea8
Uncomment Linux and Windows x64 build jobs in GitHub Actions workflow
kzryzstof Apr 6, 2026
a8d2569
Refactor upstream sync workflow to focus on canary testing; add detai…
kzryzstof Apr 6, 2026
75a3f57
Merge branch 'main' into copilot/add-game-info-in-memory
kzryzstof Apr 6, 2026
d3a54bb
Enable `pull_request` triggers in all GitHub Actions workflows
kzryzstof Apr 6, 2026
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
213 changes: 213 additions & 0 deletions .github/BRANCHING-STRATEGY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Branching Strategy for your RetroArch fork

## Core Concepts

Before reading further, understand these three things:

### What is a rebase?
A rebase takes your commits and **replays them on top of a different base commit**,
keeping history linear. Instead of a merge commit, your work simply moves forward:
```
Before: [RA v1.22.2] ── [your feature A] ── [your feature B]
After: [RA v1.23.0] ── [your feature A'] ── [your feature B']
```
Your features travel forward automatically. Requires `git push --force-with-lease`
because history is rewritten.

### What is a merge?
A merge joins two branches with a **merge commit**, preserving both histories.
Simpler than rebase, no force-push needed, but history accumulates merge commits
over time and becomes harder to read.

### Why rebase for this fork?
Because you are the sole developer, the force-push risk is zero. Rebase keeps
`main` perfectly readable: upstream commits first, then your commits on top —
making it immediately obvious what you've added versus upstream.

---

## The Four Concerns

| Concern | Lives where |
|---|---|
| Upstream RA source snapshots (read-only) | `retroarch-releases/<tag>` |
| Early breakage detection | `octelys/upstream-sync` (robot-owned, never touch directly) |
| Your custom features | `feature/<name>` branches → PR → `main` |
| Your fork releases | `main` → tagged |

---

## Branch Map

```
libretro/RetroArch
├── master ──────────────────────────────────────► octelys/upstream-sync
│ daily, via upstream-sync.yml Robot-owned canary branch.
│ Contains: upstream master
│ + your feature commits on top.
│ CI runs here.
│ NEVER develop or commit here directly.
│ NEVER merge this PR into main.
│ Force-overwritten every day.
├── tag v1.22.2 ──► retroarch-releases/v1.22.2 Read-only upstream snapshot.
│ via release-branch-sync.yml Used ONLY as a rebase target
│ for main. Never commit here.
└── tag v1.23.0 ──► retroarch-releases/v1.23.0 (same)
│ YOU manually rebase main onto this
│ when ready to absorb the new release
main: [v1.23.0 code] ── [feature A'] ── [feature B']
│ │
│ you branch off here git tag octelys.1
│ │
├── feature/ws-server ──► PR ──► main ▼
├── feature/achievement-events ► PR ──► main GitHub Release
└── feature/... "RetroArch 1.23.0-octelys.1"
```

---

## The two automated pipelines

### Pipeline 1 — `upstream-sync.yml` (daily canary)

**Trigger:** every day at 06:00 UTC, or manually.

**What it does:**
1. Fetches the latest upstream `master`
2. Creates branch `octelys/upstream-sync` = upstream master + your feature commits from `main` cherry-picked on top
3. Force-pushes it (overwrites yesterday's canary)
4. Opens (or updates) a PR so CI runs against it

**What you do with it:**
- ✅ CI green → your features are compatible with today's upstream. Close the PR.
- ❌ CI red → upstream broke something. Fix your `feature/*` branch, merge it into `main`. The next daily run will reopen a fresh canary.
- 🚫 Never merge this PR into `main`.
- 🚫 Never commit to `octelys/upstream-sync` directly.

---

### Pipeline 2 — `release-branch-sync.yml` (release tracker)

**Trigger:** every day at 07:00 UTC, or manually (you can supply a specific tag).

**What it does:**
1. Fetches the latest upstream release tag (e.g. `v1.23.0`)
2. Checks whether `retroarch-releases/v1.23.0` already exists in your fork
3. If not, creates and pushes it at the exact release commit SHA

**What you do with it:**
- When you see a new `retroarch-releases/<tag>` branch appear, that is your signal
that a new upstream release has shipped and you can absorb it into `main`.
- 🚫 Never commit to these branches.

---

## Step-by-step: absorbing a new upstream release into main

> Do this after a new `retroarch-releases/<tag>` branch has appeared AND the
> daily canary CI is green (your features are confirmed compatible).

```zsh
# 1. Pull the new release branch from your fork
git fetch origin retroarch-releases/v1.23.0

# 2. Switch to main
git checkout main

# 3. Rebase your feature commits on top of the new upstream release
git rebase origin/retroarch-releases/v1.23.0

# 4. If conflicts appear during rebase:
# For .github/workflows — always keep YOUR version:
# git checkout --ours .github/workflows/
# git add .github/workflows/
# git rebase --continue
# For source files — resolve manually, then:
# git add <resolved-file>
# git rebase --continue

# 5. Push (force required because rebase rewrites commit SHAs)
git push origin main --force-with-lease
```

After this, `main` = `[RA v1.23.0 code] + [your features]`. ✅

---

## Step-by-step: publishing a fork release

> Do this after main has been rebased onto the desired upstream release.

```zsh
# Your tag is just your own suffix.
# Build.yml automatically fetches the upstream version and prepends it.
git tag octelys.1
git push origin octelys.1
# → Build.yml fires → GitHub Release created: "RetroArch 1.23.0-octelys.1"
```

To publish a second release on the same upstream version:
```zsh
git tag octelys.2
git push origin octelys.2
# → GitHub Release: "RetroArch 1.23.0-octelys.2"
```

---

## Step-by-step: developing a new feature

```zsh
# 1. Branch off main (which is already on top of the latest upstream release)
git checkout -b feature/my-new-thing main

# 2. Work, commit as usual
git add .
git commit -m "feat: my new thing"

# 3. Push and open a PR into main
git push origin feature/my-new-thing
# → Open PR on GitHub: feature/my-new-thing → main
```

---

## What each branch is — quick reference

| Branch | Owner | Purpose | Can I commit here? |
|---|---|---|---|
| `main` | You | Latest stable RA release + your features. Release base. | ✅ Yes (via PRs) |
| `feature/<name>` | You | Work-in-progress feature | ✅ Yes |
| `retroarch-releases/<tag>` | Robot | Upstream release snapshot. Rebase target only. | 🚫 No |
| `octelys/upstream-sync` | Robot | Daily canary. CI alarm bell. | 🚫 No |

---

## What each pipeline does — quick reference

| Workflow | Trigger | Role | Touches main? |
|---|---|---|---|
| `upstream-sync.yml` | Daily 06:00 UTC | Canary: upstream master + your features → CI | 🚫 No |
| `release-branch-sync.yml` | Daily 07:00 UTC | Creates `retroarch-releases/<tag>` on new upstream release | 🚫 No |
| `Build.yml` | Your tag push | Builds and publishes fork release. Detects RA version from git history, names release `<upstream-ver>-<your-tag>`. | 🚫 No |
| `MacOS.yml` / `Windows-x64-MXE.yml` / etc. | Called by `Build.yml` or PRs | CI builds | 🚫 No |

---

## Summary

> `retroarch-releases/<tag>` = frozen upstream snapshots — rebase targets, nothing else
>
> `octelys/upstream-sync` = daily robot canary — read CI result, never commit
>
> `main` = **your branch** — latest stable RA release + your features — develop and release from here
>
> `feature/<name>` = short-lived work branches — PR into `main` when done
>
> tags on `main` = your published releases

164 changes: 164 additions & 0 deletions .github/workflows/Build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: Build
run-name: ${{ github.ref_name }} build run

on:
push:
tags:
- '*'
branches:
- main
repository_dispatch:
types: [run_build]

permissions:
contents: write

jobs:

build-linux:
name: Linux (i686)
uses: ./.github/workflows/Linux.yml

build-macos:
name: macOS
uses: ./.github/workflows/MacOS.yml

build-windows-x64:
name: Windows x64 (MXE)
uses: ./.github/workflows/Windows-x64-MXE.yml

#build-windows-arm64:
# name: Windows ARM64 (MSVC)
# uses: ./.github/workflows/Windows-ARM64.yml

create-release:
name: Create Release
if: github.ref_type == 'tag'
runs-on: ubuntu-latest
needs:
#- build-linux
- build-macos
#- build-windows-x64
#- build-windows-arm64
defaults:
run:
shell: bash

steps:
- name: Check Release Tag
id: check
run: |
: Check Release Tag
if [[ "${RUNNER_DEBUG}" ]]; then set -x; fi
shopt -s extglob

# Accept any non-empty tag — the fork uses free-form tags like
# "octelys.1" whose version is built by combining with the
# upstream RA release number. Pre-release is flagged by the
# presence of -beta or -rc anywhere in the tag.
TAG="${GITHUB_REF_NAME}"
if [[ -z "$TAG" ]]; then
echo 'validTag=false' >> $GITHUB_OUTPUT
else
echo 'validTag=true' >> $GITHUB_OUTPUT
if [[ "$TAG" =~ -[bB]eta|-[rR][cC] ]]; then
echo 'prerelease=true' >> $GITHUB_OUTPUT
else
echo 'prerelease=false' >> $GITHUB_OUTPUT
fi
fi

- name: Checkout repository
if: fromJSON(steps.check.outputs.validTag)
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Resolve upstream RetroArch version from git history
id: upstream
if: fromJSON(steps.check.outputs.validTag)
run: |
: Resolve upstream RetroArch version from git history
# Add upstream remote and fetch all release tags
git remote add upstream https://github.com/libretro/RetroArch.git
git fetch upstream 'refs/tags/v*:refs/tags/upstream-v*' --no-tags 2>/dev/null || true

# Find the most recent upstream tag that is an ancestor of HEAD.
# This tells us exactly which RA release main was rebased onto.
RA_TAG=$(git tag --list 'upstream-v*' --sort=-version:refname \
| while read -r t; do
if git merge-base --is-ancestor "$t" HEAD 2>/dev/null; then
echo "$t"
break
fi
done)

# Strip the 'upstream-' prefix we added during fetch, then strip 'v'
RA_TAG="${RA_TAG#upstream-}"
RA_VERSION="${RA_TAG#v}"

if [[ -z "$RA_VERSION" ]]; then
echo "::warning::Could not determine upstream RA version from git history. Falling back to API."
RA_VERSION=$(curl -fsSL \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ github.token }}" \
https://api.github.com/repos/libretro/RetroArch/releases/latest \
| jq -r '.tag_name // empty' | sed 's/^v//')
fi

echo "ra_version=${RA_VERSION}" >> $GITHUB_OUTPUT
echo "Detected upstream RA version: ${RA_VERSION}"

- name: Build combined version string
id: ver
if: fromJSON(steps.check.outputs.validTag)
run: |
: Build combined version string
MY_TAG="${GITHUB_REF_NAME}"
RA="${{ steps.upstream.outputs.ra_version }}"
COMBINED="${RA}-${MY_TAG}"
echo "version=${COMBINED}" >> $GITHUB_OUTPUT

- name: Download Build Artifacts
uses: actions/download-artifact@v4
if: fromJSON(steps.check.outputs.validTag)
id: download

- name: Rename artifacts to versioned names
if: fromJSON(steps.check.outputs.validTag)
run: |
: Rename artifacts to versioned names
if [[ "${RUNNER_DEBUG}" ]]; then set -x; fi
shopt -s extglob
VERSION="${{ steps.ver.outputs.version }}"
for f in **/retroarch-macos-*.zip; do
dir=$(dirname "$f")
mv "$f" "${dir}/retroarch-macos-${VERSION}.zip"
done

- name: Generate Checksums
if: fromJSON(steps.check.outputs.validTag)
run: |
: Generate Checksums
if [[ "${RUNNER_DEBUG}" ]]; then set -x; fi
shopt -s extglob

echo "### Checksums" > ${{ github.workspace }}/CHECKSUMS.txt
for file in **/@(*.exe|*.tar.gz|*.zip); do
echo " ${file##*/}: $(sha256sum \"${file}\" | cut -d ' ' -f 1)" >> ${{ github.workspace }}/CHECKSUMS.txt
done

- name: Create GitHub Release
if: fromJSON(steps.check.outputs.validTag)
uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564
with:
draft: false
prerelease: ${{ fromJSON(steps.check.outputs.prerelease) }}
tag_name: ${{ github.ref_name }}
name: RetroArch ${{ steps.ver.outputs.version }}
generate_release_notes: true
body_path: ${{ github.workspace }}/CHECKSUMS.txt
files: |
${{ github.workspace }}/**/*.exe
${{ github.workspace }}/**/*.zip
${{ github.workspace }}/**/*.tar.gz
Loading
Loading