Files
molecules-ai-openclaw/.gitea/workflows/ci.yml
T
hongming d9e471cbcc
CI / Patch overlay integrity (push) Failing after 4s
CI / all-required (push) Failing after 3s
Build and Publish Patched OpenClaw / sync-upstream (pull_request) Has been skipped
CI / Patch overlay integrity (pull_request) Successful in 4s
CI / all-required (pull_request) Successful in 3s
Build and Publish Patched OpenClaw / test (pull_request) Failing after 15m55s
ci: add CI/all-required gate (fix phantom required check)
main branch protection requires 'CI / all-required (pull_request)' but the sole
workflow was build-and-publish.yml (name 'Build and Publish Patched OpenClaw'),
so that context was NEVER posted -> every PR sat permanently grey/pending. Add a
hermetic, deterministic CI workflow (no upstream fetch / registry / index) that
validates the patch overlay this repo owns and emits the required all-required
context. The heavy networked build stays in build-and-publish.yml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 17:00:23 -07:00

108 lines
4.4 KiB
YAML

name: CI
# Phantom-required-check fix (CI-robustness).
#
# main branch protection requires exactly the status context
# `CI / all-required (pull_request)`
# but the only workflow in this repo was `build-and-publish.yml`
# (workflow name "Build and Publish Patched OpenClaw"), so NOTHING ever
# posted `CI / all-required` → every PR sat permanently grey/pending and
# could never satisfy branch protection. This workflow emits that exact
# context.
#
# It is deliberately HERMETIC and deterministic: it validates the patch
# OVERLAY that this repo owns (it stores only the patched files on top of
# upstream openclaw) WITHOUT any network access — no upstream clone, no
# registry, no package index — so a transient network/registry blip can
# never false-red the required merge gate. The heavy, network-dependent
# real build/publish continues to run in build-and-publish.yml (which
# already triggers on pull_request); this gate guarantees the overlay is
# structurally sound before that runs.
on: [push, pull_request]
env:
GITHUB_SERVER_URL: https://git.moleculesai.app
permissions:
contents: read
jobs:
overlay-integrity:
name: Patch overlay integrity
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Validate patch overlay (hermetic — no upstream fetch)
run: |
set -euo pipefail
fail() { echo "::error::$*"; exit 1; }
# 1. PATCHED_VERSION.md must exist and pin a concrete upstream ref.
test -f PATCHED_VERSION.md || fail "PATCHED_VERSION.md missing"
UPSTREAM_REF=$(awk '/^Upstream:/ {print $2; exit}' PATCHED_VERSION.md)
test -n "$UPSTREAM_REF" || fail "PATCHED_VERSION.md has no 'Upstream: <ref>' pin"
# A 40-hex commit SHA is what build-and-publish.yml checks out; a
# floating tag/branch would make the build non-reproducible.
echo "$UPSTREAM_REF" | grep -Eq '^[0-9a-f]{40}$' \
|| fail "Upstream ref '$UPSTREAM_REF' is not a 40-hex commit SHA (build must pin a reproducible ref)"
echo "::notice::upstream pinned at $UPSTREAM_REF"
# 2. The patched source tree this repo overlays must be present and
# non-empty (build-and-publish.yml does `cp -r src/. upstream/src/`).
test -d src || fail "src/ patch tree missing"
test -n "$(find src -type f -print -quit)" || fail "src/ patch tree is empty — nothing to overlay"
# 3. Dockerfile must exist (the publish job builds it).
test -f Dockerfile || fail "Dockerfile missing"
echo "::notice::patch overlay OK ($(find src -type f | wc -l) patched file(s))"
- name: Validate workflow YAML parses (hermetic)
run: |
set -euo pipefail
python3 - <<'PY'
import glob, sys, yaml
bad = 0
for f in sorted(glob.glob(".gitea/workflows/*.yml") + glob.glob(".gitea/workflows/*.yaml")):
try:
yaml.safe_load(open(f, encoding="utf-8"))
print("ok ", f)
except Exception as e:
print(f"::error::{f}: {e}"); bad += 1
sys.exit(1 if bad else 0)
PY
# Stable aggregate required-context. Branch protection pins exactly
# `CI / all-required (pull_request)`; this job emits it and is green IFF
# every real job above succeeded. Mirrors the fleet `all-required`
# convention (molecule-external-workspace-sdk / template-langgraph / -hermes).
all-required:
name: all-required
needs: [overlay-integrity]
if: ${{ always() }}
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Assert every required job succeeded
run: |
set -euo pipefail
results='${{ toJSON(needs) }}'
echo "$results"
echo "$results" | python3 -c '
import json, sys
ns = json.load(sys.stdin)
# Green only if each needed job is success (or a legitimate skip).
# failure/cancelled/None => NOT green => hard-fail the required gate.
bad = [(k, v.get("result")) for k, v in ns.items()
if v.get("result") not in ("success", "skipped")]
if bad:
print("FAIL: required jobs not green:", file=sys.stderr)
for k, r in bad:
print(f" - {k}: {r}", file=sys.stderr)
sys.exit(1)
print(f"OK: all {len(ns)} required job(s) succeeded")
'