require 'octokit' require 'mime-types' module DPL class Provider class Releases < Provider require 'pathname' BOOLEAN_PARAMS = %w( draft prerelease ) def self.new(context, options) super(context, options.merge!({needs_git_http_user_agent: false})) end def travis_tag # Check if $TRAVIS_TAG is unset or set but empty if context.env.fetch('TRAVIS_TAG','') == '' nil else context.env['TRAVIS_TAG'] end end def get_tag if travis_tag.nil? @tag ||= `git describe --tags --exact-match 2>/dev/null`.chomp else @tag ||= travis_tag end end def api connection_options = { :request => { :timeout => 180, :open_timeout => 180 } } if (options[:username] || options[:user]) and options[:password] @api ||= Octokit::Client.new(:login => options[:username] || options[:user], :password => options[:password], :auto_paginate => true, :connection_options => connection_options) else @api ||= Octokit::Client.new(:access_token => option(:api_key, :token), :auto_paginate => true, :connection_options => connection_options) end end def slug options.fetch(:repo) { context.env['TRAVIS_REPO_SLUG'] } end def releases @releases ||= api.releases(slug) end def user @user ||= api.user end def files if options[:file_glob] Array(options[:file]).map do |glob| Dir.glob(glob) end.flatten else Array(options[:file]) end end def needs_key? false end def check_app log "Deploying to repo: #{slug}" context.shell 'git fetch --tags' if travis_tag.nil? log "Current tag is: #{get_tag}" end def setup_auth user.login end def check_auth setup_auth unless api.scopes.include? 'public_repo' or api.scopes.include? 'repo' raise Error, "Dpl does not have permission to upload assets. Make sure your token contains the repo or public_repo scope." end log "Logged in as #{user.name}" end def push_app tag_matched = false release_url = nil booleanize!(options) if options[:release_number] tag_matched = true release_url = "https://api.github.com/repos/" + slug + "/releases/" + options[:release_number] else releases.each do |release| if release.tag_name == get_tag release_url = release.rels[:self].href tag_matched = true end end end #If for some reason GitHub hasn't already created a release for the tag, create one if tag_matched == false release_url = api.create_release(slug, get_tag, options.merge({:draft => true})).rels[:self].href end files.each do |file| unless File.exist?(file) log "#{file} does not exist." next end unless File.file?(file) log "#{file} is not a regular file. Skipping." next end existing_url = nil filename = Pathname.new(file).basename.to_s api.release_assets(release_url).each do |existing_file| if existing_file.name == filename existing_url = existing_file.url end end if !existing_url upload_file(file, filename, release_url) elsif existing_url && options[:overwrite] log "#{filename} already exists, overwriting." api.delete_release_asset(existing_url) upload_file(file, filename, release_url) else log "#{filename} already exists, skipping." end end if ! options.key?(:tag_name) && options[:draft] options[:tag_name] = get_tag.tap {|tag| log "Setting tag_name to #{tag}"} end if same_repo? && !options.key?(:target_commitish) options[:target_commitish] = sha.tap {|commitish| log "Setting target_commitish to #{commitish}"} end api.update_release(release_url, {:draft => false}.merge(options)) end def upload_file(file, filename, release_url) content_type = MIME::Types.type_for(file).first.to_s if content_type.empty? # Specify the default content type, as it is required by GitHub content_type = "application/octet-stream" end api.upload_asset(release_url, file, {:name => filename, :content_type => content_type}) end def same_repo? slug == context.env['TRAVIS_REPO_SLUG'] end def booleanize!(opts) opts.map do |k,v| opts[k] = if BOOLEAN_PARAMS.include?(k.to_s.squeeze.downcase) case v.to_s.downcase when 'true' true when 'false' false else v end else v end end end end end end