shipit-engine 0.28.0 → 0.28.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdb3736fb9999c0409f7b81081a52467f33a39ee419f2a40e14e6aca73866263
4
- data.tar.gz: f58bfcbbc8084bb18cf2234ed0a75658a5c6bc9e2b593bc8a2b90e5f89d030b5
3
+ metadata.gz: b1e854d10e7f525e0a9af5a02bfb432ae6cd091079a8adae14894fc2e42415f2
4
+ data.tar.gz: 250798a87f4662d2a13e01090a31f4fc3bf82df6b206468002ca5098c792d951
5
5
  SHA512:
6
- metadata.gz: 19ffafe44e93c6f02f277c5208160a605286557f5080cf3569355fcfa85b2a8583eace47a89c1ac223490ad157de451f0837343d5b818e891c9794b27ca20554
7
- data.tar.gz: 57be6895de1d5757a48b603cfb4796316f477b791feef7cfc876dc57b5226d869e65b2332e920e695e3edbba3bd99b39dc75e0e3ceeab2b6aee851eaeea15c2e
6
+ metadata.gz: 8872ae9ba8ed5dcbf9de6dca1d46d40f87d9b870a5927e4b31ab62f794713b9ec030f4b8e13cf344ab2fc588d501e6d35532f13019f70815247a11fdfac0e8c8
7
+ data.tar.gz: 146fc5d4fec1d577d5b49bbee57b3dc9d9f391522be6e6f8877dcf80b62438eafa908454439124843ba5034e96afaaae93632b3e61f8ef1211542d297d7a4666
@@ -142,8 +142,9 @@ pre {
142
142
  .less-important {
143
143
  color: $grey;
144
144
  margin-bottom: 0em;
145
- margin-top: 1em;
145
+ margin-top: 5em;
146
146
  p {
147
+ margin-top: 1.5rem;
147
148
  margin-bottom: 0.5em;
148
149
  }
149
150
  }
@@ -1,6 +1,6 @@
1
1
  module Shipit
2
2
  class FetchDeployedRevisionJob < BackgroundJob
3
- queue_as :default
3
+ queue_as :deploys
4
4
 
5
5
  def perform(stack)
6
6
  return if stack.active_task?
@@ -2,7 +2,7 @@ module Shipit
2
2
  class GithubSyncJob < BackgroundJob
3
3
  include BackgroundJob::Unique
4
4
 
5
- MAX_FETCHED_COMMITS = 10
5
+ MAX_FETCHED_COMMITS = 25
6
6
  queue_as :default
7
7
 
8
8
  self.timeout = 60
@@ -2,6 +2,8 @@ module Shipit
2
2
  class UpdateGithubLastDeployedRefJob < BackgroundJob
3
3
  queue_as :default
4
4
 
5
+ # We do not prefix 'refs/' because Octokit methods will do this automatically.
6
+ BRANCH_REF_PREFIX = 'heads'.freeze
5
7
  DEPLOY_PREFIX = 'shipit-deploy'.freeze
6
8
 
7
9
  def perform(stack)
@@ -20,7 +22,7 @@ module Shipit
20
22
  private
21
23
 
22
24
  def create_full_ref(stack_environment)
23
- [DEPLOY_PREFIX, stack_environment].join("/")
25
+ [BRANCH_REF_PREFIX, DEPLOY_PREFIX, stack_environment].join("/")
24
26
  end
25
27
 
26
28
  def create_ref(client:, repo_name:, ref:, sha:)
@@ -8,7 +8,7 @@ module Shipit
8
8
  end
9
9
 
10
10
  def refresh_status
11
- Rails.cache.write(CACHE_KEY, Shipit.github.api.github_status)
11
+ Rails.cache.write(CACHE_KEY, Shipit.github.api_status)
12
12
  rescue Faraday::Error, Octokit::ServerError
13
13
  end
14
14
  end
@@ -100,7 +100,7 @@ module Shipit
100
100
  assign_attributes(
101
101
  github_id: github_user.id,
102
102
  name: github_user.name || github_user.login, # Name is not mandatory on GitHub
103
- email: github_user.email,
103
+ email: appropriate_email_for(github_user),
104
104
  login: github_user.login,
105
105
  avatar_url: github_user.avatar_url,
106
106
  api_url: github_user.url,
@@ -123,5 +123,27 @@ module Shipit
123
123
  rescue Octokit::NotFound
124
124
  false
125
125
  end
126
+
127
+ def email_valid_and_preferred?(email_address)
128
+ org_domains = Shipit.preferred_org_emails
129
+ return true if org_domains.blank?
130
+ return false if email_address.blank?
131
+
132
+ org_domains.any? { |domain| email_address.end_with?("@#{domain}") }
133
+ end
134
+
135
+ def appropriate_email_for(github_user)
136
+ return github_user.email if email_valid_and_preferred?(github_user.email)
137
+
138
+ begin
139
+ github_api.emails
140
+ .sort_by { |e| e.primary ? 0 : 1 }
141
+ .map(&:email)
142
+ .find { |e| email_valid_and_preferred?(e) }
143
+ rescue Octokit::NotFound, Octokit::Forbidden
144
+ # If the user hasn't agreed to the necessary permission, we can't access their private emails.
145
+ nil
146
+ end
147
+ end
126
148
  end
127
149
  end
@@ -33,7 +33,7 @@
33
33
 
34
34
  <div id="layout-content">
35
35
  <% github_status = Shipit::GithubStatus.status
36
- unless github_status.nil? || github_status[:status] == 'good' %>
36
+ unless github_status.nil? || github_status[:status] == 'operational' %>
37
37
  <div class="banner github-status banner--orange hidden">
38
38
  <div class="banner__inner wrapper">
39
39
  <div class="banner__content">
@@ -9,18 +9,6 @@
9
9
  <%= render 'shipit/deploys/summary', commits: @deploy.commits %>
10
10
  </section>
11
11
 
12
- <% unless @deploy.commits_since.empty? %>
13
- <section class="less-important">
14
-
15
- <p>The following commits are <strong>not</strong> included in this deploy.
16
- Please ensure that none of these commits are needed for what
17
- <strong>is</strong> being deployed (for example, if they contain the revert
18
- of a broken change).</p>
19
-
20
- <%= render 'shipit/deploys/summary', commits: @deploy.commits_since %>
21
- </section>
22
- <% end %>
23
-
24
12
  <%= render_monitoring @stack %>
25
13
 
26
14
  <%= render_checks @commit %>
@@ -37,4 +25,21 @@
37
25
  <%= f.submit class: 'btn btn--primary btn--large trigger-deploy' %>
38
26
  </section>
39
27
  <% end %>
28
+
29
+ <% unless @deploy.commits_since.empty? %>
30
+ <section class="less-important">
31
+ <header class="section-header">
32
+ <h2>Commits not included in this deploy</h2>
33
+ </header>
34
+
35
+ <div>
36
+ <p>The following commits are <strong>not</strong> included in this deploy.
37
+ Please ensure that none of these commits are needed for what
38
+ <strong>is</strong> being deployed (for example, if they contain the revert
39
+ of a broken change).</p>
40
+
41
+ <%= render 'shipit/deploys/summary', commits: @deploy.commits_since %>
42
+ </div>
43
+ </section>
44
+ <% end %>
40
45
  </div>
data/lib/shipit.rb CHANGED
@@ -47,7 +47,7 @@ require 'shipit/deploy_commands'
47
47
  require 'shipit/rollback_commands'
48
48
  require 'shipit/environment_variables'
49
49
  require 'shipit/stat'
50
- require 'shipit/strip_cache_control'
50
+ require 'shipit/github_http_cache_middleware'
51
51
  require 'shipit/cast_value'
52
52
  require 'shipit/line_buffer'
53
53
 
@@ -60,7 +60,7 @@ module Shipit
60
60
  delegate :table_name_prefix, to: :secrets
61
61
 
62
62
  attr_accessor :disable_api_authentication, :timeout_exit_codes
63
- attr_writer :internal_hook_receivers, :task_logger
63
+ attr_writer :internal_hook_receivers, :task_logger, :preferred_org_emails
64
64
 
65
65
  self.timeout_exit_codes = [].freeze
66
66
 
@@ -106,22 +106,6 @@ module Shipit
106
106
  end
107
107
  end
108
108
 
109
- def new_faraday_stack
110
- Faraday::RackBuilder.new do |builder|
111
- builder.use(
112
- Faraday::HttpCache,
113
- shared_cache: false,
114
- store: Rails.cache,
115
- logger: Rails.logger,
116
- serializer: NullSerializer,
117
- )
118
- builder.use StripCacheControl
119
- builder.use Octokit::Response::RaiseError
120
- builder.adapter Faraday.default_adapter
121
- yield builder if block_given?
122
- end
123
- end
124
-
125
109
  def api_clients_secret
126
110
  secrets.api_clients_secret.presence || secrets.secret_key_base
127
111
  end
@@ -196,6 +180,10 @@ module Shipit
196
180
  @internal_hook_receivers ||= []
197
181
  end
198
182
 
183
+ def preferred_org_emails
184
+ @preferred_org_emails ||= []
185
+ end
186
+
199
187
  def task_logger
200
188
  @task_logger ||= Logger.new(nil)
201
189
  end
@@ -25,6 +25,7 @@ module Shipit
25
25
 
26
26
  DOMAIN = 'github.com'.freeze
27
27
  AuthenticationFailed = Class.new(StandardError)
28
+ API_STATUS_ID = 'brv1bkgrwx7q'.freeze
28
29
 
29
30
  attr_reader :oauth_teams, :domain, :bot_login
30
31
 
@@ -53,6 +54,13 @@ module Shipit
53
54
  client
54
55
  end
55
56
 
57
+ def api_status
58
+ conn = Faraday.new(url: 'https://www.githubstatus.com')
59
+ response = conn.get('/api/v2/components.json')
60
+ parsed = JSON.parse(response.body, symbolize_names: true)
61
+ parsed[:components].find { |c| c[:id] == API_STATUS_ID }
62
+ end
63
+
56
64
  def verify_webhook_signature(signature, message)
57
65
  return true unless webhook_secret
58
66
 
@@ -118,7 +126,7 @@ module Shipit
118
126
 
119
127
  def new_client(options = {})
120
128
  client = Octokit::Client.new(options.reverse_merge(api_endpoint: api_endpoint))
121
- client.middleware = Shipit.new_faraday_stack
129
+ client.middleware = faraday_stack
122
130
  client
123
131
  end
124
132
 
@@ -126,6 +134,21 @@ module Shipit
126
134
 
127
135
  attr_reader :webhook_secret, :oauth_id, :oauth_secret
128
136
 
137
+ def faraday_stack
138
+ @faraday_stack ||= Faraday::RackBuilder.new do |builder|
139
+ builder.use(
140
+ Faraday::HttpCache,
141
+ shared_cache: false,
142
+ store: Rails.cache,
143
+ logger: Rails.logger,
144
+ serializer: NullSerializer,
145
+ )
146
+ builder.use GitHubHTTPCacheMiddleware
147
+ builder.use Octokit::Response::RaiseError
148
+ builder.adapter Faraday.default_adapter
149
+ end
150
+ end
151
+
129
152
  def app_id
130
153
  @app_id ||= @config.fetch(:app_id)
131
154
  end
@@ -0,0 +1,56 @@
1
+ module Shipit
2
+ class GitHubHTTPCacheMiddleware < Faraday::Middleware
3
+ def call(request_env)
4
+ @app.call(request_env).on_complete do |response_env|
5
+ if headers = response_env[:response_headers]
6
+
7
+ # We're removing max-age and s-maxage because some endpoints,
8
+ # especially /<repo>/commits, returns a max-age=0. This means that
9
+ # if two commits are pushed within 1 minute of each others, we won't
10
+ # see the second one. So instead we still issue the request, but we
11
+ # revalidate it.
12
+ cache_control = parse(headers['cache-control'].to_s)
13
+ cache_control.delete('max-age')
14
+ cache_control.delete('s-maxage')
15
+ cache_control['no-cache'] = true
16
+ cache_control['must-revalidate'] = true
17
+ headers['cache-control'] = dump(cache_control)
18
+
19
+ # We're removing `Authorization` from the `Vary` header because
20
+ # Faraday::HttpCache has a very limited garbage collection support
21
+ # and this cause cache entries to grow indefinitely.
22
+ # See https://github.com/Shopify/shipit-engine/issues/935 for
23
+ # more details.
24
+ vary = parse(headers['vary'].to_s)
25
+ vary.delete('authorization')
26
+ headers['vary'] = dump(vary)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def dump(directives)
34
+ directives.map do |k, v|
35
+ if v == true
36
+ k
37
+ else
38
+ "#{k}=#{v}"
39
+ end
40
+ end.join(', ')
41
+ end
42
+
43
+ def parse(header)
44
+ directives = {}
45
+
46
+ header.delete(' ').split(',').each do |part|
47
+ next if part.empty?
48
+
49
+ name, value = part.split('=', 2)
50
+ directives[name.downcase] = (value || true) unless name.empty?
51
+ end
52
+
53
+ directives
54
+ end
55
+ end
56
+ end
@@ -1,3 +1,3 @@
1
1
  module Shipit
2
- VERSION = '0.28.0'.freeze
2
+ VERSION = '0.28.1'.freeze
3
3
  end
@@ -1,8 +1,11 @@
1
1
  require 'faker'
2
- require 'fakeweb'
2
+ require 'webmock'
3
+ include WebMock::API
4
+ WebMock.enable!
5
+ WebMock.allow_net_connect!
3
6
 
4
7
  # Sometimes on Travis the background job runs immediately so provide a response to fake hooks
5
- FakeWeb.register_uri(:post, %r{https://example\.com/}, status: %w(200 OK))
8
+ stub_request(:post, %r{https://example\.com/}).to_return(status: %w(200 OK))
6
9
 
7
10
  # Cheap hack to allow rake db:seed to work
8
11
  module Shipit
@@ -8,7 +8,7 @@ module Shipit
8
8
  end
9
9
 
10
10
  test "#perform delivers a delivery" do
11
- FakeWeb.register_uri(:post, @delivery.url, body: 'OK')
11
+ stub_request(:post, @delivery.url).to_return(body: 'OK')
12
12
  @job.perform(@delivery)
13
13
  assert_equal 'sent', @delivery.reload.status
14
14
  end
@@ -17,15 +17,15 @@ module Shipit
17
17
 
18
18
  test "#perform rejects unmergeable PRs and merge the others" do
19
19
  PullRequest.any_instance.stubs(:refresh!)
20
- FakeWeb.register_uri(:put, "#{@pending_pr.api_url}/merge", status: %w(200 OK), body: {
20
+ stub_request(:put, "#{@pending_pr.api_url}/merge").to_return(status: %w(200 OK), body: {
21
21
  sha: "6dcb09b5b57875f334f61aebed695e2e4193db5e",
22
22
  merged: true,
23
23
  message: "Pull Request successfully merged",
24
24
  }.to_json)
25
25
  branch_url = "https://api.github.com/repos/shopify/shipit-engine/git/refs/heads/feature-62"
26
- FakeWeb.register_uri(:delete, branch_url, status: %w(204 No content))
26
+ stub_request(:delete, branch_url).to_return(status: %w(204 No content))
27
27
  pulls_url = "https://api.github.com/repos/shopify/shipit-engine/pulls?base=feature-62"
28
- FakeWeb.register_uri(:get, pulls_url, status: %w(200 OK), body: '[]')
28
+ stub_request(:get, pulls_url).to_return(status: %w(200 OK), body: '[]')
29
29
 
30
30
  @job.perform(@stack)
31
31
 
@@ -35,7 +35,7 @@ module Shipit
35
35
 
36
36
  test "#perform rejects PRs if the merge attempt fails" do
37
37
  PullRequest.any_instance.stubs(:refresh!)
38
- FakeWeb.register_uri(:put, "#{@pending_pr.api_url}/merge", status: %w(405 Method not allowed), body: {
38
+ stub_request(:put, "#{@pending_pr.api_url}/merge").to_return(status: %w(405 Method not allowed), body: {
39
39
  message: "Pull Request is not mergeable",
40
40
  documentation_url: "https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button",
41
41
  }.to_json)
@@ -8,22 +8,23 @@ module Shipit
8
8
  @deploy = @stack.deploys.last
9
9
  @commit = @deploy.until_commit
10
10
  @api_client = Shipit.github.api
11
- @expected_ref_prefix = "shipit-deploy/#{@stack.environment}"
12
11
  @expected_name = @stack.github_repo_name
13
12
  @expected_sha = @commit.sha
14
13
 
15
- expected_ref = ["refs", @expected_ref_prefix].join('/')
16
- ref_url = "http://api.github.test.com/shopify/shipit-engine/git/#{expected_ref}"
14
+ expected_ref_suffix = "shipit-deploy/#{@stack.environment}"
15
+ @expected_ref = ["heads", expected_ref_suffix].join('/')
16
+
17
+ ref_url = "http://api.github.test.com/shopify/shipit-engine/git/#{@expected_ref}"
17
18
  commit_url = "https://api.github.test.com/repos/shopify/shipit-engine/git/commits/#{@commit.sha}"
18
19
  response_inner_obj = OpenStruct.new(sha: @commit.sha, type: "commit", url: commit_url)
19
- @response = OpenStruct.new(ref: expected_ref, node_id: "blah", url: ref_url, object: response_inner_obj)
20
+ @response = OpenStruct.new(ref: @expected_ref, node_id: "blah", url: ref_url, object: response_inner_obj)
20
21
  end
21
22
 
22
23
  test "#perform will create a ref when one is not present" do
23
24
  Octokit::UnprocessableEntity.any_instance.stubs(:build_error_message).returns("Reference does not exist")
24
25
 
25
- @api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).raises(Octokit::UnprocessableEntity)
26
- @api_client.expects(:create_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).returns(@response)
26
+ @api_client.expects(:update_ref).with(@expected_name, @expected_ref, @expected_sha).raises(Octokit::UnprocessableEntity)
27
+ @api_client.expects(:create_ref).with(@expected_name, @expected_ref, @expected_sha).returns(@response)
27
28
 
28
29
  result = @job.perform(@stack)
29
30
 
@@ -38,7 +39,7 @@ module Shipit
38
39
  @commit.sha = new_sha
39
40
  @commit.save
40
41
 
41
- @api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, new_sha).returns(@response)
42
+ @api_client.expects(:update_ref).with(@expected_name, @expected_ref, new_sha).returns(@response)
42
43
 
43
44
  result = @job.perform(@stack)
44
45
 
@@ -48,8 +49,8 @@ module Shipit
48
49
  test '#perform will raise an exception for non ref existence errors' do
49
50
  Octokit::UnprocessableEntity.any_instance.stubs(:build_error_message).returns("Some other error.")
50
51
 
51
- @api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).raises(Octokit::UnprocessableEntity)
52
- @api_client.expects(:create_ref).with(@expected_name, @expected_ref_prefix, @expected_sha).never
52
+ @api_client.expects(:update_ref).with(@expected_name, @expected_ref, @expected_sha).raises(Octokit::UnprocessableEntity)
53
+ @api_client.expects(:create_ref).with(@expected_name, @expected_ref, @expected_sha).never
53
54
 
54
55
  assert_raises Octokit::UnprocessableEntity do
55
56
  @job.perform(@stack)
@@ -72,7 +73,7 @@ module Shipit
72
73
  new_deploy.status = "faulty"
73
74
  new_deploy.save
74
75
 
75
- @api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, new_sha).returns(@response)
76
+ @api_client.expects(:update_ref).with(@expected_name, @expected_ref, new_sha).returns(@response)
76
77
  result = @job.perform(@stack)
77
78
 
78
79
  assert_equal @response, result
@@ -81,7 +82,7 @@ module Shipit
81
82
  new_deploy.status = "success"
82
83
  new_deploy.save
83
84
 
84
- @api_client.expects(:update_ref).with(@expected_name, @expected_ref_prefix, new_commit.sha).returns(@response)
85
+ @api_client.expects(:update_ref).with(@expected_name, @expected_ref, new_commit.sha).returns(@response)
85
86
  @job.perform(@stack)
86
87
  end
87
88
  end
@@ -8,6 +8,12 @@ module Shipit
8
8
  @pr.message = "Merge pull request #31 from Shopify/improve-polling\n\nSeveral improvements to polling"
9
9
  @stack.reload
10
10
  @commit = shipit_commits(:first)
11
+
12
+ stub_request(:get, "https://api.github.com/user/emails").to_return(
13
+ status: %w(200 OK),
14
+ body: {}.to_json,
15
+ headers: {"Content-Type" => "application/json"},
16
+ )
11
17
  end
12
18
 
13
19
  test '.create_from_github handle unknown users' do
@@ -24,7 +24,7 @@ module Shipit
24
24
 
25
25
  test "#send! post the payload and update the status to `sent`" do
26
26
  headers = {'content-type' => 'text/plain', 'content-length' => '2'}
27
- FakeWeb.register_uri(:post, @delivery.url, headers.merge(body: 'OK'))
27
+ stub_request(:post, @delivery.url).to_return(headers: headers, body: 'OK')
28
28
 
29
29
  assert_equal 'scheduled', @delivery.status
30
30
  @delivery.send!
@@ -3,6 +3,7 @@ require 'test_helper'
3
3
  module Shipit
4
4
  class UsersTest < ActiveSupport::TestCase
5
5
  setup do
6
+ @previous_preferred_org_emails = Shipit.preferred_org_emails
6
7
  @user = shipit_users(:walrus)
7
8
  @github_user = stub(
8
9
  id: 42,
@@ -12,6 +13,8 @@ module Shipit
12
13
  avatar_url: 'https://avatars.githubusercontent.com/u/42?v=3',
13
14
  url: 'https://api.github.com/user/george',
14
15
  )
16
+ @org_domain = "shopify.com"
17
+ @emails_url = "https://api.github.com/user/emails"
15
18
  @minimal_github_user = stub(
16
19
  id: 43,
17
20
  name: nil,
@@ -23,6 +26,10 @@ module Shipit
23
26
  )
24
27
  end
25
28
 
29
+ teardown do
30
+ Shipit.preferred_org_emails = @previous_preferred_org_emails
31
+ end
32
+
26
33
  test "find_or_create_from_github persist a new user if he is unknown" do
27
34
  assert_difference 'User.count', 1 do
28
35
  fetch_user
@@ -58,10 +65,103 @@ module Shipit
58
65
  end
59
66
 
60
67
  test "find_or_create_from_github accepts minimal users without name nor email" do
68
+ Shipit.preferred_org_emails = [].freeze
61
69
  user = User.find_or_create_from_github(@minimal_github_user)
62
70
  assert_equal @minimal_github_user.login, user.login
63
71
  end
64
72
 
73
+ test "find_or_create_from_github selects any email when org email is unspecified" do
74
+ github_org_user = stub(
75
+ id: 42,
76
+ name: 'Jim Jones',
77
+ login: 'jim',
78
+ email: "jim@#{@org_domain}",
79
+ avatar_url: 'https://avatars.githubusercontent.com/u/42?v=3',
80
+ url: 'https://api.github.com/user/jim',
81
+ )
82
+
83
+ Shipit.preferred_org_emails = [].freeze
84
+ user = User.find_or_create_from_github(github_org_user)
85
+ assert_equal github_org_user.email, user.email
86
+ end
87
+
88
+ test "find_or_create_from_github selects org email for user" do
89
+ Shipit.preferred_org_emails = [@org_domain]
90
+ expected_email = "myuser@#{@org_domain}"
91
+
92
+ stub_request(:get, @emails_url).to_return(
93
+ status: %w(200 OK),
94
+ body: [{email: expected_email}].to_json,
95
+ headers: {"Content-Type" => "application/json"},
96
+ )
97
+
98
+ user = User.find_or_create_from_github(@github_user)
99
+ assert_equal expected_email, user.email
100
+ end
101
+
102
+ test "find_or_create_from_github selects private and primary org email for user when necessary" do
103
+ Shipit.preferred_org_emails = [@org_domain]
104
+ expected_email = "myuser@#{@org_domain}"
105
+ result_email_records = [
106
+ {
107
+ email: "notmyuser1@#{@org_domain}",
108
+ primary: false,
109
+ },
110
+ {
111
+ email: "notmyuser2@#{@org_domain}",
112
+ },
113
+ {
114
+ email: expected_email,
115
+ primary: true,
116
+ },
117
+ ]
118
+
119
+ stub_request(:get, @emails_url).to_return(
120
+ status: %w(200 OK),
121
+ body: result_email_records.to_json,
122
+ headers: {"Content-Type" => "application/json"},
123
+ )
124
+
125
+ user = User.find_or_create_from_github(@github_user)
126
+ assert_equal expected_email, user.email
127
+ end
128
+
129
+ test "find_or_create_from_github selects no email when org emails are provided but not found" do
130
+ Shipit.preferred_org_emails = [@org_domain]
131
+ result_email_records = [
132
+ {
133
+ email: "notmyuser1@not#{@org_domain}",
134
+ primary: false,
135
+ },
136
+ {
137
+ email: "notmyuser2@not#{@org_domain}",
138
+ },
139
+ ]
140
+
141
+ stub_request(:get, @emails_url).to_return(
142
+ status: %w(200 OK),
143
+ body: result_email_records.to_json,
144
+ headers: {"Content-Type" => "application/json"},
145
+ )
146
+
147
+ user = User.find_or_create_from_github(@github_user)
148
+ assert_nil user.email
149
+ end
150
+
151
+ test "find_or_create_from_github handles user 404" do
152
+ Shipit.preferred_org_emails = [@org_domain]
153
+ Octokit::Client.any_instance.expects(:emails).raises(Octokit::NotFound)
154
+ user = User.find_or_create_from_github(@minimal_github_user)
155
+ assert_nil user.email
156
+ end
157
+
158
+ test "find_or_create_from_github handles user 403" do
159
+ Shipit.preferred_org_emails = [@org_domain]
160
+ Octokit::Client.any_instance.expects(:emails).raises(Octokit::Forbidden)
161
+ user = User.find_or_create_from_github(@minimal_github_user)
162
+ assert_nil user.email
163
+ end
164
+
65
165
  test "#identifiers_for_ping returns a hash with the user's github_id, name, email and github_login" do
66
166
  user = shipit_users(:bob)
67
167
  expected_ouput = {github_id: user.github_id, name: user.name, email: user.email, github_login: user.login}
data/test/test_helper.rb CHANGED
@@ -3,8 +3,7 @@ ENV["RAILS_ENV"] ||= "test"
3
3
  require 'simplecov'
4
4
  SimpleCov.start 'rails'
5
5
 
6
- require 'fakeweb'
7
- FakeWeb.allow_net_connect = false
6
+ require 'webmock/minitest'
8
7
 
9
8
  require File.expand_path('../../test/dummy/config/environment.rb', __FILE__)
10
9
  ActiveRecord::Migrator.migrations_paths = [
@@ -13,6 +13,34 @@ module Shipit
13
13
  end
14
14
  end
15
15
 
16
+ test "#api_status" do
17
+ stub_request(:get, "https://www.githubstatus.com/api/v2/components.json").to_return(
18
+ status: 200,
19
+ body: %(
20
+ {
21
+ "page":{},
22
+ "components":[
23
+ {
24
+ "id":"brv1bkgrwx7q",
25
+ "name":"API Requests",
26
+ "status":"operational",
27
+ "created_at":"2017-01-31T20:01:46.621Z",
28
+ "updated_at":"2019-07-23T18:41:18.197Z",
29
+ "position":2,
30
+ "description":"Requests for GitHub APIs",
31
+ "showcase":false,
32
+ "group_id":null,
33
+ "page_id":"kctbh9vrtdwd",
34
+ "group":false,
35
+ "only_show_if_degraded":false
36
+ }
37
+ ]
38
+ }
39
+ ),
40
+ )
41
+ assert_equal "operational", app.api_status[:status]
42
+ end
43
+
16
44
  test "#domain defaults to github.com" do
17
45
  assert_equal 'github.com', @github.domain
18
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shipit-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.28.0
4
+ version: 0.28.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-19 00:00:00.000000000 Z
11
+ date: 2019-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -706,6 +706,7 @@ files:
706
706
  - lib/shipit/first_parent_commits_iterator.rb
707
707
  - lib/shipit/flock.rb
708
708
  - lib/shipit/github_app.rb
709
+ - lib/shipit/github_http_cache_middleware.rb
709
710
  - lib/shipit/line_buffer.rb
710
711
  - lib/shipit/null_serializer.rb
711
712
  - lib/shipit/octokit_check_runs.rb
@@ -715,7 +716,6 @@ files:
715
716
  - lib/shipit/simple_message_verifier.rb
716
717
  - lib/shipit/stack_commands.rb
717
718
  - lib/shipit/stat.rb
718
- - lib/shipit/strip_cache_control.rb
719
719
  - lib/shipit/task_commands.rb
720
720
  - lib/shipit/version.rb
721
721
  - lib/snippets/assert-egg-version-tag
@@ -908,155 +908,154 @@ required_rubygems_version: !ruby/object:Gem::Requirement
908
908
  - !ruby/object:Gem::Version
909
909
  version: '0'
910
910
  requirements: []
911
- rubyforge_project:
912
- rubygems_version: 2.7.6
911
+ rubygems_version: 3.0.3
913
912
  signing_key:
914
913
  specification_version: 4
915
914
  summary: Application deployment software
916
915
  test_files:
917
- - test/helpers/hooks_helper.rb
918
- - test/helpers/links_helper.rb
919
- - test/helpers/fixture_aliases_helper.rb
920
- - test/helpers/json_helper.rb
921
- - test/helpers/payloads_helper.rb
922
- - test/helpers/api_helper.rb
923
- - test/helpers/queries_helper.rb
924
- - test/models/membership_test.rb
925
- - test/models/rollbacks_test.rb
926
- - test/models/output_chunk_test.rb
927
- - test/models/pull_request_test.rb
928
- - test/models/team_test.rb
929
- - test/models/commit_deployment_status_test.rb
930
- - test/models/deploy_spec_test.rb
931
- - test/models/task_definitions_test.rb
932
- - test/models/stacks_test.rb
933
- - test/models/undeployed_commits_test.rb
934
- - test/models/shipit/check_run_test.rb
935
- - test/models/github_hook_test.rb
936
- - test/models/status/group_test.rb
937
- - test/models/status/missing_test.rb
938
- - test/models/api_client_test.rb
939
- - test/models/deploys_test.rb
940
- - test/models/hook_test.rb
941
- - test/models/commit_checks_test.rb
942
- - test/models/status_test.rb
943
- - test/models/users_test.rb
944
- - test/models/commit_deployment_test.rb
945
- - test/models/release_statuses_test.rb
946
- - test/models/duration_test.rb
947
- - test/models/tasks_test.rb
948
- - test/models/delivery_test.rb
949
- - test/models/commits_test.rb
950
- - test/fixtures/payloads/check_suite_master.json
951
- - test/fixtures/payloads/push_not_master.json
952
- - test/fixtures/payloads/status_master.json
953
- - test/fixtures/payloads/push_master.json
954
- - test/fixtures/timeout
955
- - test/fixtures/shipit/users.yml
956
- - test/fixtures/shipit/output_chunks.yml
957
- - test/fixtures/shipit/teams.yml
958
- - test/fixtures/shipit/github_hooks.yml
959
- - test/fixtures/shipit/hooks.yml
960
- - test/fixtures/shipit/commits.yml
961
- - test/fixtures/shipit/commit_deployments.yml
962
- - test/fixtures/shipit/statuses.yml
963
- - test/fixtures/shipit/stacks.yml
964
- - test/fixtures/shipit/pull_requests.yml
965
- - test/fixtures/shipit/api_clients.yml
966
- - test/fixtures/shipit/tasks.yml
967
- - test/fixtures/shipit/release_statuses.yml
968
- - test/fixtures/shipit/memberships.yml
969
- - test/fixtures/shipit/commit_deployment_statuses.yml
970
- - test/fixtures/shipit/deliveries.yml
971
- - test/fixtures/shipit/check_runs.yml
972
- - test/dummy/config/secrets.yml
973
- - test/dummy/config/boot.rb
974
- - test/dummy/config/database.postgresql.yml
975
- - test/dummy/config/database.mysql.yml
976
- - test/dummy/config/locales/en.yml
977
- - test/dummy/config/environments/production.rb
978
- - test/dummy/config/environments/test.rb
979
- - test/dummy/config/environments/development.rb
980
- - test/dummy/config/application.rb
981
- - test/dummy/config/routes.rb
982
- - test/dummy/config/initializers/0_load_development_secrets.rb
983
- - test/dummy/config/initializers/wrap_parameters.rb
984
- - test/dummy/config/initializers/session_store.rb
985
- - test/dummy/config/initializers/inflections.rb
986
- - test/dummy/config/initializers/cookies_serializer.rb
987
- - test/dummy/config/initializers/assets.rb
988
- - test/dummy/config/initializers/mime_types.rb
989
- - test/dummy/config/initializers/filter_parameter_logging.rb
990
- - test/dummy/config/initializers/backtrace_silencers.rb
991
- - test/dummy/config/environment.rb
992
- - test/dummy/config/database.yml
993
- - test/dummy/Rakefile
916
+ - test/dummy/public/favicon.ico
917
+ - test/dummy/public/500.html
918
+ - test/dummy/public/422.html
919
+ - test/dummy/public/404.html
920
+ - test/dummy/db/seeds.rb
921
+ - test/dummy/db/schema.rb
922
+ - test/dummy/bin/rake
994
923
  - test/dummy/bin/bundle
995
924
  - test/dummy/bin/rails
996
- - test/dummy/bin/rake
997
925
  - test/dummy/bin/setup
998
- - test/dummy/public/422.html
999
- - test/dummy/public/favicon.ico
1000
- - test/dummy/public/404.html
1001
- - test/dummy/public/500.html
1002
- - test/dummy/app/helpers/application_helper.rb
926
+ - test/dummy/app/views/layouts/application.html.erb
1003
927
  - test/dummy/app/assets/stylesheets/application.css
1004
928
  - test/dummy/app/assets/javascripts/application.js
1005
- - test/dummy/app/views/layouts/application.html.erb
1006
929
  - test/dummy/app/controllers/application_controller.rb
1007
- - test/dummy/db/seeds.rb
1008
- - test/dummy/db/schema.rb
930
+ - test/dummy/app/helpers/application_helper.rb
1009
931
  - test/dummy/config.ru
1010
- - test/controllers/deploys_controller_test.rb
932
+ - test/dummy/Rakefile
933
+ - test/dummy/config/application.rb
934
+ - test/dummy/config/database.yml
935
+ - test/dummy/config/locales/en.yml
936
+ - test/dummy/config/secrets.yml
937
+ - test/dummy/config/boot.rb
938
+ - test/dummy/config/database.mysql.yml
939
+ - test/dummy/config/initializers/filter_parameter_logging.rb
940
+ - test/dummy/config/initializers/session_store.rb
941
+ - test/dummy/config/initializers/backtrace_silencers.rb
942
+ - test/dummy/config/initializers/mime_types.rb
943
+ - test/dummy/config/initializers/cookies_serializer.rb
944
+ - test/dummy/config/initializers/0_load_development_secrets.rb
945
+ - test/dummy/config/initializers/assets.rb
946
+ - test/dummy/config/initializers/wrap_parameters.rb
947
+ - test/dummy/config/initializers/inflections.rb
948
+ - test/dummy/config/environment.rb
949
+ - test/dummy/config/routes.rb
950
+ - test/dummy/config/database.postgresql.yml
951
+ - test/dummy/config/environments/test.rb
952
+ - test/dummy/config/environments/development.rb
953
+ - test/dummy/config/environments/production.rb
954
+ - test/controllers/webhooks_controller_test.rb
955
+ - test/controllers/rollbacks_controller_test.rb
956
+ - test/controllers/github_authentication_controller_test.rb
957
+ - test/controllers/merge_status_controller_test.rb
958
+ - test/controllers/commit_checks_controller_test.rb
959
+ - test/controllers/ccmenu_controller_test.rb
1011
960
  - test/controllers/stacks_controller_test.rb
1012
- - test/controllers/status_controller_test.rb
1013
- - test/controllers/api/deploys_controller_test.rb
1014
- - test/controllers/api/locks_controller_test.rb
1015
- - test/controllers/api/stacks_controller_test.rb
1016
- - test/controllers/api/release_statuses_controller_test.rb
961
+ - test/controllers/deploys_controller_test.rb
962
+ - test/controllers/api/hooks_controller_test.rb
1017
963
  - test/controllers/api/ccmenu_controller_test.rb
964
+ - test/controllers/api/stacks_controller_test.rb
965
+ - test/controllers/api/base_controller_test.rb
966
+ - test/controllers/api/locks_controller_test.rb
967
+ - test/controllers/api/deploys_controller_test.rb
1018
968
  - test/controllers/api/commits_controller_test.rb
1019
- - test/controllers/api/outputs_controller_test.rb
1020
- - test/controllers/api/hooks_controller_test.rb
969
+ - test/controllers/api/release_statuses_controller_test.rb
1021
970
  - test/controllers/api/pull_requests_controller_test.rb
1022
971
  - test/controllers/api/tasks_controller_test.rb
1023
- - test/controllers/api/base_controller_test.rb
1024
- - test/controllers/commit_checks_controller_test.rb
1025
- - test/controllers/release_statuses_controller_test.rb
1026
- - test/controllers/webhooks_controller_test.rb
1027
- - test/controllers/ccmenu_controller_test.rb
1028
- - test/controllers/rollbacks_controller_test.rb
972
+ - test/controllers/api/outputs_controller_test.rb
973
+ - test/controllers/status_controller_test.rb
1029
974
  - test/controllers/commits_controller_test.rb
1030
- - test/controllers/github_authentication_controller_test.rb
975
+ - test/controllers/release_statuses_controller_test.rb
1031
976
  - test/controllers/pull_requests_controller_test.rb
1032
977
  - test/controllers/tasks_controller_test.rb
1033
- - test/controllers/merge_status_controller_test.rb
978
+ - test/unit/command_test.rb
979
+ - test/unit/commands_test.rb
980
+ - test/unit/line_buffer_test.rb
981
+ - test/unit/deploy_commands_test.rb
982
+ - test/unit/shipit_test.rb
983
+ - test/unit/rollback_commands_test.rb
984
+ - test/unit/csv_serializer_test.rb
985
+ - test/unit/variable_definition_test.rb
986
+ - test/unit/github_url_helper_test.rb
987
+ - test/unit/environment_variables_test.rb
988
+ - test/unit/github_app_test.rb
989
+ - test/models/release_statuses_test.rb
990
+ - test/models/deploys_test.rb
991
+ - test/models/undeployed_commits_test.rb
992
+ - test/models/team_test.rb
993
+ - test/models/rollbacks_test.rb
994
+ - test/models/commit_checks_test.rb
995
+ - test/models/github_hook_test.rb
996
+ - test/models/task_definitions_test.rb
997
+ - test/models/tasks_test.rb
998
+ - test/models/output_chunk_test.rb
999
+ - test/models/commit_deployment_status_test.rb
1000
+ - test/models/delivery_test.rb
1001
+ - test/models/users_test.rb
1002
+ - test/models/commit_deployment_test.rb
1003
+ - test/models/duration_test.rb
1004
+ - test/models/api_client_test.rb
1005
+ - test/models/shipit/check_run_test.rb
1006
+ - test/models/commits_test.rb
1007
+ - test/models/status/group_test.rb
1008
+ - test/models/status/missing_test.rb
1009
+ - test/models/deploy_spec_test.rb
1010
+ - test/models/stacks_test.rb
1011
+ - test/models/hook_test.rb
1012
+ - test/models/membership_test.rb
1013
+ - test/models/status_test.rb
1014
+ - test/models/pull_request_test.rb
1034
1015
  - test/test_command_integration.rb
1035
- - test/test_helper.rb
1036
- - test/jobs/destroy_stack_job_test.rb
1037
- - test/jobs/fetch_deployed_revision_job_test.rb
1038
- - test/jobs/fetch_commit_stats_job_test.rb
1016
+ - test/helpers/hooks_helper.rb
1017
+ - test/helpers/queries_helper.rb
1018
+ - test/helpers/json_helper.rb
1019
+ - test/helpers/fixture_aliases_helper.rb
1020
+ - test/helpers/payloads_helper.rb
1021
+ - test/helpers/links_helper.rb
1022
+ - test/helpers/api_helper.rb
1023
+ - test/jobs/emit_event_job_test.rb
1024
+ - test/jobs/unique_job_test.rb
1039
1025
  - test/jobs/merge_pull_requests_job_test.rb
1026
+ - test/jobs/deliver_hook_job_test.rb
1040
1027
  - test/jobs/update_github_last_deployed_ref_job_test.rb
1041
- - test/jobs/cache_deploy_spec_job_test.rb
1042
- - test/jobs/emit_event_job_test.rb
1028
+ - test/jobs/refresh_status_job_test.rb
1029
+ - test/jobs/fetch_deployed_revision_job_test.rb
1030
+ - test/jobs/purge_old_deliveries_job_test.rb
1043
1031
  - test/jobs/refresh_github_user_job_test.rb
1044
1032
  - test/jobs/chunk_rollup_job_test.rb
1045
1033
  - test/jobs/mark_deploy_healthy_job_test.rb
1046
- - test/jobs/refresh_status_job_test.rb
1047
- - test/jobs/purge_old_deliveries_job_test.rb
1048
- - test/jobs/deliver_hook_job_test.rb
1049
- - test/jobs/github_sync_job_test.rb
1034
+ - test/jobs/fetch_commit_stats_job_test.rb
1035
+ - test/jobs/cache_deploy_spec_job_test.rb
1050
1036
  - test/jobs/perform_task_job_test.rb
1051
- - test/jobs/unique_job_test.rb
1052
- - test/unit/environment_variables_test.rb
1053
- - test/unit/commands_test.rb
1054
- - test/unit/github_app_test.rb
1055
- - test/unit/rollback_commands_test.rb
1056
- - test/unit/command_test.rb
1057
- - test/unit/shipit_test.rb
1058
- - test/unit/line_buffer_test.rb
1059
- - test/unit/csv_serializer_test.rb
1060
- - test/unit/deploy_commands_test.rb
1061
- - test/unit/variable_definition_test.rb
1062
- - test/unit/github_url_helper_test.rb
1037
+ - test/jobs/github_sync_job_test.rb
1038
+ - test/jobs/destroy_stack_job_test.rb
1039
+ - test/fixtures/timeout
1040
+ - test/fixtures/shipit/check_runs.yml
1041
+ - test/fixtures/shipit/release_statuses.yml
1042
+ - test/fixtures/shipit/users.yml
1043
+ - test/fixtures/shipit/output_chunks.yml
1044
+ - test/fixtures/shipit/deliveries.yml
1045
+ - test/fixtures/shipit/hooks.yml
1046
+ - test/fixtures/shipit/github_hooks.yml
1047
+ - test/fixtures/shipit/statuses.yml
1048
+ - test/fixtures/shipit/memberships.yml
1049
+ - test/fixtures/shipit/teams.yml
1050
+ - test/fixtures/shipit/tasks.yml
1051
+ - test/fixtures/shipit/api_clients.yml
1052
+ - test/fixtures/shipit/stacks.yml
1053
+ - test/fixtures/shipit/commits.yml
1054
+ - test/fixtures/shipit/pull_requests.yml
1055
+ - test/fixtures/shipit/commit_deployments.yml
1056
+ - test/fixtures/shipit/commit_deployment_statuses.yml
1057
+ - test/fixtures/payloads/status_master.json
1058
+ - test/fixtures/payloads/push_master.json
1059
+ - test/fixtures/payloads/push_not_master.json
1060
+ - test/fixtures/payloads/check_suite_master.json
1061
+ - test/test_helper.rb
@@ -1,40 +0,0 @@
1
- module Shipit
2
- class StripCacheControl < Faraday::Middleware
3
- def call(request_env)
4
- @app.call(request_env).on_complete do |response_env|
5
- if headers = response_env[:response_headers]
6
- headers.delete('last-modified')
7
- directives = parse(headers['cache-control'].to_s)
8
- directives.delete('max-age')
9
- directives.delete('s-maxage')
10
- headers['cache-control'] = dump(directives)
11
- end
12
- end
13
- end
14
-
15
- private
16
-
17
- def dump(directives)
18
- directives.map do |k, v|
19
- if v == true
20
- k
21
- else
22
- "#{k}=#{v}"
23
- end
24
- end.join(', ')
25
- end
26
-
27
- def parse(header)
28
- directives = {}
29
-
30
- header.delete(' ').split(',').each do |part|
31
- next if part.empty?
32
-
33
- name, value = part.split('=', 2)
34
- directives[name.downcase] = (value || true) unless name.empty?
35
- end
36
-
37
- directives
38
- end
39
- end
40
- end