class FlashFlow::Release::PercyClient

Public Class Methods

new(config={}) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 10
def initialize(config={})
  @client = initialize_connection!(config)
  @compliance_config = config['compliance']
  @release_sha = config['release_sha']
end

Public Instance Methods

find_latest_by_sha(sha) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 16
def find_latest_by_sha(sha)
  response = get_builds
  commit = find_commit_by_sha(response, sha)
  find_build_by_commit_id(response, commit['id'])
end
gen_pdf_diffs(output_file, build_id=nil, threshold=0.0) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 40
def gen_pdf_diffs(output_file, build_id=nil, threshold=0.0)
  # TODO: Switch this over to Percy.get_comparisons at some point
  build_id ||= get_build_id
  PdfDiffGenerator.new.generate(get_comparisons(build_id), output_file, threshold)
end
qa_approved?(sha=nil) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 46
def qa_approved?(sha=nil)
  build = find_latest_by_sha(sha || @release_sha)
  !build['approved-at'].nil?
end
send_compliance_email() click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 22
def send_compliance_email
  max_wait_time = @compliance_config['max_wait_time'] || 0
  delay = @compliance_config['delay'] || 1
  build = find_completed_build_by_sha(@release_sha, max_wait_time, delay)

  unless build_approved?(build)
    gen_compliance_pdf_file(build)
  end
end
send_release_email() click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 32
def send_release_email
  build = find_latest_by_sha(@release_sha)

  unless build_approved?(build)
    mailer.deliver!(:compliance, { percy_build_url: build['web-url'] })
  end
end

Private Instance Methods

build_approved?(build) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 145
def build_approved?(build)
  !build.nil? && !build['approved-at'].nil?
end
build_completed?(build) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 149
def build_completed?(build)
  build['state'] == 'finished';
end
builds_collection(response) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 131
def builds_collection(response)
  response.fetch('data', [])
    .select do |h|
    h['type'] == 'builds' &&
      h.dig('attributes', 'web-url') &&
      h.dig('relationships', 'commit', 'data', 'type') == 'commits'
  end
end
commits_data(response) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 140
def commits_data(response)
  response.fetch('included', { 'id' => nil })
    .select { |data| data['type'] == 'commits' }
end
compose_compliance_email_body(build) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 89
def compose_compliance_email_body(build)
  @compliance_config['message'].sub('%percy_url%', build['web-url'])
end
extract_build_id(build) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 98
def extract_build_id(build)
  build['web-url'].split('/').last
end
find_build_by_commit_id(response, commit_id) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 124
def find_build_by_commit_id(response, commit_id)
  builds_collection(response)
    .select { |b| b.dig('relationships', 'commit', 'data', 'id') == commit_id }
    .sort_by { |b| DateTime.parse(b.dig('attributes', 'created-at')) }.last
    &.fetch('attributes', {}) || {}
end
find_commit_by_sha(response, sha) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 120
def find_commit_by_sha(response, sha)
  commits_data(response).detect { |h| h.dig('attributes', 'sha') == sha }
end
find_completed_build_by_sha(sha, max_wait_time=5, delay=1) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 53
def find_completed_build_by_sha(sha, max_wait_time=5, delay=1)
  max_wait_time *= 60
  delay *= 60
  build = find_latest_by_sha(sha)
  start_time = Time.now

  until build_completed?(build) do
    return nil if Time.now - start_time >= max_wait_time
    putc '#'
    sleep delay
    build = find_latest_by_sha(sha)
  end
  build
end
gen_compliance_file_name(build_id) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 85
def gen_compliance_file_name(build_id)
  "/tmp/#{@compliance_config['file_prefix']}#{build_id}"
end
gen_compliance_pdf_file(build) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 68
def gen_compliance_pdf_file(build)
  build_id = extract_build_id(build)
  base_file_name = gen_compliance_file_name(build_id)
  drive = GoogleDrive.new
  existing_files = drive.find_files("name contains '#{File.basename(base_file_name)}' and mimeType = 'application/pdf'")

  if existing_files.empty?
    file_name = "#{base_file_name}_#{Time.now.strftime('%Y%m%dT%H%M')}.pdf"
    gen_pdf_diffs(file_name, build_id)

    puts "Uploading #{file_name} to Google Drive"
    drive.upload_file(file_name, @compliance_config.merge({ email_body: compose_compliance_email_body(build) }))
  else
    puts "This build has already been processed: #{existing_files.first.name}."
  end
end
get_build_id(sha=nil) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 93
def get_build_id(sha=nil)
  build = find_latest_by_sha(sha || @release_sha)
  extract_build_id(build)
end
get_builds() click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 116
def get_builds
  @client.get("#{Percy.config.api_url}/repos/#{Percy.config.repo}/builds/")
end
get_comparisons(build_id) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 112
def get_comparisons(build_id)
  @client.get("#{Percy.config.api_url}/builds/#{build_id}/comparisons")
end
initialize_connection!(config) click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 102
def initialize_connection!(config)
  if config['token'].nil?
    raise RuntimeError.new('Percy token must be set in your flash flow config.')
  end

  Percy.client.config.access_token = config['token']
  Percy.client.config.repo = config['repo'] unless config['repo'].nil?
  Percy.client
end
mailer() click to toggle source
# File lib/flash_flow/release/percy_client.rb, line 153
def mailer
  @mailer ||= FlashFlow::Mailer::Base.new(Config.configuration.smtp)
end