Skip to content

fix(sync): keep the retryable short-circuit within the line-count baseline #3618

fix(sync): keep the retryable short-circuit within the line-count baseline

fix(sync): keep the retryable short-circuit within the line-count baseline #3618

name: Backend Hermetic E2E
on:
pull_request:
branches: main
merge_group:
types: [checks_requested]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: backend-hermetic-e2e-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
scope:
name: Detect Hermetic Backend Scope
runs-on: ubuntu-latest
timeout-minutes: 2
outputs:
applies: ${{ steps.scope.outputs.applies }}
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Decide whether hermetic backend coverage applies
id: scope
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
MERGE_GROUP_BASE_SHA: ${{ github.event.merge_group.base_sha }}
run: |
case "$EVENT_NAME" in
pull_request) base_sha="$PR_BASE_SHA" ;;
merge_group) base_sha="$MERGE_GROUP_BASE_SHA" ;;
workflow_dispatch)
echo "applies=true" >> "$GITHUB_OUTPUT"
exit 0
;;
*)
echo "Unsupported event for hermetic backend scope: $EVENT_NAME" >&2
exit 1
;;
esac
if [[ -z "$base_sha" ]] || ! git cat-file -e "${base_sha}^{commit}"; then
echo "Cannot resolve hermetic backend scope base: ${base_sha:-<empty>}" >&2
exit 1
fi
changed_files="$(git diff --name-only "$base_sha"...HEAD)"
printf '%s\n' "$changed_files"
if grep -Eq '^(backend/|package\.json$|package-lock\.json$|\.github/workflows/backend-hermetic-e2e\.yml$)' <<<"$changed_files"; then
echo "applies=true" >> "$GITHUB_OUTPUT"
else
echo "applies=false" >> "$GITHUB_OUTPUT"
fi
hermetic-e2e:
name: Hermetic Backend E2E
runs-on: ubuntu-latest
timeout-minutes: 10
needs: scope
if: needs.scope.outputs.applies == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version-file: backend/.python-version
- name: Set up uv
# astral-sh/setup-uv v7, pinned to an immutable commit for CI supply-chain stability.
uses: astral-sh/setup-uv@ecd24dd710f2fb0dca1693a67af11fc4a5c5ec84
with:
enable-cache: true
cache-dependency-glob: backend/pylock*.toml
- name: Install backend and e2e dependencies
working-directory: backend
run: uv pip sync pylock.toml --system
- name: Restore tokenizer cache
uses: actions/cache@v6
with:
path: ${{ runner.temp }}/tiktoken-cache
key: tiktoken-${{ runner.os }}-${{ hashFiles('backend/pylock.toml') }}
- name: Prewarm tokenizer cache
env:
TIKTOKEN_CACHE_DIR: ${{ runner.temp }}/tiktoken-cache
run: python backend/scripts/prewarm_tiktoken_cache.py
- name: Run hermetic backend e2e harness
env:
E2E_PYTEST_TIMEOUT: 120s
TIKTOKEN_CACHE_DIR: ${{ runner.temp }}/tiktoken-cache
run: bash backend/testing/e2e/run.sh -q --tb=short
listen-pusher-stack-gauntlet:
name: Listen Pusher Stack Gauntlet
runs-on: ubuntu-latest
timeout-minutes: 20
needs: scope
if: needs.scope.outputs.applies == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version-file: backend/.python-version
- name: Set up uv
uses: astral-sh/setup-uv@ecd24dd710f2fb0dca1693a67af11fc4a5c5ec84
with:
enable-cache: true
cache-dependency-glob: backend/pylock*.toml
- name: Install backend dependencies in the gauntlet virtualenv
working-directory: backend
run: |
uv venv .venv
uv pip sync pylock.toml --python .venv/bin/python
- name: Set up Node.js for the Firestore emulator
uses: actions/setup-node@v7
with:
node-version: '22'
cache: npm
cache-dependency-path: package-lock.json
- name: Install pinned Firebase CLI dependencies
run: |
for attempt in 1 2 3; do
if npm ci --ignore-scripts --prefer-offline --no-audit --fund=false; then
exit 0
fi
if [[ "$attempt" == 3 ]]; then
echo "Pinned Firebase CLI dependency install failed after 3 attempts." >&2
npm cache verify || true
exit 1
fi
echo "npm ci failed on attempt $attempt/3; verifying cache before bounded retry." >&2
npm cache verify
sleep "$attempt"
done
- name: Set up Java for the Firestore emulator
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
- name: Install Redis server
run: |
sudo apt-get update
sudo apt-get install --yes redis-server
- name: Run listen to pusher stack gauntlet
run: npm run test:listen-pusher-stack:emulator -- --state-dir "$RUNNER_TEMP/listen-pusher-stack"
- name: Show listen gauntlet process diagnostics on failure
if: failure()
run: |
state_dir="$RUNNER_TEMP/listen-pusher-stack"
if [[ -d "$state_dir" ]]; then
find "$state_dir" -type f \( -name '*.log' -o -name '*.jsonl' \) -print -exec tail -n 160 {} \;
else
echo "Listen gauntlet state directory was not retained."
fi
sync-cloud-tasks-stack-gauntlet:
name: Sync Cloud Tasks Stack Gauntlet
runs-on: ubuntu-latest
timeout-minutes: 20
needs: scope
if: needs.scope.outputs.applies == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version-file: backend/.python-version
- name: Set up uv
uses: astral-sh/setup-uv@ecd24dd710f2fb0dca1693a67af11fc4a5c5ec84
with:
enable-cache: true
cache-dependency-glob: backend/pylock*.toml
- name: Install backend dependencies in the gauntlet virtualenv
working-directory: backend
run: |
uv venv .venv
uv pip sync pylock.toml --python .venv/bin/python
- name: Set up Node.js for the Firestore emulator
uses: actions/setup-node@v7
with:
node-version: '22'
cache: npm
cache-dependency-path: package-lock.json
- name: Install pinned Firebase CLI dependencies
run: |
for attempt in 1 2 3; do
if npm ci --ignore-scripts --prefer-offline --no-audit --fund=false; then
exit 0
fi
if [[ "$attempt" == 3 ]]; then
echo "Pinned Firebase CLI dependency install failed after 3 attempts." >&2
npm cache verify || true
exit 1
fi
echo "npm ci failed on attempt $attempt/3; verifying cache before bounded retry." >&2
npm cache verify
sleep "$attempt"
done
- name: Set up Java for the Firestore emulator
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
- name: Install Redis server
run: |
sudo apt-get update
sudo apt-get install --yes redis-server
- name: Run Sync Cloud Tasks stack gauntlet
run: npm run test:sync-cloud-tasks-stack:emulator
replay-harness-phase0a-gauntlet:
name: Replay Harness Phase 0A Feasibility (advisory)
runs-on: ubuntu-latest
timeout-minutes: 20
needs: scope
if: needs.scope.outputs.applies == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version-file: backend/.python-version
- name: Set up uv
uses: astral-sh/setup-uv@ecd24dd710f2fb0dca1693a67af11fc4a5c5ec84
with:
enable-cache: true
cache-dependency-glob: backend/pylock*.toml
- name: Install backend dependencies in the gauntlet virtualenv
working-directory: backend
run: |
uv venv .venv
uv pip sync pylock.toml --python .venv/bin/python
- name: Set up Node.js for the Firestore emulator
uses: actions/setup-node@v7
with:
node-version: '22'
cache: npm
cache-dependency-path: package-lock.json
- name: Install pinned Firebase CLI dependencies
run: npm ci --ignore-scripts
- name: Set up Java for the Firestore emulator
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
- name: Install Redis server
run: |
sudo apt-get update
sudo apt-get install --yes redis-server
- name: Run Phase 0A replay harness feasibility experiment
env:
# Fixed state root so failed-job evidence (logs/attestations) is retained
# at a known path for the failure step below.
OMI_REPLAY_STATE_ROOT: ${{ runner.temp }}/omi-replay-harness
run: npm run test:replay-harness-phase0a:emulator
- name: Show replay harness logs on failure
if: failure()
run: |
state_root="$RUNNER_TEMP/omi-replay-harness"
if [[ -d "$state_root" ]]; then
find "$state_root" -type f \( -name '*.log' -o -name 'attestation.json' \) -print -exec sh -c 'echo "===== $1 ====="; tail -n 160 "$1"' _ {} \;
else
echo "Replay harness state directory was not retained."
fi
merge-gate:
name: Backend Hermetic Merge Gate
runs-on: ubuntu-latest
timeout-minutes: 2
if: ${{ always() }}
needs: [scope, hermetic-e2e, listen-pusher-stack-gauntlet, sync-cloud-tasks-stack-gauntlet]
steps:
- name: Fail closed on selected hermetic checks
env:
SCOPE_RESULT: ${{ needs.scope.result }}
SCOPE_APPLIES: ${{ needs.scope.outputs.applies }}
HERMETIC_E2E_RESULT: ${{ needs.hermetic-e2e.result }}
LISTEN_PUSHER_RESULT: ${{ needs.listen-pusher-stack-gauntlet.result }}
SYNC_CLOUD_TASKS_RESULT: ${{ needs.sync-cloud-tasks-stack-gauntlet.result }}
run: |
if [[ "$SCOPE_RESULT" != 'success' ]]; then
echo "Hermetic backend scope failed with result: $SCOPE_RESULT" >&2
exit 1
fi
case "$SCOPE_APPLIES" in
true) required_result='success' ;;
false) required_result='skipped' ;;
*)
echo "Hermetic backend scope produced an invalid result: ${SCOPE_APPLIES:-<empty>}" >&2
exit 1
;;
esac
failed=0
for result_name in HERMETIC_E2E_RESULT LISTEN_PUSHER_RESULT SYNC_CLOUD_TASKS_RESULT; do
result="${!result_name}"
if [[ "$result" != "$required_result" ]]; then
echo "$result_name must be $required_result, got ${result:-<empty>}" >&2
failed=1
fi
done
exit "$failed"