Skip to content

Commit 13280ec

Browse files
authored
Merge pull request #33 from openmoq/tarball-deps
Replace getdeps with tarball and standalone build paths
2 parents 582d01c + 8df231f commit 13280ec

9 files changed

Lines changed: 439 additions & 4 deletions

File tree

.github/workflows/ci.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
checks: write
12+
13+
jobs:
14+
build:
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- name: linux
20+
preset: default
21+
build_dir: build
22+
- name: asan debug
23+
preset: san
24+
build_dir: build-san
25+
name: ${{ matrix.name }}
26+
runs-on: ubuntu-22.04
27+
steps:
28+
- uses: actions/checkout@v4
29+
with:
30+
submodules: true
31+
32+
- name: Install system dependencies
33+
run: bash deps/moxygen/standalone/install-system-deps.sh
34+
35+
- name: Download moxygen release tarball
36+
env:
37+
GH_TOKEN: ${{ github.token }}
38+
run: bash scripts/setup-deps-tarball.sh
39+
40+
- name: Configure
41+
run: bash scripts/configure.sh ${{ matrix.build_dir }} ${{ matrix.preset }}
42+
43+
- name: Build
44+
run: cmake --build ${{ matrix.build_dir }} -j$(nproc)
45+
46+
- name: Test
47+
env:
48+
ASAN_OPTIONS: ${{ matrix.name == 'asan debug' && 'detect_leaks=1:abort_on_error=1' || '' }}
49+
run: ctest --test-dir ${{ matrix.build_dir }} --output-on-failure --output-junit test-results.xml
50+
51+
- name: Publish test results
52+
uses: dorny/test-reporter@v1.9.1
53+
if: success() || failure()
54+
with:
55+
name: "test (${{ matrix.name }})"
56+
path: ${{ matrix.build_dir }}/test-results.xml
57+
reporter: java-junit

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ _CPack_Packages/
2424

2525
# OS
2626
.DS_Store
27+
28+
# IDE / tools
29+
.vscode/
30+
.claude/

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ if(ORLY_BUILD_TESTS)
6565
)
6666
target_link_libraries(o_rly_relay_test PRIVATE
6767
o_rly_core
68-
moxygen::moqtest_utils
6968
moxygen::moxygen_events_moq_folly_executor_impl
7069
GTest::gtest_main
7170
GTest::gmock

CMakePresets.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"binaryDir": "${sourceDir}/build",
1414
"cacheVariables": {
1515
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
16-
"CMAKE_FIND_LIBRARY_SUFFIXES": ".a"
16+
"CMAKE_FIND_LIBRARY_SUFFIXES": ".a",
17+
"CMAKE_MODULE_PATH": "${sourceDir}/cmake"
1718
}
1819
},
1920
{
@@ -24,7 +25,8 @@
2425
"cacheVariables": {
2526
"CMAKE_BUILD_TYPE": "Debug",
2627
"ORLY_ENABLE_SANITIZERS": "ON",
27-
"CMAKE_FIND_LIBRARY_SUFFIXES": ".a"
28+
"CMAKE_FIND_LIBRARY_SUFFIXES": ".a",
29+
"CMAKE_MODULE_PATH": "${sourceDir}/cmake"
2830
}
2931
}
3032
],

cmake/Findc-ares.cmake

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Findc-ares.cmake
2+
# Wraps system c-ares for platforms where libc-ares-dev does not install
3+
# cmake config files (e.g. Ubuntu 22.04 with generic cmake >= 3.25 binary).
4+
5+
if(TARGET c-ares::cares)
6+
return()
7+
endif()
8+
9+
find_library(c-ares_LIBRARY NAMES cares)
10+
find_path(c-ares_INCLUDE_DIR NAMES ares.h)
11+
12+
include(FindPackageHandleStandardArgs)
13+
find_package_handle_standard_args(c-ares
14+
REQUIRED_VARS c-ares_LIBRARY c-ares_INCLUDE_DIR
15+
)
16+
17+
if(c-ares_FOUND AND NOT TARGET c-ares::cares)
18+
add_library(c-ares::cares UNKNOWN IMPORTED)
19+
set_target_properties(c-ares::cares PROPERTIES
20+
IMPORTED_LOCATION "${c-ares_LIBRARY}"
21+
INTERFACE_INCLUDE_DIRECTORIES "${c-ares_INCLUDE_DIR}"
22+
)
23+
endif()

deps/moxygen

Submodule moxygen updated 245 files

design/GITHUB_WORKFLOW.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Two-Branch Architecture for openmoq/moxygen
2+
3+
## Context
4+
5+
The current single-branch approach has compounding problems: patches modify
6+
upstream files creating perpetual conflicts, getdeps builds 30+ deps producing
7+
1.7 GB tarballs, and the sync workflow has grown complex. The standalone build
8+
(upstream PR #99, merged) eliminates most of this: no manifests, 5 FetchContent
9+
deps, ~50-150 MB artifacts.
10+
11+
## The Full Flow
12+
13+
### Branches
14+
15+
- **`main`** — Pure upstream mirror. Unmodified copy of latest green upstream
16+
commit. No openmoq files. No workflows run. Not the default branch.
17+
- **`openmoq-main`** (DEFAULT) — Working branch. All openmoq customizations.
18+
Developer PRs go here. Artifacts published from here.
19+
20+
### Daily sync cycle
21+
22+
```
23+
upstream (facebookexperimental/moxygen)
24+
25+
│ 1. Sync workflow scans last 20 commits, picks newest green one
26+
27+
28+
main (pure mirror)
29+
│ 2. Fast-forward push: main = upstream green commit
30+
│ No workflows fire (all disabled on fork)
31+
32+
│ 3. Check: is main already ancestor of openmoq-main?
33+
│ YES → done, nothing to merge
34+
│ NO → continue
35+
36+
37+
PR: main → openmoq-main
38+
│ 4. GitHub App bot creates PR (bot identity, not you)
39+
│ 5. PAT (OMOQ_SYNC_TOKEN) approves PR (different identity, satisfies review)
40+
│ 6. Auto-merge enabled
41+
42+
│ 7. CI fires: standalone build on ubuntu + macOS (PR event)
43+
│ PASS → auto-merge fires → merged to openmoq-main
44+
│ FAIL → PR stays open, Slack alert, developer resolves
45+
46+
47+
openmoq-main (merge lands)
48+
│ 8. Push to openmoq-main triggers publish-artifacts
49+
│ 9. Standalone build on all 4 platforms
50+
│ 10. Release created: build-<sha> with per-platform tarballs
51+
52+
53+
orelay submodule can point to this commit
54+
```
55+
56+
### Developer workflow
57+
58+
Normal trunk-based git. Developers open PRs against `openmoq-main`. CI runs
59+
standalone build. Reviews + merge as usual. Changes persist through upstream
60+
syncs because git merge handles it — once a merge conflict is resolved, the
61+
merge base advances and the same conflict doesn't recur.
62+
63+
Two classes of local mods:
64+
- **Upstreamable**: commit on openmoq-main, PR upstream when ready. When upstream
65+
absorbs it, next sync merge resolves cleanly (or trivial conflict, resolved once).
66+
- **Non-upstreamable**: permanent commits on openmoq-main. Git merge carries them
67+
forward naturally.
68+
69+
### What runs where
70+
71+
| Branch | Workflows | Trigger |
72+
|--------|-----------|---------|
73+
| `main` | **NOTHING** (all upstream workflows disabled) ||
74+
| PR → `openmoq-main` | `openmoq-ci.yml` (standalone build) | `pull_request` |
75+
| `openmoq-main` (push) | `openmoq-publish-artifacts.yml` | `push` |
76+
| `openmoq-main` (cron) | `openmoq-upstream-sync.yml` | `schedule` / `workflow_dispatch` |
77+
78+
---
79+
80+
## Implementation
81+
82+
### Phase 1: Setup (do first, one-time)
83+
84+
**1a. Create GitHub App** (manual, in GitHub UI)
85+
- Go to `https://github.com/organizations/openmoq/settings/apps/new`
86+
- Name: `openmoq-sync-bot` (or similar)
87+
- Permissions: Contents R/W, Pull requests R/W, Workflows R/W
88+
- Webhook: off
89+
- Install on `openmoq/moxygen` only
90+
- Store: `OMOQ_APP_ID` (variable) + `OMOQ_APP_PRIVATE_KEY` (secret)
91+
92+
**1b. Create branches and set default**
93+
```bash
94+
git fetch upstream main
95+
# Create openmoq-main from current main (has all openmoq files)
96+
git checkout -b openmoq-main origin/main
97+
git push -u origin openmoq-main
98+
# Set as default
99+
gh api repos/openmoq/moxygen -X PATCH -f default_branch=openmoq-main
100+
# Reset main to pure upstream
101+
git push origin upstream/main:refs/heads/main --force-with-lease
102+
```
103+
104+
**1c. Branch protection**
105+
- Remove protection from `main` (bot pushes directly)
106+
- Add protection on `openmoq-main` (required check: standalone build, 1 review)
107+
108+
**1d. Disable upstream workflows** via API
109+
- getdeps_linux, getdeps_mac, standalone, docker-build-amd64, docker-build-arm64,
110+
docker-interop-client — all disabled
111+
112+
**Verification**: `main` = upstream exactly. `openmoq-main` = default with all
113+
openmoq files. No upstream workflows fire on push to main.
114+
115+
### Phase 2: Sync workflow (rewrite)
116+
117+
`.github/workflows/openmoq-upstream-sync.yml` on `openmoq-main`:
118+
119+
1. Generate app token (`actions/create-github-app-token@v2`)
120+
2. Checkout `openmoq-main` with app token (for push access)
121+
3. Scan upstream for newest green commit (reuse existing logic)
122+
4. Fast-forward `main`: `git push origin $SHA:refs/heads/main`
123+
5. Check if merge needed (`merge-base --is-ancestor`)
124+
6. Create PR `main``openmoq-main` using app token (bot identity)
125+
7. Approve PR using `OMOQ_SYNC_TOKEN` (your identity, satisfies review)
126+
8. Enable auto-merge using app token
127+
9. Slack on failure
128+
129+
Key simplifications vs current:
130+
- No candidate branches, no patches, no conflict auto-resolution
131+
- PR is `main``openmoq-main` (if already open, it auto-updates on next push)
132+
133+
### Phase 3: CI + artifact publishing (rewrite)
134+
135+
**`openmoq-ci.yml`** (new) — runs on PRs to `openmoq-main`:
136+
- Standalone build on ubuntu-22.04 + macos-15
137+
- `cmake -B _build -S standalone && cmake --build _build && ctest`
138+
139+
**`openmoq-publish-artifacts.yml`** (rewrite) — runs on push to `openmoq-main`:
140+
- 4-platform matrix (ubuntu, macos, bookworm-amd64, bookworm-arm64)
141+
- `cmake -B _build -S standalone -DCMAKE_INSTALL_PREFIX=install/`
142+
- `cmake --build _build && cmake --install _build`
143+
- Package: gather install prefix + any needed headers into tarball
144+
- Release: `create-release.sh` (unchanged)
145+
146+
**Headers**: `cmake --install` should install headers for all deps (each
147+
FetchContent dep has its own install rules). If moxygen's own headers aren't
148+
covered, the packaging script gathers them from source. This is a packaging
149+
concern — we verify during Phase 3 and handle in the collection script.
150+
151+
**New `collect-artifacts-standalone.sh`**: takes `--install-prefix` and
152+
`--src-dir`, strips debug symbols, packages tarball. Much simpler than current
153+
getdeps-based version.
154+
155+
### Phase 4: Cleanup
156+
157+
- Delete `openmoq/patches/` (no longer needed)
158+
- Delete/archive old `collect-artifacts.sh`
159+
- Update `openmoq/README.md` and `GITHUB_WORKFLOW.md`
160+
- Clean up stale branches
161+
- Update o-rly `.gitmodules` to track `openmoq-main`
162+
163+
### Phase 5: End-to-end verification
164+
165+
1. Trigger sync → main advances → PR created (bot) → approved (you) → CI passes → merged
166+
2. Publish-artifacts fires → standalone build → tarball ~50-150 MB → release
167+
3. Conflict test: local mod on openmoq-main + upstream touches same file → PR open → Slack → resolve
168+
169+
---
170+
171+
## Files
172+
173+
| File | Action | Phase |
174+
|------|--------|-------|
175+
| `.github/workflows/openmoq-upstream-sync.yml` | Rewrite for two-branch + app token | 2 |
176+
| `.github/workflows/openmoq-ci.yml` | Create (standalone build CI) | 3 |
177+
| `.github/workflows/openmoq-publish-artifacts.yml` | Rewrite for standalone build | 3 |
178+
| `openmoq/scripts/collect-artifacts-standalone.sh` | Create | 3 |
179+
| `openmoq/scripts/collect-artifacts.sh` | Delete | 4 |
180+
| `openmoq/patches/` | Delete directory | 4 |
181+
| `openmoq/README.md` | Update | 4 |
182+
| `o-rly/design/GITHUB_WORKFLOW.md` | Update | 4 |
183+
| `o-rly/.gitmodules` | Track `openmoq-main` | 4 |

scripts/setup-deps-standalone.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env bash
2+
# setup-deps-standalone.sh — Build moxygen + deps from source (standalone/FetchContent).
3+
#
4+
# Uses deps/moxygen/standalone/CMakeLists.txt which fetches Meta OSS deps
5+
# (folly, fizz, wangle, mvfst, proxygen) via FetchContent and builds them
6+
# as static libraries alongside moxygen. Installs everything to .scratch/
7+
# moxygen-install and writes cmake_prefix_path.txt for configure.sh.
8+
#
9+
# This is the "deep" build — slower first time but fully self-contained.
10+
# Subsequent builds are incremental (cmake only rebuilds what changed).
11+
#
12+
# Usage:
13+
# ./scripts/setup-deps-standalone.sh
14+
#
15+
# System deps required (Ubuntu):
16+
# deps/moxygen/standalone/install-system-deps.sh
17+
18+
set -euo pipefail
19+
20+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
22+
SCRATCH="${ORLY_SCRATCH_PATH:-${PROJECT_ROOT}/.scratch}"
23+
MOXYGEN_DIR="${PROJECT_ROOT}/deps/moxygen"
24+
STANDALONE_SRC="${MOXYGEN_DIR}/standalone"
25+
BUILD_DIR="${SCRATCH}/standalone-build"
26+
INSTALL_DIR="${SCRATCH}/moxygen-install"
27+
28+
if [[ ! -e "$MOXYGEN_DIR/.git" ]]; then
29+
echo "Error: deps/moxygen submodule not initialized." >&2
30+
echo " Run: git submodule update --init" >&2
31+
exit 1
32+
fi
33+
34+
if [[ ! -f "${STANDALONE_SRC}/CMakeLists.txt" ]]; then
35+
echo "Error: standalone/CMakeLists.txt not found in moxygen submodule" >&2
36+
exit 1
37+
fi
38+
39+
NPROC=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
40+
41+
echo "==> Configuring standalone moxygen build..."
42+
cmake -S "$STANDALONE_SRC" -B "$BUILD_DIR" \
43+
-G Ninja \
44+
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
45+
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \
46+
-DBUNDLE_DEPS=ON \
47+
-DBUILD_TESTS=OFF \
48+
-DBUILD_SHARED_LIBS=OFF
49+
50+
echo "==> Building ($NPROC jobs)..."
51+
cmake --build "$BUILD_DIR" -j"$NPROC"
52+
53+
echo "==> Installing to $INSTALL_DIR..."
54+
rm -rf "$INSTALL_DIR"
55+
cmake --install "$BUILD_DIR"
56+
57+
# ── Write cmake_prefix_path.txt ───────────────────────────────────────────────
58+
59+
mkdir -p "$SCRATCH"
60+
echo "$INSTALL_DIR" > "${SCRATCH}/cmake_prefix_path.txt"
61+
echo "standalone" > "${SCRATCH}/deps-mode"
62+
63+
NLIBS=$(find "$INSTALL_DIR/lib" -name '*.a' 2>/dev/null | wc -l)
64+
echo "==> Done: $NLIBS static libs in $INSTALL_DIR"

0 commit comments

Comments
 (0)