shipit-engine 0.35.1 → 0.36.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/README.md +7 -7
- data/app/controllers/concerns/shipit/authentication.rb +5 -1
- data/app/controllers/shipit/api/base_controller.rb +13 -1
- data/app/controllers/shipit/api/rollbacks_controller.rb +1 -1
- data/app/controllers/shipit/api/stacks_controller.rb +8 -2
- data/app/controllers/shipit/api/tasks_controller.rb +19 -2
- data/app/helpers/shipit/stacks_helper.rb +11 -0
- data/app/models/concerns/shipit/deferred_touch.rb +3 -3
- data/app/models/shipit/anonymous_user.rb +4 -0
- data/app/models/shipit/commit_checks.rb +3 -3
- data/app/models/shipit/task.rb +3 -3
- data/app/models/shipit/user.rb +23 -9
- data/app/serializers/shipit/stack_serializer.rb +1 -1
- data/app/views/shipit/deploys/_deploy.html.erb +1 -5
- data/app/views/shipit/stacks/_banners.html.erb +1 -1
- data/app/views/shipit/stacks/_settings_form.erb +55 -0
- data/app/views/shipit/stacks/settings.html.erb +1 -55
- data/app/views/shipit/stacks/show.html.erb +1 -1
- data/config/locales/en.yml +1 -1
- data/config/routes.rb +4 -0
- data/db/migrate/20211103154121_increase_github_team_slug_size.rb +5 -0
- data/lib/shipit/engine.rb +13 -5
- data/lib/shipit/stack_commands.rb +1 -1
- data/lib/shipit/version.rb +1 -1
- data/lib/shipit.rb +5 -2
- data/test/controllers/api/hooks_controller_test.rb +1 -1
- data/test/controllers/api/rollback_controller_test.rb +1 -0
- data/test/controllers/api/stacks_controller_test.rb +25 -0
- data/test/controllers/api/tasks_controller_test.rb +56 -0
- data/test/controllers/stacks_controller_test.rb +11 -0
- data/test/dummy/config/application.rb +1 -2
- data/test/dummy/db/schema.rb +2 -2
- data/test/fixtures/shipit/check_runs.yml +3 -3
- data/test/fixtures/shipit/commits.yml +101 -101
- data/test/fixtures/shipit/deliveries.yml +1 -1
- data/test/fixtures/shipit/merge_requests.yml +19 -19
- data/test/fixtures/shipit/stacks.yml +28 -28
- data/test/fixtures/shipit/statuses.yml +16 -16
- data/test/fixtures/shipit/tasks.yml +65 -65
- data/test/fixtures/shipit/users.yml +2 -5
- data/test/models/commits_test.rb +6 -6
- data/test/models/tasks_test.rb +2 -2
- data/test/models/team_test.rb +21 -2
- data/test/models/users_test.rb +29 -9
- data/test/unit/deploy_commands_test.rb +1 -1
- metadata +175 -173
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3336765264c2c554f5dd879ac8ed409b08e4f5b281bbd9127132b688d23184ee
         | 
| 4 | 
            +
              data.tar.gz: ac55d9a82c007326c9a231b784d887be1a826ba11cc71c581888a0018ffaed7b
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a770a63ffadea62d25d8244265d5ea9552930fee64951d6c4b1e5be4a518271d54d34161b83a8760c9331c6f2758995e61114000bfcf5675b0353a955cc41bad
         | 
| 7 | 
            +
              data.tar.gz: 7e7d3629476bab8aa1ab7655e099e6218b511fe728ef9161a2591835ae2c369cd22724e7c193243fd29779574ea1148b2adb97119ce8a04def1a46df0168d62c
         | 
    
        data/README.md
    CHANGED
    
    | @@ -390,7 +390,7 @@ machine: | |
| 390 390 |  | 
| 391 391 | 
             
            <h3 id="ci">CI</h3>
         | 
| 392 392 |  | 
| 393 | 
            -
            **<code>ci.require</code>** contains an array of the [statuses context](https:// | 
| 393 | 
            +
            **<code>ci.require</code>** contains an array of the [statuses context](https://docs.github.com/en/rest/reference/commits#commit-statuses) you want Shipit to disallow deploys if any of them is missing on the commit being deployed.
         | 
| 394 394 |  | 
| 395 395 | 
             
            For example:
         | 
| 396 396 | 
             
            ```yml
         | 
| @@ -399,7 +399,7 @@ ci: | |
| 399 399 | 
             
                - ci/circleci
         | 
| 400 400 | 
             
            ```
         | 
| 401 401 |  | 
| 402 | 
            -
            **<code>ci.hide</code>** contains an array of the [statuses context](https:// | 
| 402 | 
            +
            **<code>ci.hide</code>** contains an array of the [statuses context](https://docs.github.com/en/rest/reference/commits#commit-statuses) you want Shipit to ignore.
         | 
| 403 403 |  | 
| 404 404 | 
             
            For example:
         | 
| 405 405 | 
             
            ```yml
         | 
| @@ -408,7 +408,7 @@ ci: | |
| 408 408 | 
             
                - ci/circleci
         | 
| 409 409 | 
             
            ```
         | 
| 410 410 |  | 
| 411 | 
            -
            **<code>ci.allow_failures</code>** contains an array of the [statuses context](https:// | 
| 411 | 
            +
            **<code>ci.allow_failures</code>** contains an array of the [statuses context](https://docs.github.com/en/rest/reference/commits#commit-statuses) you want to be visible but not to required for deploy.
         | 
| 412 412 |  | 
| 413 413 | 
             
            For example:
         | 
| 414 414 | 
             
            ```yml
         | 
| @@ -417,7 +417,7 @@ ci: | |
| 417 417 | 
             
                - ci/circleci
         | 
| 418 418 | 
             
            ```
         | 
| 419 419 |  | 
| 420 | 
            -
            **<code>ci.blocking</code>** contains an array of the [statuses context](https:// | 
| 420 | 
            +
            **<code>ci.blocking</code>** contains an array of the [statuses context](https://docs.github.com/en/rest/reference/commits#commit-statuses) you want to disallow deploys if any of them is missing or failing on any of the commits being deployed.
         | 
| 421 421 |  | 
| 422 422 | 
             
            For example:
         | 
| 423 423 | 
             
            ```yml
         | 
| @@ -440,7 +440,7 @@ merge: | |
| 440 440 | 
             
              revalidate_after: 12m30s
         | 
| 441 441 | 
             
            ```
         | 
| 442 442 |  | 
| 443 | 
            -
            **<code>merge.require</code>** contains an array of the [statuses context](https:// | 
| 443 | 
            +
            **<code>merge.require</code>** contains an array of the [statuses context](https://docs.github.com/en/rest/reference/commits#commit-statuses) that you want Shipit to consider as failing if they aren't present on the pull request. Defaults to `ci.require` if present, or empty otherwise.
         | 
| 444 444 |  | 
| 445 445 | 
             
            For example:
         | 
| 446 446 | 
             
            ```yml
         | 
| @@ -449,7 +449,7 @@ merge: | |
| 449 449 | 
             
                - continuous-integration/travis-ci/push
         | 
| 450 450 | 
             
            ```
         | 
| 451 451 |  | 
| 452 | 
            -
            **<code>merge.ignore</code>** contains an array of the [statuses context](https:// | 
| 452 | 
            +
            **<code>merge.ignore</code>** contains an array of the [statuses context](https://docs.github.com/en/rest/reference/commits#commit-statuses) that you want Shipit not to consider when merging pull requests. Defaults to the union of `ci.allow_failures` and `ci.hide` if any is present or empty otherwise.
         | 
| 453 453 |  | 
| 454 454 | 
             
            For example:
         | 
| 455 455 | 
             
            ```yml
         | 
| @@ -458,7 +458,7 @@ merge: | |
| 458 458 | 
             
                - codeclimate
         | 
| 459 459 | 
             
            ```
         | 
| 460 460 |  | 
| 461 | 
            -
            **<code>merge.method</code>** the [merge method](https:// | 
| 461 | 
            +
            **<code>merge.method</code>** the [merge method](https://docs.github.com/en/rest/reference/pulls#merge-a-pull-request--parameters) to use for this stack. If it's not set the default merge method will be used. Can be either `merge`, `squash` or `rebase`.
         | 
| 462 462 |  | 
| 463 463 | 
             
            For example:
         | 
| 464 464 | 
             
            ```yml
         | 
| @@ -17,7 +17,11 @@ module Shipit | |
| 17 17 | 
             
                private
         | 
| 18 18 |  | 
| 19 19 | 
             
                def force_github_authentication
         | 
| 20 | 
            -
                  if  | 
| 20 | 
            +
                  if current_user.logged_in? && current_user.requires_fresh_login?
         | 
| 21 | 
            +
                    Rails.logger.warn("User #{current_user.id} requires a fresh login, logging out...")
         | 
| 22 | 
            +
                    reset_session
         | 
| 23 | 
            +
                    redirect_to(Shipit::Engine.routes.url_helpers.github_authentication_path(origin: request.original_url))
         | 
| 24 | 
            +
                  elsif Shipit.authentication_disabled? || current_user.logged_in?
         | 
| 21 25 | 
             
                    unless current_user.authorized?
         | 
| 22 26 | 
             
                      team_handles = Shipit.github_teams.map(&:handle)
         | 
| 23 27 | 
             
                      team_list = team_handles.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')
         | 
| @@ -28,6 +28,18 @@ module Shipit | |
| 28 28 |  | 
| 29 29 | 
             
                  private
         | 
| 30 30 |  | 
| 31 | 
            +
                  module BasicAuth
         | 
| 32 | 
            +
                    # Workaround for https://github.com/rails/rails/pull/44610
         | 
| 33 | 
            +
                    extend ActionController::HttpAuthentication::Basic
         | 
| 34 | 
            +
                    extend self
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    private
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def has_basic_credentials?(request)
         | 
| 39 | 
            +
                      request.authorization.present? && (auth_scheme(request).downcase == "basic")
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 31 43 | 
             
                  def namespace_for_serializer
         | 
| 32 44 | 
             
                    nil
         | 
| 33 45 | 
             
                  end
         | 
| @@ -36,7 +48,7 @@ module Shipit | |
| 36 48 | 
             
                    @current_api_client = if Shipit.disable_api_authentication
         | 
| 37 49 | 
             
                      UnlimitedApiClient.new
         | 
| 38 50 | 
             
                    else
         | 
| 39 | 
            -
                       | 
| 51 | 
            +
                      BasicAuth.authenticate(request) do |*parts|
         | 
| 40 52 | 
             
                        token = parts.select(&:present?).join('--')
         | 
| 41 53 | 
             
                        ApiClient.authenticate(token)
         | 
| 42 54 | 
             
                      end
         | 
| @@ -21,7 +21,7 @@ module Shipit | |
| 21 21 | 
             
                      param_error!(:force, "Can't rollback, deploy in progress")
         | 
| 22 22 | 
             
                    elsif stack.active_task?
         | 
| 23 23 | 
             
                      active_task = stack.active_task
         | 
| 24 | 
            -
                      active_task.abort!(aborted_by: current_user, rollback_once_aborted_to: deploy)
         | 
| 24 | 
            +
                      active_task.abort!(aborted_by: current_user, rollback_once_aborted_to: deploy, rollback_once_aborted: true)
         | 
| 25 25 | 
             
                      response = active_task
         | 
| 26 26 | 
             
                    else
         | 
| 27 27 | 
             
                      response = deploy.trigger_rollback(current_user, env: deploy_env, force: params.force, lock: params.lock)
         | 
| @@ -27,7 +27,7 @@ module Shipit | |
| 27 27 | 
             
                    requires :repo_name, String
         | 
| 28 28 | 
             
                    accepts :environment, String
         | 
| 29 29 | 
             
                    accepts :branch, String
         | 
| 30 | 
            -
                    accepts :deploy_url, String
         | 
| 30 | 
            +
                    accepts :deploy_url, String, allow_nil: true
         | 
| 31 31 | 
             
                    accepts :ignore_ci, Boolean
         | 
| 32 32 | 
             
                    accepts :merge_queue_enabled, Boolean
         | 
| 33 33 | 
             
                    accepts :continuous_deployment, Boolean
         | 
| @@ -40,8 +40,9 @@ module Shipit | |
| 40 40 | 
             
                  end
         | 
| 41 41 |  | 
| 42 42 | 
             
                  params do
         | 
| 43 | 
            +
                    accepts :environment, String
         | 
| 43 44 | 
             
                    accepts :branch, String
         | 
| 44 | 
            -
                    accepts :deploy_url, String
         | 
| 45 | 
            +
                    accepts :deploy_url, String, allow_nil: true
         | 
| 45 46 | 
             
                    accepts :ignore_ci, Boolean
         | 
| 46 47 | 
             
                    accepts :merge_queue_enabled, Boolean
         | 
| 47 48 | 
             
                    accepts :continuous_deployment, Boolean
         | 
| @@ -60,6 +61,11 @@ module Shipit | |
| 60 61 | 
             
                    head(:accepted)
         | 
| 61 62 | 
             
                  end
         | 
| 62 63 |  | 
| 64 | 
            +
                  def refresh
         | 
| 65 | 
            +
                    GithubSyncJob.perform_later(id: stack.id)
         | 
| 66 | 
            +
                    render_resource(stack, status: :accepted)
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
             | 
| 63 69 | 
             
                  private
         | 
| 64 70 |  | 
| 65 71 | 
             
                  def create_params
         | 
| @@ -3,14 +3,14 @@ module Shipit | |
| 3 3 | 
             
              module Api
         | 
| 4 4 | 
             
                class TasksController < BaseController
         | 
| 5 5 | 
             
                  require_permission :read, :stack
         | 
| 6 | 
            -
                  require_permission :deploy, :stack, only:  | 
| 6 | 
            +
                  require_permission :deploy, :stack, only: %i(trigger abort)
         | 
| 7 7 |  | 
| 8 8 | 
             
                  def index
         | 
| 9 9 | 
             
                    render_resources(stack.tasks)
         | 
| 10 10 | 
             
                  end
         | 
| 11 11 |  | 
| 12 12 | 
             
                  def show
         | 
| 13 | 
            -
                    render_resource( | 
| 13 | 
            +
                    render_resource(task)
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 16 | 
             
                  params do
         | 
| @@ -23,6 +23,23 @@ module Shipit | |
| 23 23 | 
             
                      message: 'A task is already running.',
         | 
| 24 24 | 
             
                    })
         | 
| 25 25 | 
             
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def abort
         | 
| 28 | 
            +
                    if task.active?
         | 
| 29 | 
            +
                      task.abort!(aborted_by: current_user)
         | 
| 30 | 
            +
                      head(:accepted)
         | 
| 31 | 
            +
                    else
         | 
| 32 | 
            +
                      render(status: :method_not_allowed, json: {
         | 
| 33 | 
            +
                        message: "This task is not currently running.",
         | 
| 34 | 
            +
                      })
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  private
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def task
         | 
| 41 | 
            +
                    stack.tasks.find(params[:id])
         | 
| 42 | 
            +
                  end
         | 
| 26 43 | 
             
                end
         | 
| 27 44 | 
             
              end
         | 
| 28 45 | 
             
            end
         | 
| @@ -36,6 +36,17 @@ module Shipit | |
| 36 36 | 
             
                  link_to(t("deploy_button.caption.#{deploy_state}"), url, class: classes, data: data)
         | 
| 37 37 | 
             
                end
         | 
| 38 38 |  | 
| 39 | 
            +
                def rollback_button(deploy)
         | 
| 40 | 
            +
                  if deploy.stack.active_task?
         | 
| 41 | 
            +
                    link_to('Deploy in progress...', '#', class: 'btn disabled deploy-action')
         | 
| 42 | 
            +
                  else
         | 
| 43 | 
            +
                    url = rollback_stack_deploy_path(deploy.stack, deploy)
         | 
| 44 | 
            +
                    classes = %w(btn btn--delete deploy-action rollback-action)
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    link_to('Rollback to this deploy...', url, class: classes)
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 39 50 | 
             
                def github_change_url(commit)
         | 
| 40 51 | 
             
                  if commit.pull_request?
         | 
| 41 52 | 
             
                    github_pull_request_url(commit)
         | 
| @@ -49,9 +49,9 @@ module Shipit | |
| 49 49 | 
             
                  end
         | 
| 50 50 |  | 
| 51 51 | 
             
                  def fetch_members
         | 
| 52 | 
            -
                    Shipit.redis.multi do
         | 
| 53 | 
            -
                       | 
| 54 | 
            -
                       | 
| 52 | 
            +
                    Shipit.redis.multi do |transaction|
         | 
| 53 | 
            +
                      transaction.sunionstore(TMP_KEY, SET_KEY)
         | 
| 54 | 
            +
                      transaction.del(SET_KEY)
         | 
| 55 55 | 
             
                    end
         | 
| 56 56 |  | 
| 57 57 | 
             
                    yield Shipit.redis.smembers(TMP_KEY).map { |r| r.split('|') }
         | 
| @@ -44,9 +44,9 @@ module Shipit | |
| 44 44 | 
             
                end
         | 
| 45 45 |  | 
| 46 46 | 
             
                def write(output)
         | 
| 47 | 
            -
                  Shipit.redis.pipelined do
         | 
| 48 | 
            -
                     | 
| 49 | 
            -
                     | 
| 47 | 
            +
                  Shipit.redis.pipelined do |pipeline|
         | 
| 48 | 
            +
                    pipeline.append(key('output'), output)
         | 
| 49 | 
            +
                    pipeline.expire(key('output'), OUTPUT_TTL)
         | 
| 50 50 | 
             
                  end
         | 
| 51 51 | 
             
                end
         | 
| 52 52 |  | 
    
        data/app/models/shipit/task.rb
    CHANGED
    
    | @@ -313,9 +313,9 @@ module Shipit | |
| 313 313 | 
             
                end
         | 
| 314 314 |  | 
| 315 315 | 
             
                def request_abort
         | 
| 316 | 
            -
                  Shipit.redis.pipelined do
         | 
| 317 | 
            -
                     | 
| 318 | 
            -
                     | 
| 316 | 
            +
                  Shipit.redis.pipelined do |pipeline|
         | 
| 317 | 
            +
                    pipeline.incr(abort_key)
         | 
| 318 | 
            +
                    pipeline.expire(abort_key, 1.month.to_i)
         | 
| 319 319 | 
             
                  end
         | 
| 320 320 | 
             
                end
         | 
| 321 321 |  | 
    
        data/app/models/shipit/user.rb
    CHANGED
    
    | @@ -3,6 +3,8 @@ module Shipit | |
| 3 3 | 
             
              class User < Record
         | 
| 4 4 | 
             
                DEFAULT_AVATAR = URI.parse('https://avatars.githubusercontent.com/u/583231?')
         | 
| 5 5 |  | 
| 6 | 
            +
                self.ignored_columns = %w(encrypted_github_access_token_iv)
         | 
| 7 | 
            +
             | 
| 6 8 | 
             
                has_many :memberships
         | 
| 7 9 | 
             
                has_many :teams, through: :memberships
         | 
| 8 10 | 
             
                has_many :authored_commits, class_name: :Commit, foreign_key: :author_id, inverse_of: :author
         | 
| @@ -11,7 +13,10 @@ module Shipit | |
| 11 13 |  | 
| 12 14 | 
             
                validates :name, presence: true
         | 
| 13 15 |  | 
| 14 | 
            -
                 | 
| 16 | 
            +
                encrypts :encrypted_github_access_token
         | 
| 17 | 
            +
                alias_attribute :github_access_token, :encrypted_github_access_token
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                after_find :discard_outdated_credentials!
         | 
| 15 20 |  | 
| 16 21 | 
             
                def self.find_or_create_by_login!(login)
         | 
| 17 22 | 
             
                  find_or_create_by!(login: login) do |user|
         | 
| @@ -56,14 +61,6 @@ module Shipit | |
| 56 61 | 
             
                  end
         | 
| 57 62 | 
             
                end
         | 
| 58 63 |  | 
| 59 | 
            -
                alias_method :original_github_access_token, :github_access_token
         | 
| 60 | 
            -
                def github_access_token
         | 
| 61 | 
            -
                  original_github_access_token
         | 
| 62 | 
            -
                rescue OpenSSL::Cipher::CipherError
         | 
| 63 | 
            -
                  update_columns(encrypted_github_access_token: nil, encrypted_github_access_token_iv: nil)
         | 
| 64 | 
            -
                  nil
         | 
| 65 | 
            -
                end
         | 
| 66 | 
            -
             | 
| 67 64 | 
             
                def github_api
         | 
| 68 65 | 
             
                  return Shipit.github.api unless github_access_token
         | 
| 69 66 |  | 
| @@ -123,8 +120,25 @@ module Shipit | |
| 123 120 | 
             
                  DEFAULT_AVATAR.dup
         | 
| 124 121 | 
             
                end
         | 
| 125 122 |  | 
| 123 | 
            +
                # https://github.blog/2021-04-05-behind-githubs-new-authentication-token-formats
         | 
| 124 | 
            +
                GITHUB_TOKEN_FORMAT = /^gh[a-z]_/
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                def requires_fresh_login?
         | 
| 127 | 
            +
                  github_access_token.present? && !github_access_token.match(GITHUB_TOKEN_FORMAT)
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 126 130 | 
             
                private
         | 
| 127 131 |  | 
| 132 | 
            +
                def discard_outdated_credentials!
         | 
| 133 | 
            +
                  if encrypted_github_access_token_before_type_cast.present?
         | 
| 134 | 
            +
                    begin
         | 
| 135 | 
            +
                      encrypted_github_access_token
         | 
| 136 | 
            +
                    rescue ActiveRecord::Encryption::Errors::Decryption
         | 
| 137 | 
            +
                      update_column(:encrypted_github_access_token, nil)
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 128 142 | 
             
                def identify_renamed_user!
         | 
| 129 143 | 
             
                  last_commit = commits.last
         | 
| 130 144 | 
             
                  return unless last_commit
         | 
| @@ -8,7 +8,7 @@ module Shipit | |
| 8 8 | 
             
                attributes :id, :repo_owner, :repo_name, :environment, :html_url, :url, :tasks_url, :deploy_url,
         | 
| 9 9 | 
             
                  :merge_requests_url, :deploy_spec, :undeployed_commits_count, :is_locked, :lock_reason, :continuous_deployment,
         | 
| 10 10 | 
             
                  :created_at, :updated_at, :locked_since, :last_deployed_at, :branch, :merge_queue_enabled, :is_archived,
         | 
| 11 | 
            -
                  :archived_since
         | 
| 11 | 
            +
                  :archived_since, :ignore_ci
         | 
| 12 12 |  | 
| 13 13 | 
             
                def url
         | 
| 14 14 | 
             
                  api_stack_url(object)
         | 
| @@ -55,11 +55,7 @@ | |
| 55 55 | 
             
              <% unless read_only %>
         | 
| 56 56 | 
             
                <div class="deploy-actions">
         | 
| 57 57 | 
             
                  <% if deploy.rollbackable? %>
         | 
| 58 | 
            -
                     | 
| 59 | 
            -
                      <%= link_to 'Deploy in progress...', '#', class: 'btn disabled deploy-action' %>
         | 
| 60 | 
            -
                    <% else %>
         | 
| 61 | 
            -
                      <%= link_to 'Rollback to this deploy...', rollback_stack_deploy_path(@stack, deploy), class: 'btn btn--delete deploy-action rollback-action' %>
         | 
| 62 | 
            -
                    <% end %>
         | 
| 58 | 
            +
                    <%= rollback_button(deploy) %>
         | 
| 63 59 | 
             
                  <% elsif deploy.currently_deployed? && !deploy.stack.active_task? %>
         | 
| 64 60 | 
             
                    <%= redeploy_button(deploy.until_commit) %>
         | 
| 65 61 | 
             
                  <% end %>
         | 
| @@ -23,7 +23,7 @@ | |
| 23 23 | 
             
                      <%= link_to stack.github_repo_name, github_repo_url(stack.repo_owner, stack.repo_name) %>
         | 
| 24 24 | 
             
                      has been inaccessible for <%= time_ago_in_words(stack.inaccessible_since) %>.
         | 
| 25 25 |  | 
| 26 | 
            -
                      This could be a permission issue, or the  | 
| 26 | 
            +
                      This could be a permission issue, or the repo could have changed on GitHub.
         | 
| 27 27 | 
             
                    </p>
         | 
| 28 28 | 
             
                  </div>
         | 
| 29 29 | 
             
                </div>
         | 
| @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            <div class="setting-section">
         | 
| 2 | 
            +
            	<%= form_with scope: :stack, url: stack_path(stack), method: :patch do |f| %>
         | 
| 3 | 
            +
            		<div class="field-wrapper">
         | 
| 4 | 
            +
            			<%= f.label :environment %>
         | 
| 5 | 
            +
            			<%= f.text_field :environment, placeholder: 'production' %>
         | 
| 6 | 
            +
            		</div>
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            		<div class="field-wrapper">
         | 
| 9 | 
            +
            			<span>Branch: <%= stack.branch %></span>
         | 
| 10 | 
            +
            		</div>
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            		<div class="field-wrapper">
         | 
| 13 | 
            +
            			<%= f.label :deploy_url, 'Deploy URL (Where is this stack deployed to?)' %>
         | 
| 14 | 
            +
            			<%= f.text_field :deploy_url, placeholder: 'https://' %>
         | 
| 15 | 
            +
            		</div>
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            		<div class="field-wrapper">
         | 
| 18 | 
            +
            			<%= f.check_box :continuous_deployment %>
         | 
| 19 | 
            +
            			<%= f.label :continuous_deployment, 'Enable continuous deployment' %>
         | 
| 20 | 
            +
            		</div>
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            		<div class="field-wrapper">
         | 
| 23 | 
            +
            			<%= f.check_box :merge_queue_enabled %>
         | 
| 24 | 
            +
            			<%= f.label :merge_queue_enabled, 'Enable merge queue' %>
         | 
| 25 | 
            +
            		</div>
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            		<div class="field-wrapper">
         | 
| 28 | 
            +
            			<%= f.check_box :ignore_ci %>
         | 
| 29 | 
            +
            			<%= f.label :ignore_ci, "Don't require CI to deploy" %>
         | 
| 30 | 
            +
            		</div>
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            		<%= f.submit class: "btn", value: "Save" %>
         | 
| 33 | 
            +
            	<% end %>
         | 
| 34 | 
            +
            </div>
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            <div class="setting-section">
         | 
| 37 | 
            +
            	<h5>Lock deploys</h5>
         | 
| 38 | 
            +
            	<%= form_with scope: :stack, url: stack_path(@stack), method: :patch do |f| %>
         | 
| 39 | 
            +
            		<div class="field-wrapper">
         | 
| 40 | 
            +
            			<%= f.label :lock_reason, 'Reason for lock' %>
         | 
| 41 | 
            +
            			<%= f.text_area :lock_reason %>
         | 
| 42 | 
            +
            		</div>
         | 
| 43 | 
            +
            		<% if @stack.locked? %>
         | 
| 44 | 
            +
            			<%= f.submit class: "btn", value: "Update Reason" %>
         | 
| 45 | 
            +
            		<% else %>
         | 
| 46 | 
            +
            				<%= f.submit class: "btn", value: "Lock" %>
         | 
| 47 | 
            +
            		<% end %>
         | 
| 48 | 
            +
            	<% end %>
         | 
| 49 | 
            +
            	<% if @stack.locked? %>
         | 
| 50 | 
            +
            		<%= form_with scope: :stack, url: stack_path(@stack), method: :patch do |f| %>
         | 
| 51 | 
            +
            			<%= f.hidden_field :lock_reason, value: nil %>
         | 
| 52 | 
            +
            			<%= f.submit class: "btn btn--primary", value: "Unlock" %>
         | 
| 53 | 
            +
            		<%- end -%>
         | 
| 54 | 
            +
            	<% end %>
         | 
| 55 | 
            +
            </div>
         | 
| @@ -6,61 +6,7 @@ | |
| 6 6 | 
             
                  <h2>Settings (Stack #<%= @stack.id %>)</h2>
         | 
| 7 7 | 
             
                </header>
         | 
| 8 8 |  | 
| 9 | 
            -
                 | 
| 10 | 
            -
                  <%= form_with scope: :stack, url: stack_path(@stack), method: :patch do |f| %>
         | 
| 11 | 
            -
                    <div class="field-wrapper">
         | 
| 12 | 
            -
                      <%= f.label :environment %>
         | 
| 13 | 
            -
                      <%= f.text_field :environment, placeholder: 'production' %>
         | 
| 14 | 
            -
                    </div>
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                    <div class="field-wrapper">
         | 
| 17 | 
            -
                      <span>Branch: <%= @stack.branch %></span>
         | 
| 18 | 
            -
                    </div>
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                    <div class="field-wrapper">
         | 
| 21 | 
            -
                      <%= f.label :deploy_url, 'Deploy URL (Where is this stack deployed to?)' %>
         | 
| 22 | 
            -
                      <%= f.text_field :deploy_url, placeholder: 'https://' %>
         | 
| 23 | 
            -
                    </div>
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                    <div class="field-wrapper">
         | 
| 26 | 
            -
                      <%= f.check_box :continuous_deployment %>
         | 
| 27 | 
            -
                      <%= f.label :continuous_deployment, 'Enable continuous deployment' %>
         | 
| 28 | 
            -
                    </div>
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    <div class="field-wrapper">
         | 
| 31 | 
            -
                      <%= f.check_box :merge_queue_enabled %>
         | 
| 32 | 
            -
                      <%= f.label :merge_queue_enabled, 'Enable merge queue' %>
         | 
| 33 | 
            -
                    </div>
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                    <div class="field-wrapper">
         | 
| 36 | 
            -
                      <%= f.check_box :ignore_ci %>
         | 
| 37 | 
            -
                      <%= f.label :ignore_ci, "Don't require CI to deploy" %>
         | 
| 38 | 
            -
                    </div>
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                    <%= f.submit class: "btn", value: "Save" %>
         | 
| 41 | 
            -
                  <% end %>
         | 
| 42 | 
            -
                </div>
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                <div class="setting-section">
         | 
| 45 | 
            -
                  <h5>Lock deploys</h5>
         | 
| 46 | 
            -
                  <%= form_with scope: :stack, url: stack_path(@stack), method: :patch do |f| %>
         | 
| 47 | 
            -
                    <div class="field-wrapper">
         | 
| 48 | 
            -
                      <%= f.label :lock_reason, 'Reason for lock' %>
         | 
| 49 | 
            -
                      <%= f.text_area :lock_reason %>
         | 
| 50 | 
            -
                    </div>
         | 
| 51 | 
            -
                    <% if @stack.locked? %>
         | 
| 52 | 
            -
                      <%= f.submit class: "btn", value: "Update Reason" %>
         | 
| 53 | 
            -
                    <% else %>
         | 
| 54 | 
            -
                        <%= f.submit class: "btn", value: "Lock" %>
         | 
| 55 | 
            -
                    <% end %>
         | 
| 56 | 
            -
                  <% end %>
         | 
| 57 | 
            -
                  <% if @stack.locked? %>
         | 
| 58 | 
            -
                    <%= form_with scope: :stack, url: stack_path(@stack), method: :patch do |f| %>
         | 
| 59 | 
            -
                      <%= f.hidden_field :lock_reason, value: nil %>
         | 
| 60 | 
            -
                      <%= f.submit class: "btn btn--primary", value: "Unlock" %>
         | 
| 61 | 
            -
                    <%- end -%>
         | 
| 62 | 
            -
                  <% end %>
         | 
| 63 | 
            -
                </div>
         | 
| 9 | 
            +
                <%= render partial: 'shipit/stacks/settings_form', locals: { stack: @stack } %>
         | 
| 64 10 |  | 
| 65 11 | 
             
                <div class="setting-section">
         | 
| 66 12 | 
             
                  <h5>Resynchronize this stack</h5>
         | 
    
        data/config/locales/en.yml
    CHANGED
    
    | @@ -41,7 +41,7 @@ en: | |
| 41 41 | 
             
                reject: Mark the release as faulty
         | 
| 42 42 | 
             
              deploy_button:
         | 
| 43 43 | 
             
                hint:
         | 
| 44 | 
            -
                  max_commits:  | 
| 44 | 
            +
                  max_commits: Use caution when deploying more than %{maximum} commits at once.
         | 
| 45 45 | 
             
                  blocked: This commit range includes a commit that can't be deployed.
         | 
| 46 46 | 
             
                caption:
         | 
| 47 47 | 
             
                  pending: Pending CI
         | 
    
        data/config/routes.rb
    CHANGED
    
    | @@ -20,6 +20,7 @@ Shipit::Engine.routes.draw do | |
| 20 20 | 
             
                  get '/' => 'stacks#show'
         | 
| 21 21 | 
             
                  delete '/' => 'stacks#destroy'
         | 
| 22 22 | 
             
                  patch '/' => 'stacks#update'
         | 
| 23 | 
            +
                  post '/refresh' => 'stacks#refresh'
         | 
| 23 24 | 
             
                end
         | 
| 24 25 |  | 
| 25 26 | 
             
                scope '/stacks/*stack_id', stack_id: stack_id_format, as: :stack do
         | 
| @@ -27,6 +28,9 @@ Shipit::Engine.routes.draw do | |
| 27 28 | 
             
                  resource :lock, only: %i(create update destroy)
         | 
| 28 29 | 
             
                  resources :tasks, only: %i(index show) do
         | 
| 29 30 | 
             
                    resource :output, only: :show
         | 
| 31 | 
            +
                    member do
         | 
| 32 | 
            +
                      put :abort
         | 
| 33 | 
            +
                    end
         | 
| 30 34 | 
             
                  end
         | 
| 31 35 | 
             
                  resources :deploys, only: %i(index create) do
         | 
| 32 36 | 
             
                    resources :release_statuses, only: %i(create)
         | 
    
        data/lib/shipit/engine.rb
    CHANGED
    
    | @@ -5,7 +5,7 @@ module Shipit | |
| 5 5 |  | 
| 6 6 | 
             
                paths['app/models'] << 'app/serializers' << 'app/serializers/concerns'
         | 
| 7 7 |  | 
| 8 | 
            -
                initializer 'shipit.config' do |app|
         | 
| 8 | 
            +
                initializer 'shipit.config', before: 'active_record_encryption.configuration' do |app|
         | 
| 9 9 | 
             
                  Rails.application.routes.default_url_options[:host] = Shipit.host
         | 
| 10 10 | 
             
                  Shipit::Engine.routes.default_url_options[:host] = Shipit.host
         | 
| 11 11 | 
             
                  Pubsubstub.redis_url = Shipit.redis_url.to_s
         | 
| @@ -28,8 +28,6 @@ module Shipit | |
| 28 28 | 
             
                    path.end_with?('.svg') || (path.start_with?('emoji/') && path.end_with?('.png'))
         | 
| 29 29 | 
             
                  end
         | 
| 30 30 |  | 
| 31 | 
            -
                  ActionDispatch::ExceptionWrapper.rescue_responses[Shipit::TaskDefinition::NotFound.name] = :not_found
         | 
| 32 | 
            -
             | 
| 33 31 | 
             
                  ActiveModel::Serializer._root = false
         | 
| 34 32 | 
             
                  ActiveModel::ArraySerializer._root = false
         | 
| 35 33 | 
             
                  ActiveModel::Serializer.include(Engine.routes.url_helpers)
         | 
| @@ -45,9 +43,19 @@ module Shipit | |
| 45 43 | 
             
                    app.config.middleware.insert_after(::Rack::Runtime, Shipit::SameSiteCookieMiddleware)
         | 
| 46 44 | 
             
                  end
         | 
| 47 45 |  | 
| 48 | 
            -
                  app. | 
| 49 | 
            -
                     | 
| 46 | 
            +
                  if app.credentials.active_record_encryption.blank? && Shipit.user_access_tokens_key.present?
         | 
| 47 | 
            +
                    # For ease of upgrade, we derive an Active Record encryption config automatically.
         | 
| 48 | 
            +
                    # But if AR Encryption is already configured, we just use that
         | 
| 49 | 
            +
                    app.credentials[:active_record_encryption] = {
         | 
| 50 | 
            +
                      primary_key: Shipit.user_access_tokens_key,
         | 
| 51 | 
            +
                      key_derivation_salt: Digest::SHA256.digest("salt:".b + Shipit.user_access_tokens_key),
         | 
| 52 | 
            +
                    }
         | 
| 50 53 | 
             
                  end
         | 
| 51 54 | 
             
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                config.after_initialize do
         | 
| 57 | 
            +
                  ActionDispatch::ExceptionWrapper.rescue_responses[Shipit::TaskDefinition::NotFound.name] = :not_found
         | 
| 58 | 
            +
                  ActionController::Base.include(Shipit::ActiveModelSerializersPatch)
         | 
| 59 | 
            +
                end
         | 
| 52 60 | 
             
              end
         | 
| 53 61 | 
             
            end
         | 
| @@ -16,7 +16,7 @@ module Shipit | |
| 16 16 | 
             
                def fetch
         | 
| 17 17 | 
             
                  create_directories
         | 
| 18 18 | 
             
                  if valid_git_repository?(@stack.git_path)
         | 
| 19 | 
            -
                    git('fetch', 'origin', '--tags', @stack.branch, env: env, chdir: @stack.git_path)
         | 
| 19 | 
            +
                    git('fetch', 'origin', '--quiet', '--tags', @stack.branch, env: env, chdir: @stack.git_path)
         | 
| 20 20 | 
             
                  else
         | 
| 21 21 | 
             
                    @stack.clear_git_cache!
         | 
| 22 22 | 
             
                    git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env: env, chdir: @stack.deploys_path)
         | 
    
        data/lib/shipit/version.rb
    CHANGED
    
    
    
        data/lib/shipit.rb
    CHANGED
    
    | @@ -5,7 +5,6 @@ require 'state_machines-activerecord' | |
| 5 5 | 
             
            require 'validate_url'
         | 
| 6 6 | 
             
            require 'responders'
         | 
| 7 7 | 
             
            require 'explicit-parameters'
         | 
| 8 | 
            -
            require 'attr_encrypted'
         | 
| 9 8 |  | 
| 10 9 | 
             
            require 'sass-rails'
         | 
| 11 10 | 
             
            require 'coffee-rails'
         | 
| @@ -153,7 +152,11 @@ module Shipit | |
| 153 152 | 
             
              end
         | 
| 154 153 |  | 
| 155 154 | 
             
              def user_access_tokens_key
         | 
| 156 | 
            -
                 | 
| 155 | 
            +
                if secrets.user_access_tokens_key.present?
         | 
| 156 | 
            +
                  secrets.user_access_tokens_key
         | 
| 157 | 
            +
                elsif secrets.secret_key_base
         | 
| 158 | 
            +
                  Digest::SHA256.digest("user_access_tokens_key" + secrets.secret_key_base)
         | 
| 159 | 
            +
                end
         | 
| 157 160 | 
             
              end
         | 
| 158 161 |  | 
| 159 162 | 
             
              def host
         |