Deployment & CI/CD

Deploy Python Workers globally in 30 seconds with Wrangler, or automate your entire deployment pipeline with the Python SDK.

Quick Deploy with Wrangler

# Install wrangler (once)
bun install -g wrangler

# Local development with hot reload
wrangler dev main.py

# Deploy to production
wrangler deploy  # 30 seconds to global deployment

CI/CD Automation with the Python SDK

Automate your entire deployment pipeline programmatically:

from cloudflare import Cloudflare
import os
import hashlib
from pathlib import Path
from typing import Dict

class CloudflareDeployment:
    """CI/CD deployment automation"""

    def __init__(self, api_token: str):
        self.client = Cloudflare(api_token=api_token)

    def deploy_worker(
        self,
        script_name: str,
        script_path: str,
        env_vars: Dict[str, str]
    ):
        """Deploy a Worker script"""
        with open(script_path, 'r') as f:
            script_content = f.read()

        # Calculate hash for versioning
        script_hash = hashlib.sha256(
            script_content.encode()
        ).hexdigest()[:8]

        # Upload with environment variables as secrets
        bindings = [
            {
                "type": "secret_text",
                "name": key,
                "text": value,
            }
            for key, value in env_vars.items()
        ]

        result = self.client.workers.scripts.update(
            script_name,
            account_id=os.environ["CLOUDFLARE_ACCOUNT_ID"],
            metadata={
                "main_module": "index.js",
                "bindings": bindings,
                "compatibility_date": "2024-01-01",
                "tags": [
                    f"version:{script_hash}",
                    "env:production"
                ],
            },
            files={
                "index.js": (
                    "index.js",
                    script_content.encode(),
                    "application/javascript",
                )
            },
        )

        print(f"Deployed {script_name} version {script_hash}")
        return result

Static Site Deployment

def deploy_pages_project(
    self,
    project_name: str,
    build_directory: str
):
    """Deploy a Pages project"""
    deployment = self.client.pages.projects.deployments.create(
        account_id=os.environ["CLOUDFLARE_ACCOUNT_ID"],
        project_name=project_name,
    )

    # Upload files
    for file_path in Path(build_directory).rglob("*"):
        if file_path.is_file():
            relative_path = file_path.relative_to(build_directory)
            # Upload each file to the deployment
            print(f"Uploading: {relative_path}")

    return deployment

Rollbacks

Roll back to a previous version by tag:

def rollback(self, script_name: str, version_tag: str):
    """Rollback to a previous version"""
    versions = self.client.workers.scripts.versions.list(
        account_id=os.environ["CLOUDFLARE_ACCOUNT_ID"],
        script_name=script_name,
    )

    # Find the version to rollback to
    for version in versions:
        if version_tag in version.tags:
            # Deploy this version
            self.client.workers.scripts.versions.deployment.create(
                account_id=os.environ["CLOUDFLARE_ACCOUNT_ID"],
                script_name=script_name,
                version_id=version.id,
            )
            print(f"Rolled back to version {version_tag}")
            return

    raise ValueError(f"Version {version_tag} not found")

Cache Management

def purge_cache(self, zone_id: str):
    """Purge CDN cache after deployment"""
    self.client.cache.purge(
        zone_id=zone_id,
        purge_everything=True,
    )
    print("Cache purged")

GitHub Actions Example

# Usage in a CI/CD pipeline
if __name__ == "__main__":
    deployer = CloudflareDeployment(
        os.environ["CLOUDFLARE_API_TOKEN"]
    )

    # Deploy Worker
    deployer.deploy_worker(
        "api-worker",
        "dist/worker.js",
        {
            "DATABASE_URL": os.environ["DATABASE_URL"],
            "API_KEY": os.environ["API_KEY"],
        }
    )

    # Deploy static site
    deployer.deploy_pages_project("my-site", "build/")

    # Clear cache
    deployer.purge_cache(os.environ["CLOUDFLARE_ZONE_ID"])

Wrangler Configuration Reference

# wrangler.toml
name = "my-python-worker"
main = "main.py"
compatibility_date = "2024-01-01"

# Bindings
[[kv_namespaces]]
binding = "KV"
id = "your-kv-namespace-id"

[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"

[ai]
binding = "AI"

# Queues
[[queues.producers]]
binding = "TASK_QUEUE"
queue = "my-task-queue"

[[queues.consumers]]
queue = "my-task-queue"
max_batch_size = 10

# Cron Triggers
[triggers]
crons = ["*/5 * * * *"]  # Every 5 minutes