Skip to content

Commit

Permalink
Merge ee0401a into d9a4421
Browse files Browse the repository at this point in the history
  • Loading branch information
BanzaiMan committed Aug 21, 2019
2 parents d9a4421 + ee0401a commit 83a4748
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 241 deletions.
2 changes: 1 addition & 1 deletion bin/readme
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ $: << File.expand_path('../../lib', __FILE__)
require 'erb'
require 'dpl'

SKIP = %i(help heroku)
SKIP = %i(help heroku pages)

def providers
consts = Dpl::Provider.registry.values
Expand Down
253 changes: 13 additions & 240 deletions lib/dpl/providers/pages.rb
Original file line number Diff line number Diff line change
@@ -1,249 +1,22 @@
module Dpl
module Providers
class Pages < Provider
status :alpha

full_name 'GitHub Pages'

description sq(<<-str)
tbd
str

gem 'octokit', '~> 4.14.0'
gem 'public_suffix', '~> 3.0.3'

required :github_token, :deploy_key

opt '--github_token TOKEN', 'GitHub oauth token with repo permission', secret: true
opt '--deploy_key KEY', 'A base64-encoded, private deploy key with write access to the repository', note: 'RSA keys are too long to fit into a Travis CI secure variable, but ECDSA-521 fits', see: 'https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys'
opt '--repo SLUG', 'Repo slug', default: :repo_slug
opt '--target_branch BRANCH', 'Branch to push force to', default: 'gh-pages'
opt '--keep_history', 'Create incremental commit instead of doing push force', default: true
opt '--commit_message MSG', default: 'Deploy %{project_name} to %{url}:%{target_branch}'
opt '--allow_empty_commit', 'Allow an empty commit to be created', requires: :keep_history
opt '--committer_from_gh', 'Use the token\'s owner name and email for commit. Overrides the email and name options'
opt '--verbose', 'Be verbose about the deploy process'
opt '--local_dir DIR', 'Directory to push to GitHub Pages', default: '.'
opt '--fqdn FQDN', 'Writes your website\'s domain name to the CNAME file'
opt '--project_name NAME', 'Used in the commit message only (defaults to fqdn or the current repo slug)'
opt '--email EMAIL', 'Committer email', default: 'deploy@travis-ci.org'
opt '--name NAME', 'Committer name', default: 'Deploy Bot'
opt '--deployment_file', 'Enable creation of a deployment-info file'
opt '--github_url URL', default: 'github.com'

needs :git

msgs login: 'Authenticated as %s',
invalid_token: 'The provided GitHub token is invalid (error: %s)',
insufficient_scopes: 'Dpl does not have permission to access %{url} using the provided GitHub token. Please make sure the token have the repo or public_repo scope.',
setup_deploy_key: 'Setting up deploy key in %{path}',
deploy: 'Deploying branch %{target_branch} to %{github_url}',
keep_history: 'The deployment is configured to preserve the target branch if it exists on remote.',
work_dir: 'Using temporary work directory %{work_dir}',
committer_from_gh: 'The repo is configured to use committer user and email.',
setup_dir: 'The source dir for deployment is %s',
git_clone: 'Cloning the branch %{target_branch} from the remote repo',
git_init: 'Initializing local git repo',
git_checkout: 'Checking out orphan branch %{target_branch}',
copy_files: 'Copying %{src_dir} contents to %{work_dir}',
git_config: 'Configuring git committer to be %{committer_name} <%{committer_email}>',
prepare: 'Preparing to deploy %{target_branch} branch to gh-pages',
git_push: 'Pushing to %{url}'

cmds git_clone: 'git clone --quiet --branch="%{target_branch}" --depth=1 "%{remote_url}" . > /dev/null 2>&1',
git_init: 'git init .',
git_checkout: 'git checkout --orphan "%{target_branch}"',
check_deploy_key: 'ssh -i %{key} -T %{git_url}',
copy_files: 'rsync -rl --exclude .git --delete "%{src_dir}/" .',
git_config_email: 'git config user.email "%{committer_email}"',
git_config_name: 'git config user.name "%{committer_name}"',
deployment_file: 'touch "deployed at %{now} by %{committer_name}"',
cname: 'echo "%{fqdn}" > CNAME',
git_add: 'git add -A .',
git_commit: 'git commit%{git_commit_opts} -qm "%{commit_message}"',
git_show: 'git show --stat-count=10 HEAD',
git_push: 'git push%{git_push_opts} --quiet "%{remote_url}" "%{target_branch}":"%{target_branch}" > /dev/null 2>&1'

errs copy_files: 'Failed to copy %{src_dir}.',
check_deploy_key: 'Failed to authenticate using the deploy key',
git_init: 'Failed to create new git repo',
git_checkout: 'Failed to create the orphan branch',
git_push: 'Failed to push the build to %{url}:%{target_branch}'

def login
github_token? ? login_token : login_deploy_key
end

def setup
info :setup_dir, src_dir
info :committer_from_gh if committer_from_gh?
end

def prepare
info :deploy
info :keep_history if keep_history?
debug :work_dir
Dir.chdir(work_dir)
end

def deploy
git_clone? ? git_clone : git_init
copy_files
git_config
git_commit
git_push
git_status if verbose?
end

private

def login_token
user.login
info :login, user.login
error :insufficient_scopes unless sufficient_scopes?
rescue Octokit::Unauthorized => e
error :invalid_token, e.message
end

def login_deploy_key
setup_deploy_key if deploy_key?
end

def git_clone?
keep_history? && git_branch_exists?
end

def git_clone
shell :git_clone, echo: false
end

def git_init
shell :git_init
shell :git_checkout
end

def copy_files
shell :copy_files
end

def git_config
info :git_config
shell :git_config_name, echo: false
shell :git_config_email, echo: false
end

def git_commit
info :prepare
shell :deployment_file if deployment_file?
shell :cname if fqdn?
shell :git_add
shell :git_commit
shell :git_show
end

def git_push
shell :git_push, echo: false
end

def git_status
shell 'git status'
end

def setup_deploy_key
path = "~/.dpl/deploy_key"
info :setup_deploy_key, path: path
write_file path, decoded_deploy_key, 0600
setup_git_ssh path
shell :check_deploy_key, key: path
end

def decoded_deploy_key
Base64.decode64(deploy_key)
def self.new(ctx, args)
return super unless registry_key.to_sym == :pages
arg = args.detect { |arg| arg.include? '--strategy' }
strategy = arg ? arg.split('=', 2).last : 'git'
Provider[:"pages:#{strategy}"].new(ctx, args)
end

def git_branch_exists?
git_ls_remote?(remote_url, target_branch)
end

def git_commit_opts
' --allow-empty' if allow_empty_commit?
end

def git_push_opts
' --force' unless keep_history?
end

def committer_name
committer_from_gh? ? user.name || name : name
end

def committer_email
committer_from_gh? ? user.email || email : email
end

def commit_message
interpolate(super)
end

def project_name
super || fqdn || repo_slug
end

def name
"#{super} (from Travis CI)"
end

def sufficient_scopes?
api.scopes.include?('public_repo') || api.scopes.include?('repo')
end

def remote_url
github_token? ? https_url_with_token : git_url
end

def https_url_with_token
"https://#{github_token}@#{url}"
end
opt '--strategy NAME', 'GitHub Pages deployment strategy', default: 'git', enum: %w(api git), internal: true
opt '--github_token TOKEN', 'GitHub oauth token with repo permission', required: true, secret: true
opt '--repo SLUG', 'GitHub repo slug', default: :repo_slug

def git_url
"git@#{github_url}:#{slug}.git"
end

def url
"#{github_url}/#{slug}.git"
end

def slug
repo || repo_slug
end

def user
@user ||= api.user
end

def src_dir
@src_dir ||= expand(local_dir)
end

def work_dir
@work_dir ||= tmp_dir
end

def api
@api ||= Octokit::Client.new(access_token: github_token, api_endpoint: api_endpoint)
end

def api_endpoint
github_url == 'github.com' ? 'https://api.github.com/' : "https://#{github_url}/api/v3/"
end

def now
Time.now
end

def debug(*args)
info *args if verbose?
end
msgs deploy: 'Deploying to repo: %{slug}',
insufficient_scopes: 'Dpl does not have permission to deploy to GitHub Pages. Ensure your token has repo scope.'
end
end
end

require 'dpl/providers/pages/git'
require 'dpl/providers/pages/api'
99 changes: 99 additions & 0 deletions lib/dpl/providers/pages/api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
require 'timeout'

module Dpl
module Providers
class Pages
class Api < Pages
PAGES_PREVIEW_MEDIA_TYPE = 'application/vnd.github.mister-fantastic-preview+json'

# suppress warnings about preview API
ENV['OCTOKIT_SILENT'] = 'true'

TIMEOUTS = {
timeout: 180,
open_timeout: 180
}

gem 'octokit', '~> 4.14.0'

status :alpha

full_name 'GitHub Pages (API)'

description sq(<<-str)
This provider requests GitHub Pages build for the repository given by
the `--repo` flag, or the current one, if the flag is not given.
Note that `dpl` does not perform any check about the fitness of the request;
it is assumed that the target repository (and the branch that GitHub Pages is
configured to use) is ready for building.
For example, if your GitHub Pages is configured to use `gh-pages` but the
deployment is run on the `master` branch, you would have to ensure that the
`gh-pages` would be updated accordingly during the build.
str

msgs pages_not_found: 'GitHub Pages not found for %{slug}. ' \
'Given token has insufficient scope (\'repo\' or \'public_repo\'), ' \
'or GitHub Pages is not enabled for this repo (see https://github.com/%{slug}/settings)',
build_pages_request_timeout: 'GitHub Pages build request timed out',
deploy_start: 'Requesting GitHub Pages build using API'

def validate
error :pages_not_found unless pages_enabled?
end

def deploy
info :deploy_start

api.request_page_build slug

response = api.pages slug
logger.debug response

Timeout::timeout(30) do
until response.status == 'built'
response = api.pages slug
logger.debug response
sleep 1
end
end

latest_pages_build = api.latest_pages_build slug
if msg = latest_pages_build.error.message
error "Build failed: #{msg}"
end

info "Pages deployed to #{response.html_url}, using commit #{latest_pages_build.commit}"
logger.debug latest_pages_build

rescue Octokit::Forbidden => fb
error fb.message
rescue Timeout::Error => to
error :build_pages_request_timeout
end

private

def slug
repo || repo_slug
end

def api
::Octokit.default_media_type = PAGES_PREVIEW_MEDIA_TYPE unless @api

@api ||= Octokit::Client.new(**creds, auto_paginate: true, connection_options: { request: TIMEOUTS })
end

def creds
{ access_token: github_token }
end

def pages_enabled?
api.pages slug
rescue Octokit::NotFound => e
false
end

end
end
end
end

0 comments on commit 83a4748

Please sign in to comment.