Skip to content

Instantly share code, notes, and snippets.

@mfts
Last active April 4, 2024 13:38
Show Gist options
  • Save mfts/ea23b2b9e42d571aa77cf003862b93c3 to your computer and use it in GitHub Desktop.
Save mfts/ea23b2b9e42d571aa77cf003862b93c3 to your computer and use it in GitHub Desktop.
Setup Heroku Review App with Cloudflare DNS
{
"environments": {
"review": {
"scripts": {
"postdeploy": "bundle exec rake heroku:review_app_setup",
"pr-predestroy": "bundle exec rake heroku:review_app_predestroy"
}
}
}
}
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
@starverdiyev
Copy link

@mfts your script works after adding sni param. I just added acme, because we needed https. But without https, your script in working mode:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment