Skip to content

feat: Cloudflare Artifacts REST API client#6

Merged
ivarvong merged 2 commits into
mainfrom
cloudflare-artifacts-rest-api
May 6, 2026
Merged

feat: Cloudflare Artifacts REST API client#6
ivarvong merged 2 commits into
mainfrom
cloudflare-artifacts-rest-api

Conversation

@ivarvong
Copy link
Copy Markdown
Owner

@ivarvong ivarvong commented May 6, 2026

Summary

  • Full Cloudflare Artifacts REST API client. Six repo endpoints (create / list / get / delete / fork / import) plus three token endpoints (create / list / delete). Function and field names mirror upstream verbatim (create_repo, default_branch, plaintext, expires_at, …) so the client can be cross-referenced against the upstream TypeScript types directly.
  • Exgit.CloudflareArtifacts.new/1 returns a %Req.Request{} with bearer auth + base_url pre-configured; per-endpoint functions lean on Req's :path_params and :json steps — no manual URL building. Errors come back as {:error, %Req.Response{}} so callers can pattern-match on upstream codes (e.g. code: 10103 for ttl out of range); transport-level failures pass through Req's exception. %Repo{} and %Token{} redact :token / :plaintext in their Inspect impls.
  • Bypass-backed unit suite covers every endpoint's URL, body, query params, auth header, and v4 envelope parsing, plus a regression pin on Req's path-segment URL-encoding. Live lifecycle smoketest (:cloudflare_api) creates a fresh repo, mints write+read tokens, pushes via exgit, clones via exgit with byte-equality, lists/revokes tokens, and deletes the repo.

New env vars (live test only)

The :cloudflare_api tag is excluded by default and is decoupled from the existing :cloudflare tag, so this PR doesn't change CI behavior. To wire the lifecycle test in CI later, add:

  • CF_ACCOUNT_ID — Cloudflare account ID (generic, not artifact-specific)
  • CF_API_TOKEN — Cloudflare API token with Artifacts > Edit (generic)
  • CF_ARTIFACT_NAMESPACE (optional, defaults to "default")

Test plan

  • mix format --check-formatted
  • mix compile --warnings-as-errors
  • MIX_ENV=dev mix credo --strict
  • MIX_ENV=dev mix dialyzer
  • mix test --warnings-as-errors — 720 tests, 0 failures
  • mix deps.unlock --check-unused
  • Live lifecycle test passing against a real Cloudflare account in ~5s (full create → write-token → push → read-token → clone with byte-equality → list → revoke → delete)

🤖 Generated with Claude Code

ivarvong and others added 2 commits May 6, 2026 16:45
Wraps the full control plane documented at
https://developers.cloudflare.com/artifacts/api/rest-api/ — six repo
endpoints (create / list / get / delete / fork / import) and three
token endpoints (create / list / delete) — so repos and git tokens
can be managed end-to-end alongside the existing wire-protocol
support.

Function and field names mirror upstream verbatim (`create_repo`,
`default_branch`, `plaintext`, `expires_at`, …) so the client can be
cross-referenced against the Cloudflare TypeScript types directly.
`Exgit.CloudflareArtifacts.new/1` returns a `%Req.Request{}` configured
with bearer auth and `base_url`; per-endpoint functions use Req's
`:path_params` and `:json` steps with no manual URL building.

Errors are surfaced as `{:error, %Req.Response{}}` so callers can
pattern-match on upstream codes directly (e.g. `code: 10103` for
`ttl out of range`). Transport-level failures pass through Req's
exception unchanged. `%Repo{}` and `%Token{}` redact the `:token` and
`:plaintext` fields in their `Inspect` impls.

Tests:
* Bypass-backed unit suite covering every endpoint's URL, body, query
  params, auth header, and v4 envelope parsing — including a pin on
  Req's path-segment URL-encoding behavior.
* Live lifecycle smoketest (`:cloudflare_api`) that creates a fresh
  repo, mints write+read tokens, pushes via exgit, clones via exgit
  with byte-equality assertion, lists/revokes tokens, and deletes the
  repo. Gated on `CF_ARTIFACT_ACCOUNT_ID` + `CF_ARTIFACT_API_TOKEN`.

The new `:cloudflare_api` tag is decoupled from `:cloudflare` so
the existing wire-roundtrip CI step is unaffected; the lifecycle
test opts in once new secrets are wired.

Adds Bypass as a test-only dep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first pass prefixed both with `CF_ARTIFACT_` for symmetry with
the existing `CF_ARTIFACT_REMOTE` / `CF_ARTIFACT_TOKEN` (which are
artifact-scoped — a wire URL and a repo-scoped git token). But the
account ID and API token are *generic* Cloudflare credentials —
reusable across any CF product — so the artifact prefix was wrong.
`CF_ARTIFACT_NAMESPACE` keeps its prefix since it really is
artifact-specific.

Verified end-to-end against a real account: full lifecycle
(create → write-token → push → read-token → clone with byte-equal
verification → list → revoke → delete) completes in ~5s.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ivarvong ivarvong merged commit 6252d8e into main May 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant