Last active
April 4, 2024 13:38
-
-
Save mfts/ea23b2b9e42d571aa77cf003862b93c3 to your computer and use it in GitHub Desktop.
Setup Heroku Review App with Cloudflare DNS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"environments": { | |
"review": { | |
"scripts": { | |
"postdeploy": "bundle exec rake heroku:review_app_setup", | |
"pr-predestroy": "bundle exec rake heroku:review_app_predestroy" | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace :heroku do | |
desc 'Setup Cloudflare DNS record for Heroku Review App' | |
task :review_app_setup do | |
require 'cloudflare' | |
require 'platform-api' | |
require 'octokit' | |
custom_domain = 'example.com'.freeze | |
# Heroku app names are default "<name>-pr-<pull request ID>" | |
heroku_app_name = ENV['HEROKU_APP_NAME'] | |
email = ENV['CLOUDFLARE_EMAIL'] | |
key = ENV['CLOUDFLARE_KEY'] | |
pr_number = ENV['HEROKU_PR_NUMBER'] | |
subdomain = "app-pr-#{pr_number}" | |
wild_subdomain = ["*", subdomain].join('.') | |
# Configure custom domain in Heroku | |
heroku_client = PlatformAPI.connect_oauth ENV['HEROKU_PLATFORM_TOKEN'] | |
hostname = [subdomain, custom_domain].join('.') | |
heroku_client.domain.create(heroku_app_name, hostname: hostname, sni_endpoint: nil) | |
heroku_domain = heroku_client.domain.info(heroku_app_name, hostname)["cname"] | |
# Also add wildcard (*.) subdomain | |
wild_hostname = [wild_subdomain, custom_domain].join('.') | |
heroku_client.domain.create(heroku_app_name, hostname: wild_hostname, sni_endpoint: nil) | |
wild_heroku_domain = heroku_client.domain.info(heroku_app_name, wild_hostname)["cname"] | |
Cloudflare.connect(key: key, email: email) do |connection| | |
# Get a specific zone: | |
zone = connection.zones.find_by_id(ENV['CLOUDFLARE_ZONE_ID']) | |
# Search existing records | |
dns_record = zone.dns_records.find_by_name(subdomain) | |
wild_dns_record = zone.dns_records.find_by_name(wild_subdomain) | |
# Add a DNS record. Here we add an A record for `batman.example.com`: | |
if dns_record == nil | |
# Create DNS record in Cloudflare | |
zone.dns_records.create('CNAME', subdomain, heroku_domain, proxied: false) | |
end | |
if wild_dns_record == nil | |
zone.dns_records.create('CNAME', wild_subdomain, wild_heroku_domain, proxied: false) | |
end | |
end | |
# Add PR comment with deployment URL | |
github_client = Octokit::Client.new(:access_token => ENV['GITHUB_TOKEN']) | |
github_client.add_comment(ENV['GITHUB_REPO'], pr_number.to_i, "The review app has been deployed here: <a href='http://#{hostname}' target='_blank'>#{hostname}</a>") | |
end | |
desc 'Remove DNS Record from Cloudflare for Heroku Review App upon deletion' | |
task :review_app_predestroy do | |
require 'cloudflare' | |
# Cleanup subdomain DNS record for Heroku review app | |
custom_domain = 'example.com'.freeze | |
heroku_app_name = ENV['HEROKU_APP_NAME'] | |
email = ENV['CLOUDFLARE_EMAIL'] | |
key = ENV['CLOUDFLARE_KEY'] | |
pr_number = ENV['HEROKU_PR_NUMBER'] | |
subdomain = "app-pr-#{pr_number}" | |
wild_subdomain = ["*", subdomain].join('.') | |
Cloudflare.connect(key: key, email: email) do |connection| | |
# Get a specific zone: | |
zone = connection.zones.find_by_id(ENV['CLOUDFLARE_ZONE_ID']) | |
dns_record = zone.dns_records.find_by_name([subdomain, custom_domain].join('.')) | |
wild_dns_record = zone.dns_records.find_by_name([wild_subdomain, custom_domain].join('.')) | |
dns_record.delete if dns_record != nil | |
wild_dns_record.delete if wild_dns_record != nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@mfts your script works after adding sni param. I just added acme, because we needed https. But without https, your script in working mode:)