repomatic.cloudflare.api module¶
Reach the Cloudflare v4 API: the credential, the account and the transport.
repomatic.cloudflare.pages and repomatic.cloudflare.r2 share
this module. It also holds the errors they raise and the status labels of
their reports.
The credential resolves in this order, so the same command works in CI and on a laptop without a token ever landing on a command line:
CLOUDFLARE_API_TOKENfrom the environment (what CI uses).The OAuth token
wrangler loginstores locally.
The account is never declared: the credential settles it. GET /accounts
answers what the token sees, and one scoped to nothing but Cloudflare Pages:
Edit still enumerates the account it belongs to, so CI carries the token
alone. When a credential sees several accounts, account() asks which one
owns the project, and fails rather than guesses when that question has no
single answer. No identifier is ever hardcoded either: repositories using this
are public, and account IDs do not belong in them.
Caution
Never gate anything on GET /user/tokens/verify: that endpoint is
user-scoped, so an account-owned token (the recommended kind, cfat_ prefix)
answers 401 there while every project call succeeds. Proving the credential
against the project it is meant to touch is the only verification that means
anything, which is what every mode of both commands does implicitly.
- repomatic.cloudflare.api.API_ROOT: Final = 'https://api.cloudflare.com/client/v4'¶
Cloudflare v4 API root every call is relative to.
- repomatic.cloudflare.api.API_TIMEOUT: Final = 30¶
Socket timeout in seconds, wider than repomatic’s JSON default: a PATCH that stalls mid-write is worth waiting out rather than retrying blind.
- repomatic.cloudflare.api.EXPIRY_WARNING_DAYS: Final = 30¶
How close a token’s expiry gets before
--checkstarts warning.Cloudflare notifies about neither an approaching expiry nor a passed one, so the monthly Docs run carrying this check is the only calendar the token has. A month of warnings is enough to rotate without ever reaching the red run.
- repomatic.cloudflare.api.STATUS_WIDTH: Final = 6¶
Columns the label of a report line takes, so the messages line up.
- repomatic.cloudflare.api.WRANGLER_CONFIG_FILE: Final = PosixPath('.wrangler/config/default.toml')¶
Where
wrangler loginstores its OAuth token, under a configuration directory. Seewrangler_config_paths().
- exception repomatic.cloudflare.api.CloudflareError[source]¶
Bases:
RuntimeErrorRaised when the Cloudflare API refuses or a credential cannot be found.
- exception repomatic.cloudflare.api.CloudflareHTTPError(message, status)[source]¶
Bases:
CloudflareErrorAn HTTP-level refusal from the Cloudflare API, carrying its status.
Lets a caller act on which refusal arrived (a
404meaning “create it” is a different instruction than a403meaning “stop”) without parsing the message string it was raised with.- status¶
The HTTP status the API answered with.
- class repomatic.cloudflare.api.Status(*values)[source]¶
Bases:
StrEnumThe label that opens one line of a Cloudflare command’s report.
- DRIFT = 'DRIFT'¶
The live state differs from the declared one.
- NOTE = 'note'¶
A step the command could not do, left to do by hand.
- OK = 'ok'¶
A step done, or a state that matches the declared one.
- WARN = 'WARN'¶
Nothing fails yet, but something needs a hand soon.
- repomatic.cloudflare.api.print_status(label, message)[source]¶
Print one line of a report, its message past the label column.
- repomatic.cloudflare.api.refusal(label, status, detail)[source]¶
Build the error a failed request raises, on the REST or the S3 API.
- Parameters:
label (
str) – The request, likeGET /accounts. It names the request without its URL, which embeds the account ID on the S3 API.status (
int|None) – The HTTP status of a refusal.Nonewhen no answer came.detail (
str) – The start of the answer’s body for a refusal, else the reason the transport gave.
- Return type:
- Returns:
A
CloudflareHTTPErrorfor a refusal, else aCloudflareError.
- repomatic.cloudflare.api.wrangler_config_paths()[source]¶
Where
wrangler loginmay have stored its OAuth token, in probe order.Resolved on each call, so the home directory and
XDG_CONFIG_HOMEare the ones the process sees now, not the ones it saw at import. wrangler keeps its configuration in the XDG configuration directory, which macOS puts under~/Library/Preferences. That path comes first on macOS, and is not probed on any other platform.
- repomatic.cloudflare.api.api_token()[source]¶
Find the credential every call sends.
- Return type:
- Returns:
CLOUDFLARE_API_TOKEN, else the OAuth token of a localwrangler login.- Raises:
CloudflareError – When neither holds a credential, or when the
wrangler loginsession expired.
- repomatic.cloudflare.api.call(path, token, method='GET', body=None)[source]¶
Send one request to the REST API, and return the
resultit answers.The request goes through
repomatic.http.request(). A refusal, a timeout and a dropped connection all arrive as one error, which this turns into aCloudflareErrorthe commands catch.- Parameters:
- Return type:
- Returns:
The
resultmember of the answer.- Raises:
CloudflareHTTPError – When the API refuses the request.
CloudflareError – When no answer came, or when the answer is not JSON or reports errors.
- repomatic.cloudflare.api.account(token, project)[source]¶
Find the account to act on, from the credential alone.
The token settles the usual case on its own: it enumerates its own account through
GET /accountseven when scoped to nothing butCloudflare Pages: Edit. A credential seeing several accounts falls back to asking where project lives, probing each account’s copy of it: exactly one owner is an answer, anything else fails rather than guesses, since deploying into a guessed account is worse than not deploying.- Parameters:
token (
str) – The credential, fromapi_token().project (
str) – The Pages project, which settles a credential that sees several accounts.
- Return type:
- Returns:
The account ID.
- Raises:
CloudflareError – When no account, or more than one, answers.
- repomatic.cloudflare.api.token_expiry_warning(token, account_id)[source]¶
Warn when the credential expires soon.
Best effort by design, and it must never fail a run: the account-scoped verify endpoint answers for account-owned tokens, the user-scoped one for user tokens, and each rejects the other kind. A credential that verifies nowhere still deploys fine, so an unreadable expiry is silence, not an error.
- repomatic.cloudflare.api.zone_for(domain, token)[source]¶
Find the zone hosting domain, or
Noneif the credential sees none.The zone is rarely the domain itself:
docs.example.comlives inexample.com. Labels are stripped from the left until a zone answers, stopping at two, which is as far as a registrable name goes for the ordinary suffixes. Reading zones needsZone → Read, which a deploy token scoped to Pages alone does not carry, so this answersNonerather than raising: the DNS half of attaching a domain is optional work that a narrower credential cannot do.
- repomatic.cloudflare.api.resolve_project(project=None)[source]¶
Name the Pages project a command acts on.
- Parameters:
project (
str|None) – The project the caller named, if any.- Return type:
- Returns:
project, else the
cloudflare_projectthe deploy job reads too. Empty when neither names a project.