Three-Plane CI Setup
InfoConnect CI has three execution planes. The control plane is the fast, required pull-request gate. Blacksmith runs the heavy GitHub Actions jobs. CircleCI runs the non-blocking nightly batch workflow.
Plane map
| Plane | Configuration | Workloads | Merge policy |
|---|---|---|---|
| GitHub control | .github/workflows/control-plane.yml | Ruff lint and format, Python just typecheck, frontend typecheck and lint, Python/docs/frontend license audits | Required |
| Blacksmith heavy | .github/workflows/ci.yml | Qdrant-backed pytest and coverage, issue #108 acceptance, docs/frontend production builds, frontend tests and bundle sentinel | test is the merge gate; the remaining active heavy checks are visible, non-blocking evidence |
| CircleCI batch | .circleci/config.yml | Nightly Python lint/format/typecheck and advisory license audit, docs/frontend license and quality checks, issue #108 acceptance, real-Qdrant isolation and coverage, docs build, and frontend tests/build/sentinel | Non-blocking |
Cloudflare Pages deployment and release workflows remain on stock GitHub-hosted runners.
Provider status
Blacksmith
The Blacksmith GitHub App is installed for the NeuralEngine-AI organization, has access to infoconnect-search-engine, and provides the blacksmith-2vcpu-ubuntu-2404 label used by all four heavy jobs. The control plane remains on ubuntu-24.04. No self-hosted runner registration is required.
CircleCI repository connection and schedule
CircleCI is connected through the GitHub OAuth integration for github/NeuralEngine-AI/infoconnect-search-engine. The pipeline definition reads .circleci/config.yml, and the existing VCS trigger watches all pushes.
The checked-in justfile owns the nightly phase recipes and the advisory Python license verdict, while .circleci/config.yml invokes those recipes and owns the run_nightly guard. The parameter defaults to false; the nightly-regression workflow still runs only when an external trigger supplies true. The nightly-regression-schedule workflow invokes the same job directly from CircleCI's config-file scheduler.
Every nightly check runs in one nightly-regression-suite job on CircleCI's Docker small resource class (cimg/python:3.11-node plus the pinned Qdrant service container). The suite mirrors every active non-security control and heavy check. It does not attach the restricted infoconnect-ci context because no current step needs a secret, which allows the CircleCI scheduling system to own the run.
Required schedule
The config file declares the schedule; no captain UI action remains:
nightly-regression-schedule:
triggers:
- schedule:
cron: "0 2 * * *"
filters:
branches:
only:
- main
CircleCI's config scheduler runs the shared nightly batch plane every day at 02:00 UTC on main. The schedule cannot set run_nightly; the existing parameter-gated workflow remains available for valid user/API-triggered pipelines, while the scheduled workflow selects the same nightly-regression-suite job directly. This keeps one job graph and does not create a second nightly command convention.
Permission denied diagnosis
The manual trigger recorded in PR 211 returned Permission denied, and live inspection initially showed an empty branch picker. The pipeline definition and all-pushes trigger were present, so the failure occurred while CircleCI resolved repository branches through the triggering user's GitHub OAuth grant, before config execution or restricted-context authorization.
Opening https://app.circleci.com/settings/user and selecting Refresh permissions restored the displayed dnth and NeuralEngine-AI connections. A second manual-trigger check could select fm/ic-ci-3plane-followup for both config and checkout sources, auto-filled run_nightly, and enabled Run pipeline. Submitting that authorized-looking form with run_nightly=true still returned Permission denied; no CircleCI pipeline was created. Refreshing CircleCI's permission cache is therefore insufficient.
Only the CI captain may perform CircleCI's full GitHub re-authentication: sign out of CircleCI, open GitHub Settings → Applications → Authorized OAuth Apps → CircleCI, select Revoke access, clear CircleCI browser cookies, then sign back into CircleCI through GitHub and grant NeuralEngine-AI access. GitHub organization approval or SSO authorization may require a NeuralEngine-AI owner. Full re-authentication clears CircleCI user keys, so automation and other contributors must not perform it.
After full GitHub OAuth re-authentication, a captain may still trigger a feature branch with boolean run_nightly=true to validate the manual path. A created pipeline whose nightly-regression workflow starts nightly-regression-suite is the execution evidence; config validation or an enabled Run pipeline button is not execution evidence.
The config-file schedule removes the former captain-owned post-merge scheduling step. The first scheduled pipeline after this change should be attributed to the config-file schedule and should start nightly-regression-schedule on main at its configured 02:00 UTC window.
Security follow-up
The GitHub Actions security job remains disabled with if: ${{ false }}. Its gitleaks, pip-audit, Semgrep, Docker smoke, and Trivy body remains intact for a separate re-arm.
CircleCI's nightly intentionally excludes all security scans, Docker runtime smoke, Trivy scans, and their artifacts. Those checks remain wholly owned by ic-security-rearm.
Follow-up issue ic-security-rearm owns the security re-arm and the PYSEC-2026-3716 remediation. This CI quota follow-up makes no datasets dependency or pip-audit remediation change.
Secrets, contexts, and variables
Secret names below are exact; values must be provisioned in the named provider and must never be committed.
GitHub Actions
| Name | Scope | Use | Current status |
|---|---|---|---|
CODECOV_TOKEN | Repository or organization secret | Codecov authentication for the preserved test coverage upload when the Codecov project requires token auth | No repository-level value was visible to this task's GitHub token; tokenless upload remains supported if Codecov accepts it |
CLOUDFLARE_API_TOKEN | Repository or organization secret | Existing Cloudflare Pages deploy workflow | Referenced by .github/workflows/cloudflare-pages.yml; verify the organization-level secret if deployment runs |
CLOUDFLARE_ACCOUNT_ID | Repository or organization secret | Existing Cloudflare Pages deploy workflow | Existing repository secret |
DOCKERHUB_USERNAME | Repository or organization secret | Future registry push only | Not used or required: security builds images locally |
DOCKERHUB_TOKEN | Repository or organization secret | Future registry push only | Not used or required: security builds images locally |
The deferred Blacksmith security job builds local infoconnect-api and infoconnect-embedding images for smoke and Trivy scans when ic-security-rearm removes its disabled guard. It does not push to a registry, so that follow-up requires no registry credential.
CircleCI
| Name | Scope | Use | Current status |
|---|---|---|---|
infoconnect-ci | Existing restricted CircleCI context | Reserved for future provider-side values | Not attached; the active nightly needs no secret |
CODECOV_TOKEN | infoconnect-ci context variable, only if needed | Future CircleCI Codecov upload | Not used by the current config; add it to the context rather than as a project plaintext variable |
The CircleCI schedule needs no project token or secret. GitHub OAuth supplies repository access only after the CI captain completes the full re-authentication flow above.
Branch protection recommendation
Require these GitHub checks before merging into main:
- The three checks from
Control Plane: Python quality and license audit, Docs dependency license audit, and Frontend quality and license audit. - Blacksmith
test(the Qdrant-backed pytest and Codecov job).
Keep issue #108 acceptance, docs build, frontend tests/build/sentinel, CircleCI nightly, and the disabled security follow-up non-blocking. Do not make the nightly batch a merge gate; it is intentionally scheduled and may be delayed by CircleCI jitter.
Validation commands
Run these checks when editing the provider workflow or CircleCI config:
go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 \
-ignore 'label "blacksmith-2vcpu-ubuntu-2404" is unknown' \
.github/workflows/ci.yml .github/workflows/control-plane.yml
uvx --from yamllint yamllint \
-d '{extends: relaxed, rules: {line-length: disable}}' \
.github/workflows/ci.yml .github/workflows/control-plane.yml .circleci/config.yml
circleci config validate .circleci/config.yml
When the CircleCI CLI is not installed, use the official container instead:
docker run --rm -v "$PWD:/repo" -w /repo \
circleci/circleci-cli:latest circleci config validate .circleci/config.yml
The CircleCI nightly contains no placeholder or future-suite job. Security scans remain deliberately disabled and owned by ic-security-rearm.