Class: Cloudflare::Email::WorkerDeployer

Inherits:
Object
  • Object
show all
Defined in:
lib/cloudflare/email/worker_deployer.rb

Overview

Deploys and manages the shipped Cloudflare Email Worker via the Cloudflare API directly — no wrangler, no Node, no npm required.

Required API token scopes:

Account  Workers Scripts  Edit

Usage:

deployer = Cloudflare::Email::WorkerDeployer.new(
  account_id: ..., api_token: ...,
)
deployer.deploy(script_path: "cloudflare-worker/src/index.js")
deployer.put_secret("INGRESS_SECRET", "...")
deployer.put_secret("RAILS_INGRESS_URL", "https://...")

Constant Summary collapse

SCRIPT_NAME_PREFIX =
"cloudflare-email-ingress".freeze
DEFAULT_COMPATIBILITY_DATE =
"2026-04-01".freeze
API_BASE =
"https://api.cloudflare.com/client/v4".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(account_id:, api_token:, script_name: nil, compatibility_date: DEFAULT_COMPATIBILITY_DATE, api_base: API_BASE) ⇒ WorkerDeployer

Returns a new instance of WorkerDeployer.

Raises:

  • (ArgumentError)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/cloudflare/email/worker_deployer.rb', line 40

def initialize(account_id:, api_token:,
               script_name: nil,
               compatibility_date: DEFAULT_COMPATIBILITY_DATE,
               api_base: API_BASE)
  script_name ||= self.class.default_script_name
  raise ArgumentError, "account_id is required" if .to_s.empty?
  raise ArgumentError, "api_token is required"  if api_token.to_s.empty?

  @account_id         = 
  @api_token          = api_token
  @script_name        = script_name
  @compatibility_date = compatibility_date
  @api_base           = api_base
end

Instance Attribute Details

#script_nameObject (readonly)

Returns the value of attribute script_name.



25
26
27
# File 'lib/cloudflare/email/worker_deployer.rb', line 25

def script_name
  @script_name
end

Class Method Details

.default_script_nameObject

Default Worker name includes the current Rails environment so a dev tunnel never stomps on the production Worker’s RAILS_INGRESS_URL. Override via ‘script_name:` for tests or explicit control.



30
31
32
33
# File 'lib/cloudflare/email/worker_deployer.rb', line 30

def self.default_script_name
  env = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env.to_s : ENV["RAILS_ENV"].to_s
  default_script_name_with_env(env)
end

.default_script_name_with_env(env) ⇒ Object



35
36
37
38
# File 'lib/cloudflare/email/worker_deployer.rb', line 35

def self.default_script_name_with_env(env)
  env = "production" if env.to_s.empty?
  "#{SCRIPT_NAME_PREFIX}-#{env}"
end

Instance Method Details

#delete_scriptObject

Delete the Worker. Useful for teardown in tests.



100
101
102
103
104
105
# File 'lib/cloudflare/email/worker_deployer.rb', line 100

def delete_script
  request(
    method: :delete,
    path:   "/accounts/#{@account_id}/workers/scripts/#{@script_name}",
  )
end

#delete_secret(name) ⇒ Object

Delete a Worker secret by name.



83
84
85
86
87
88
# File 'lib/cloudflare/email/worker_deployer.rb', line 83

def delete_secret(name)
  request(
    method: :delete,
    path:   "/accounts/#{@account_id}/workers/scripts/#{@script_name}/secrets/#{name}",
  )
end

#deploy(script_path: nil, source: nil) ⇒ Object

Uploads/updates the Worker script. Accepts either ‘script_path:` (a path to a .js file) or `source:` (the JS source string directly).

Raises:

  • (ArgumentError)


57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/cloudflare/email/worker_deployer.rb', line 57

def deploy(script_path: nil, source: nil)
  source ||= File.read(script_path) if script_path
  raise ArgumentError, "must pass script_path: or source:" if source.nil?

  boundary = "----cf-email-#{SecureRandom.hex(16)}"
  body     = build_multipart(boundary, source)

  request(
    method: :put,
    path:   "/accounts/#{@account_id}/workers/scripts/#{@script_name}",
    body:   body,
    content_type: "multipart/form-data; boundary=#{boundary}",
  )
end

#exists?Boolean

True if the Worker script already exists.

Returns:

  • (Boolean)


91
92
93
94
95
96
97
# File 'lib/cloudflare/email/worker_deployer.rb', line 91

def exists?
  response = raw_request(
    method: :get,
    path:   "/accounts/#{@account_id}/workers/scripts/#{@script_name}",
  )
  response.code.to_i == 200
end

#put_secret(name, value) ⇒ Object

Set/update a Worker secret.



73
74
75
76
77
78
79
80
# File 'lib/cloudflare/email/worker_deployer.rb', line 73

def put_secret(name, value)
  request(
    method: :put,
    path:   "/accounts/#{@account_id}/workers/scripts/#{@script_name}/secrets",
    body:   JSON.generate({ name: name.to_s, text: value.to_s, type: "secret_text" }),
    content_type: "application/json",
  )
end