Command-line reference¶
In the locked development environment, run the command line through uv:
uv run python -m extra_codeowners --help
An installed package provides the equivalent extra-codeowners executable.
Global options¶
These options apply to the top-level command:
| Option | Meaning |
|---|---|
--help |
Print the command list and exit. |
--show-completion |
Print completion setup for the current shell. Review the output before applying it. |
--install-completion |
Install completion for the current shell. This changes the current user's shell configuration. |
serve¶
serve starts the FastAPI webhook service, the in-process durable worker, and the scheduled reconciler.
uv run python -m extra_codeowners serve [OPTIONS]
serve accepts these options:
| Option | Type | Default | Meaning |
|---|---|---|---|
--host |
string | Current EXTRA_CODEOWNERS_HOST value |
Bind address. A command-line value overrides the environment. |
--port |
integer | Current EXTRA_CODEOWNERS_PORT value |
Bind port from 1 through 65535. A command-line value overrides the environment. |
--help |
flag | off | Print command help and exit. |
All other service configuration comes from the typed runtime settings. Uvicorn access logs are disabled because the App Manifest callback puts a one-use code in its query string. Structured application logs provide operational context without recording request URLs.
The command exits nonzero if startup configuration is invalid or the server cannot bind.
In production mode, startup rejects:
- missing GitHub App credentials
- a webhook secret shorter than 32 bytes
- a GitHub API URL that does not use HTTPS
- a database URL that does not use the exact
postgresql+psycopgdriver - a PostgreSQL URL without one explicit host, database, username, and nonempty password
- a remote PostgreSQL URL that does not use
sslmode=verify-full - any ambient libpq connection variable.
The weaker require and verify-ca modes are rejected because they do not
verify the database hostname. Every production URL must name exactly one
nonempty host or Unix-socket path; hostless and comma-separated multi-host URLs
are rejected. TLS may be omitted only for localhost, 127.0.0.1, ::1, a
Unix-socket path, or a local-proxy path. A query-string host overrides the
URL authority only when the authority omits its host. A hostaddr is allowed
only with that explicit host and sslmode=verify-full.
Connection-service URLs, PGSERVICE, PGSERVICEFILE, .pgpass, and
PGPASSFILE are unsupported. The URL accepts only host, hostaddr,
sslmode, and sslrootcert query parameters. sslrootcert must be a nonempty
absolute path. Percent-encode reserved characters in the required username and
password. The process pins search_path=public; caller-supplied options are
rejected.
See the runtime settings reference for
the complete ambient-variable denylist. The same production database rules
apply to database migrate, database check, queue-status, and
requeue-dead.
Setup mode also requires a setup-state secret containing at least 32 bytes and an HTTPS public URL that contains only an origin—no credentials, path, query, or fragment.
database migrate¶
database migrate upgrades the configured database to the one Alembic head
bundled with the installed application. It then validates the required release
contract, even when the database was already at that head.
uv run python -m extra_codeowners database migrate \
--lock-timeout-seconds 60
The migration options are:
| Option | Type | Default | Meaning |
|---|---|---|---|
--lock-timeout-seconds |
number | 60 |
Wait from 0.1 through 300 seconds for the migration lock. |
--adopt-pre-alembic-schema / --no-adopt-pre-alembic-schema |
flag | off | In the 0.1.0 artifact only, adopt an unversioned schema that exactly matches immutable revision 0001_initial_schema and whose provenance and backup the operator has verified. |
--help |
flag | off | Print command help and exit. |
On success, the final line names the bundled revision:
Database is at migration 0003_shared_head_epochs.
Production mode applies the same PostgreSQL and transport checks as serve. A
PostgreSQL migration takes a session advisory lock, waits no longer than the
selected lock timeout, limits each SQL statement to 60 seconds, and pins
search_path=public. PostgreSQL releases the lock if the migrator's connection
closes after a failure or interruption.
The success line appears only after Alembic reaches the expected head and the required release contract passes. A database already at the expected head still receives that validation. A mismatch exits nonzero; the migrator does not repair an unexpected schema that happens to carry the right revision.
Normal application startup never runs migrations. Read the upgrade and restore procedure before using the adoption flag. Every change to the Alembic head requires a database restore before an older artifact can start again; additive SQL is not an exception.
database check¶
database check inspects the configured database without changing it.
uv run python -m extra_codeowners database check
On success, the final line names the compatible revision:
Database migration 0003_shared_head_epochs is compatible.
The command exits nonzero when it cannot connect or when the required release contract is missing or wrong. It checks:
- the single Alembic revision and application compatibility marker
- every required table and its exact column set
- column types, lengths, nullability, PostgreSQL time-zone mode, defaults, identities, computed values, autoincrement behavior, and canonical owned integer-sequence type, start, increment, bounds, cache, and cycle settings
- ordered, exact-named primary keys and exact named unique constraints
- exact named index columns, uniqueness, predicates, and supported options
- exact named check-constraint expressions
- the absence of foreign keys on required application tables
- safe PostgreSQL constraint and index catalog states.
For PostgreSQL, expected primary-key, unique, and check constraints must be
validated and nondeferrable. The primary-key and unique backing indexes, along
with the other expected indexes, must have their canonical immediate, valid,
ready, live btree state, uniqueness, and predicate.
This is the application's required-release-contract, not a universal proof
of every object or policy in the database. It does not print the database URL
or stored repository metadata.
validate-policy¶
validate-policy parses repository policy and, optionally, organization policy without contacting GitHub.
uv run python -m extra_codeowners validate-policy \
--repository REPOSITORY_POLICY_FILE \
[--organization ORGANIZATION_POLICY_FILE]
The validation options are:
| Option | Type | Required | Meaning |
|---|---|---|---|
--repository |
readable file path | yes | Repository policy to parse. Its default runtime location is .github/extra-codeowners.toml. |
--organization |
readable file path | no | Organization policy to parse. At runtime, both policy types use the configured policy path. |
--help |
flag | no | Print command help and exit. |
On success, the final line is:
Policy files are valid.
The command exits nonzero for an unreadable or missing file, invalid TOML, unknown fields, an unsupported schema version, invalid application identities or aliases, invalid owners or delegation patterns, conflicting labels, and other policy-model constraints. When --organization is present, the command also compiles the two files together and rejects a repository delegation that names an unenrolled application alias.
Offline validation cannot prove that:
- an enrolled App ID, bot user ID, or slug exists on GitHub
- the App installation can read the target and organization-policy repositories
- a repository delegation alias exists in organization policy when
--organizationwas omitted - the repository's actual
CODEOWNERSfile and owners are valid on GitHub - a pull request currently has enough review evidence.
The GitHub check fails closed when live evidence is missing or invalid.
queue-status¶
queue-status reports aggregate counts from the configured durable database.
uv run python -m extra_codeowners queue-status
Sample output:
pending=3 dead=0
pending includes pending and currently leased exact-head invalidation,
pull-request evaluation, and authority fan-out rows. dead counts legacy or
manually introduced terminal evaluation and authority rows. The command reads
EXTRA_CODEOWNERS_DATABASE_URL and does not show repository names,
pull-request numbers, errors, or delivery IDs.
The command is read-only and requires the exact database revision used by the installed application.
Exit status has the following meaning:
| Exit status | Meaning |
|---|---|
0 |
The database was reachable and both counts were returned. |
| Nonzero | Settings validation, connection, or schema compatibility failed. |
requeue-dead¶
requeue-dead returns a bounded batch of terminal rows to the pending queue. Current workers never create terminal rows: evaluation and authority failures stay pending and retry indefinitely. Migration 0002_retry_dead_jobs also reactivates rows left by the earlier pre-release retry contract.
This command remains available as a compatibility recovery hook. It selects the oldest authority fan-out rows first, then fills any remaining batch capacity with the oldest pull-request evaluation rows.
uv run python -m extra_codeowners requeue-dead --limit 100
The recovery options are:
| Option | Type | Default | Meaning |
|---|---|---|---|
--limit |
integer | 100 |
Requeue from 1 through 10000 rows. Authority rows are selected before evaluation rows. |
--help |
flag | off | Print command help and exit. |
Sample output:
requeued=1
This command changes durable state. For each selected row, it clears the lease and last error, resets the attempt count, and makes the row immediately available as pending. A worker then fetches current GitHub and policy evidence; stored scheduling hints never count as approval evidence.
requeue-dead is not routine retry control. Current pending work retries on its own, and operators must not create terminal rows manually. After the underlying dependency, permission, rate-limit, or evidence problem is corrected, recovery appears in queue-status, worker logs, and the check on the current head.