...@@ -343,6 +343,7 @@ class Project < ApplicationRecord ...@@ -343,6 +343,7 @@ class Project < ApplicationRecord
delegate :last_pipeline, to: :commit, allow_nil: true delegate :last_pipeline, to: :commit, allow_nil: true
delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true delegate :external_dashboard_url, to: :metrics_setting, allow_nil: true, prefix: true
delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci
delegate :forward_deployment_enabled, :forward_deployment_enabled=, :forward_deployment_enabled?, to: :ci_cd_settings
# Validations # Validations
validates :creator, presence: true, on: :create validates :creator, presence: true, on: :create
... ...
......
...@@ -18,6 +18,8 @@ class ProjectCiCdSetting < ApplicationRecord ...@@ -18,6 +18,8 @@ class ProjectCiCdSetting < ApplicationRecord
}, },
allow_nil: true allow_nil: true
default_value_for :forward_deployment_enabled, true
def self.available? def self.available?
@available ||= @available ||=
ActiveRecord::Migrator.current_version >= MINIMUM_SCHEMA_VERSION ActiveRecord::Migrator.current_version >= MINIMUM_SCHEMA_VERSION
...@@ -28,6 +30,10 @@ class ProjectCiCdSetting < ApplicationRecord ...@@ -28,6 +30,10 @@ class ProjectCiCdSetting < ApplicationRecord
super super
end end
def forward_deployment_enabled?
super && ::Feature.enabled?(:forward_deployment_enabled, project)
end
private private
def set_default_git_depth def set_default_git_depth
... ...
......
...@@ -14,6 +14,7 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated ...@@ -14,6 +14,7 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
unmet_prerequisites: 'The job failed to complete prerequisite tasks', unmet_prerequisites: 'The job failed to complete prerequisite tasks',
scheduler_failure: 'The scheduler failed to assign job to the runner, please try again or contact system administrator', scheduler_failure: 'The scheduler failed to assign job to the runner, please try again or contact system administrator',
data_integrity_failure: 'There has been a structural integrity problem detected, please contact system administrator', data_integrity_failure: 'There has been a structural integrity problem detected, please contact system administrator',
forward_deployment_failure: 'The deployment job is older than the previously succeeded deployment job, and therefore cannot be run',
invalid_bridge_trigger: 'This job could not be executed because downstream pipeline trigger definition is invalid', invalid_bridge_trigger: 'This job could not be executed because downstream pipeline trigger definition is invalid',
downstream_bridge_project_not_found: 'This job could not be executed because downstream bridge project could not be found', downstream_bridge_project_not_found: 'This job could not be executed because downstream bridge project could not be found',
insufficient_bridge_permissions: 'This job could not be executed because of insufficient permissions to create a downstream pipeline', insufficient_bridge_permissions: 'This job could not be executed because of insufficient permissions to create a downstream pipeline',
... ...
......
# frozen_string_literal: true
module Deployments
class OlderDeploymentsDropService
attr_reader :deployment
def initialize(deployment_id)
@deployment = Deployment.find_by_id(deployment_id)
end
def execute
return unless @deployment&.running?
older_deployments.find_each do |older_deployment|
older_deployment.deployable&.drop!(:forward_deployment_failure)
rescue => e
Gitlab::ErrorTracking.track_exception(e, subject_id: @deployment.id, deployment_id: older_deployment.id)
end
end
private
def older_deployments
@deployment
.environment
.active_deployments
.older_than(@deployment)
.with_deployable
end
end
end
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
= _('Keyboard Shortcuts') = _('Keyboard Shortcuts')
%small %small
= link_to _('(Show all)'), '#', class: 'js-more-help-button' = link_to _('(Show all)'), '#', class: 'js-more-help-button'
.js-toggle-shortcuts
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') } %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": true } &times; %span{ "aria-hidden": true } &times;
.modal-body .modal-body
... ...
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
= link_to _("Help"), help_path = link_to _("Help"), help_path
%li %li
= link_to _("Support"), support_url = link_to _("Support"), support_url
%li
%button.js-shortcuts-modal-trigger{ type: "button" }
= _("Keyboard shortcuts")
%span.text-secondary.float-right{ "aria-hidden": true }= '?'.html_safe
= render_if_exists "shared/learn_gitlab_menu_item" = render_if_exists "shared/learn_gitlab_menu_item"
%li.divider %li.divider
%li %li
... ...
......
...@@ -21,4 +21,5 @@ ...@@ -21,4 +21,5 @@
= render "projects/pipelines/with_tabs", pipeline: @pipeline = render "projects/pipelines/with_tabs", pipeline: @pipeline
.js-pipeline-details-vue{ data: { endpoint: project_pipeline_path(@project, @pipeline, format: :json), .js-pipeline-details-vue{ data: { endpoint: project_pipeline_path(@project, @pipeline, format: :json),
test_report_endpoint: test_report_project_pipeline_path(@project, @pipeline, format: :json) } } test_report_endpoint: test_report_project_pipeline_path(@project, @pipeline, format: :json),
test_reports_count_endpoint: test_reports_count_project_pipeline_path(@project, @pipeline, format: :json) } }
...@@ -225,6 +225,12 @@ ...@@ -225,6 +225,12 @@
:latency_sensitive: :latency_sensitive:
:resource_boundary: :cpu :resource_boundary: :cpu
:weight: 3 :weight: 3
- :name: deployment:deployments_forward_deployment
:feature_category: :continuous_delivery
:has_external_dependencies:
:latency_sensitive:
:resource_boundary: :unknown
:weight: 3
- :name: deployment:deployments_success - :name: deployment:deployments_success
:feature_category: :continuous_delivery :feature_category: :continuous_delivery
:has_external_dependencies: :has_external_dependencies:
... ...
......
# frozen_string_literal: true
module Deployments
class ForwardDeploymentWorker
include ApplicationWorker
queue_namespace :deployment
feature_category :continuous_delivery
def perform(deployment_id)
Deployments::OlderDeploymentsDropService.new(deployment_id).execute
end
end
end
---
title: Allow keyboard shortcuts to be disabled
merge_request: 18782
author:
type: added
---
title: Allow to deploy only forward deployments
merge_request: 22959
author:
type: changed
---
title: Correctly render mermaid digrams inside details blocks
merge_request: 23662
author:
type: fixed
# frozen_string_literal: true
class AddRestrictDeploymentOrderToProjectCiCdSettings < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
add_column :project_ci_cd_settings, :forward_deployment_enabled, :boolean
end
end
...@@ -4,32 +4,11 @@ class ScheduleLinkLfsObjects < ActiveRecord::Migration[6.0] ...@@ -4,32 +4,11 @@ class ScheduleLinkLfsObjects < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
DOWNTIME = false DOWNTIME = false
MIGRATION = 'LinkLfsObjects'
BATCH_SIZE = 1_000
disable_ddl_transaction! disable_ddl_transaction!
class Project < ActiveRecord::Base
include EachBatch
self.table_name = 'projects'
end
def up def up
fork_network_members = # no-op as background migration being schedule times out in some instances
Gitlab::BackgroundMigration::LinkLfsObjects::ForkNetworkMember
.select(1)
.with_non_existing_lfs_objects
.where('fork_network_members.project_id = projects.id')
forks = Project.where('EXISTS (?)', fork_network_members)
queue_background_migration_jobs_by_range_at_intervals(
forks,
MIGRATION,
BackgroundMigrationWorker.minimum_interval,
batch_size: BATCH_SIZE
)
end end
def down def down
... ...
......
...@@ -3166,6 +3166,7 @@ ActiveRecord::Schema.define(version: 2020_02_13_204737) do ...@@ -3166,6 +3166,7 @@ ActiveRecord::Schema.define(version: 2020_02_13_204737) do
t.boolean "group_runners_enabled", default: true, null: false t.boolean "group_runners_enabled", default: true, null: false
t.boolean "merge_pipelines_enabled" t.boolean "merge_pipelines_enabled"
t.integer "default_git_depth" t.integer "default_git_depth"
t.boolean "forward_deployment_enabled"
t.index ["project_id"], name: "index_project_ci_cd_settings_on_project_id", unique: true t.index ["project_id"], name: "index_project_ci_cd_settings_on_project_id", unique: true
end end
... ...
......
...@@ -6,7 +6,10 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html' ...@@ -6,7 +6,10 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html'
# GitLab keyboard shortcuts # GitLab keyboard shortcuts
GitLab has many useful keyboard shortcuts to make it easier to access different features. GitLab has many useful keyboard shortcuts to make it easier to access different features.
You can see the quick reference sheet within GitLab itself with <kbd>Shift</kbd> + <kbd>?</kbd>. You can see a modal listing keyboard shortcuts within GitLab itself by pressing <kbd>?</kbd>,
or clicking **Keyboard shortcuts** in the Help menu at the top right.
From [GitLab 12.8 onwards](https://gitlab.com/gitlab-org/gitlab/issues/22113),
keyboard shortcuts can be disabled using the **Enable**/**Disable** toggle in this modal window.
The [Global Shortcuts](#global-shortcuts) work from any area of GitLab, but you must The [Global Shortcuts](#global-shortcuts) work from any area of GitLab, but you must
be in specific pages for the other shortcuts to be available, as explained in each be in specific pages for the other shortcuts to be available, as explained in each
... ...
......
...@@ -24,24 +24,7 @@ module Gitlab ...@@ -24,24 +24,7 @@ module Gitlab
end end
def perform(start_id, end_id) def perform(start_id, end_id)
select_query = # no-op as some queries times out
ForkNetworkMember
.select('lop.lfs_object_id, fork_network_members.project_id')
.with_non_existing_lfs_objects
.where(project_id: start_id..end_id)
return if select_query.empty?
execute <<-SQL
INSERT INTO lfs_objects_projects (lfs_object_id, project_id)
#{select_query.to_sql}
SQL
end
private
def execute(sql)
::ActiveRecord::Base.connection.execute(sql)
end end
end end
end end
... ...
......
...@@ -19,6 +19,7 @@ module Gitlab ...@@ -19,6 +19,7 @@ module Gitlab
unmet_prerequisites: 'unmet prerequisites', unmet_prerequisites: 'unmet prerequisites',
scheduler_failure: 'scheduler failure', scheduler_failure: 'scheduler failure',
data_integrity_failure: 'data integrity failure', data_integrity_failure: 'data integrity failure',
forward_deployment_failure: 'forward deployment failure',
invalid_bridge_trigger: 'downstream pipeline trigger definition is invalid', invalid_bridge_trigger: 'downstream pipeline trigger definition is invalid',
downstream_bridge_project_not_found: 'downstream project could not be found', downstream_bridge_project_not_found: 'downstream project could not be found',
insufficient_bridge_permissions: 'no permissions to trigger downstream pipeline', insufficient_bridge_permissions: 'no permissions to trigger downstream pipeline',
... ...
......
...@@ -63,7 +63,7 @@ module Quality ...@@ -63,7 +63,7 @@ module Quality
'get', 'get',
RESOURCE_LIST, RESOURCE_LIST,
%(--namespace "#{namespace}"), %(--namespace "#{namespace}"),
'-o custom-columns=NAME:.metadata.name' '-o name'
] ]
run_command(command).lines.map(&:strip) run_command(command).lines.map(&:strip)
end end
... ...
......
...@@ -375,6 +375,12 @@ msgid_plural "%{releases} releases" ...@@ -375,6 +375,12 @@ msgid_plural "%{releases} releases"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%{screenreaderOnlyStart}Keyboard shorcuts%{screenreaderOnlyEnd} Disabled"
msgstr ""
msgid "%{screenreaderOnlyStart}Keyboard shorcuts%{screenreaderOnlyEnd} Enabled"
msgstr ""
msgid "%{service_title} activated." msgid "%{service_title} activated."
msgstr "" msgstr ""
...@@ -7155,6 +7161,9 @@ msgstr "" ...@@ -7155,6 +7161,9 @@ msgstr ""
msgid "Enable mirror configuration" msgid "Enable mirror configuration"
msgstr "" msgstr ""
msgid "Enable or disable keyboard shortcuts"
msgstr ""
msgid "Enable or disable the Pseudonymizer data collection." msgid "Enable or disable the Pseudonymizer data collection."
msgstr "" msgstr ""
...@@ -10945,6 +10954,9 @@ msgstr "" ...@@ -10945,6 +10954,9 @@ msgstr ""
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "" msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
msgid "Kubernetes" msgid "Kubernetes"
msgstr "" msgstr ""
...@@ -15857,6 +15869,9 @@ msgstr "" ...@@ -15857,6 +15869,9 @@ msgstr ""
msgid "Remove child epic from an epic" msgid "Remove child epic from an epic"
msgstr "" msgstr ""
msgid "Remove description history"
msgstr ""
msgid "Remove due date" msgid "Remove due date"
msgstr "" msgstr ""
...@@ -17780,6 +17795,9 @@ msgstr "" ...@@ -17780,6 +17795,9 @@ msgstr ""
msgid "Something went wrong while closing the %{issuable}. Please try again later" msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "" msgstr ""
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
msgid "Something went wrong while deleting the image." msgid "Something went wrong while deleting the image."
msgstr "" msgstr ""
... ...
......