Skip to content

Commit f8cef5e

Browse files
committed
Add pwb:sharding:provision_new task etc
1 parent aac91db commit f8cef5e

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

lib/tasks/sharding.rake

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,159 @@ namespace :pwb do
5454
rescue Pwb::TenantShardMigrator::MigrationError => e
5555
puts "Migration aborted: #{e.message}"
5656
end
57+
58+
desc "Create and provision a new website on a specific shard"
59+
task :provision_new, [:subdomain, :shard_name] => :environment do |_, args|
60+
subdomain = args[:subdomain]&.strip&.downcase
61+
shard_name = args[:shard_name]&.strip
62+
63+
unless subdomain && shard_name
64+
puts "Usage: rake 'pwb:sharding:provision_new[subdomain,shard_name]'"
65+
puts ""
66+
puts "Examples:"
67+
puts " rake 'pwb:sharding:provision_new[brisbane,demo]'"
68+
puts " rake 'pwb:sharding:provision_new[my-agency,shard_1]'"
69+
puts ""
70+
puts "Options (via ENV):"
71+
puts " SITE_TYPE=residential|commercial|vacation_rental (default: residential)"
72+
puts " SEED_PACK=base|residential|commercial (default: base)"
73+
puts " OWNER_EMAIL=user@example.com (optional - creates owner user)"
74+
puts " SKIP_PROPERTIES=true (skip seeding sample properties)"
75+
puts ""
76+
puts "Available shards:"
77+
Pwb::ShardRegistry.logical_shards.each do |logical|
78+
status = Pwb::ShardRegistry.configured?(logical) ? "configured" : "not configured"
79+
puts " #{logical} (#{status})"
80+
end
81+
next
82+
end
83+
84+
target_shard = shard_name.to_sym
85+
86+
# Validate shard
87+
unless Pwb::ShardRegistry.configured?(target_shard)
88+
puts "ERROR: Shard '#{target_shard}' is not configured in database.yml"
89+
puts ""
90+
puts "Available configured shards:"
91+
Pwb::ShardRegistry.logical_shards.each do |logical|
92+
puts " #{logical}" if Pwb::ShardRegistry.configured?(logical)
93+
end
94+
next
95+
end
96+
97+
# Check if website already exists
98+
existing = Pwb::Website.find_by(subdomain: subdomain)
99+
if existing
100+
puts "ERROR: Website with subdomain '#{subdomain}' already exists (id: #{existing.id}, shard: #{existing.shard_name})"
101+
next
102+
end
103+
104+
# Configuration from ENV
105+
site_type = ENV.fetch('SITE_TYPE', 'residential')
106+
seed_pack = ENV.fetch('SEED_PACK', 'base')
107+
owner_email = ENV['OWNER_EMAIL']
108+
skip_properties = ENV['SKIP_PROPERTIES'] == 'true'
109+
110+
puts "\n=== Provisioning New Website ==="
111+
puts "Subdomain: #{subdomain}"
112+
puts "Shard: #{target_shard}"
113+
puts "Site type: #{site_type}"
114+
puts "Seed pack: #{seed_pack}"
115+
puts "Owner email: #{owner_email || '(none)'}"
116+
puts "Skip properties: #{skip_properties}"
117+
puts "=" * 40
118+
119+
ActiveRecord::Base.transaction do
120+
# Create owner user if email provided
121+
user = nil
122+
if owner_email.present?
123+
user = Pwb::User.find_or_create_by!(email: owner_email.downcase) do |u|
124+
u.password = SecureRandom.hex(16)
125+
u.onboarding_state = 'active'
126+
end
127+
puts "\nOwner user: #{user.email} (id: #{user.id})"
128+
end
129+
130+
# Create the website
131+
website = Pwb::Website.new(
132+
subdomain: subdomain,
133+
site_type: site_type,
134+
shard_name: target_shard.to_s,
135+
seed_pack_name: seed_pack,
136+
provisioning_state: 'pending',
137+
owner_email: owner_email
138+
)
139+
140+
unless website.save
141+
puts "ERROR: Failed to create website: #{website.errors.full_messages.join(', ')}"
142+
raise ActiveRecord::Rollback
143+
end
144+
145+
puts "Website created: id=#{website.id}"
146+
147+
# Create owner membership if user exists
148+
if user
149+
Pwb::UserMembership.create!(
150+
user: user,
151+
website: website,
152+
role: 'owner',
153+
active: true
154+
)
155+
user.update!(website: website)
156+
puts "Owner membership created"
157+
end
158+
159+
# Provision the website
160+
puts "\nProvisioning website..."
161+
service = Pwb::ProvisioningService.new
162+
result = service.provision_website(website: website, skip_properties: skip_properties) do |progress|
163+
puts " #{progress[:percentage]}% - #{progress[:message]}"
164+
end
165+
166+
unless result[:success]
167+
puts "\nERROR: Provisioning failed: #{result[:errors].join(', ')}"
168+
raise ActiveRecord::Rollback
169+
end
170+
171+
website.reload
172+
puts "\n=== Provisioning Complete ==="
173+
puts "Website ID: #{website.id}"
174+
puts "Subdomain: #{website.subdomain}"
175+
puts "Shard: #{website.shard_name}"
176+
puts "State: #{website.provisioning_state}"
177+
178+
base_domain = ENV.fetch('BASE_DOMAIN', 'propertywebbuilder.com')
179+
puts "URL: https://#{website.subdomain}.#{base_domain}"
180+
181+
if website.locked_pending_email_verification?
182+
puts "\nNote: Website is locked pending email verification."
183+
puts "To go live immediately, run:"
184+
puts " rake 'pwb:sharding:go_live[#{website.id}]'"
185+
end
186+
end
187+
rescue StandardError => e
188+
puts "\nERROR: #{e.message}"
189+
puts e.backtrace.first(5).join("\n") if ENV['DEBUG']
190+
end
191+
192+
desc "Force a website to go live (skip email verification)"
193+
task :go_live, [:website_id] => :environment do |_, args|
194+
unless args[:website_id]
195+
puts "Usage: rake 'pwb:sharding:go_live[website_id]'"
196+
next
197+
end
198+
199+
website = Pwb::Website.find(args[:website_id])
200+
201+
unless website.locked_pending_email_verification?
202+
puts "Website is not in locked state (current: #{website.provisioning_state})"
203+
next
204+
end
205+
206+
website.verify_and_go_live!
207+
puts "Website #{website.subdomain} is now live!"
208+
rescue AASM::InvalidTransition => e
209+
puts "ERROR: Cannot transition to live: #{e.message}"
210+
end
57211
end
58212
end

0 commit comments

Comments
 (0)