name: CI Gate # Single required status check for all PRs. # # Path-filtered CI workflows can't be marked as required in branch # protection: on a PR that doesn't touch their paths they never report, and # the required check hangs at "Expected" forever. This gate solves that. It # runs on every PR, detects which packages changed, calls only the relevant # package CI workflows (as reusable workflows), and the final "CI Gate" job # reports the aggregate result — success when every invoked pipeline passed # (skipped pipelines are fine), failure when any failed. # # Branch protection should require exactly one status check: "CI Gate". # # Package CI workflows keep their own push-to-main and workflow_dispatch # triggers; only their pull_request triggers moved here. To wire in a new # package: add a filter under the `changes` job, a call job that `uses:` the # package workflow, and list the call job in the gate's `needs`. on: pull_request: concurrency: group: ci-gate-${{ github.event.pull_request.number }} cancel-in-progress: true permissions: contents: read pull-requests: read jobs: changes: name: Detect changed packages runs-on: ubuntu-latest outputs: python_sdk: ${{ steps.filter.outputs.python_sdk }} ts_sdk: ${{ steps.filter.outputs.ts_sdk }} cli_python: ${{ steps.filter.outputs.cli_python }} cli_node: ${{ steps.filter.outputs.cli_node }} openclaw: ${{ steps.filter.outputs.openclaw }} opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }} pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }} docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }} steps: - uses: dorny/paths-filter@v3 id: filter with: # Each filter mirrors the package workflow's old pull_request # paths, plus the package workflow file itself and this gate file # (changing either must re-exercise the pipeline). filters: | python_sdk: - 'mem0/**' - 'tests/**' - 'pyproject.toml' - '.github/workflows/ci.yml' - '.github/workflows/ci-gate.yml' ts_sdk: - 'mem0-ts/**' - '.github/workflows/ts-sdk-ci.yml' - '.github/workflows/ci-gate.yml' cli_python: - 'cli/python/**' - '.github/workflows/cli-python-ci.yml' - '.github/workflows/ci-gate.yml' cli_node: - 'cli/node/**' - '.github/workflows/cli-node-ci.yml' - '.github/workflows/ci-gate.yml' openclaw: - 'integrations/openclaw/**' - '.github/workflows/openclaw-checks.yml' - '.github/workflows/ci-gate.yml' opencode_plugin: - 'integrations/mem0-plugin/.opencode-plugin/**' - '.github/workflows/opencode-plugin-checks.yml' - '.github/workflows/ci-gate.yml' pi_agent_plugin: - 'integrations/pi-agent-plugin/**' - '.github/workflows/pi-agent-plugin-checks.yml' - '.github/workflows/ci-gate.yml' docs_llms_txt: - 'docs/**/*.mdx' - 'docs/llms.txt' - 'scripts/check-llms-txt-coverage.py' - 'scripts/llms-txt-ignore.txt' - '.github/workflows/docs-llms-txt-check.yml' - '.github/workflows/ci-gate.yml' python-sdk: name: Python SDK needs: changes if: needs.changes.outputs.python_sdk == 'true' uses: ./.github/workflows/ci.yml secrets: inherit ts-sdk: name: TypeScript SDK needs: changes if: needs.changes.outputs.ts_sdk == 'true' uses: ./.github/workflows/ts-sdk-ci.yml secrets: inherit cli-python: name: Python CLI needs: changes if: needs.changes.outputs.cli_python == 'true' uses: ./.github/workflows/cli-python-ci.yml secrets: inherit cli-node: name: Node CLI needs: changes if: needs.changes.outputs.cli_node == 'true' uses: ./.github/workflows/cli-node-ci.yml secrets: inherit openclaw: name: OpenClaw needs: changes if: needs.changes.outputs.openclaw == 'true' uses: ./.github/workflows/openclaw-checks.yml secrets: inherit opencode-plugin: name: OpenCode Plugin needs: changes if: needs.changes.outputs.opencode_plugin == 'true' uses: ./.github/workflows/opencode-plugin-checks.yml secrets: inherit pi-agent-plugin: name: Pi Agent Plugin needs: changes if: needs.changes.outputs.pi_agent_plugin == 'true' uses: ./.github/workflows/pi-agent-plugin-checks.yml secrets: inherit docs-llms-txt: name: docs llms.txt needs: changes if: needs.changes.outputs.docs_llms_txt == 'true' uses: ./.github/workflows/docs-llms-txt-check.yml secrets: inherit gate: name: CI Gate needs: - changes - python-sdk - ts-sdk - cli-python - cli-node - openclaw - opencode-plugin - pi-agent-plugin - docs-llms-txt if: always() runs-on: ubuntu-latest steps: - name: Evaluate pipeline results env: NEEDS: ${{ toJSON(needs) }} run: | echo "$NEEDS" | jq -r 'to_entries[] | "\(.key): \(.value.result)"' failed=$(echo "$NEEDS" | jq -r '[to_entries[] | select(.value.result == "failure" or .value.result == "cancelled") | .key] | join(", ")') if [ -n "$failed" ]; then echo "::error::Failing pipelines: $failed" exit 1 fi echo "All pipelines relevant to this change passed."