shipit-engine 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/app/assets/javascripts/shipit/stacks.js.coffee +15 -1
 - data/app/assets/stylesheets/_base/_icons.scss +18 -0
 - data/app/assets/stylesheets/_base/_status-items.scss +28 -0
 - data/app/assets/stylesheets/_pages/_commits.scss +1 -5
 - data/app/assets/stylesheets/_pages/_deploy.scss +60 -3
 - data/app/controllers/concerns/shipit/authentication.rb +1 -1
 - data/app/controllers/shipit/merge_status_controller.rb +2 -0
 - data/app/controllers/shipit/release_statuses_controller.rb +36 -0
 - data/app/jobs/shipit/append_delayed_release_status_job.rb +17 -0
 - data/app/jobs/shipit/cache_deploy_spec_job.rb +2 -0
 - data/app/jobs/shipit/clear_git_cache_job.rb +1 -1
 - data/app/jobs/shipit/create_release_statuses_job.rb +11 -0
 - data/app/jobs/shipit/deferred_touch_job.rb +2 -0
 - data/app/jobs/shipit/deliver_hook_job.rb +1 -0
 - data/app/jobs/shipit/merge_pull_requests_job.rb +2 -0
 - data/app/jobs/shipit/perform_commit_checks_job.rb +2 -0
 - data/app/jobs/shipit/perform_task_job.rb +2 -4
 - data/app/jobs/shipit/refresh_pull_request_job.rb +2 -0
 - data/app/models/shipit/anonymous_user.rb +1 -1
 - data/app/models/shipit/commit.rb +36 -3
 - data/app/models/shipit/deploy.rb +43 -0
 - data/app/models/shipit/deploy_spec.rb +16 -2
 - data/app/models/shipit/deploy_spec/bundler_discovery.rb +5 -1
 - data/app/models/shipit/deploy_spec/file_system.rb +4 -0
 - data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +1 -1
 - data/app/models/shipit/ephemeral_commit_checks.rb +2 -4
 - data/app/models/shipit/hook.rb +36 -3
 - data/app/models/shipit/pull_request.rb +4 -2
 - data/app/models/shipit/release_status.rb +41 -0
 - data/app/models/shipit/rollback.rb +9 -0
 - data/app/models/shipit/stack.rb +4 -9
 - data/app/models/shipit/status/common.rb +4 -0
 - data/app/models/shipit/status/group.rb +2 -1
 - data/app/models/shipit/status/missing.rb +4 -0
 - data/app/models/shipit/status/unknown.rb +15 -0
 - data/app/models/shipit/task.rb +4 -0
 - data/app/models/shipit/user.rb +16 -3
 - data/app/serializers/shipit/stack_serializer.rb +1 -1
 - data/app/views/shipit/deploys/_deploy.html.erb +18 -2
 - data/config/locales/en.yml +3 -0
 - data/config/routes.rb +2 -0
 - data/db/migrate/20180802172632_allow_commit_without_author.rb +6 -0
 - data/db/migrate/20180906083930_create_release_statuses.rb +21 -0
 - data/lib/shipit.rb +5 -0
 - data/lib/shipit/command.rb +14 -18
 - data/lib/shipit/deploy_commands.rb +0 -4
 - data/lib/shipit/engine.rb +1 -1
 - data/lib/shipit/first_parent_commits_iterator.rb +1 -1
 - data/lib/shipit/flock.rb +43 -0
 - data/lib/shipit/github_app.rb +5 -3
 - data/lib/shipit/rollback_commands.rb +6 -0
 - data/lib/shipit/task_commands.rb +1 -5
 - data/lib/shipit/version.rb +1 -1
 - data/test/controllers/release_statuses_controller_test.rb +23 -0
 - data/test/dummy/db/schema.rb +18 -3
 - data/test/dummy/db/seeds.rb +4 -0
 - data/test/fixtures/shipit/commits.yml +13 -0
 - data/test/fixtures/shipit/release_statuses.yml +16 -0
 - data/test/fixtures/shipit/stacks.yml +4 -0
 - data/test/jobs/append_delayed_release_status_job_test.rb +25 -0
 - data/test/jobs/cache_deploy_spec_job_test.rb +1 -2
 - data/test/jobs/emit_event_job_test.rb +1 -1
 - data/test/jobs/github_sync_job_test.rb +1 -0
 - data/test/models/commits_test.rb +54 -1
 - data/test/models/deploy_spec_test.rb +83 -11
 - data/test/models/deploys_test.rb +52 -0
 - data/test/models/hook_test.rb +1 -28
 - data/test/models/pull_request_test.rb +19 -0
 - data/test/models/release_statuses_test.rb +28 -0
 - data/test/models/rollbacks_test.rb +2 -0
 - data/test/models/stacks_test.rb +1 -1
 - data/test/test_helper.rb +5 -0
 - data/test/unit/rollback_commands_test.rb +35 -0
 - metadata +121 -104
 
    
        data/app/models/shipit/deploy.rb
    CHANGED
    
    | 
         @@ -9,6 +9,7 @@ module Shipit 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  after_transition to: :success, do: :schedule_merges
         
     | 
| 
       10 
10 
     | 
    
         
             
                  after_transition to: :success, do: :update_undeployed_commits_count
         
     | 
| 
       11 
11 
     | 
    
         
             
                  after_transition to: :aborted, do: :trigger_revert_if_required
         
     | 
| 
      
 12 
     | 
    
         
            +
                  after_transition any => any, do: :update_release_status
         
     | 
| 
       12 
13 
     | 
    
         
             
                  after_transition any => any, do: :update_commit_deployments
         
     | 
| 
       13 
14 
     | 
    
         
             
                  after_transition any => any, do: :update_last_deploy_time
         
     | 
| 
       14 
15 
     | 
    
         
             
                end
         
     | 
| 
         @@ -33,6 +34,7 @@ module Shipit 
     | 
|
| 
       33 
34 
     | 
    
         | 
| 
       34 
35 
     | 
    
         
             
                before_create :denormalize_commit_stats
         
     | 
| 
       35 
36 
     | 
    
         
             
                after_create :create_commit_deployments
         
     | 
| 
      
 37 
     | 
    
         
            +
                after_create :update_release_status
         
     | 
| 
       36 
38 
     | 
    
         
             
                after_commit :broadcast_update
         
     | 
| 
       37 
39 
     | 
    
         | 
| 
       38 
40 
     | 
    
         
             
                delegate :broadcast_update, :filter_deploy_envs, to: :stack
         
     | 
| 
         @@ -143,6 +145,21 @@ module Shipit 
     | 
|
| 
       143 
145 
     | 
    
         
             
                  confirmations.abs >= CONFIRMATIONS_REQUIRED
         
     | 
| 
       144 
146 
     | 
    
         
             
                end
         
     | 
| 
       145 
147 
     | 
    
         | 
| 
      
 148 
     | 
    
         
            +
                delegate :last_release_status, to: :until_commit
         
     | 
| 
      
 149 
     | 
    
         
            +
                def append_release_status(state, description, user: self.user)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  status = until_commit.create_release_status!(
         
     | 
| 
      
 151 
     | 
    
         
            +
                    state,
         
     | 
| 
      
 152 
     | 
    
         
            +
                    user: user.presence,
         
     | 
| 
      
 153 
     | 
    
         
            +
                    target_url: permalink,
         
     | 
| 
      
 154 
     | 
    
         
            +
                    description: description,
         
     | 
| 
      
 155 
     | 
    
         
            +
                  )
         
     | 
| 
      
 156 
     | 
    
         
            +
                  status
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                def permalink
         
     | 
| 
      
 160 
     | 
    
         
            +
                  Shipit::Engine.routes.url_helpers.stack_deploy_url(stack, self)
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
       146 
163 
     | 
    
         
             
                private
         
     | 
| 
       147 
164 
     | 
    
         | 
| 
       148 
165 
     | 
    
         
             
                def create_commit_deployments
         
     | 
| 
         @@ -151,6 +168,32 @@ module Shipit 
     | 
|
| 
       151 
168 
     | 
    
         
             
                  end
         
     | 
| 
       152 
169 
     | 
    
         
             
                end
         
     | 
| 
       153 
170 
     | 
    
         | 
| 
      
 171 
     | 
    
         
            +
                def update_release_status
         
     | 
| 
      
 172 
     | 
    
         
            +
                  return unless stack.release_status?
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                  case status
         
     | 
| 
      
 175 
     | 
    
         
            +
                  when 'pending'
         
     | 
| 
      
 176 
     | 
    
         
            +
                    append_release_status('pending', "A deploy was triggered on #{stack.environment}")
         
     | 
| 
      
 177 
     | 
    
         
            +
                  when 'failed', 'error', 'timedout'
         
     | 
| 
      
 178 
     | 
    
         
            +
                    append_release_status('error', "The deploy on #{stack.environment} did not succeed (#{status})")
         
     | 
| 
      
 179 
     | 
    
         
            +
                  when 'aborted', 'aborting'
         
     | 
| 
      
 180 
     | 
    
         
            +
                    append_release_status('failure', "The deploy on #{stack.environment} was canceled")
         
     | 
| 
      
 181 
     | 
    
         
            +
                  when 'success'
         
     | 
| 
      
 182 
     | 
    
         
            +
                    delay = stack.release_status_delay
         
     | 
| 
      
 183 
     | 
    
         
            +
                    if delay.zero?
         
     | 
| 
      
 184 
     | 
    
         
            +
                      append_release_status('success', "The deploy on #{stack.environment} succeeded")
         
     | 
| 
      
 185 
     | 
    
         
            +
                    elsif delay.positive?
         
     | 
| 
      
 186 
     | 
    
         
            +
                      append_release_status('pending', "The deploy on #{stack.environment} succeeded")
         
     | 
| 
      
 187 
     | 
    
         
            +
                      AppendDelayedReleaseStatusJob.set(wait: delay).perform_later(
         
     | 
| 
      
 188 
     | 
    
         
            +
                        self,
         
     | 
| 
      
 189 
     | 
    
         
            +
                        cursor: until_commit.release_statuses.last,
         
     | 
| 
      
 190 
     | 
    
         
            +
                        status: 'success',
         
     | 
| 
      
 191 
     | 
    
         
            +
                        description: "No issue were signaled after #{delay}",
         
     | 
| 
      
 192 
     | 
    
         
            +
                      )
         
     | 
| 
      
 193 
     | 
    
         
            +
                    end
         
     | 
| 
      
 194 
     | 
    
         
            +
                  end
         
     | 
| 
      
 195 
     | 
    
         
            +
                end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
       154 
197 
     | 
    
         
             
                def update_commit_deployments
         
     | 
| 
       155 
198 
     | 
    
         
             
                  commit_deployments.append_status(status)
         
     | 
| 
       156 
199 
     | 
    
         
             
                end
         
     | 
| 
         @@ -67,6 +67,20 @@ module Shipit 
     | 
|
| 
       67 
67 
     | 
    
         
             
                  config('deploy', 'max_commits') { 8 }
         
     | 
| 
       68 
68 
     | 
    
         
             
                end
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
      
 70 
     | 
    
         
            +
                def release_status?
         
     | 
| 
      
 71 
     | 
    
         
            +
                  !!release_status_context
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def release_status_context
         
     | 
| 
      
 75 
     | 
    
         
            +
                  config('status', 'context')
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def release_status_delay
         
     | 
| 
      
 79 
     | 
    
         
            +
                  if delay = config('status', 'delay') { config('deploy', 'interval') }
         
     | 
| 
      
 80 
     | 
    
         
            +
                    Duration.parse(delay)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
       70 
84 
     | 
    
         
             
                def pause_between_deploys
         
     | 
| 
       71 
85 
     | 
    
         
             
                  Duration.parse(config('deploy', 'interval') { 0 })
         
     | 
| 
       72 
86 
     | 
    
         
             
                end
         
     | 
| 
         @@ -131,7 +145,7 @@ module Shipit 
     | 
|
| 
       131 
145 
     | 
    
         
             
                end
         
     | 
| 
       132 
146 
     | 
    
         | 
| 
       133 
147 
     | 
    
         
             
                def hidden_statuses
         
     | 
| 
       134 
     | 
    
         
            -
                  Array.wrap(config('ci', 'hide'))
         
     | 
| 
      
 148 
     | 
    
         
            +
                  Array.wrap(config('ci', 'hide')) + [release_status_context].compact
         
     | 
| 
       135 
149 
     | 
    
         
             
                end
         
     | 
| 
       136 
150 
     | 
    
         | 
| 
       137 
151 
     | 
    
         
             
                def required_statuses
         
     | 
| 
         @@ -161,7 +175,7 @@ module Shipit 
     | 
|
| 
       161 
175 
     | 
    
         | 
| 
       162 
176 
     | 
    
         
             
                def pull_request_ignored_statuses
         
     | 
| 
       163 
177 
     | 
    
         
             
                  if config('merge', 'require') || config('merge', 'ignore')
         
     | 
| 
       164 
     | 
    
         
            -
                    Array.wrap(config('merge', 'ignore'))
         
     | 
| 
      
 178 
     | 
    
         
            +
                    Array.wrap(config('merge', 'ignore')) + [release_status_context].compact
         
     | 
| 
       165 
179 
     | 
    
         
             
                  else
         
     | 
| 
       166 
180 
     | 
    
         
             
                    soft_failing_statuses | hidden_statuses
         
     | 
| 
       167 
181 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -19,8 +19,12 @@ module Shipit 
     | 
|
| 
       19 
19 
     | 
    
         
             
                    end
         
     | 
| 
       20 
20 
     | 
    
         
             
                  end
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
                  def discover_machine_env
         
     | 
| 
      
 23 
     | 
    
         
            +
                    super.merge('BUNDLE_PATH' => bundle_path.to_s)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       22 
26 
     | 
    
         
             
                  def bundle_install
         
     | 
| 
       23 
     | 
    
         
            -
                    bundle = %(bundle  
     | 
| 
      
 27 
     | 
    
         
            +
                    bundle = %(bundle install #{frozen_flag} --jobs 4 --path #{bundle_path} --retry 2)
         
     | 
| 
       24 
28 
     | 
    
         
             
                    bundle += " --without=#{bundler_without.join(':')}" unless bundler_without.empty?
         
     | 
| 
       25 
29 
     | 
    
         
             
                    [remove_ruby_version_from_gemfile, bundle]
         
     | 
| 
       26 
30 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -57,6 +57,10 @@ module Shipit 
     | 
|
| 
       57 
57 
     | 
    
         
             
                        'checks' => review_checks,
         
     | 
| 
       58 
58 
     | 
    
         
             
                      },
         
     | 
| 
       59 
59 
     | 
    
         
             
                      'plugins' => plugins,
         
     | 
| 
      
 60 
     | 
    
         
            +
                      'status' => {
         
     | 
| 
      
 61 
     | 
    
         
            +
                        'context' => release_status_context,
         
     | 
| 
      
 62 
     | 
    
         
            +
                        'delay' => release_status_delay,
         
     | 
| 
      
 63 
     | 
    
         
            +
                      },
         
     | 
| 
       60 
64 
     | 
    
         
             
                      'dependencies' => {'override' => dependencies_steps},
         
     | 
| 
       61 
65 
     | 
    
         
             
                      'deploy' => {
         
     | 
| 
       62 
66 
     | 
    
         
             
                        'override' => deploy_steps,
         
     | 
| 
         @@ -14,10 +14,8 @@ module Shipit 
     | 
|
| 
       14 
14 
     | 
    
         
             
                  commands = StackCommands.new(stack)
         
     | 
| 
       15 
15 
     | 
    
         
             
                  commands.with_temporary_working_directory(commit: commit) do |directory|
         
     | 
| 
       16 
16 
     | 
    
         
             
                    deploy_spec = DeploySpec::FileSystem.new(directory, stack.environment)
         
     | 
| 
       17 
     | 
    
         
            -
                     
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                      capture_all(build_commands(deploy_spec.review_checks, chdir: directory))
         
     | 
| 
       20 
     | 
    
         
            -
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                    capture_all(build_commands(deploy_spec.dependencies_steps, chdir: directory))
         
     | 
| 
      
 18 
     | 
    
         
            +
                    capture_all(build_commands(deploy_spec.review_checks, chdir: directory))
         
     | 
| 
       21 
19 
     | 
    
         
             
                  end
         
     | 
| 
       22 
20 
     | 
    
         
             
                  self
         
     | 
| 
       23 
21 
     | 
    
         
             
                rescue Command::Error
         
     | 
    
        data/app/models/shipit/hook.rb
    CHANGED
    
    | 
         @@ -1,5 +1,38 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Shipit
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Hook < ActiveRecord::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                class DeliverySpec
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(event:, url:, content_type:, payload:)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @event = event
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @url = url
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @content_type = content_type
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @payload = payload
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def send!
         
     | 
| 
      
 12 
     | 
    
         
            +
                    http.post(url, payload)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  private
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  attr_reader :event, :url, :content_type, :payload
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def http
         
     | 
| 
      
 20 
     | 
    
         
            +
                    Faraday::Connection.new do |connection|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      connection.headers = headers
         
     | 
| 
      
 22 
     | 
    
         
            +
                      connection.adapter Faraday.default_adapter
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def headers
         
     | 
| 
      
 27 
     | 
    
         
            +
                    {
         
     | 
| 
      
 28 
     | 
    
         
            +
                      'User-Agent' => 'Shipit Webhook',
         
     | 
| 
      
 29 
     | 
    
         
            +
                      'Content-Type' => content_type,
         
     | 
| 
      
 30 
     | 
    
         
            +
                      'X-Shipit-Event' => event,
         
     | 
| 
      
 31 
     | 
    
         
            +
                      'Accept' => '*/*',
         
     | 
| 
      
 32 
     | 
    
         
            +
                    }
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       3 
36 
     | 
    
         
             
                default_scope { order :id }
         
     | 
| 
       4 
37 
     | 
    
         | 
| 
       5 
38 
     | 
    
         
             
                DELIVERIES_LOG_SIZE = 500
         
     | 
| 
         @@ -71,12 +104,12 @@ module Shipit 
     | 
|
| 
       71 
104 
     | 
    
         
             
                end
         
     | 
| 
       72 
105 
     | 
    
         | 
| 
       73 
106 
     | 
    
         
             
                def deliver!(event, payload)
         
     | 
| 
       74 
     | 
    
         
            -
                   
     | 
| 
       75 
     | 
    
         
            -
                    event: event,
         
     | 
| 
      
 107 
     | 
    
         
            +
                  DeliverHookJob.perform_later(
         
     | 
| 
      
 108 
     | 
    
         
            +
                    event: event.to_s,
         
     | 
| 
       76 
109 
     | 
    
         
             
                    url: delivery_url,
         
     | 
| 
       77 
110 
     | 
    
         
             
                    content_type: CONTENT_TYPES[content_type],
         
     | 
| 
       78 
111 
     | 
    
         
             
                    payload: serialize_payload(payload),
         
     | 
| 
       79 
     | 
    
         
            -
                  ) 
     | 
| 
      
 112 
     | 
    
         
            +
                  )
         
     | 
| 
       80 
113 
     | 
    
         
             
                end
         
     | 
| 
       81 
114 
     | 
    
         | 
| 
       82 
115 
     | 
    
         
             
                def purge_old_deliveries!(keep: DELIVERIES_LOG_SIZE)
         
     | 
| 
         @@ -2,6 +2,8 @@ module Shipit 
     | 
|
| 
       2 
2 
     | 
    
         
             
              class PullRequest < ApplicationRecord
         
     | 
| 
       3 
3 
     | 
    
         
             
                include DeferredTouch
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
                MERGE_REQUEST_FIELD = 'Merge-Requested-By'.freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       5 
7 
     | 
    
         
             
                WAITING_STATUSES = %w(fetching pending).freeze
         
     | 
| 
       6 
8 
     | 
    
         
             
                QUEUED_STATUSES = %w(pending revalidating).freeze
         
     | 
| 
       7 
9 
     | 
    
         
             
                REJECTION_REASONS = %w(ci_failing merge_conflict requires_rebase).freeze
         
     | 
| 
         @@ -188,7 +190,7 @@ module Shipit 
     | 
|
| 
       188 
190 
     | 
    
         | 
| 
       189 
191 
     | 
    
         
             
                def any_status_checks_failed?
         
     | 
| 
       190 
192 
     | 
    
         
             
                  status = StatusChecker.new(head, head.statuses, stack.cached_deploy_spec)
         
     | 
| 
       191 
     | 
    
         
            -
                  status.failure? || status.error?
         
     | 
| 
      
 193 
     | 
    
         
            +
                  status.failure? || status.error? || status.missing?
         
     | 
| 
       192 
194 
     | 
    
         
             
                end
         
     | 
| 
       193 
195 
     | 
    
         | 
| 
       194 
196 
     | 
    
         
             
                def waiting?
         
     | 
| 
         @@ -245,7 +247,7 @@ module Shipit 
     | 
|
| 
       245 
247 
     | 
    
         | 
| 
       246 
248 
     | 
    
         
             
                def merge_message
         
     | 
| 
       247 
249 
     | 
    
         
             
                  return title unless merge_requested_by
         
     | 
| 
       248 
     | 
    
         
            -
                  "#{title}\n\ 
     | 
| 
      
 250 
     | 
    
         
            +
                  "#{title}\n\n#{MERGE_REQUEST_FIELD}: #{merge_requested_by.login}\n"
         
     | 
| 
       249 
251 
     | 
    
         
             
                end
         
     | 
| 
       250 
252 
     | 
    
         | 
| 
       251 
253 
     | 
    
         
             
                def stale?
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Shipit
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ReleaseStatus < ActiveRecord::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                MAX_DESCRIPTION_LENGTH = 140
         
     | 
| 
      
 4 
     | 
    
         
            +
                include DeferredTouch
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                belongs_to :stack
         
     | 
| 
      
 7 
     | 
    
         
            +
                belongs_to :commit
         
     | 
| 
      
 8 
     | 
    
         
            +
                belongs_to :user, optional: true
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                deferred_touch stack: :updated_at, commit: :updated_at
         
     | 
| 
      
 11 
     | 
    
         
            +
                after_commit :schedule_create_release_statuses, on: :create
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                scope :to_be_created, -> { where(github_id: nil).order(id: :asc) }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                STATES = %w(pending success failure error).freeze
         
     | 
| 
      
 16 
     | 
    
         
            +
                validates :state, presence: true, inclusion: {in: STATES}
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def create_status_on_github!
         
     | 
| 
      
 19 
     | 
    
         
            +
                  return true if github_id?
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  update!(github_id: create_status_on_github.id)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                private
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def create_status_on_github
         
     | 
| 
      
 27 
     | 
    
         
            +
                  Shipit.github.api.create_status(
         
     | 
| 
      
 28 
     | 
    
         
            +
                    stack.github_repo_name,
         
     | 
| 
      
 29 
     | 
    
         
            +
                    commit.sha,
         
     | 
| 
      
 30 
     | 
    
         
            +
                    state,
         
     | 
| 
      
 31 
     | 
    
         
            +
                    context: stack.release_status_context,
         
     | 
| 
      
 32 
     | 
    
         
            +
                    target_url: target_url,
         
     | 
| 
      
 33 
     | 
    
         
            +
                    description: description&.truncate(MAX_DESCRIPTION_LENGTH),
         
     | 
| 
      
 34 
     | 
    
         
            +
                  )
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def schedule_create_release_statuses
         
     | 
| 
      
 38 
     | 
    
         
            +
                  CreateReleaseStatusesJob.perform_later(commit)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -34,6 +34,15 @@ module Shipit 
     | 
|
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
                private
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
      
 37 
     | 
    
         
            +
                def update_release_status
         
     | 
| 
      
 38 
     | 
    
         
            +
                  return unless stack.release_status?
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  case status
         
     | 
| 
      
 41 
     | 
    
         
            +
                  when 'pending'
         
     | 
| 
      
 42 
     | 
    
         
            +
                    deploy.append_release_status('failure', "A rollback #{stack.to_param} was triggered")
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       37 
46 
     | 
    
         
             
                def lock_reverted_commits
         
     | 
| 
       38 
47 
     | 
    
         
             
                  stack.lock_reverted_commits!
         
     | 
| 
       39 
48 
     | 
    
         
             
                end
         
     | 
    
        data/app/models/shipit/stack.rb
    CHANGED
    
    | 
         @@ -73,8 +73,8 @@ module Shipit 
     | 
|
| 
       73 
73 
     | 
    
         
             
                validates :lock_reason, length: {maximum: 4096}
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
                serialize :cached_deploy_spec, DeploySpec
         
     | 
| 
       76 
     | 
    
         
            -
                delegate :find_task_definition, :supports_rollback?, :links,
         
     | 
| 
       77 
     | 
    
         
            -
                         :supports_fetch_deployed_revision?, to: :cached_deploy_spec, allow_nil: true
         
     | 
| 
      
 76 
     | 
    
         
            +
                delegate :find_task_definition, :supports_rollback?, :links, :release_status?, :release_status_delay,
         
     | 
| 
      
 77 
     | 
    
         
            +
                         :release_status_context, :supports_fetch_deployed_revision?, to: :cached_deploy_spec, allow_nil: true
         
     | 
| 
       78 
78 
     | 
    
         | 
| 
       79 
79 
     | 
    
         
             
                def self.refresh_deployed_revisions
         
     | 
| 
       80 
80 
     | 
    
         
             
                  find_each.select(&:supports_fetch_deployed_revision?).each(&:async_refresh_deployed_revision)
         
     | 
| 
         @@ -307,13 +307,8 @@ module Shipit 
     | 
|
| 
       307 
307 
     | 
    
         
             
                  File.join(base_path, "git")
         
     | 
| 
       308 
308 
     | 
    
         
             
                end
         
     | 
| 
       309 
309 
     | 
    
         | 
| 
       310 
     | 
    
         
            -
                def acquire_git_cache_lock(timeout: 15,  
     | 
| 
       311 
     | 
    
         
            -
                   
     | 
| 
       312 
     | 
    
         
            -
                    "stack:#{id}:git-cache-lock",
         
     | 
| 
       313 
     | 
    
         
            -
                    Shipit.redis,
         
     | 
| 
       314 
     | 
    
         
            -
                    timeout: timeout,
         
     | 
| 
       315 
     | 
    
         
            -
                    expiration: expiration,
         
     | 
| 
       316 
     | 
    
         
            -
                  ).lock(&block)
         
     | 
| 
      
 310 
     | 
    
         
            +
                def acquire_git_cache_lock(timeout: 15, &block)
         
     | 
| 
      
 311 
     | 
    
         
            +
                  Flock.new(git_path.to_s + '.lock').lock(timeout: timeout, &block)
         
     | 
| 
       317 
312 
     | 
    
         
             
                end
         
     | 
| 
       318 
313 
     | 
    
         | 
| 
       319 
314 
     | 
    
         
             
                def clear_git_cache!
         
     | 
| 
         @@ -29,7 +29,8 @@ module Shipit 
     | 
|
| 
       29 
29 
     | 
    
         
             
                    @statuses = visible_statuses.sort_by!(&:context)
         
     | 
| 
       30 
30 
     | 
    
         
             
                  end
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                  delegate :pending?, :success?, :error?, :failure?, :unknown?, :state, :simple_state, 
     | 
| 
      
 32 
     | 
    
         
            +
                  delegate :pending?, :success?, :error?, :failure?, :unknown?, :missing?, :state, :simple_state,
         
     | 
| 
      
 33 
     | 
    
         
            +
                           to: :significant_status
         
     | 
| 
       33 
34 
     | 
    
         
             
                  delegate :each, :size, :map, to: :statuses
         
     | 
| 
       34 
35 
     | 
    
         
             
                  delegate :required_statuses, to: :commit
         
     | 
| 
       35 
36 
     | 
    
         | 
| 
         @@ -1,18 +1,33 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Shipit
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Status
         
     | 
| 
       3 
3 
     | 
    
         
             
                class Unknown
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include GlobalID::Identification
         
     | 
| 
       4 
5 
     | 
    
         
             
                  include Common
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    def find(id)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      new(Commit.find(id))
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       6 
13 
     | 
    
         
             
                  attr_reader :commit
         
     | 
| 
       7 
14 
     | 
    
         | 
| 
       8 
15 
     | 
    
         
             
                  def initialize(commit)
         
     | 
| 
       9 
16 
     | 
    
         
             
                    @commit = commit
         
     | 
| 
       10 
17 
     | 
    
         
             
                  end
         
     | 
| 
       11 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
                  def id
         
     | 
| 
      
 20 
     | 
    
         
            +
                    commit.id
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       12 
23 
     | 
    
         
             
                  def state
         
     | 
| 
       13 
24 
     | 
    
         
             
                    'unknown'.freeze
         
     | 
| 
       14 
25 
     | 
    
         
             
                  end
         
     | 
| 
       15 
26 
     | 
    
         | 
| 
      
 27 
     | 
    
         
            +
                  def missing?
         
     | 
| 
      
 28 
     | 
    
         
            +
                    true
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       16 
31 
     | 
    
         
             
                  def target_url
         
     | 
| 
       17 
32 
     | 
    
         
             
                    nil
         
     | 
| 
       18 
33 
     | 
    
         
             
                  end
         
     | 
    
        data/app/models/shipit/task.rb
    CHANGED
    
    
    
        data/app/models/shipit/user.rb
    CHANGED
    
    | 
         @@ -8,6 +8,8 @@ module Shipit 
     | 
|
| 
       8 
8 
     | 
    
         
             
                has_many :commits, foreign_key: :committer_id, inverse_of: :committer
         
     | 
| 
       9 
9 
     | 
    
         
             
                has_many :tasks
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                validates :name, presence: true
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       11 
13 
     | 
    
         
             
                attr_encrypted :github_access_token, key: Shipit.user_access_tokens_key
         
     | 
| 
       12 
14 
     | 
    
         | 
| 
       13 
15 
     | 
    
         
             
                def self.find_or_create_by_login!(login)
         
     | 
| 
         @@ -16,8 +18,19 @@ module Shipit 
     | 
|
| 
       16 
18 
     | 
    
         
             
                  end
         
     | 
| 
       17 
19 
     | 
    
         
             
                end
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                def self.find_or_create_committer_from_github_commit(github_commit)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  find_or_create_from_github(github_commit.committer.presence || github_commit.commit.committer.presence)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def self.find_or_create_author_from_github_commit(github_commit)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  if github_commit.commit.message =~ /^#{PullRequest::MERGE_REQUEST_FIELD}: ([\w\-\.]+)$/
         
     | 
| 
      
 27 
     | 
    
         
            +
                    return find_or_create_by_login!($1)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  find_or_create_from_github(github_commit.author.presence || github_commit.commit.author.presence)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
       19 
32 
     | 
    
         
             
                def self.find_or_create_from_github(github_user)
         
     | 
| 
       20 
     | 
    
         
            -
                  find_from_github(github_user) || create_from_github 
     | 
| 
      
 33 
     | 
    
         
            +
                  find_from_github(github_user) || create_from_github(github_user)
         
     | 
| 
       21 
34 
     | 
    
         
             
                end
         
     | 
| 
       22 
35 
     | 
    
         | 
| 
       23 
36 
     | 
    
         
             
                def self.find_from_github(github_user)
         
     | 
| 
         @@ -25,8 +38,8 @@ module Shipit 
     | 
|
| 
       25 
38 
     | 
    
         
             
                  find_by(github_id: github_user.id)
         
     | 
| 
       26 
39 
     | 
    
         
             
                end
         
     | 
| 
       27 
40 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                def self.create_from_github 
     | 
| 
       29 
     | 
    
         
            -
                  create 
     | 
| 
      
 41 
     | 
    
         
            +
                def self.create_from_github(github_user)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  create(github_user: github_user)
         
     | 
| 
       30 
43 
     | 
    
         
             
                end
         
     | 
| 
       31 
44 
     | 
    
         | 
| 
       32 
45 
     | 
    
         
             
                def self.refresh_shard(shard_index, shards_count)
         
     |