-
Notifications
You must be signed in to change notification settings - Fork 367
/
pages.rb
213 lines (170 loc) · 7.28 KB
/
pages.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
require 'octokit'
module DPL
class Provider
class Pages < Provider
"""Implements Github Pages deployment
Options:
- repo [optional, for pushed to other repos]
- github-token [required]
- github-url [optional, defaults to github.com]
- target-branch [optional, defaults to gh-pages]
- keep-history [optional, defaults to false]
- allow-empty-commit [optional, defaults to false]
- committer-from-gh [optional, defaults to false]
- verbose [optional, defaults to false]
- local-dir [optional, defaults to `pwd`]
- fqdn [optional]
- project-name [optional, defaults to fqdn or repo slug]
- email [optional, defaults to deploy@travis-ci.org]
- name [optional, defaults to Deployment Bot]
- deployment-file [optional, defaults to false]
"""
require 'tmpdir'
def initialize(context, options)
super
@build_dir = File.absolute_path(options[:local_dir] || '.', src_dir)
print_step "The target dir for deployment is '#{@build_dir}'."
@project_name = options[:project_name] || fqdn || slug
@target_branch = options[:target_branch] || 'gh-pages'
@gh_fqdn = fqdn
@gh_url = options[:url] || options[:github_url] || 'github.com'
@keep_history = !!keep_history
@allow_empty_commit = !!allow_empty_commit
@committer_from_gh = !!committer_from_gh
@verbose = !!verbose
@gh_email = options[:email] || 'deploy@travis-ci.org'
@gh_name = "#{options[:name] || 'Deployment Bot'} (from Travis CI)"
@deployment_file = !!options[:deployment_file]
@gh_ref = "#{@gh_url}/#{slug}.git"
@git_push_opts = @keep_history ? '' : ' --force'
@git_commit_opts = (@allow_empty_commit and @keep_history) ? ' --allow-empty' : ''
print_step "The repo is configured to use committer user and email." if @committer_from_gh
end
def gh_token
@gh_token ||= option(:github_token, :token)
end
def gh_remote_url
@gh_remote_url ||= "https://#{gh_token}@#{@gh_ref}"
end
def fqdn
options.fetch(:fqdn) { nil }
end
def slug
options.fetch(:repo) { context.env['TRAVIS_REPO_SLUG'] }
end
def src_dir
context.env['TRAVIS_BUILD_DIR'] or Dir.pwd
end
def keep_history
options.fetch(:keep_history, false)
end
def committer_from_gh
options.fetch(:committer_from_gh, false)
end
def allow_empty_commit
options.fetch(:allow_empty_commit, false)
end
def verbose
# Achtung! Never verbosify git, since it may expose user's token.
options.fetch(:verbose, false)
end
def api # Borrowed from Releases provider
error 'gh-token must be provided for Pages provider to work.' unless gh_token
return @api if @api
api_opts = { :access_token => gh_token }
api_opts[:api_endpoint] = @gh_url == 'github.com' ? "https://api.github.com/" : "https://#{@gh_url}/api/v3/"
@api = Octokit::Client.new(api_opts)
end
def user
@user ||= api.user
end
def setup_auth
user.login
end
def check_auth
setup_auth
unless api.scopes.include? 'public_repo' or api.scopes.include? 'repo'
error "Dpl does not have permission to access #{@gh_url} using it. Make sure your token contains the repo or public_repo scope."
end
log "Logged in as @#{user.login} (#{user.name})"
rescue Octokit::Unauthorized => exc
error "gh-token is invalid. Details: #{exc}"
end
def needs_key?
false
end
def print_step(msg)
log msg if @verbose
end
def github_pull_or_init(target_dir)
unless @keep_history
github_init(target_dir)
return
end
print_step "Trying to clone a single branch #{@target_branch} from existing repo..."
unless context.shell "git clone --quiet --branch='#{@target_branch}' --depth=1 '#{gh_remote_url}' '#{target_dir}' > /dev/null 2>&1"
# if such branch doesn't exist at remote, init it from scratch
print_step "Cloning #{@target_branch} branch failed"
FileUtils.rm_rf(target_dir)
Dir.mkdir(target_dir) # Restore dir destroyed by failed `git clone`
github_init(target_dir)
end
end
def github_init(target_dir)
FileUtils.cd(target_dir, :verbose => true) do
print_step "Creating a brand new local repo from scratch in dir #{Dir.pwd}..."
context.shell "git init" or raise 'Could not create new git repo'
print_step 'Repo created successfully'
context.shell "git checkout --orphan '#{@target_branch}'" or raise 'Could not create an orphan git branch'
print_step "An orphan branch #{@target_branch} created successfully"
end
end
def identify_preferred_committer
if @committer_from_gh and gh_token
return (user.name or @gh_name), (user.email or @gh_email)
end
return @gh_name, @gh_email
end
def github_configure
committer_name, committer_email = identify_preferred_committer
print_step "Configuring git committer to be #{committer_name} <#{committer_email}> (workdir: #{Dir.pwd})"
context.shell "git config user.email '#{committer_email}'"
context.shell "git config user.name '#{committer_name}'"
end
def github_commit
committer_name, _ = identify_preferred_committer
print_step "Preparing to deploy #{@target_branch} branch to gh-pages (workdir: #{Dir.pwd})"
context.shell "touch \"deployed at `date` by #{committer_name}\"" if @deployment_file
context.shell "echo '#{@gh_fqdn}' > CNAME" if @gh_fqdn
context.shell 'git add -A .'
context.shell "git commit#{@git_commit_opts} -qm 'Deploy #{@project_name} to #{@gh_ref}:#{@target_branch}'"
context.shell 'git show --stat-count=10 HEAD'
end
def github_deploy
print_step "Doing the git push (workdir: #{Dir.pwd})..."
unless context.shell "git push#{@git_push_opts} --quiet '#{gh_remote_url}' '#{@target_branch}':'#{@target_branch}' > /dev/null 2>&1"
error "Couldn't push the build to #{@gh_ref}:#{@target_branch}"
end
end
def push_app
print_step "Starting deployment of #{@target_branch} branch to GitHub Pages..."
print_step "The deployment is configured to preserve the target branch if it exists on remote" if @keep_history
Dir.mktmpdir do |tmpdir|
workdir = "#{tmpdir}/work"
Dir.mkdir(workdir)
print_step "Created a temporary work directory #{workdir}"
github_pull_or_init(workdir)
FileUtils.cd(workdir, :verbose => true) do
print_step "Copying #{@build_dir} contents to #{workdir} (workdir: #{Dir.pwd})..."
context.shell "rsync -rl --exclude .git --delete '#{@build_dir}/' '#{workdir}'" or error "Could not copy #{@build_dir}."
github_configure
github_commit
github_deploy
context.shell "git status" if @verbose
end
end
print_step "App has been pushed"
end
end
end
end