Files
enteros-openclaw/.gitea/workflows/build-and-publish.yml
T
core-devops 4b9b9a3962
Build and Publish Patched OpenClaw / sync-upstream (push) Has been skipped
minimal-validate baseline hygiene OK
Build and Publish Patched OpenClaw / test (push) Successful in 36m0s
CI / Patch overlay integrity (push) Successful in 13s
minimal-ci / minimal-validate (push) Successful in 25s
CI / all-required (push) Successful in 12s
fix(ci): upstream-sync opens a PR instead of pushing to protected main (#2)
2026-07-07 16:46:28 +00:00

187 lines
7.7 KiB
YAML

name: Build and Publish Patched OpenClaw
# This repo stores ONLY the patched files on top of upstream openclaw.
# CI clones upstream, overlays our patches, then tests/builds/publishes.
#
# This is a PUBLISH pipeline: its `test`/build/publish jobs clone upstream from
# github.com and `pnpm install` from registry.npmjs.org. The self-hosted Gitea
# runner pool is air-gapped from the public internet, so those steps hard-fail
# with ENOTFOUND — a pipeline/network condition, not a code defect. Running it on
# `pull_request` made every PR red and (post require-all/['*']) would block ALL
# merges. PR correctness is gated by ci.yml (Patch overlay integrity +
# CI/all-required), which is hermetic. Keep push/schedule so the pipeline still
# runs where outbound network is available; drop the pull_request trigger.
on:
push:
branches: [main, feature/*]
schedule:
- cron: '0 9 * * *'
env:
NODE_VERSION: '22'
UPSTREAM_REPO: https://github.com/openclaw/openclaw.git
REGISTRY: git.moleculesai.app
IMAGE_NAME: molecule-ai/openclaw
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: patches
- name: Clone upstream openclaw
run: |
UPSTREAM_REF=$(awk '/^Upstream:/ {print $2; exit}' patches/PATCHED_VERSION.md)
test -n "$UPSTREAM_REF"
git init upstream
git -C upstream remote add origin ${{ env.UPSTREAM_REPO }}
git -C upstream fetch --depth 1 origin "$UPSTREAM_REF"
git -C upstream checkout --detach FETCH_HEAD
- name: Apply patches over upstream
run: |
cp -r patches/src/. upstream/src/
cp patches/Dockerfile upstream/Dockerfile 2>/dev/null || true
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pnpm
run: npm install -g pnpm@9
- name: Install dependencies
working-directory: upstream
run: pnpm install --no-frozen-lockfile
- name: Run MCP patch tests
working-directory: upstream
run: |
pnpm exec vitest run \
src/agents/pi-bundle-mcp-runtime.test.ts \
src/agents/pi-bundle-mcp-push-notification.test.ts \
src/agents/pi-bundle-mcp-optimizations.test.ts
- name: Build patched upstream
working-directory: upstream
run: pnpm build
- name: Upload build artifact
uses: actions/upload-artifact@v3
with:
name: openclaw-dist
path: upstream/dist/
retention-days: 7
sync-upstream:
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
# The version bump must go through review like every other change.
# `main` is branch-protected (the pre-receive hook declines direct
# pushes), so this job pushes the bump to a `sync/upstream-<sha>` branch
# and opens a PR — it must NEVER `git push origin main`. The old direct
# push failed on every scheduled run ("pre-receive hook declined") and
# turned main's combined status red.
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "gitea-actions[bot]"
git config user.email "gitea-actions[bot]@git.moleculesai.app"
- name: Add upstream remote
run: git remote add upstream ${{ env.UPSTREAM_REPO }}
- name: Fetch upstream
run: git fetch upstream main
- name: Check if upstream has new commits
id: check
run: |
# Compare latest upstream commit with what our patches were based on
UPSTREAM_SHA=$(git rev-parse upstream/main)
PATCHED_VERSION=$(cat PATCHED_VERSION.md 2>/dev/null | grep "^Upstream:" | cut -d' ' -f2 || echo "")
if [ "$UPSTREAM_SHA" = "$PATCHED_VERSION" ]; then
echo "sync_needed=false" >> $GITHUB_OUTPUT
else
echo "sync_needed=true" >> $GITHUB_OUTPUT
echo "upstream_sha=$UPSTREAM_SHA" >> $GITHUB_OUTPUT
fi
- name: Run tests on new upstream (smoke check before reporting)
id: smoke
if: steps.check.outputs.sync_needed == 'true'
run: |
git clone --depth 1 ${{ env.UPSTREAM_REPO }} /tmp/upstream-new
cp -r src/. /tmp/upstream-new/src/
cd /tmp/upstream-new
npm install -g pnpm@9
pnpm install --no-frozen-lockfile
if pnpm exec vitest run src/agents/pi-bundle-mcp-runtime.test.ts; then
echo "smoke=pass" >> $GITHUB_OUTPUT
else
echo "smoke=fail" >> $GITHUB_OUTPUT
echo "::warning::MCP patch tests failed against new upstream — the sync PR needs a manual rebase of the patch overlay before merge."
fi
# Open a PR with the version bump instead of pushing to the
# branch-protected `main` (the old `git push origin main` was declined
# by the pre-receive hook on every scheduled run).
- name: Open upstream-sync PR
if: steps.check.outputs.sync_needed == 'true'
env:
GITEA_TOKEN: ${{ secrets.AUTO_SYNC_TOKEN || secrets.GITHUB_TOKEN }}
UPSTREAM_SHA: ${{ steps.check.outputs.upstream_sha }}
SMOKE: ${{ steps.smoke.outputs.smoke }}
REPO: ${{ github.repository }}
# Talk to the SAME Gitea instance the runner already uses for
# checkout/push (`github.server_url`), not the hardcoded public
# CF-fronted host — the self-hosted runner reaches Gitea on its
# internal address and egress to the CF edge is blocked.
API_BASE: ${{ github.server_url }}/api/v1
run: |
set -euo pipefail
BRANCH="sync/upstream-${UPSTREAM_SHA}"
# Idempotent: if the sync branch already exists upstream, an earlier
# run already opened the PR — nothing to do.
if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then
echo "Branch $BRANCH already exists — sync PR already open, skipping."
exit 0
fi
printf 'Upstream: %s\nUpdated: %s\n' \
"$UPSTREAM_SHA" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > PATCHED_VERSION.md
git add PATCHED_VERSION.md
git commit -m "chore: note upstream sync to ${UPSTREAM_SHA}"
git push origin "HEAD:${BRANCH}"
if [ "$SMOKE" = "fail" ]; then
BODY="Scheduled upstream sync to \`${UPSTREAM_SHA}\`.\n\n⚠️ MCP patch smoke tests FAILED against the new upstream — the patch overlay needs a manual rebase before this can merge. Do not merge until \`test\` is green."
else
BODY="Scheduled upstream sync to \`${UPSTREAM_SHA}\`.\n\nMCP patch smoke tests passed against the new upstream. Review + let \`test\` run before merge."
fi
# Create the PR via the Gitea API. 201 = created.
HTTP=$(curl -s -o /tmp/pr_resp.json -w '%{http_code}' \
-X POST "${API_BASE}/repos/${REPO}/pulls" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"chore: sync upstream openclaw to ${UPSTREAM_SHA}\",\"body\":\"${BODY}\"}")
echo "PR create HTTP ${HTTP}"
cat /tmp/pr_resp.json
# 201 created; 409 = a PR for this head already exists (idempotent OK).
if [ "$HTTP" != "201" ] && [ "$HTTP" != "409" ]; then
echo "::error::Failed to open upstream-sync PR (HTTP ${HTTP})"
exit 1
fi