diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-07 21:09:53 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-07 21:09:53 +0300 |
commit | 5edd0d173ff0bc377348bf3585fa309eee783e32 (patch) | |
tree | d71d995f018e56453e438f7b670c6597e45b4dd6 /app | |
parent | 61d62a296064e0330cffec7ed4b7914371b4984b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
20 files changed, 178 insertions, 102 deletions
diff --git a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue index a2d94fb8083..5d8daffae4a 100644 --- a/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue +++ b/app/assets/javascripts/alerts_service_settings/components/alerts_service_form.vue @@ -180,9 +180,11 @@ export default { /> </span> </div> - <gl-button v-gl-modal.authKeyModal class="mt-2" :disabled="isDisabled">{{ - $options.RESET_KEY - }}</gl-button> + <span class="gl-display-flex gl-justify-content-end"> + <gl-button v-gl-modal.authKeyModal class="gl-mt-2" :disabled="isDisabled">{{ + $options.RESET_KEY + }}</gl-button> + </span> <gl-modal modal-id="authKeyModal" :title="$options.RESET_KEY" diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue index 56ecf0d9c55..3c1ffde41c8 100644 --- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue +++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue @@ -512,9 +512,14 @@ export default { /> </template> </gl-form-input-group> - <gl-button v-gl-modal.authKeyModal :disabled="!selectedService.active" class="gl-mt-3">{{ - $options.i18n.resetKey - }}</gl-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button + v-gl-modal.authKeyModal + :disabled="!selectedService.active" + class="gl-mt-3" + >{{ $options.i18n.resetKey }}</gl-button + > + </div> <gl-modal modal-id="authKeyModal" :title="$options.i18n.resetKey" @@ -541,11 +546,16 @@ export default { max-rows="10" /> </gl-form-group> - <gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{ - $options.i18n.testAlertInfo - }}</gl-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{ + $options.i18n.testAlertInfo + }}</gl-button> + </div> </template> <div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between"> + <gl-button category="primary" :disabled="!canSaveConfig" @click="onReset"> + {{ __('Cancel') }} + </gl-button> <gl-button variant="success" category="primary" @@ -554,9 +564,6 @@ export default { > {{ __('Save changes') }} </gl-button> - <gl-button variant="default" category="primary" :disabled="!canSaveConfig" @click="onReset"> - {{ __('Cancel') }} - </gl-button> </div> </gl-form> </div> diff --git a/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue b/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue index f60be52d6ca..9c28801306c 100644 --- a/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue +++ b/app/assets/javascripts/custom_metrics/components/custom_metrics_form.vue @@ -1,5 +1,5 @@ <script> -import { GlDeprecatedButton } from '@gitlab/ui'; +import { GlButton } from '@gitlab/ui'; import { __, s__ } from '~/locale'; import csrf from '~/lib/utils/csrf'; import CustomMetricsFormFields from './custom_metrics_form_fields.vue'; @@ -10,7 +10,7 @@ export default { components: { CustomMetricsFormFields, DeleteCustomMetricModal, - GlDeprecatedButton, + GlButton, }, props: { customMetricsPath: { @@ -76,15 +76,10 @@ export default { @formValidation="formValidation" /> <div class="form-actions"> - <gl-deprecated-button variant="success" :disabled="!formIsValid" @click="submit"> + <gl-button variant="success" category="primary" :disabled="!formIsValid" @click="submit"> {{ saveButtonText }} - </gl-deprecated-button> - <gl-deprecated-button - variant="secondary" - class="float-right" - :href="editProjectServicePath" - >{{ __('Cancel') }}</gl-deprecated-button - > + </gl-button> + <gl-button class="float-right" :href="editProjectServicePath">{{ __('Cancel') }}</gl-button> <delete-custom-metric-modal v-if="metricPersisted" :delete-metric-url="customMetricsPath" diff --git a/app/assets/javascripts/error_tracking_settings/components/app.vue b/app/assets/javascripts/error_tracking_settings/components/app.vue index 7ae847e6105..34dff6c58d5 100644 --- a/app/assets/javascripts/error_tracking_settings/components/app.vue +++ b/app/assets/javascripts/error_tracking_settings/components/app.vue @@ -1,11 +1,11 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; -import { GlDeprecatedButton } from '@gitlab/ui'; +import { GlDeprecatedButton as GlButton } from '@gitlab/ui'; import ProjectDropdown from './project_dropdown.vue'; import ErrorTrackingForm from './error_tracking_form.vue'; export default { - components: { ProjectDropdown, ErrorTrackingForm, GlDeprecatedButton }, + components: { ProjectDropdown, ErrorTrackingForm, GlButton }, props: { initialApiHost: { type: String, @@ -92,13 +92,15 @@ export default { @select-project="updateSelectedProject" /> </div> - <gl-deprecated-button - :disabled="settingsLoading" - class="js-error-tracking-button" - variant="success" - @click="handleSubmit" - > - {{ __('Save changes') }} - </gl-deprecated-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button + :disabled="settingsLoading" + class="js-error-tracking-button" + variant="success" + @click="handleSubmit" + > + {{ __('Save changes') }} + </gl-button> + </div> </div> </template> diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue index 8d1e542b8ad..59327e36f5f 100644 --- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue +++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue @@ -93,9 +93,11 @@ export default { </a> </p> </gl-form-group> - <gl-button variant="success" category="primary" @click="updateGrafanaIntegration"> - {{ __('Save Changes') }} - </gl-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button variant="success" category="primary" @click="updateGrafanaIntegration"> + {{ __('Save Changes') }} + </gl-button> + </div> </form> </div> </section> diff --git a/app/assets/javascripts/incidents_settings/components/alerts_form.vue b/app/assets/javascripts/incidents_settings/components/alerts_form.vue index a394f404ee1..5872ac39c96 100644 --- a/app/assets/javascripts/incidents_settings/components/alerts_form.vue +++ b/app/assets/javascripts/incidents_settings/components/alerts_form.vue @@ -123,17 +123,18 @@ export default { <span>{{ $options.i18n.sendEmail.label }}</span> </gl-form-checkbox> </gl-form-group> - - <gl-button - ref="submitBtn" - data-qa-selector="save_changes_button" - :disabled="loading" - variant="success" - type="submit" - class="js-no-auto-disable" - > - {{ $options.i18n.saveBtnLabel }} - </gl-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button + ref="submitBtn" + data-qa-selector="save_changes_button" + :disabled="loading" + variant="success" + type="submit" + class="js-no-auto-disable" + > + {{ $options.i18n.saveBtnLabel }} + </gl-button> + </div> </form> </div> </template> diff --git a/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue b/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue index 7b37fddd630..5b5dd8bf49e 100644 --- a/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue +++ b/app/assets/javascripts/incidents_settings/components/pagerduty_form.vue @@ -149,15 +149,17 @@ export default { </template> </gl-sprintf> </div> - <gl-button - v-gl-modal.resetWebhookModal - class="gl-mt-3" - :disabled="loading" - :loading="resettingWebhook" - data-testid="webhook-reset-btn" - > - {{ $options.i18n.webhookUrl.resetWebhookUrl }} - </gl-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button + v-gl-modal.resetWebhookModal + class="gl-mt-3" + :disabled="loading" + :loading="resettingWebhook" + data-testid="webhook-reset-btn" + > + {{ $options.i18n.webhookUrl.resetWebhookUrl }} + </gl-button> + </div> <gl-modal modal-id="resetWebhookModal" :title="$options.i18n.webhookUrl.resetWebhookUrl" @@ -168,16 +170,17 @@ export default { {{ $options.i18n.webhookUrl.restKeyInfo }} </gl-modal> </gl-form-group> - - <gl-button - ref="submitBtn" - :disabled="isSaveDisabled" - variant="success" - type="submit" - class="js-no-auto-disable" - > - {{ $options.i18n.saveBtnLabel }} - </gl-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button + ref="submitBtn" + :disabled="isSaveDisabled" + variant="success" + type="submit" + class="js-no-auto-disable" + > + {{ $options.i18n.saveBtnLabel }} + </gl-button> + </div> </form> </div> </template> diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue index 4ff29cd581b..d838b1db53f 100644 --- a/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue +++ b/app/assets/javascripts/monitoring/components/dashboard_panel_builder.vue @@ -55,7 +55,7 @@ export default { </script> <template> <div> - <div class="gl-display-flex gl-mx-n3"> + <div class="gl-xs-flex-direction-column gl-display-flex gl-mx-n3"> <gl-card class="gl-flex-grow-1 gl-flex-basis-0 gl-mx-3"> <template #header> <h2 class="gl-font-size-h2 gl-my-3">{{ s__('Metrics|1. Define and preview panel') }}</h2> @@ -76,6 +76,7 @@ export default { variant="success" category="secondary" :data-clipboard-text="yml" + class="gl-xs-w-full gl-xs-mb-3" @click="$toast.show(s__('Metrics|Panel YAML copied'))" > {{ s__('Metrics|Copy YAML') }} @@ -84,7 +85,7 @@ export default { type="submit" variant="success" :disabled="panelPreviewIsLoading" - class="js-no-auto-disable" + class="js-no-auto-disable gl-xs-w-full" > {{ s__('Metrics|Preview panel') }} </gl-button> @@ -127,13 +128,19 @@ export default { <gl-button ref="viewDocumentationBtn" category="secondary" + class="gl-xs-w-full gl-xs-mb-3" variant="info" target="_blank" :href="addDashboardDocumentationPath" > {{ s__('Metrics|View documentation') }} </gl-button> - <gl-button ref="openRepositoryBtn" variant="success" :href="projectPath"> + <gl-button + ref="openRepositoryBtn" + variant="success" + :href="projectPath" + class="gl-xs-w-full" + > {{ s__('Metrics|Open repository') }} </gl-button> </div> diff --git a/app/assets/javascripts/operation_settings/components/metrics_settings.vue b/app/assets/javascripts/operation_settings/components/metrics_settings.vue index 2cce315cdbb..7fe986ef201 100644 --- a/app/assets/javascripts/operation_settings/components/metrics_settings.vue +++ b/app/assets/javascripts/operation_settings/components/metrics_settings.vue @@ -1,12 +1,12 @@ <script> import { mapState, mapActions } from 'vuex'; -import { GlDeprecatedButton, GlLink } from '@gitlab/ui'; +import { GlDeprecatedButton as GlButton, GlLink } from '@gitlab/ui'; import ExternalDashboard from './form_group/external_dashboard.vue'; import DashboardTimezone from './form_group/dashboard_timezone.vue'; export default { components: { - GlDeprecatedButton, + GlButton, GlLink, ExternalDashboard, DashboardTimezone, @@ -34,7 +34,7 @@ export default { <h3 class="js-section-header h4"> {{ s__('MetricsSettings|Metrics dashboard') }} </h3> - <gl-deprecated-button class="js-settings-toggle">{{ __('Expand') }}</gl-deprecated-button> + <gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button> <p class="js-section-sub-header"> {{ s__('MetricsSettings|Manage Metrics Dashboard settings.') }} <gl-link :href="helpPage">{{ __('Learn more') }}</gl-link> @@ -44,9 +44,11 @@ export default { <form> <dashboard-timezone /> <external-dashboard /> - <gl-deprecated-button variant="success" @click="saveChanges"> - {{ __('Save Changes') }} - </gl-deprecated-button> + <div class="gl-display-flex gl-justify-content-end"> + <gl-button variant="success" @click="saveChanges"> + {{ __('Save Changes') }} + </gl-button> + </div> </form> </div> </section> diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb index ec8e70af315..278d77be1ca 100644 --- a/app/controllers/concerns/wiki_actions.rb +++ b/app/controllers/concerns/wiki_actions.rb @@ -67,6 +67,8 @@ module WikiActions @ref = params[:version_id] @path = page.path + Gitlab::UsageDataCounters::WikiPageCounter.count(:view) + render 'shared/wikis/show' elsif file_blob send_blob(wiki.repository, file_blob) diff --git a/app/controllers/projects/pipelines/tests_controller.rb b/app/controllers/projects/pipelines/tests_controller.rb index f03274bf32e..e2a3af358aa 100644 --- a/app/controllers/projects/pipelines/tests_controller.rb +++ b/app/controllers/projects/pipelines/tests_controller.rb @@ -35,23 +35,19 @@ module Projects # rubocop: disable CodeReuse/ActiveRecord def builds - pipeline.latest_builds.where(id: build_params) + @builds ||= pipeline.latest_builds.for_ids(build_ids).presence || render_404 end - def build_params + def build_ids return [] unless params[:build_ids] params[:build_ids].split(",") end def test_suite - if builds.present? - builds.map do |build| - build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new) - end.sum - else - render_404 - end + builds.map do |build| + build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new) + end.sum end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/models/ci/pipeline_artifact.rb b/app/models/ci/pipeline_artifact.rb index daa54aaafe3..5bcf49d3f8e 100644 --- a/app/models/ci/pipeline_artifact.rb +++ b/app/models/ci/pipeline_artifact.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# This class is being used to persist generated report consumable by gitlab frontend in a pipeline context. +# This class is being used to persist additional artifacts after a pipeline completes, which is a great place to cache a computed result in object storage module Ci class PipelineArtifact < ApplicationRecord diff --git a/app/models/repository.rb b/app/models/repository.rb index f4244764338..9d876321217 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -43,7 +43,7 @@ class Repository gitlab_ci_yml branch_names tag_names branch_count tag_count avatar exists? root_ref merged_branch_names has_visible_content? issue_template_names merge_request_template_names - user_defined_metrics_dashboard_paths xcode_project?).freeze + user_defined_metrics_dashboard_paths xcode_project? has_ambiguous_refs?).freeze # Methods that use cache_method but only memoize the value MEMOIZED_CACHED_METHODS = %i(license).freeze @@ -196,6 +196,31 @@ class Repository tag_exists?(ref) && branch_exists?(ref) end + # It's possible for a tag name to be a prefix (including slash) of a branch + # name, or vice versa. For instance, a tag named `foo` means we can't create a + # tag `foo/bar`, but we _can_ create a branch `foo/bar`. + # + # If we know a repository has no refs of this type (which is the common case) + # then separating refs from paths - as in ExtractsRef - can be faster. + # + # This method only checks one level deep, so only prefixes that contain no + # slashes are considered. If a repository has a tag `foo/bar` and a branch + # `foo/bar/baz`, it will return false. + def has_ambiguous_refs? + return false unless branch_names.present? && tag_names.present? + + with_slash, no_slash = (branch_names + tag_names).partition { |ref| ref.include?('/') } + + return false if with_slash.empty? + + prefixes = no_slash.map { |ref| Regexp.escape(ref) }.join('|') + prefix_regex = %r{^#{prefixes}/} + + with_slash.any? do |ref| + prefix_regex.match?(ref) + end + end + def expand_ref(ref) if tag_exists?(ref) Gitlab::Git::TAG_REF_PREFIX + ref diff --git a/app/models/service.rb b/app/models/service.rb index ea99b0c27e4..40e7e5552d1 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -48,13 +48,16 @@ class Service < ApplicationRecord belongs_to :project, inverse_of: :services has_one :service_hook - validates :project_id, presence: true, unless: -> { template? || instance? } - validates :project_id, absence: true, if: -> { template? || instance? } - validates :type, uniqueness: { scope: :project_id }, unless: -> { template? || instance? }, on: :create + validates :project_id, presence: true, unless: -> { template? || instance? || group_id } + validates :group_id, presence: true, unless: -> { template? || instance? || project_id } + validates :project_id, :group_id, absence: true, if: -> { template? || instance? } + validates :type, uniqueness: { scope: :project_id }, unless: -> { template? || instance? || group_id }, on: :create + validates :type, uniqueness: { scope: :group_id }, unless: -> { template? || instance? || project_id } validates :type, presence: true validates :template, uniqueness: { scope: :type }, if: -> { template? } validates :instance, uniqueness: { scope: :type }, if: -> { instance? } validate :validate_is_instance_or_template + validate :validate_belongs_to_project_or_group scope :external_issue_trackers, -> { where(category: 'issue_tracker').active } scope :external_wikis, -> { where(type: 'ExternalWikiService').active } @@ -377,6 +380,10 @@ class Service < ApplicationRecord errors.add(:template, 'The service should be a service template or instance-level integration') if template? && instance? end + def validate_belongs_to_project_or_group + errors.add(:project_id, 'The service cannot belong to both a project and a group') if project_id && group_id + end + def cache_project_has_external_issue_tracker if project && !project.destroyed? project.cache_has_external_issue_tracker diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb index 805602cd8cc..1f07d52ed4e 100644 --- a/app/services/projects/update_pages_configuration_service.rb +++ b/app/services/projects/update_pages_configuration_service.rb @@ -19,7 +19,7 @@ module Projects success rescue => e Gitlab::ErrorTracking.track_exception(e) - error(e.message) + error(e.message, pass_back: { exception: e }) end private diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 58c9bce963b..53c8489474b 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -142,7 +142,11 @@ module Projects end def update_pages_config - Projects::UpdatePagesConfigurationService.new(project).execute + if Feature.enabled?(:async_update_pages_config, project) + PagesUpdateConfigurationWorker.perform_async(project.id) + else + Projects::UpdatePagesConfigurationService.new(project).execute + end end def changing_pages_https_only? diff --git a/app/uploaders/job_artifact_uploader.rb b/app/uploaders/job_artifact_uploader.rb index 400f0b3dcc6..47976c909e8 100644 --- a/app/uploaders/job_artifact_uploader.rb +++ b/app/uploaders/job_artifact_uploader.rb @@ -36,15 +36,10 @@ class JobArtifactUploader < GitlabUploader end def hashed_path - File.join(disk_hash[0..1], disk_hash[2..3], disk_hash, - model.created_at.utc.strftime('%Y_%m_%d'), model.job_id.to_s, model.id.to_s) + Gitlab::HashedPath.new(model.created_at.utc.strftime('%Y_%m_%d'), model.job_id, model.id, root_hash: model.project_id) end def legacy_path File.join(model.created_at.utc.strftime('%Y_%m'), model.project_id.to_s, model.job_id.to_s) end - - def disk_hash - @disk_hash ||= Digest::SHA2.hexdigest(model.project_id.to_s) - end end diff --git a/app/uploaders/packages/package_file_uploader.rb b/app/uploaders/packages/package_file_uploader.rb index 20fcf0a7a32..28545b9fcdf 100644 --- a/app/uploaders/packages/package_file_uploader.rb +++ b/app/uploaders/packages/package_file_uploader.rb @@ -20,11 +20,6 @@ class Packages::PackageFileUploader < GitlabUploader private def dynamic_segment - File.join(disk_hash[0..1], disk_hash[2..3], disk_hash, - 'packages', model.package.id.to_s, 'files', model.id.to_s) - end - - def disk_hash - @disk_hash ||= Digest::SHA2.hexdigest(model.package.project_id.to_s) + Gitlab::HashedPath.new('packages', model.package.id, 'files', model.id, root_hash: model.package.project_id) end end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 3fbb81c6c81..2c871c55f0a 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -1524,6 +1524,14 @@ :weight: 1 :idempotent: :tags: [] +- :name: pages_update_configuration + :feature_category: :pages + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: true + :tags: [] - :name: phabricator_import_import_tasks :feature_category: :importers :has_external_dependencies: diff --git a/app/workers/pages_update_configuration_worker.rb b/app/workers/pages_update_configuration_worker.rb new file mode 100644 index 00000000000..d0904db6b42 --- /dev/null +++ b/app/workers/pages_update_configuration_worker.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class PagesUpdateConfigurationWorker + include ApplicationWorker + + idempotent! + feature_category :pages + + def perform(project_id) + project = Project.find_by_id(project_id) + return unless project + + result = Projects::UpdatePagesConfigurationService.new(project).execute + + # The ConfigurationService swallows all exceptions and wraps them in a status + # we need to keep this while the feature flag still allows running this + # service within a request. + # But we might as well take advantage of sidekiq retries here. + # We should let the service raise after we remove the feature flag + # https://gitlab.com/gitlab-org/gitlab/-/issues/230695 + raise result[:exception] if result[:exception] + end +end |