# frozen_string_literal: true module Dpl module Providers class Heroku < Provider register :heroku abstract gem 'faraday', '~> 1' gem 'json' gem 'netrc', '~> 0.11.0' gem 'rendezvous', '~> 0.1.3' env :heroku opt '--strategy NAME', 'Heroku deployment strategy', default: 'api', enum: %w[api git] opt '--app APP', 'Heroku app name', default: :repo_name opt '--log_level LEVEL', internal: true msgs login: 'Authenticating ... ', restart: 'Restarting dynos ... ', validate: 'Checking for app %{app} ... ', run_cmd: 'Running command %s ... ', success: 'success.', api_error: 'API request failed: %s (see %s)' URL = 'https://api.heroku.com' HEADERS = { 'Accept': 'application/vnd.heroku+json; version=3', 'User-Agent': user_agent }.freeze attr_reader :email def login print :login res = http.get('/account') handle_error(res) unless res.success? @email = JSON.parse(res.body)['email'] info :success end def validate print :validate res = http.get("/apps/#{app}") handle_error(res) unless res.success? info :success end def restart print :restart res = http.delete "/apps/#{app}/dynos" do |req| req.headers['Content-Type'] = 'application/json' end handle_error(res) unless res.success? info :success end def run_cmd(cmd) print :run_cmd, cmd res = http.post "/apps/#{app}/dynos" do |req| req.headers['Content-Type'] = 'application/json' req.body = { command: cmd, attach: true }.to_json end handle_error(res) unless res.success? rendezvous(JSON.parse(res.body)['attach_url']) end private def http @http ||= Faraday.new(url: URL, headers:) do |http| http.basic_auth(username, password) if username && password http.response :logger, logger, &method(:filter) if log_level? http.adapter Faraday.default_adapter end end def headers return HEADERS.dup if username && password HEADERS.merge('Authorization': "Bearer #{api_key}") end def filter(logger) logger.filter(/(.*Authorization: ).*/, '\1[REDACTED]') end def logger super(log_level) end def handle_error(response) body = JSON.parse(response.body) error :api_error, body['message'], body['url'] end def rendezvous(url) Rendezvous.start(url:) end # overwritten in Git, meaningless in Api def username; end def password; end end end end require 'dpl/providers/heroku/api' require 'dpl/providers/heroku/git'