All skills
openai avatar

/cloudflare-deploy

@bf9e226 official
by openaiopenai/skills28k stars
1,891

Deploy applications and infrastructure to Cloudflare using Workers, Pages, and related platform services. Use when the user asks to deploy, host, publish, or set up a project on Cloudflare.

Use this Skill: https://skilld.dev/gh/openai/skills/cloudflare-deploy

This session only. Nothing lands on disk.

referencesr2gotchas.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

R2 Gotchas & Troubleshooting

List Truncation

// ❌ WRONG: Don't compare object count when using include
while (listed.objects.length < options.limit) { ... }

// ✅ CORRECT: Always use truncated property
while (listed.truncated) {
  const next = await env.MY_BUCKET.list({ cursor: listed.cursor });
  // ...
}

Reason: include with metadata may return fewer objects per page to fit metadata.

ETag Format

// ❌ WRONG: Using etag (unquoted) in headers
headers.set('etag', object.etag); // Missing quotes

// ✅ CORRECT: Use httpEtag (quoted)
headers.set('etag', object.httpEtag);

Checksum Limits

Only ONE checksum algorithm allowed per PUT:

// ❌ WRONG: Multiple checksums
await env.MY_BUCKET.put(key, data, { md5: hash1, sha256: hash2 }); // Error

// ✅ CORRECT: Pick one
await env.MY_BUCKET.put(key, data, { sha256: hash });

Multipart Requirements

  • All parts must be uniform size (except last part)
  • Part numbers start at 1 (not 0)
  • Uncompleted uploads auto-abort after 7 days
  • resumeMultipartUpload doesn't validate uploadId existence

Conditional Operations

// Precondition failure returns object WITHOUT body
const object = await env.MY_BUCKET.get(key, {
  onlyIf: { etagMatches: '"wrong"' }
});

// Check for body, not just null
if (!object) return new Response('Not found', { status: 404 });
if (!object.body) return new Response(null, { status: 304 }); // Precondition failed

Key Validation

// ❌ DANGEROUS: Path traversal
const key = url.pathname.slice(1); // Could be ../../../etc/passwd
await env.MY_BUCKET.get(key);

// ✅ SAFE: Validate keys
if (!key || key.includes('..') || key.startsWith('/')) {
  return new Response('Invalid key', { status: 400 });
}

Storage Class Pitfalls

  • InfrequentAccess: 30-day minimum billing (even if deleted early)
  • Can't transition IA → Standard via lifecycle (use S3 CopyObject)
  • Retrieval fees apply for IA reads

Stream Length Requirement

// ❌ WRONG: Streaming unknown length fails silently
const response = await fetch(url);
await env.MY_BUCKET.put(key, response.body); // May fail without error

// ✅ CORRECT: Buffer or use Content-Length
const data = await response.arrayBuffer();
await env.MY_BUCKET.put(key, data);

// OR: Pass Content-Length if known
const object = await env.MY_BUCKET.put(key, request.body, {
  httpMetadata: {
    contentLength: parseInt(request.headers.get('content-length') || '0')
  }
});

Reason: R2 requires known length for streams. Unknown length may cause silent truncation.

S3 SDK Region Configuration

// ❌ WRONG: Missing region breaks ALL S3 SDK calls
const s3 = new S3Client({
  endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
  credentials: { ... }
});

// ✅ CORRECT: MUST set region='auto'
const s3 = new S3Client({
  region: 'auto', // REQUIRED
  endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
  credentials: { ... }
});

Reason: S3 SDK requires region. R2 uses 'auto' as placeholder.

Local Development Limits

// ❌ Miniflare/wrangler dev: Limited R2 support
// - No multipart uploads
// - No presigned URLs (requires S3 SDK + network)
// - Memory-backed storage (lost on restart)

// ✅ Use remote bindings for full features
wrangler dev --remote

// OR: Conditional logic
if (env.ENVIRONMENT === 'development') {
  // Fallback for local dev
} else {
  // Full R2 features
}

Presigned URL Expiry

// ❌ WRONG: URL expires but no client validation
const url = await getSignedUrl(s3, command, { expiresIn: 60 });
// 61 seconds later: 403 Forbidden

// ✅ CORRECT: Return expiry to client
return Response.json({
  uploadUrl: url,
  expiresAt: new Date(Date.now() + 60000).toISOString()
});

Limits

Limit Value
Object size 5 TB
Multipart part count 10,000
Multipart part min size 5 MB (except last)
Batch delete 1,000 keys
List limit 1,000 per request
Key size 1024 bytes
Custom metadata 2 KB per object
Presigned URL max expiry 7 days

Common Errors

"Stream upload failed" / Silent Truncation

Cause: Stream length unknown or Content-Length missing
Solution: Buffer data or pass explicit Content-Length

"Invalid credentials" / S3 SDK

Cause: Missing region: 'auto' in S3Client config
Solution: Always set region: 'auto' for R2

"Object not found"

Cause: Object key doesn't exist or was deleted
Solution: Verify object key correct, check if object was deleted, ensure bucket correct

"List compatibility error"

Cause: Missing or old compatibility_date, or flag not enabled
Solution: Set compatibility_date >= 2022-08-04 or enable r2_list_honor_include flag

"Multipart upload failed"

Cause: Part sizes not uniform or incorrect part number
Solution: Ensure uniform size except final part, verify part numbers start at 1

Source: SKILL.md on GitHub

2 warnings17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill provides comprehensive guidance for deploying and managing infrastructure on the Cloudflare platform. It includes extensive educational material on secure development practices, such as preventing SQL injection and managing secrets effectively. No malicious patterns or security risks were identified.

  • Socket17d

    2 alerts: gptAnomaly

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    310/310 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at bf9e226. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Activeupdated 8 months ago

README badge

README badge for openai/skills/cloudflare-deploy

Deploys applications and infrastructure to Cloudflare's platform, including Workers, Pages, D1, R2, Durable Objects, KV, and other services. Use decision trees to route to the right Cloudflare product based on compute, storage, AI, networking, security, or media needs.

Generated from the current SKILL.md.

Does this skill cover all Cloudflare products?
The skill is a consolidated index covering compute, storage, AI, networking, security, media, and developer tools on Cloudflare. It uses decision trees to route you to the right product reference, then loads detailed guidance for that product.
What authentication is required before deploying?
Run `npx wrangler whoami` to check if authenticated. For local deployment, use `wrangler login` (one-time OAuth). For CI/CD, set the `CLOUDFLARE_API_TOKEN` environment variable.
What should I do if deployment fails due to network issues?
Rerun the deploy with `sandbox_permissions=require_escalated` to grant elevated network access, which is required for outbound requests to Cloudflare during deployment.
How long does a Cloudflare deployment typically take?
Deployments may take several minutes. Use appropriate timeout values in your configuration or CI/CD environment.

Generated from the current SKILL.md. These answers refresh after source changes.