CI Configuration ⚙️

This page lists every repository variable that controls GitHub Actions CI behaviour in this repo. For the workflow catalog see workflows.md; for the CI flow see pipeline.md.

Repository variables are set under Settings → Secrets and variables → Actions → Variables.

Variables 📋

Variable

Workflow

Default (unset)

Set to activate

CI_SYNC_MAIN_SOURCE_REPOSITORY

entry-push-latest.yml

Syncs main from infinito-nexus/core before CI scope discovery

<owner>/<repo> to use another source, or false, empty, or the current repository to skip

CI_RUN_ON_MAIN

entry-push-latest.yml

Pushes to main skip CI

true to run CI on main pushes too

CI_ENABLE_AUTO_UPDATES

cron-update.yml, entry-pr-open-dependabot-close.yml

Update jobs skipped; Dependabot PRs auto-closed

true to allow update PRs (workflow-driven and Dependabot)

PLAYWRIGHT_KEEP_ALL

call-test-deploy.yml

Playwright keeps trace, screenshot and video only when a test fails

true to keep them for every test (passing runs included); the workflow forwards it as INFINITO_PLAYWRIGHT_KEEP

API_OPENAI_KEY

call-test-deploy.yml

The gateway publishes no openai/* model, and the CLI test asserts their absence

An OpenAI key, to deploy and test the route

API_ANTHROPIC_KEY

call-test-deploy.yml

The gateway publishes no anthropic/* model

An Anthropic key

API_OPENROUTER_KEY

call-test-deploy.yml

The gateway publishes no openrouter/auto model

An OpenRouter key

INFINITO_MAIL_PRODUCTION_HOST

call-test-deploy.yml

The read-only production mail assertions are skipped, because the task that runs them is gated on this host being set

The public hostname of a deployed mail server, to assert its MX, SPF, DKIM, DMARC and PTR records and its SMTP greeting after a deploy; nothing is sent and nothing is mutated

INFINITO_MAIL_PRODUCTION_RESOLVER

call-test-deploy.yml

Those assertions resolve through the runner’s own resolver

A DNS server address, to resolve the records against it instead; ignored while INFINITO_MAIL_PRODUCTION_HOST is unset

Provider keys: variable or secret? 🔑

The three API_*_KEY entries are read as ${{ secrets.X || vars.X }}, so a secret of the same name wins and the variable is the fallback. Prefer the secret: a repository variable is not masked, and the development inventory sets MASK_CREDENTIALS_IN_LOGS: false, so a key supplied as a variable can be printed by a task that echoes its own arguments.

An unset key is not an error. The provider’s route stays unpublished, the gateway serves whatever local backend the round deploys, and the litellm CLI test asserts the absence rather than skipping.

They travel as INFINITO_API_OPENAI_KEY, INFINITO_API_ANTHROPIC_KEY and INFINITO_API_OPENROUTER_KEY through the workflow env: block, the passthrough allowlist in passthrough.py, the infinito service environment in compose.yml, and land in API.<provider>.api_key in the development inventory, whose path is the SPOT behind INFINITO_INVENTORY_VARS_FILE. Skipping the compose forwarding makes them resolve to empty inside the container without any error.

Cancelling in-progress runs 🛑

Not a variable: cancellation is derived from the trigger. Every automatic run on a branch other than main is cancelled by a newer run in the same concurrency group; automatic runs on main are not, because a half-finished pipeline on the default branch is worse than a queued one. The one exception on main is a release push: a head commit whose subject starts with Release version , the subject pkgmgr writes for every release commit, cancels the run in progress so the release starts at once. A manual dispatch always supersedes, main included: someone typed it, so it is the intent that counts, not the ref.

cancel-in-progress: ${{ github.ref_name != 'main' || (github.ref_name == 'main' && startsWith(github.event.head_commit.message, 'Release version ')) }}

entry-push-latest.yml declares exactly that expression, and it fires only on push, where github.ref_name is always the pushed branch. entry-cancel-superseded.yml carries no concurrency group of its own — it is the API fallback for that group — but its push job repeats the same predicate as a job if. It does not listen on main, so a release push there relies on the group alone.

⚠️ Do not paste that expression into a workflow that listens on pull_request_target. There github.ref is the base branch, so github.ref_name is literally main and the rule collapses to a constant false — every pull request would stop cancelling its predecessor. entry-pr-change-orchestrate.yml therefore declares cancel-in-progress: true outright.

call-orchestrator.yml compares github.ref for the same reason: a called workflow inherits the caller’s ref, which is refs/pull/<n>/merge for a pull_request caller but refs/heads/main for a pull_request_target one. The ci-orchestrator job of entry-pr-change-orchestrate.yml is fenced to github.event_name == 'pull_request', so the ref the orchestrator sees from that caller is always the merge ref; widening that fence would silently put fork runs into main’s group.

entry-manual-steer.yml declares cancel-in-progress: true outright on its own group, and the orchestrator reads github.event_name — which a called workflow inherits from its caller — so a manual sweep supersedes on both levels without an input to pass down.

CI_SYNC_MAIN_SOURCE_REPOSITORY 🔄

Controls whether the push workflow updates the current repository’s main branch before any later job derives deploy scope from origin/main. This keeps fork branch pushes aligned with the canonical default branch so diff-driven role discovery sees only the branch’s own changes.

⚠️ Forced overwrite — do not work in main. When the sync runs, the current repository’s main is force-pushed from the source repository’s main. Any commit that exists only on the fork’s main is discarded without warning on the next push to any covered branch. Never commit or merge work directly into main on a synced repository. Always work on a feature/**, fix/**, or hotfix/** branch; treat main as a read-only mirror of the source. If you must use main as a working branch, disable the sync first (see To disable the sync below).

Default behaviour (variable not set): The workflow uses infinito-nexus/core as the source repository. When the current repository is already infinito-nexus/core, the same-repository skip applies.

To use a different source repository:

  1. Open the repository on GitHub.

  2. Go to Settings → Secrets and variables → Actions.

  3. Switch to the Variables tab.

  4. Click New repository variable.

  5. Set Name to CI_SYNC_MAIN_SOURCE_REPOSITORY and Value to <owner>/<repo>.

  6. Save.

To disable the sync:

Set the variable to false, 0, no, off, none, an empty value, or the current repository name.

Variable value

Behaviour

(not set)

Uses infinito-nexus/core; syncs forks and skips in infinito-nexus/core itself ✓

infinito-nexus/core in a fork

Syncs the fork’s main from infinito-nexus/core ✓

current repository

Sync skipped ✓

false, 0, no, off, none, or empty

Sync skipped ✓

CI_RUN_ON_MAIN 🎯

Controls whether pushes to main trigger the CI pipeline. Pushes to all other branches covered by the workflow (feature/**, hotfix/**, fix/**, alert-autofix-*) are unaffected.

Default behaviour (variable not set or set to any value other than true): Pushes to main are gated out at the run-policy job and CI is skipped.

To enable CI on main pushes:

  1. Open the repository on GitHub.

  2. Go to Settings → Secrets and variables → Actions.

  3. Switch to the Variables tab.

  4. Click New repository variable.

  5. Set Name to CI_RUN_ON_MAIN and Value to true.

  6. Save.

To disable again:

Delete the variable or change its value to anything other than true.

How it works:

The gate is applied inside push_ci_policy.sh, which the run-policy job invokes. When GITHUB_REF == refs/heads/main and CI_RUN_ON_MAIN != 'true', the job emits should_run=false and every downstream job is skipped.

Variable value

Ref is main

Behaviour

(not set / empty)

yes

CI skipped ✓

true

yes

CI runs ✓

any other value

yes

CI skipped ✓

(any)

no

Unaffected (CI runs per branch rules) ✓

CI_ENABLE_AUTO_UPDATES 🔄

Controls whether automated update PRs are created. Covers both the workflow-driven jobs in cron-update.yml (Docker image versions, agent skills) and PRs opened by Dependabot (gated via entry-pr-open-dependabot-close.yml, which auto-closes them).

The workflow-driven jobs additionally require the BOT_APP_CLIENT_ID and BOT_APP_PRIVATE_KEY repository secrets, see secrets.md. Without those secrets, runs fail at the token-minting step and no PR is opened.

Default behaviour (variable not set or set to any value other than true): The update-docker-image-versions job is skipped. Dependabot PRs are auto-closed on open with a comment pointing to this variable.

To enable update PRs:

  1. Open the repository on GitHub.

  2. Go to Settings → Secrets and variables → Actions.

  3. Switch to the Variables tab.

  4. Click New repository variable.

  5. Set Name to CI_ENABLE_AUTO_UPDATES and Value to true.

  6. Save.

To disable again:

Delete the variable or change its value to anything other than true.

How it works:

In cron-update.yml each job carries a job-level guard:

if: vars.CI_ENABLE_AUTO_UPDATES == 'true'

Dependabot cannot read repository variables itself, so entry-pr-open-dependabot-close.yml listens on pull_request_target (opened, reopened) and closes any PR authored by dependabot[bot] while CI_ENABLE_AUTO_UPDATES != 'true'. The workflow does not check out PR code, which keeps the elevated pull_request_target context safe.

Variable value

Workflow update jobs

Dependabot PRs

(not set / empty)

Skipped ✓

Auto-closed on open ✓

true

Run ✓

Stay open ✓

any other value

Skipped ✓

Auto-closed on open ✓

INFINITO_PLAYWRIGHT_KEEP 🎬

Controls whether Playwright keeps trace, screenshot, and video for every test or only for failing tests in the deploy-test workflow (call-test-deploy.yml). For the full propagation chain, the inventory override, and the local equivalents, see Playwright Tests.

Default behaviour (variable not set or set to any value other than true): Artefacts are retained only when a test fails.

To retain artefacts for every test:

  1. Open the repository on GitHub.

  2. Go to Settings → Secrets and variables → Actions.

  3. Switch to the Variables tab.

  4. Click New repository variable.

  5. Set Name to INFINITO_PLAYWRIGHT_KEEP and Value to true.

  6. Save.

To disable again:

Delete the variable or change its value to anything other than true.

How it works:

Each deploy-test workflow forwards the variable into its own env: block:

INFINITO_PLAYWRIGHT_KEEP: ${{ vars.INFINITO_PLAYWRIGHT_KEEP }}

Variable value

Behaviour

(not set / empty)

Trace / screenshot / video kept only on failure ✓

true

Trace / screenshot / video kept for every test ✓

any other value

Trace / screenshot / video kept only on failure ✓