Skip to content

Commit 204dd22

Browse files
[Artifacts] Improve get-started guide for Workers (#30352)
* [Artifacts] Improve get-started guide for Workers - Add try/catch error handling for repo creation with 409 conflict response - Clarify returned values and their purposes - Add bullet points explaining name and token fields - Add step to switch to Worker directory before deploy - Improve explanations throughout the guide * Update src/content/docs/artifacts/get-started/workers.mdx Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Update src/content/docs/artifacts/get-started/workers.mdx Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * [Artifacts] Additional documentation improvements - Update namespaces concept page - Expand git-client example with more details - Improve isomorphic-git example - Clarify REST API get-started instructions * [Artifacts] Address PR feedback: simplify Workers example, add errors page, fix contractions * Update errors.mdx * [Artifacts] Update workers-binding docs: remove broken get() metadata access, add metadata notes to create/import/fork * [Artifacts] Restructure errors page with linkable anchors for each error code * [Artifacts] Add token events to event subscriptions docs --------- Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent 18ec902 commit 204dd22

10 files changed

Lines changed: 157 additions & 67 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: Errors
3+
description: Error codes returned by the Artifacts REST API and Workers binding.
4+
pcx_content_type: reference
5+
sidebar:
6+
order: 4
7+
head:
8+
- tag: title
9+
content: Errors · Artifacts
10+
products:
11+
- artifacts
12+
---
13+
14+
This is a list of Artifacts errors.
15+
16+
## Error codes
17+
18+
| Name | Code | Description |
19+
|------|------|-------------|
20+
| `ALREADY_EXISTS` | 10201 | The target repository already exists in the namespace. |
21+
| `NOT_FOUND` | 10200 | The repository or remote resource does not exist. |
22+
| `IMPORT_IN_PROGRESS` | 10302 | The repository is still being imported and is not yet available. |
23+
| `FORK_IN_PROGRESS` | 10303 | The repository is still being forked and is not yet available. |
24+
| `INVALID_INPUT` | 10100 | A request parameter is missing, malformed, or outside the accepted range. |
25+
| `INVALID_REPO_NAME` | 10101 | The repository name does not meet naming requirements. |
26+
| `INVALID_TTL` | 10103 | The token TTL is outside the allowed range (60–31,536,000 seconds). |
27+
| `INVALID_URL` | 10104 | The source URL does not point to a valid git repository. |
28+
| `REMOTE_AUTH_REQUIRED` | 10106 | The remote repository requires authentication. |
29+
| `UPSTREAM_UNAVAILABLE` | 10401 | The remote git server could not be reached. |
30+
| `MEMORY_LIMIT` | 10402 | The operation exceeds service memory limits. |
31+
| `INTERNAL_ERROR` | 10400 | An unexpected internal error occurred. |

src/content/docs/artifacts/api/rest-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ Request body:
489489

490490
- `repo` <Type text="RepoName" /> <MetaInfo text="required" />
491491
- `scope` <Type text='"read" | "write"' /> <MetaInfo text='optional (default: "write")' />
492-
- `ttl` <Type text="number" /> <MetaInfo text="optional (seconds, default: 86400)" />
492+
- `ttl` <Type text="number" /> <MetaInfo text="optional" /> — Token time-to-live in seconds. Minimum 60 (1 minute), maximum 31,536,000 (1 year). Defaults to 86,400 (24 hours).
493493

494494
Response type:
495495

src/content/docs/artifacts/api/workers-binding.mdx

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ Use namespace methods on `env.ARTIFACTS` to create, list, inspect, import, or de
6464
- `opts.setDefaultBranch` <Type text="string" /> <MetaInfo text="optional" />
6565
- Returns <Type text="Promise<ArtifactsCreateRepoResult>" />
6666

67+
`create()` returns repo metadata including `name`, `remote`, `defaultBranch`, and an initial token. Save these values if you need them later.
68+
6769
<TypeScriptExample>
6870

6971
```ts
@@ -85,20 +87,21 @@ async function createRepo(artifacts: Artifacts) {
8587

8688
</TypeScriptExample>
8789

88-
The returned token encodes its expiry directly in the `?expires=` suffix.
89-
9090
### `get(name)`
9191

9292
- `name` <Type text="RepoName" /> <MetaInfo text="required" />
9393
- Returns <Type text="Promise<ArtifactsRepo>" />
9494
- Throws if the repo does not exist or is not ready yet.
9595

96+
`get()` returns a handle to an existing repo. Use the handle to call async methods on the repo, such as `createToken()`, `listTokens()`, `revokeToken()`, and `fork()`.
97+
9698
<TypeScriptExample>
9799

98100
```ts
99101
async function getRepoHandle(artifacts: Artifacts) {
100102
const repo = await artifacts.get("starter-repo");
101-
return repo;
103+
const token = await repo.createToken("read", 3600);
104+
return token;
102105
}
103106
```
104107

@@ -142,6 +145,8 @@ Import a repository from an external git remote.
142145
- `params.target.opts.readOnly` <Type text="boolean" /> <MetaInfo text="optional" />
143146
- Returns <Type text="Promise<ArtifactsCreateRepoResult>" />
144147

148+
`import()` returns repo metadata including `name`, `remote`, `defaultBranch`, and an initial token. Save the `remote` and `name` values if you need them later.
149+
145150
<TypeScriptExample>
146151

147152
```ts
@@ -166,8 +171,6 @@ async function importFromGitHub(artifacts: Artifacts) {
166171

167172
</TypeScriptExample>
168173

169-
Imported repos return the same create-style token format. The token encodes its expiry directly in the `?expires=` suffix.
170-
171174
### `delete(name)`
172175

173176
- `name` <Type text="RepoName" /> <MetaInfo text="required" />
@@ -185,18 +188,7 @@ async function deleteRepo(artifacts: Artifacts) {
185188

186189
## Repo handle methods
187190

188-
Call `await artifacts.get(name)` to get a repo handle. The handle extends `ArtifactsRepoInfo`, so repo metadata (`id`, `name`, `remote`, `defaultBranch`, etc.) is available directly as properties.
189-
190-
<TypeScriptExample>
191-
192-
```ts
193-
async function getRemoteUrl(artifacts: Artifacts) {
194-
const repo = await artifacts.get("starter-repo");
195-
return repo.remote;
196-
}
197-
```
198-
199-
</TypeScriptExample>
191+
Call `await artifacts.get(name)` to get a repo handle. Use the handle to call async methods on the repo.
200192

201193
### `createToken(scope?, ttl?)`
202194

@@ -260,6 +252,8 @@ async function revokeToken(artifacts: Artifacts, tokenOrId: string) {
260252
- `opts.defaultBranchOnly` <Type text="boolean" /> <MetaInfo text="optional" />
261253
- Returns <Type text="Promise<ArtifactsCreateRepoResult>" />
262254

255+
`fork()` returns metadata for the new repo. Save the `remote` and `name` values if you need them later.
256+
263257
<TypeScriptExample>
264258

265259
```ts
@@ -300,24 +294,14 @@ export default {
300294
});
301295
}
302296

303-
if (request.method === "GET" && url.pathname === "/repos/starter-repo") {
304-
const repo = await env.ARTIFACTS.get("starter-repo");
305-
return Response.json({
306-
id: repo.id,
307-
name: repo.name,
308-
remote: repo.remote,
309-
defaultBranch: repo.defaultBranch,
310-
});
311-
}
312-
313297
if (request.method === "POST" && url.pathname === "/tokens") {
314298
const repo = await env.ARTIFACTS.get("starter-repo");
315299
const token = await repo.createToken("read", 3600);
316300
return Response.json(token);
317301
}
318302

319303
return Response.json(
320-
{ message: "Use POST /repos, GET /repos/starter-repo, or POST /tokens." },
304+
{ message: "Use POST /repos or POST /tokens." },
321305
{ status: 404 },
322306
);
323307
},

src/content/docs/artifacts/concepts/namespaces.mdx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ products:
1010

1111
import { WranglerConfig } from "~/components";
1212

13-
Artifacts uses namespaces as top-level containers for repositories. Use them to separate repositories by environment, such as `prod`, `staging`, and `dev`, or by tenant and shard.
13+
Artifacts uses namespaces as top-level containers for repositories. Use them to separate repositories by environment, such as `prod`, `staging`, and `dev`, by tenant, or shard.
1414

15-
You do not create namespaces separately.
16-
17-
Choose a namespace name, then use that name in your Wrangler config or REST API path when you create the first repo. Artifacts creates the namespace implicitly at that point.
15+
Namespaces are created implicitly — there is no separate step to create one. You choose a namespace name, then reference it in your Wrangler config or REST API path. The first time you create a repository under that name, Artifacts creates the namespace for you automatically.
1816

1917
## Use namespaces as containers
2018

src/content/docs/artifacts/examples/git-client.mdx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,52 @@ products:
88
- artifacts
99
---
1010

11-
Use this pattern when you want to discover a repo over the REST API and then hand the returned HTTPS remote to a standard Git client.
11+
You can use a standard Git client to interact with Artifacts repos. This example walks through clone, but the same approach works for fetch, pull, push, and any other Git operation.
12+
13+
To do this, you need to:
14+
- Fetch the repo's remote URL from the REST API
15+
- Mint a short-lived token scoped to that repo
16+
17+
Once you have the remote URL and token, you can use them to run Git commands against the repo.
1218

1319
This example assumes the repo already exists and that you have a [Cloudflare API token](/fundamentals/api/get-started/create-token/) with **Artifacts** > **Edit**.
1420

1521
## Fetch the remote and clone the repo
1622

17-
First, fetch the repo metadata from the REST API. Then mint a read token for that repo and use the returned remote with `git clone`.
23+
Replace the placeholder values with your account ID, API token, and repo name. The script fetches the repo's remote URL from the API, mints a read-only token that expires in one hour, and clones the repo to a local directory.
1824

1925
The example below uses `jq` to extract fields from the JSON responses.
2026

2127
```bash
28+
# Set your account details
2229
export ACCOUNT_ID="<YOUR_ACCOUNT_ID>"
2330
export ARTIFACTS_NAMESPACE="default"
2431
export ARTIFACTS_REPO="starter-repo"
2532
export CLOUDFLARE_API_TOKEN="<YOUR_API_TOKEN>"
2633
export ARTIFACTS_BASE_URL="https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/artifacts/namespaces/$ARTIFACTS_NAMESPACE"
2734

35+
# Fetch the repo's remote URL
2836
REPO_JSON=$(curl --silent "$ARTIFACTS_BASE_URL/repos/$ARTIFACTS_REPO" \
2937
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
3038

3139
ARTIFACTS_REMOTE=$(printf '%s' "$REPO_JSON" | jq -r '.result.remote')
3240

41+
# Mint a short-lived read token
3342
TOKEN_JSON=$(curl --silent "$ARTIFACTS_BASE_URL/tokens" \
3443
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
3544
--header "Content-Type: application/json" \
3645
--data "{\"repo\":\"$ARTIFACTS_REPO\",\"scope\":\"read\",\"ttl\":3600}")
3746

3847
ARTIFACTS_TOKEN=$(printf '%s' "$TOKEN_JSON" | jq -r '.result.plaintext')
3948

49+
# Clone the repo
4050
git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" clone "$ARTIFACTS_REMOTE" artifacts-clone
4151
```
52+
You now have a standard Git checkout in `./artifacts-clone`.
4253

4354
This flow is useful when another system owns repo discovery or access control, but your local tooling still expects a normal git remote.
4455

56+
### Authentication
4557
Treat `ARTIFACTS_TOKEN` as a secret. Keep it out of logs, and prefer `http.extraHeader` over saving credentials in a remote URL.
4658

4759
If you need a self-contained remote URL for a short-lived workflow, extract the token secret and build the authenticated remote only for that command:

src/content/docs/artifacts/examples/isomorphic-git.mdx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ products:
1010

1111
import { Details, PackageManagers, TypeScriptExample } from "~/components";
1212

13-
Use [isomorphic-git](https://isomorphic-git.org/) in a Cloudflare Worker when you need Git operations without a Git binary.
13+
Use [isomorphic-git](https://isomorphic-git.org/) to run Git operations on Artifacts repos directly from a Cloudflare Worker.
1414

15-
This works with Artifacts because Artifacts exposes standard Git smart HTTP remotes. In Workers, pair `isomorphic-git/http/web` with a small in-memory filesystem because the runtime does not expose a local disk.
15+
The Artifacts binding creates and manages repos, but it cannot read or write files inside them — for that, you need Git. Since Workers do not have a git binary or a local filesystem, `isomorphic-git` fills that gap. It provides Git operations like init, commit, and push as JavaScript function calls, using an in-memory filesystem in place of a real disk.
1616

17-
## Install the dependency
17+
Use this when your Worker needs to programmatically build and push file trees to an Artifacts repo — for example, an AI agent that generates code and commits it, or an automation that clones a repo, modifies files, and pushes changes back.
18+
19+
## Prerequisites
20+
21+
Follow the [Artifacts Workers setup guide](/artifacts/get-started/workers/) to set up a Worker with an Artifacts binding.
22+
23+
### Install the dependency
1824

1925
Install `isomorphic-git` in your Worker project:
2026

@@ -43,17 +49,20 @@ export interface Env {
4349

4450
export default {
4551
async fetch(_request: Request, env: Env) {
52+
// Create a new Artifacts repo
4653
const repoName = `worker-demo-${crypto.randomUUID().slice(0, 8)}`;
4754
const created = await env.ARTIFACTS.create(repoName);
4855

49-
// Artifacts returns art_v1_<secret>?expires=<unix_seconds>.
50-
// For Git Basic auth, pass only the secret as the password.
56+
// Artifacts tokens include expiry metadata: art_v1_<secret>?expires=<unix_seconds>
57+
// Git Basic auth expects only the token secret as the password
5158
const tokenSecret = created.token.split("?expires=")[0];
59+
60+
// Set up an in-memory filesystem and initialize a Git repo
5261
const dir = "/workspace";
5362
const fs = new MemoryFS();
54-
5563
await git.init({ fs, dir, defaultBranch: "main" });
5664

65+
// Write files
5766
await fs.promises.writeFile(
5867
`${dir}/README.md`,
5968
"# Artifacts repo created from a Worker\n",
@@ -63,6 +72,7 @@ export default {
6372
'export const message = "hello from Artifacts";\n',
6473
);
6574

75+
// Stage and commit
6676
await git.add({ fs, dir, filepath: "README.md" });
6777
await git.add({ fs, dir, filepath: "src/index.ts" });
6878

@@ -76,6 +86,7 @@ export default {
7686
},
7787
});
7888

89+
// Push to the Artifacts remote
7990
const push = await git.push({
8091
fs,
8192
http,

src/content/docs/artifacts/get-started/rest-api.mdx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ You need:
2929
- A local `git` client.
3030
- `jq`, if you want to extract response fields automatically.
3131

32-
For Workers-based access instead of direct HTTP calls, use the [Workers get started guide](/artifacts/get-started/workers/).
32+
If you want to create and manage repos directly from a Worker (instead of calling the REST API), use the [Workers get started guide](/artifacts/get-started/workers/).
3333

3434
## 1. Export your environment variables
3535

36-
Set the variables used in the examples:
36+
Set the following variables using your Cloudflare account ID and Artifacts API token:
3737

3838
```sh
3939
export ARTIFACTS_NAMESPACE="default"
@@ -45,7 +45,7 @@ export ARTIFACTS_BASE_URL="https://api.cloudflare.com/client/v4/accounts/$ACCOUN
4545

4646
Use a unique repo name each time you run this guide.
4747

48-
Artifacts uses Bearer authentication for control-plane requests:
48+
Artifacts uses Bearer authentication for API requests:
4949

5050
```txt
5151
Authorization: Bearer $CLOUDFLARE_API_TOKEN
@@ -82,10 +82,11 @@ The response resembles the following:
8282
"messages": []
8383
}
8484
```
85+
The response includes two values which you will need for Git operations:
86+
- `remote`: the Git remote URL for this repo. `<ACCOUNT_ID>` will be your actual Cloudflare account ID. Use this URL for all Git commands (git push, git clone). Note that this uses a different URL than the REST API you used to create the repo.
87+
- `token`: a short-lived credential for Git operations. The token encodes its expiry directly in the `?expires=` suffix as a Unix timestamp.
8588

86-
The REST control-plane base URL and the returned Git remote use different hosts. Use the exact `result.remote` value for Git operations. The example above uses `<ACCOUNT_ID>` as a placeholder for your Cloudflare account ID.
8789

88-
The returned token encodes its expiry directly in the `?expires=` suffix.
8990

9091
Copy the `remote` and `token` values from `result` into local shell variables:
9192

0 commit comments

Comments
 (0)