diff options
author | Sean Carroll <scarroll@gitlab.com> | 2019-08-05 09:16:25 +0000 |
---|---|---|
committer | Sean Carroll <scarroll@gitlab.com> | 2019-08-05 09:16:25 +0000 |
commit | 09d5ad822c52337b975843fd2d4e079ce1f5e932 (patch) | |
tree | 71486aac99b1651598e24f2edc045158eae7267b | |
parent | 23d393e38788dc9af022916b1465b9c3a3e3f3f3 (diff) | |
parent | fccbe0f97a76ba85daf745b4dd98375a5cd8f03f (diff) | |
download | gitlab-ce-55360-redundant-index-in-the-releases-table.tar.gz |
Merge branch 'master' into '55360-redundant-index-in-the-releases-table'55360-redundant-index-in-the-releases-table
# Conflicts:
# db/schema.rb
127 files changed, 1680 insertions, 552 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 2bdde9fedaf..d2148f01441 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -8,7 +8,7 @@ .use-pg: &use-pg services: - - name: postgres:9.6.11 + - name: postgres:9.6.14 command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine @@ -19,7 +19,7 @@ dependencies: - setup-test-env services: - - docker:stable-dind + - docker:19.03.0-dind variables: NODE_ENV: "production" RAILS_ENV: "production" diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml index 24b4eb3a4c1..8a89232fdd4 100644 --- a/.gitlab/ci/rails.gitlab-ci.yml +++ b/.gitlab/ci/rails.gitlab-ci.yml @@ -1,12 +1,12 @@ .use-pg: &use-pg services: - - name: postgres:9.6.11 + - name: postgres:9.6.14 command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine .use-pg-10: &use-pg-10 services: - - name: postgres:10.7 + - name: postgres:10.9 command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index 076858e6c8a..ed6690c1023 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -35,7 +35,7 @@ <<: *review-base image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine services: - - docker:stable-dind + - docker:19.03.0-dind tags: - gitlab-org - docker @@ -264,6 +264,7 @@ danger-review: except: refs: - master + - /^[\d-]+-stable(-ee)?$/ variables: - $CI_COMMIT_REF_NAME =~ /^ce-to-ee-.*/ - $CI_COMMIT_REF_NAME =~ /.*-stable(-ee)?-prepare-.*/ diff --git a/.mdlrc.style b/.mdlrc.style index 0ca3611df0b..36fbba3543b 100644 --- a/.mdlrc.style +++ b/.mdlrc.style @@ -5,12 +5,19 @@ # for more detailed information on the rules and styles. rule "MD001" +rule "MD002" rule "MD003", :style => :atx +rule "MD006" rule "MD011" +rule "MD019" +rule "MD022" rule "MD023" +rule "MD025" +rule "MD028" rule "MD032" rule "MD034" rule "MD037" +rule "MD038" # Should not be used currently: diff --git a/.prettierignore b/.prettierignore index dc9e572ab54..c9b945ac96d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,4 @@ # ignore stylesheets for now as this clashes with our linter *.css *.scss +*.md diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index aacfa0d87e6..5f5c8044b49 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -48,6 +48,9 @@ export default class Clusters { } = document.querySelector('.js-edit-cluster-form').dataset; this.clusterId = clusterId; + this.clusterNewlyCreatedKey = `cluster_${this.clusterId}_newly_created`; + this.clusterBannerDismissedKey = `cluster_${this.clusterId}_banner_dismissed`; + this.store = new ClustersStore(); this.store.setHelpPaths(helpPath, ingressHelpPath, ingressDnsHelpPath); this.store.setManagePrometheusPath(managePrometheusPath); @@ -81,18 +84,19 @@ export default class Clusters { this.showTokenButton = document.querySelector('.js-show-cluster-token'); this.tokenField = document.querySelector('.js-cluster-token'); this.ingressDomainHelpText = document.querySelector('.js-ingress-domain-help-text'); - this.ingressDomainSnippet = this.ingressDomainHelpText.querySelector( - '.js-ingress-domain-snippet', - ); + this.ingressDomainSnippet = + this.ingressDomainHelpText && + this.ingressDomainHelpText.querySelector('.js-ingress-domain-snippet'); Clusters.initDismissableCallout(); initSettingsPanels(); - setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area')); + const toggleButtonsContainer = document.querySelector('.js-cluster-enable-toggle-area'); + if (toggleButtonsContainer) { + setupToggleButtons(toggleButtonsContainer); + } this.initApplications(clusterType); - if (this.store.state.status !== 'created') { - this.updateContainer(null, this.store.state.status, this.store.state.statusReason); - } + this.updateContainer(null, this.store.state.status, this.store.state.statusReason); this.addListeners(); if (statusPath) { @@ -247,35 +251,56 @@ export default class Clusters { setBannerDismissedState(status, isDismissed) { if (AccessorUtilities.isLocalStorageAccessSafe()) { - window.localStorage.setItem( - `cluster_${this.clusterId}_banner_dismissed`, - `${status}_${isDismissed}`, - ); + window.localStorage.setItem(this.clusterBannerDismissedKey, `${status}_${isDismissed}`); } } isBannerDismissed(status) { let bannerState; if (AccessorUtilities.isLocalStorageAccessSafe()) { - bannerState = window.localStorage.getItem(`cluster_${this.clusterId}_banner_dismissed`); + bannerState = window.localStorage.getItem(this.clusterBannerDismissedKey); } return bannerState === `${status}_true`; } - updateContainer(prevStatus, status, error) { - this.hideAll(); + setClusterNewlyCreated(state) { + if (AccessorUtilities.isLocalStorageAccessSafe()) { + window.localStorage.setItem(this.clusterNewlyCreatedKey, Boolean(state)); + } + } + + isClusterNewlyCreated() { + // once this is true, it will always be true for a given page load + if (!this.isNewlyCreated) { + let newlyCreated; + if (AccessorUtilities.isLocalStorageAccessSafe()) { + newlyCreated = window.localStorage.getItem(this.clusterNewlyCreatedKey); + } + + this.isNewlyCreated = newlyCreated === 'true'; + } + return this.isNewlyCreated; + } - if (this.isBannerDismissed(status)) { + updateContainer(prevStatus, status, error) { + if (status !== 'created' && this.isBannerDismissed(status)) { return; } this.setBannerDismissedState(status, false); - // We poll all the time but only want the `created` banner to show when newly created - if (this.store.state.status !== 'created' || prevStatus !== this.store.state.status) { + if (prevStatus !== status) { + this.hideAll(); + switch (status) { case 'created': - this.successContainer.classList.remove('hidden'); + if (this.isClusterNewlyCreated()) { + this.setClusterNewlyCreated(false); + this.successContainer.classList.remove('hidden'); + } else if (prevStatus) { + this.setClusterNewlyCreated(true); + window.location.reload(); + } break; case 'errored': this.errorContainer.classList.remove('hidden'); @@ -292,7 +317,6 @@ export default class Clusters { this.creatingContainer.classList.remove('hidden'); break; default: - this.hideAll(); } } } diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue index 2ff6d5e32e2..e067eb13c54 100644 --- a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue +++ b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue @@ -2,9 +2,12 @@ import { GlModal } from '@gitlab/ui'; import { sprintf, s__ } from '~/locale'; import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click'; -import { INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants'; +import { HELM, INGRESS, CERT_MANAGER, PROMETHEUS, RUNNER, KNATIVE, JUPYTER } from '../constants'; const CUSTOM_APP_WARNING_TEXT = { + [HELM]: s__( + 'ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored.', + ), [INGRESS]: s__( 'ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored.', ), diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js index 4a08e158f6b..8d6a3781048 100644 --- a/app/assets/javascripts/persistent_user_callout.js +++ b/app/assets/javascripts/persistent_user_callout.js @@ -1,13 +1,17 @@ +import { parseBoolean } from './lib/utils/common_utils'; import axios from './lib/utils/axios_utils'; import { __ } from './locale'; import Flash from './flash'; +const DEFERRED_LINK_CLASS = 'deferred-link'; + export default class PersistentUserCallout { constructor(container) { - const { dismissEndpoint, featureId } = container.dataset; + const { dismissEndpoint, featureId, deferLinks } = container.dataset; this.container = container; this.dismissEndpoint = dismissEndpoint; this.featureId = featureId; + this.deferLinks = parseBoolean(deferLinks); this.init(); } @@ -15,9 +19,21 @@ export default class PersistentUserCallout { init() { const closeButton = this.container.querySelector('.js-close'); closeButton.addEventListener('click', event => this.dismiss(event)); + + if (this.deferLinks) { + this.container.addEventListener('click', event => { + const isDeferredLink = event.target.classList.contains(DEFERRED_LINK_CLASS); + + if (isDeferredLink) { + const { href, target } = event.target; + + this.dismiss(event, { href, target }); + } + }); + } } - dismiss(event) { + dismiss(event, deferredLinkOptions = null) { event.preventDefault(); axios @@ -26,6 +42,11 @@ export default class PersistentUserCallout { }) .then(() => { this.container.remove(); + + if (deferredLinkOptions) { + const { href, target } = deferredLinkOptions; + window.open(href, target); + } }) .catch(() => { Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.')); diff --git a/app/assets/javascripts/privacy_policy_update_callout.js b/app/assets/javascripts/privacy_policy_update_callout.js new file mode 100644 index 00000000000..126b1ee1132 --- /dev/null +++ b/app/assets/javascripts/privacy_policy_update_callout.js @@ -0,0 +1,8 @@ +import PersistentUserCallout from '~/persistent_user_callout'; + +function initPrivacyPolicyUpdateCallout() { + const callout = document.querySelector('.privacy-policy-update-64341'); + PersistentUserCallout.factory(callout); +} + +export default initPrivacyPolicyUpdateCallout; diff --git a/app/assets/javascripts/projects/gke_cluster_namespace/index.js b/app/assets/javascripts/projects/gke_cluster_namespace/index.js index 288740203ad..0ec4d8807b0 100644 --- a/app/assets/javascripts/projects/gke_cluster_namespace/index.js +++ b/app/assets/javascripts/projects/gke_cluster_namespace/index.js @@ -28,8 +28,10 @@ const setState = glManagedCheckbox => { const initGkeNamespace = () => { const glManagedCheckbox = document.querySelector('.js-gl-managed'); - setState(glManagedCheckbox); // this is needed in order to set the initial state - glManagedCheckbox.addEventListener('change', () => setState(glManagedCheckbox)); + if (glManagedCheckbox) { + setState(glManagedCheckbox); // this is needed in order to set the initial state + glManagedCheckbox.addEventListener('change', () => setState(glManagedCheckbox)); + } }; export default initGkeNamespace; diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index fbf16aa324a..e98030f1511 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -12,7 +12,6 @@ // If you need to add unique style that should affect only one page - use pages/ // directory. @import "at.js/dist/css/jquery.atwho"; -@import "pikaday/scss/pikaday"; @import "dropzone/dist/basic"; @import "select2/select2"; diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 6e98908eeed..262c0bf5ed2 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -127,6 +127,7 @@ .section-header ~ .section.line { margin-left: $gl-padding; + display: block; } } diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 3847a35fbab..acbcf0ded17 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -160,6 +160,8 @@ module ApplicationSettingsHelper :akismet_api_key, :akismet_enabled, :allow_local_requests_from_hooks_and_services, + :allow_local_requests_from_web_hooks_and_services, + :allow_local_requests_from_system_hooks, :dns_rebinding_protection_enabled, :archive_builds_in_human_readable, :authorized_keys_enabled, diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 4bb09bf3b53..b7a4d7aa803 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -21,7 +21,8 @@ module ApplicationSettingImplementation { after_sign_up_text: nil, akismet_enabled: false, - allow_local_requests_from_hooks_and_services: false, + allow_local_requests_from_web_hooks_and_services: false, + allow_local_requests_from_system_hooks: true, dns_rebinding_protection_enabled: true, authorized_keys_enabled: true, # TODO default to false if the instance is configured to use AuthorizedKeysCommand container_registry_token_expire_delay: 5, diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index dd2bfc42af9..ac88d9714ac 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -715,18 +715,14 @@ module Ci depended_jobs = depends_on_builds - # find all jobs that are dependent on - if options[:dependencies].present? - depended_jobs = depended_jobs.select do |job| - options[:dependencies].include?(job.name) - end + # find all jobs that are needed + if Feature.enabled?(:ci_dag_support, project) && needs.exists? + depended_jobs = depended_jobs.where(name: needs.select(:name)) end - # find all jobs that are needed by this one - if options[:needs].present? - depended_jobs = depended_jobs.select do |job| - options[:needs].include?(job.name) - end + # find all jobs that are dependent on + if options[:dependencies].present? + depended_jobs = depended_jobs.where(name: options[:dependencies]) end depended_jobs diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 3515f0b83ee..ffab4e82f90 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -504,8 +504,9 @@ module Ci return [] unless config_processor strong_memoize(:stage_seeds) do - seeds = config_processor.stages_attributes.map do |attributes| - Gitlab::Ci::Pipeline::Seed::Stage.new(self, attributes) + seeds = config_processor.stages_attributes.inject([]) do |previous_stages, attributes| + seed = Gitlab::Ci::Pipeline::Seed::Stage.new(self, attributes, previous_stages) + previous_stages + [seed] end seeds.select(&:included?) diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index a83d06c4b00..3a175fec148 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -14,6 +14,7 @@ module Clusters include ::Clusters::Concerns::ApplicationCore include ::Clusters::Concerns::ApplicationStatus + include ::Gitlab::Utils::StrongMemoize default_value_for :version, Gitlab::Kubernetes::Helm::HELM_VERSION @@ -29,11 +30,22 @@ module Clusters self.status = 'installable' if cluster&.platform_kubernetes_active? end - # We will implement this in future MRs. - # Basically we need to check all other applications are not installed - # first. + # It can only be uninstalled if there are no other applications installed + # or with intermitent installation statuses in the database. def allowed_to_uninstall? - false + strong_memoize(:allowed_to_uninstall) do + applications = nil + + Clusters::Cluster::APPLICATIONS.each do |application_name, klass| + next if application_name == 'helm' + + extra_apps = Clusters::Applications::Helm.where('EXISTS (?)', klass.select(1).where(cluster_id: cluster_id)) + + applications = applications.present? ? applications.or(extra_apps) : extra_apps + end + + !applications.exists? + end end def install_command @@ -44,6 +56,14 @@ module Clusters ) end + def uninstall_command + Gitlab::Kubernetes::Helm::ResetCommand.new( + name: name, + files: files, + rbac: cluster.platform_kubernetes_rbac? + ) + end + def has_ssl? ca_key.present? && ca_cert.present? end diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb index 96f526e8a36..5eae23659ae 100644 --- a/app/models/clusters/applications/knative.rb +++ b/app/models/clusters/applications/knative.rb @@ -84,7 +84,7 @@ module Clusters private def delete_knative_services_and_metrics - delete_knative_services + delete_knative_istio_metrics.to_a + delete_knative_services + delete_knative_istio_metrics end def delete_knative_services @@ -117,11 +117,15 @@ module Clusters end def install_knative_metrics - ["kubectl apply -f #{METRICS_CONFIG}"] if cluster.application_prometheus_available? + return [] unless cluster.application_prometheus_available? + + ["kubectl apply -f #{METRICS_CONFIG}"] end def delete_knative_istio_metrics - ["kubectl delete --ignore-not-found -f #{METRICS_CONFIG}"] if cluster.application_prometheus_available? + return [] unless cluster.application_prometheus_available? + + ["kubectl delete --ignore-not-found -f #{METRICS_CONFIG}"] end def verify_cluster? diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index f5375d29f3a..5eb535cab58 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -64,7 +64,7 @@ module Clusters name: name, rbac: cluster.platform_kubernetes_rbac?, files: files, - predelete: delete_knative_istio_metrics.to_a + predelete: delete_knative_istio_metrics ) end @@ -104,11 +104,15 @@ module Clusters end def install_knative_metrics - ["kubectl apply -f #{Clusters::Applications::Knative::METRICS_CONFIG}"] if cluster.application_knative_available? + return [] unless cluster.application_knative_available? + + ["kubectl apply -f #{Clusters::Applications::Knative::METRICS_CONFIG}"] end def delete_knative_istio_metrics - ["kubectl delete -f #{Clusters::Applications::Knative::METRICS_CONFIG}"] if cluster.application_knative_available? + return [] unless cluster.application_knative_available? + + ["kubectl delete -f #{Clusters::Applications::Knative::METRICS_CONFIG}"] end end end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index d7eb78db5b8..a9c29fb390b 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -49,6 +49,10 @@ class CommitStatus < ApplicationRecord where('EXISTS (?)', needs).preload(:needs) end + scope :without_needs, -> do + where('NOT EXISTS (?)', Ci::BuildNeed.scoped_build.select(1)) + end + # We use `CommitStatusEnums.failure_reasons` here so that EE can more easily # extend this `Hash` with new values. enum_with_nil failure_reason: ::CommitStatusEnums.failure_reasons diff --git a/app/models/concerns/group_descendant.rb b/app/models/concerns/group_descendant.rb index cfffd845e43..ed14b73ac1b 100644 --- a/app/models/concerns/group_descendant.rb +++ b/app/models/concerns/group_descendant.rb @@ -42,7 +42,7 @@ module GroupDescendant parent = child.parent exception = ArgumentError.new <<~MSG - parent: [GroupDescendant: #{parent.inspect}] was not preloaded for [#{child.inspect}]") + Parent was not preloaded for child when rendering group hierarchy. This error is not user facing, but causes a +1 query. MSG extras = { @@ -50,7 +50,7 @@ module GroupDescendant child: child.inspect, preloaded: preloaded.map(&:full_path) } - issue_url = 'https://gitlab.com/gitlab-org/gitlab-ce/issues/40785' + issue_url = 'https://gitlab.com/gitlab-org/gitlab-ce/issues/49404' Gitlab::Sentry.track_exception(exception, issue_url: issue_url, extra: extras) end diff --git a/app/models/concerns/update_project_statistics.rb b/app/models/concerns/update_project_statistics.rb index 570a735973f..869b3490f3f 100644 --- a/app/models/concerns/update_project_statistics.rb +++ b/app/models/concerns/update_project_statistics.rb @@ -73,15 +73,10 @@ module UpdateProjectStatistics def schedule_namespace_aggregation_worker run_after_commit do - next unless schedule_aggregation_worker? + next if project.nil? Namespaces::ScheduleAggregationWorker.perform_async(project.namespace_id) end end - - def schedule_aggregation_worker? - !project.nil? && - Feature.enabled?(:update_statistics_namespace, project.root_ancestor) - end end end diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb index 90b4588a325..3d54d17e787 100644 --- a/app/models/hooks/system_hook.rb +++ b/app/models/hooks/system_hook.rb @@ -14,8 +14,10 @@ class SystemHook < WebHook default_value_for :repository_update_events, true default_value_for :merge_requests_events, false + validates :url, system_hook_url: true + # Allow urls pointing localhost and the local network def allow_local_requests? - true + Gitlab::CurrentSettings.allow_local_requests_from_system_hooks? end end diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index daf7ff4b771..16fc7fdbd48 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -15,8 +15,8 @@ class WebHook < ApplicationRecord has_many :web_hook_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent - validates :url, presence: true, public_url: { allow_localhost: lambda(&:allow_local_requests?), - allow_local_network: lambda(&:allow_local_requests?) } + validates :url, presence: true + validates :url, public_url: true, unless: ->(hook) { hook.is_a?(SystemHook) } validates :token, format: { without: /\n/ } validates :push_events_branch_filter, branch_filter: true @@ -35,6 +35,6 @@ class WebHook < ApplicationRecord # Allow urls pointing localhost and the local network def allow_local_requests? - false + Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services? end end diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb index 3802d258664..47999a3694e 100644 --- a/app/models/project_statistics.rb +++ b/app/models/project_statistics.rb @@ -93,13 +93,7 @@ class ProjectStatistics < ApplicationRecord def schedule_namespace_aggregation_worker run_after_commit do - next unless schedule_aggregation_worker? - Namespaces::ScheduleAggregationWorker.perform_async(project.namespace_id) end end - - def schedule_aggregation_worker? - Feature.enabled?(:update_statistics_namespace, project&.root_ancestor) - end end diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb index e46615bcf75..a6d87101163 100644 --- a/app/services/ci/process_pipeline_service.rb +++ b/app/services/ci/process_pipeline_service.rb @@ -9,10 +9,7 @@ module Ci update_retried - success = - stage_indexes_of_created_processables.flat_map do |index| - process_stage(index) - end.any? + success = process_stages_without_needs # we evaluate dependent needs, # only when the another job has finished @@ -25,18 +22,19 @@ module Ci private - def process_stage(index) + def process_stages_without_needs + stage_indexes_of_created_processables_without_needs.flat_map do |index| + process_stage_without_needs(index) + end.any? + end + + def process_stage_without_needs(index) current_status = status_for_prior_stages(index) - return if HasStatus::BLOCKED_STATUS.include?(current_status) + return unless HasStatus::COMPLETED_STATUSES.include?(current_status) - if HasStatus::COMPLETED_STATUSES.include?(current_status) - created_processables_in_stage(index).select do |build| - Gitlab::OptimisticLocking.retry_lock(build) do |subject| - Ci::ProcessBuildService.new(project, @user) - .execute(build, current_status) - end - end + created_processables_in_stage_without_needs(index).select do |build| + process_build(build, current_status) end end @@ -56,6 +54,10 @@ module Ci return unless HasStatus::COMPLETED_STATUSES.include?(current_status) + process_build(build, current_status) + end + + def process_build(build, current_status) Gitlab::OptimisticLocking.retry_lock(build) do |subject| Ci::ProcessBuildService.new(project, @user) .execute(subject, current_status) @@ -75,17 +77,27 @@ module Ci # rubocop: enable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord - def stage_indexes_of_created_processables - created_processables.order(:stage_idx).pluck(Arel.sql('DISTINCT stage_idx')) + def stage_indexes_of_created_processables_without_needs + created_processables_without_needs.order(:stage_idx) + .pluck(Arel.sql('DISTINCT stage_idx')) end # rubocop: enable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord - def created_processables_in_stage(index) - created_processables.where(stage_idx: index) + def created_processables_in_stage_without_needs(index) + created_processables_without_needs + .where(stage_idx: index) end # rubocop: enable CodeReuse/ActiveRecord + def created_processables_without_needs + if Feature.enabled?(:ci_dag_support, project) + pipeline.processables.created.without_needs + else + pipeline.processables.created + end + end + def created_processables pipeline.processables.created end diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb index 6d675c026bb..8c294218708 100644 --- a/app/services/web_hook_service.rb +++ b/app/services/web_hook_service.rb @@ -17,8 +17,10 @@ class WebHookService @hook = hook @data = data @hook_name = hook_name.to_s - @request_options = { timeout: Gitlab.config.gitlab.webhook_timeout } - @request_options.merge!(allow_local_requests: true) if @hook.is_a?(SystemHook) + @request_options = { + timeout: Gitlab.config.gitlab.webhook_timeout, + allow_local_requests: hook.allow_local_requests? + } end def execute diff --git a/app/validators/addressable_url_validator.rb b/app/validators/addressable_url_validator.rb index 273e15ef925..bb445499cee 100644 --- a/app/validators/addressable_url_validator.rb +++ b/app/validators/addressable_url_validator.rb @@ -107,6 +107,6 @@ class AddressableUrlValidator < ActiveModel::EachValidator # calls this validator. # # See https://gitlab.com/gitlab-org/gitlab-ee/issues/9833 - ApplicationSetting.current&.allow_local_requests_from_hooks_and_services? + ApplicationSetting.current&.allow_local_requests_from_web_hooks_and_services? end end diff --git a/app/validators/system_hook_url_validator.rb b/app/validators/system_hook_url_validator.rb new file mode 100644 index 00000000000..f4253006dad --- /dev/null +++ b/app/validators/system_hook_url_validator.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# SystemHookUrlValidator +# +# Custom validator specific to SystemHook URLs. This validator works like AddressableUrlValidator but +# it blocks urls pointing to localhost or the local network depending on +# ApplicationSetting.allow_local_requests_from_system_hooks +# +# Example: +# class SystemHook < WebHook +# validates :url, system_hook_url: true +# end +# +class SystemHookUrlValidator < PublicUrlValidator + def self.allow_setting_local_requests? + ApplicationSetting.current&.allow_local_requests_from_system_hooks? + end +end diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml index 4fecdb59e1d..ad26f52aea7 100644 --- a/app/views/admin/application_settings/_outbound.html.haml +++ b/app/views/admin/application_settings/_outbound.html.haml @@ -4,9 +4,13 @@ %fieldset .form-group .form-check - = f.check_box :allow_local_requests_from_hooks_and_services, class: 'form-check-input' - = f.label :allow_local_requests_from_hooks_and_services, class: 'form-check-label' do - Allow requests to the local network from hooks and services + = f.check_box :allow_local_requests_from_web_hooks_and_services, class: 'form-check-input' + = f.label :allow_local_requests_from_web_hooks_and_services, class: 'form-check-label' do + = _('Allow requests to the local network from web hooks and services') + .form-check + = f.check_box :allow_local_requests_from_system_hooks, class: 'form-check-input' + = f.label :allow_local_requests_from_system_hooks, class: 'form-check-label' do + = _('Allow requests to the local network from system hooks') .form-group = f.label :outbound_local_requests_whitelist_raw, class: 'label-bold' do diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml index a5de67be96b..4b4278075a6 100644 --- a/app/views/clusters/clusters/_banner.html.haml +++ b/app/views/clusters/clusters/_banner.html.haml @@ -3,7 +3,8 @@ %p.js-error-reason .hidden.js-cluster-creating.bs-callout.bs-callout-info{ role: 'alert' } - = s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...') + %span.spinner.spinner-dark.spinner-sm{ 'aria-label': 'Loading' } + %span.prepend-left-4= s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...') .hidden.row.js-cluster-api-unreachable.bs-callout.bs-callout-warning{ role: 'alert' } .col-11 @@ -18,4 +19,4 @@ %button.js-close-banner.close.cluster-application-banner-close.h-100.m-0= "×" .hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' } - = s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details") + = s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine.") diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml index 4dfbb310142..913d4caa0bc 100644 --- a/app/views/clusters/clusters/show.html.haml +++ b/app/views/clusters/clusters/show.html.haml @@ -33,26 +33,29 @@ %section#cluster-integration %h4= @cluster.name = render 'banner' - = render 'form' - - = render_if_exists 'projects/clusters/prometheus_graphs' - - .cluster-applications-table#js-cluster-applications - - %section.settings#js-cluster-details{ class: ('expanded' if expanded) } - .settings-header - %h4= s_('ClusterIntegration|Kubernetes cluster details') - %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster') - .settings-content - = render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster) - - %section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) } - .settings-header - %h4= _('Advanced settings') - %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration") - .settings-content#advanced-settings-section - = render 'advanced_settings' + + - unless @cluster.status_name.in? %i/scheduled creating/ + = render 'form' + + - unless @cluster.status_name.in? %i/scheduled creating/ + = render_if_exists 'projects/clusters/prometheus_graphs' + + .cluster-applications-table#js-cluster-applications + + %section.settings#js-cluster-details{ class: ('expanded' if expanded) } + .settings-header + %h4= s_('ClusterIntegration|Kubernetes cluster details') + %button.btn.js-settings-toggle{ type: 'button' } + = expanded ? _('Collapse') : _('Expand') + %p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster') + .settings-content + = render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster) + + %section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) } + .settings-header + %h4= _('Advanced settings') + %button.btn.js-settings-toggle{ type: 'button' } + = expanded ? _('Collapse') : _('Expand') + %p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration") + .settings-content#advanced-settings-section + = render 'advanced_settings' diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml index efb3815b257..46d7c367aa7 100644 --- a/app/views/help/_shortcuts.html.haml +++ b/app/views/help/_shortcuts.html.haml @@ -24,11 +24,11 @@ %td.shortcut %kbd f %td Focus Filter - - if performance_bar_enabled? - %tr - %td.shortcut - %kbd p b - %td Show/hide the Performance Bar + %tr + %td.shortcut + %kbd p + %kbd b + %td Toggle the Performance Bar %tr %td.shortcut %kbd ? diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 20b844f9fd8..ac774803f95 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -78,4 +78,3 @@ = render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id') = render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id') = render_if_exists 'layouts/snowplow' - = render_if_exists 'layouts/pendo' if Feature.enabled?(:pendo_tracking) && !Rails.env.test? diff --git a/app/workers/namespaces/root_statistics_worker.rb b/app/workers/namespaces/root_statistics_worker.rb index 48876825564..0c1ca5eb975 100644 --- a/app/workers/namespaces/root_statistics_worker.rb +++ b/app/workers/namespaces/root_statistics_worker.rb @@ -9,7 +9,7 @@ module Namespaces def perform(namespace_id) namespace = Namespace.find(namespace_id) - return unless update_statistics_enabled_for?(namespace) && namespace.aggregation_scheduled? + return unless namespace.aggregation_scheduled? Namespaces::StatisticsRefresherService.new.execute(namespace) @@ -23,9 +23,5 @@ module Namespaces def log_error(namespace_path, error_message) Gitlab::SidekiqLogger.error("Namespace statistics can't be updated for #{namespace_path}: #{error_message}") end - - def update_statistics_enabled_for?(namespace) - Feature.enabled?(:update_statistics_namespace, namespace) - end end end diff --git a/app/workers/namespaces/schedule_aggregation_worker.rb b/app/workers/namespaces/schedule_aggregation_worker.rb index a4594b84b13..983ce4bef4a 100644 --- a/app/workers/namespaces/schedule_aggregation_worker.rb +++ b/app/workers/namespaces/schedule_aggregation_worker.rb @@ -12,7 +12,7 @@ module Namespaces namespace = Namespace.find(namespace_id) root_ancestor = namespace.root_ancestor - return unless update_statistics_enabled_for?(root_ancestor) && !root_ancestor.aggregation_scheduled? + return if root_ancestor.aggregation_scheduled? Namespace::AggregationSchedule.safe_find_or_create_by!(namespace_id: root_ancestor.id) rescue ActiveRecord::RecordNotFound @@ -37,9 +37,5 @@ module Namespaces def log_error(root_ancestor_id) Gitlab::SidekiqLogger.error("Namespace can't be scheduled for aggregation: #{root_ancestor_id} does not exist") end - - def update_statistics_enabled_for?(root_ancestor) - Feature.enabled?(:update_statistics_namespace, root_ancestor) - end end end diff --git a/changelogs/unreleased/17276-breakage-in-displaying-svg-in-the-same-repository.yml b/changelogs/unreleased/17276-breakage-in-displaying-svg-in-the-same-repository.yml new file mode 100644 index 00000000000..93936d441e7 --- /dev/null +++ b/changelogs/unreleased/17276-breakage-in-displaying-svg-in-the-same-repository.yml @@ -0,0 +1,5 @@ +--- +title: Fix inline rendering of relative paths to SVGs from the current repository +merge_request: 31352 +author: +type: fixed diff --git a/changelogs/unreleased/50130-cluster-cluster-details-update-automatically-after-cluster-is-created.yml b/changelogs/unreleased/50130-cluster-cluster-details-update-automatically-after-cluster-is-created.yml new file mode 100644 index 00000000000..dc718572cfb --- /dev/null +++ b/changelogs/unreleased/50130-cluster-cluster-details-update-automatically-after-cluster-is-created.yml @@ -0,0 +1,5 @@ +--- +title: Update cluster page automatically when cluster is created +merge_request: 27189 +author: +type: changed diff --git a/changelogs/unreleased/60516-uninstall-tiller.yml b/changelogs/unreleased/60516-uninstall-tiller.yml new file mode 100644 index 00000000000..db25e7b3338 --- /dev/null +++ b/changelogs/unreleased/60516-uninstall-tiller.yml @@ -0,0 +1,5 @@ +--- +title: Allow Helm to be uninstalled from the UI +merge_request: 27359 +author: +type: added diff --git a/changelogs/unreleased/64092-removes-update-statistics-namespace-feature-flag.yml b/changelogs/unreleased/64092-removes-update-statistics-namespace-feature-flag.yml new file mode 100644 index 00000000000..272c830a914 --- /dev/null +++ b/changelogs/unreleased/64092-removes-update-statistics-namespace-feature-flag.yml @@ -0,0 +1,5 @@ +--- +title: Enables storage statistics for root namespaces on database +merge_request: 31392 +author: +type: other diff --git a/changelogs/unreleased/64341-user-callout-deferred-link-support.yml b/changelogs/unreleased/64341-user-callout-deferred-link-support.yml new file mode 100644 index 00000000000..05230ddc124 --- /dev/null +++ b/changelogs/unreleased/64341-user-callout-deferred-link-support.yml @@ -0,0 +1,5 @@ +--- +title: Add support for deferred links in persistent user callouts. +merge_request: 30818 +author: +type: added diff --git a/changelogs/unreleased/GL-12757.yml b/changelogs/unreleased/GL-12757.yml new file mode 100644 index 00000000000..e58ecf9259f --- /dev/null +++ b/changelogs/unreleased/GL-12757.yml @@ -0,0 +1,5 @@ +--- +title: Update the container scanning CI template to use v12 of the clair scanner. +merge_request: 30809 +author: +type: changed diff --git a/changelogs/unreleased/georgekoltsov-55474-outbound-setting-system-hooks.yml b/changelogs/unreleased/georgekoltsov-55474-outbound-setting-system-hooks.yml new file mode 100644 index 00000000000..fb1acb1e9f5 --- /dev/null +++ b/changelogs/unreleased/georgekoltsov-55474-outbound-setting-system-hooks.yml @@ -0,0 +1,5 @@ +--- +title: Add new outbound network requests application setting for system hooks +merge_request: 31177 +author: +type: added diff --git a/changelogs/unreleased/leipert-improve-ansi2html.yml b/changelogs/unreleased/leipert-improve-ansi2html.yml new file mode 100644 index 00000000000..dd3582b3434 --- /dev/null +++ b/changelogs/unreleased/leipert-improve-ansi2html.yml @@ -0,0 +1,5 @@ +--- +title: Improve job log rendering performance +merge_request: 31262 +author: +type: performance diff --git a/changelogs/unreleased/patch-72.yml b/changelogs/unreleased/patch-72.yml new file mode 100644 index 00000000000..ff2bac2fc29 --- /dev/null +++ b/changelogs/unreleased/patch-72.yml @@ -0,0 +1,5 @@ +--- +title: Fix Docker in Docker (DIND) listen port behavior change by adding DOCKER_TLS_CERTDIR in CI job templates. +merge_request: 31201 +author: Cameron Boulton +type: fixed diff --git a/config/routes/project.rb b/config/routes/project.rb index 1f632765317..3113cb172f7 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -500,6 +500,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do get :realtime_changes post :create_merge_request get :discussions, format: :json + + Gitlab.ee do + get 'designs(/*vueroute)', to: 'issues#show', format: false + end end collection do diff --git a/db/migrate/20190726101050_rename_allow_local_requests_from_hooks_and_services_application_setting.rb b/db/migrate/20190726101050_rename_allow_local_requests_from_hooks_and_services_application_setting.rb new file mode 100644 index 00000000000..ac65e8d745c --- /dev/null +++ b/db/migrate/20190726101050_rename_allow_local_requests_from_hooks_and_services_application_setting.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class RenameAllowLocalRequestsFromHooksAndServicesApplicationSetting < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + rename_column_concurrently :application_settings, :allow_local_requests_from_hooks_and_services, :allow_local_requests_from_web_hooks_and_services + end + + def down + cleanup_concurrent_column_rename :application_settings, :allow_local_requests_from_web_hooks_and_services, :allow_local_requests_from_hooks_and_services + end +end diff --git a/db/migrate/20190726101133_add_allow_local_requests_from_system_hooks_to_application_settings.rb b/db/migrate/20190726101133_add_allow_local_requests_from_system_hooks_to_application_settings.rb new file mode 100644 index 00000000000..95d4f956f93 --- /dev/null +++ b/db/migrate/20190726101133_add_allow_local_requests_from_system_hooks_to_application_settings.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddAllowLocalRequestsFromSystemHooksToApplicationSettings < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + add_column(:application_settings, :allow_local_requests_from_system_hooks, + :boolean, + default: true, + null: false) + end + + def down + remove_column(:application_settings, :allow_local_requests_from_system_hooks) + end +end diff --git a/db/post_migrate/20190801114109_cleanup_allow_local_requests_from_hooks_and_services_application_setting_rename.rb b/db/post_migrate/20190801114109_cleanup_allow_local_requests_from_hooks_and_services_application_setting_rename.rb new file mode 100644 index 00000000000..127e44254ac --- /dev/null +++ b/db/post_migrate/20190801114109_cleanup_allow_local_requests_from_hooks_and_services_application_setting_rename.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class CleanupAllowLocalRequestsFromHooksAndServicesApplicationSettingRename < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_rename :application_settings, :allow_local_requests_from_hooks_and_services, :allow_local_requests_from_web_hooks_and_services + end + + def down + rename_column_concurrently :application_settings, :allow_local_requests_from_web_hooks_and_services, :allow_local_requests_from_hooks_and_services + end +end diff --git a/db/schema.rb b/db/schema.rb index a7781fe4a85..2cd726e2417 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -183,7 +183,6 @@ ActiveRecord::Schema.define(version: 2019_08_05_062636) do t.string "external_authorization_service_default_label" t.boolean "pages_domain_verification_enabled", default: true, null: false t.string "user_default_internal_regex" - t.boolean "allow_local_requests_from_hooks_and_services", default: false, null: false t.float "external_authorization_service_timeout", default: 0.5 t.text "external_auth_client_cert" t.text "encrypted_external_auth_client_key" @@ -230,6 +229,8 @@ ActiveRecord::Schema.define(version: 2019_08_05_062636) do t.string "grafana_url", default: "/-/grafana", null: false t.string "outbound_local_requests_whitelist", limit: 255, default: [], null: false, array: true t.integer "raw_blob_request_limit", default: 300, null: false + t.boolean "allow_local_requests_from_web_hooks_and_services", default: false, null: false + t.boolean "allow_local_requests_from_system_hooks", default: true, null: false t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id" t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id" t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id" diff --git a/doc/administration/geo/replication/updating_the_geo_nodes.md b/doc/administration/geo/replication/updating_the_geo_nodes.md index 550b3b07a95..39174780e24 100644 --- a/doc/administration/geo/replication/updating_the_geo_nodes.md +++ b/doc/administration/geo/replication/updating_the_geo_nodes.md @@ -10,10 +10,23 @@ all you need to do is update GitLab itself: 1. Log into each node (**primary** and **secondary** nodes). 1. [Update GitLab][update]. -1. [Update tracking database on **secondary** node](#update-tracking-database-on-secondary-node) when - the tracking database is enabled. 1. [Test](#check-status-after-updating) **primary** and **secondary** nodes, and check version in each. +### Check status after updating + +Now that the update process is complete, you may want to check whether +everything is working correctly: + +1. Run the Geo raketask on all nodes, everything should be green: + + ```sh + sudo gitlab-rake gitlab:geo:check + ``` + +1. Check the **primary** node's Geo dashboard for any errors. +1. Test the data replication by pushing code to the **primary** node and see if it + is received by **secondary** nodes. + ## Upgrading to GitLab 12.1 By default, GitLab 12.1 will attempt to automatically upgrade the embedded PostgreSQL server to 10.7 from 9.6. Please see [the omnibus documentation](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance) for the recommended procedure. @@ -419,22 +432,7 @@ is prepended with the relevant node for better clarity: sudo gitlab-ctl start ``` -## Check status after updating - -Now that the update process is complete, you may want to check whether -everything is working correctly: - -1. Run the Geo raketask on all nodes, everything should be green: - - ```sh - sudo gitlab-rake gitlab:geo:check - ``` - -1. Check the **primary** node's Geo dashboard for any errors. -1. Test the data replication by pushing code to the **primary** node and see if it - is received by **secondary** nodes. - -## Update tracking database on **secondary** node +### Update tracking database on **secondary** node After updating a **secondary** node, you might need to run migrations on the tracking database. The tracking database was added in GitLab 9.1, diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md index 42516d811a0..56665ba8b9a 100644 --- a/doc/administration/high_availability/README.md +++ b/doc/administration/high_availability/README.md @@ -172,14 +172,16 @@ environment that supports about 10,000 users. The specifications below are a representation of the work so far. The specifications may be adjusted in the future based on additional testing and iteration. -- 3 PostgreSQL - 4 CPU, 8GB RAM per node -- 1 PgBouncer - 2 CPU, 4GB RAM -- 2 Redis - 2 CPU, 8GB RAM per node -- 3 Consul/Sentinel - 2 CPU, 2GB RAM per node -- 4 Sidekiq - 4 CPU, 8GB RAM per node -- 5 GitLab application nodes - 20 CPU, 64GB RAM per node -- 1 Gitaly - 20 CPU, 64GB RAM -- 1 Monitoring node - 4 CPU, 8GB RAM +NOTE: **Note:** The specifications here were performance tested against a specific coded workload. Your exact needs may be more, depending on your workload. Your workload is influenced by factors such as - but not limited to - how active your users are, how much automation you use, mirroring, and repo/change size. + +- 3 PostgreSQL - 4 CPU, 16GiB memory per node +- 1 PgBouncer - 2 CPU, 4GiB memory +- 2 Redis - 2 CPU, 8GiB memory per node +- 3 Consul/Sentinel - 2 CPU, 2GiB memory per node +- 4 Sidekiq - 4 CPU, 16GiB memory per node +- 5 GitLab application nodes - 16 CPU, 64GiB memory per node +- 1 Gitaly - 16 CPU, 64GiB memory +- 1 Monitoring node - 2 CPU, 8GiB memory, 100GiB local storage ### Fully Distributed diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md index ea69378b249..e787af798bc 100644 --- a/doc/administration/operations/fast_ssh_key_lookup.md +++ b/doc/administration/operations/fast_ssh_key_lookup.md @@ -71,10 +71,10 @@ sudo service sshd reload Confirm that SSH is working by removing your user's SSH key in the UI, adding a new one, and attempting to pull a repo. -> **Note:** For Omnibus Docker, `AuthorizedKeysCommand` is setup by default in +NOTE: **Note:** For Omnibus Docker, `AuthorizedKeysCommand` is setup by default in GitLab 11.11 and later. -> **Warning:** Do not disable writes until SSH is confirmed to be working +CAUTION: **Caution:** Do not disable writes until SSH is confirmed to be working perfectly, because the file will quickly become out-of-date. In the case of lookup failures (which are common), the `authorized_keys` diff --git a/doc/api/services.md b/doc/api/services.md index df15e6892b0..45b49d7eb92 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -972,22 +972,28 @@ Parameters: | `channel` | string | false | Default channel to use if others are not configured | | `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines | | `notify_only_default_branch` | boolean | false | Send notifications only for the default branch | -| `push_events` | boolean | false | Enable notifications for push events | -| `issues_events` | boolean | false | Enable notifications for issue events | +| `commit_events` | boolean | false | Enable notifications for commit events | +| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | +| `confidential_note_channel` | string | false | The name of the channel to receive confidential note events notifications | +| `confidential_note_events` | boolean | false | Enable notifications for confidential note events | +| `deployment_channel` | string | false | The name of the channel to receive deployment events notifications | +| `deployment_events` | boolean | false | Enable notifications for deployment events | +| `issue_channel` | string | false | The name of the channel to receive issues events notifications | +| `issues_events` | boolean | false | Enable notifications for issue events | +| `job_events` | boolean | false | Enable notifications for job events | +| `merge_request_channel` | string | false | The name of the channel to receive merge request events notifications | | `merge_requests_events` | boolean | false | Enable notifications for merge request events | -| `tag_push_events` | boolean | false | Enable notifications for tag push events | +| `note_channel` | string | false | The name of the channel to receive note events notifications | | `note_events` | boolean | false | Enable notifications for note events | +| `pipeline_channel` | string | false | The name of the channel to receive pipeline events notifications | | `pipeline_events` | boolean | false | Enable notifications for pipeline events | -| `wiki_page_events` | boolean | false | Enable notifications for wiki page events | | `push_channel` | string | false | The name of the channel to receive push events notifications | -| `issue_channel` | string | false | The name of the channel to receive issues events notifications | -| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications | -| `merge_request_channel` | string | false | The name of the channel to receive merge request events notifications | -| `note_channel` | string | false | The name of the channel to receive note events notifications | +| `push_events` | boolean | false | Enable notifications for push events | | `tag_push_channel` | string | false | The name of the channel to receive tag push events notifications | -| `pipeline_channel` | string | false | The name of the channel to receive pipeline events notifications | +| `tag_push_events` | boolean | false | Enable notifications for tag push events | | `wiki_page_channel` | string | false | The name of the channel to receive wiki page events notifications | +| `wiki_page_events` | boolean | false | Enable notifications for wiki page events | ### Delete Slack service diff --git a/doc/api/settings.md b/doc/api/settings.md index c3ac70f0579..83125aff264 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -64,7 +64,10 @@ Example response: "performance_bar_allowed_group_id": 42, "instance_statistics_visibility_private": false, "user_show_add_ssh_key_message": true, - "local_markdown_version": 0 + "local_markdown_version": 0, + "allow_local_requests_from_hooks_and_services": true, + "allow_local_requests_from_web_hooks_and_services": true, + "allow_local_requests_from_system_hooks": false } ``` @@ -138,7 +141,10 @@ Example response: "user_show_add_ssh_key_message": true, "file_template_project_id": 1, "local_markdown_version": 0, - "geo_node_allowed_ips": "0.0.0.0/0, ::/0" + "geo_node_allowed_ips": "0.0.0.0/0, ::/0", + "allow_local_requests_from_hooks_and_services": true, + "allow_local_requests_from_web_hooks_and_services": true, + "allow_local_requests_from_system_hooks": false } ``` @@ -177,7 +183,9 @@ are listed in the descriptions of the relevant settings. | `akismet_api_key` | string | required by: `akismet_enabled` | API key for akismet spam protection. | | `akismet_enabled` | boolean | no | (**If enabled, requires:** `akismet_api_key`) Enable or disable akismet spam protection. | | `allow_group_owners_to_manage_ldap` | boolean | no | **(PREMIUM)** Set to `true` to allow group owners to manage LDAP | -| `allow_local_requests_from_hooks_and_services` | boolean | no | Allow requests to the local network from hooks and services. | +| `allow_local_requests_from_hooks_and_services` | boolean | no | (Deprecated: Use `allow_local_requests_from_web_hooks_and_services` instead) Allow requests to the local network from hooks and services. | +| `allow_local_requests_from_web_hooks_and_services` | boolean | no | Allow requests to the local network from web hooks and services. | +| `allow_local_requests_from_system_hooks` | boolean | no | Allow requests to the local network from system hooks. | | `authorized_keys_enabled` | boolean | no | By default, we write to the `authorized_keys` file to support Git over SSH without additional configuration. GitLab can be optimized to authenticate SSH keys via the database file. Only disable this if you have configured your OpenSSH server to use the AuthorizedKeysCommand. | | `auto_devops_domain` | string | no | Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages. | | `auto_devops_enabled` | boolean | no | Enable Auto DevOps for projects by default. It will automatically build, test, and deploy applications based on a predefined CI/CD configuration. | diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index c48817a5e30..c63b1e104ed 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -371,8 +371,8 @@ variables take precedence over those defined in `.gitlab-ci.yml`. There are cases where some variables cannot be used in the context of a `.gitlab-ci.yml` definition (for example under `script`). Read more about which variables are [not supported](where_variables_can_be_used.md). - -## Where variables can be used + +## Where variables can be used Click [here](where_variables_can_be_used.md) for a section that describes where and how the different types of variables can be used. @@ -484,81 +484,86 @@ Below you can find supported syntax reference: 1. Equality matching using a string - > Example: `$VARIABLE == "some value"` + Examples: - > Example: `$VARIABLE != "some value"` (introduced in GitLab 11.11) + - `$VARIABLE == "some value"` + - `$VARIABLE != "some value"` (introduced in GitLab 11.11) - You can use equality operator `==` or `!=` to compare a variable content to a - string. We support both, double quotes and single quotes to define a string - value, so both `$VARIABLE == "some value"` and `$VARIABLE == 'some value'` - are supported. `"some value" == $VARIABLE` is correct too. + You can use equality operator `==` or `!=` to compare a variable content to a + string. We support both, double quotes and single quotes to define a string + value, so both `$VARIABLE == "some value"` and `$VARIABLE == 'some value'` + are supported. `"some value" == $VARIABLE` is correct too. 1. Checking for an undefined value - > Example: `$VARIABLE == null` + Examples: - > Example: `$VARIABLE != null` (introduced in GitLab 11.11) + - `$VARIABLE == null` + - `$VARIABLE != null` (introduced in GitLab 11.11) - It sometimes happens that you want to check whether a variable is defined - or not. To do that, you can compare a variable to `null` keyword, like - `$VARIABLE == null`. This expression is going to evaluate to truth if - variable is not defined when `==` is used, or to falsey if `!=` is used. + It sometimes happens that you want to check whether a variable is defined + or not. To do that, you can compare a variable to `null` keyword, like + `$VARIABLE == null`. This expression is going to evaluate to truth if + variable is not defined when `==` is used, or to falsey if `!=` is used. 1. Checking for an empty variable - > Example: `$VARIABLE == ""` - - > Example: `$VARIABLE != ""` (introduced in GitLab 11.11) + Examples: + + - `$VARIABLE == ""` + - `$VARIABLE != ""` (introduced in GitLab 11.11) - If you want to check whether a variable is defined, but is empty, you can - simply compare it against an empty string, like `$VAR == ''` or non-empty - string `$VARIABLE != ""`. + If you want to check whether a variable is defined, but is empty, you can + simply compare it against an empty string, like `$VAR == ''` or non-empty + string `$VARIABLE != ""`. 1. Comparing two variables - > Example: `$VARIABLE_1 == $VARIABLE_2` + Examples: - > Example: `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11) + - `$VARIABLE_1 == $VARIABLE_2` + - `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11) - It is possible to compare two variables. This is going to compare values - of these variables. + It is possible to compare two variables. This is going to compare values + of these variables. 1. Variable presence check - > Example: `$STAGING` + Example: `$STAGING` - If you only want to create a job when there is some variable present, - which means that it is defined and non-empty, you can simply use - variable name as an expression, like `$STAGING`. If `$STAGING` variable - is defined, and is non empty, expression will evaluate to truth. - `$STAGING` value needs to a string, with length higher than zero. - Variable that contains only whitespace characters is not an empty variable. + If you only want to create a job when there is some variable present, + which means that it is defined and non-empty, you can simply use + variable name as an expression, like `$STAGING`. If `$STAGING` variable + is defined, and is non empty, expression will evaluate to truth. + `$STAGING` value needs to a string, with length higher than zero. + Variable that contains only whitespace characters is not an empty variable. 1. Pattern matching (introduced in GitLab 11.0) - > Example: `$VARIABLE =~ /^content.*/` + Examples: - > Example: `$VARIABLE_1 !~ /^content.*/` (introduced in GitLab 11.11) + - `$VARIABLE =~ /^content.*/` + - `$VARIABLE_1 !~ /^content.*/` (introduced in GitLab 11.11) - It is possible perform pattern matching against a variable and regular - expression. Expression like this evaluates to truth if matches are found - when using `=~`. It evaluates to truth if matches are not found when `!~` is used. + It is possible perform pattern matching against a variable and regular + expression. Expression like this evaluates to truth if matches are found + when using `=~`. It evaluates to truth if matches are not found when `!~` is used. - Pattern matching is case-sensitive by default. Use `i` flag modifier, like - `/pattern/i` to make a pattern case-insensitive. + Pattern matching is case-sensitive by default. Use `i` flag modifier, like + `/pattern/i` to make a pattern case-insensitive. 1. Conjunction / Disjunction ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27925) in GitLab 12.0) - > Example: `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` - - > Example: `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3` + Examples: - > Example: `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3` + - `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` + - `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3` + - `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3` - It is possible to join multiple conditions using `&&` or `||`. Any of the otherwise - supported syntax may be used in a conjunctive or disjunctive statement. - Precedence of operators follows standard Ruby 2.5 operation - [precedence](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html). + It is possible to join multiple conditions using `&&` or `||`. Any of the otherwise + supported syntax may be used in a conjunctive or disjunctive statement. + Precedence of operators follows standard Ruby 2.5 operation + [precedence](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html). ## Debug tracing diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md index 79c701d7abf..39f12e6886e 100644 --- a/doc/development/contributing/issue_workflow.md +++ b/doc/development/contributing/issue_workflow.md @@ -92,9 +92,6 @@ The following team labels are **true** teams per our [organization structure](ht The descriptions on the [labels page](https://gitlab.com/gitlab-org/gitlab-ce/-/labels) explain what falls under the responsibility of each team. -Within those team labels, we also have the ~backend and ~frontend labels to -indicate if an issue needs backend work, frontend work, or both. - Team labels are always capitalized so that they show up as the first label for any issue. @@ -107,15 +104,6 @@ The current stage labels can be found by [searching the labels list for `devops: These labels are [scoped labels](../../user/project/labels.md#scoped-labels-premium) and thus are mutually exclusive. -They differ from the [Team labels](#team-labels) because teams may work on -issues outside their stage. - -Normally there is a 1:1 relationship between Stage labels and Team labels, but -any issue can be picked up by any team, depending on current priorities. -So, an issue labeled ~"devops:create" may be scheduled by the ~Plan team, for -example. In such cases, it's usual to include both team labels so each team can -be aware of the progress. - The Stage labels are used to generate the [direction pages][direction-pages] automatically. [devops-stages]: https://about.gitlab.com/direction/#devops-stages @@ -130,9 +118,16 @@ The current group labels can be found by [searching the labels list for `group:: These labels are [scoped labels](../../user/project/labels.md#scoped-labels-premium) and thus are mutually exclusive. -Groups are nested beneath a particular stage, so only one stage label and one group label -can be applied to a single issue. You can find the groups listed in the -[Product Categories pages][product-categories]. +You can find the groups listed in the [Product Stages, Groups, and Categories][product-categories] page. + +We use the term group to map down product requirements from our product stages. +As a team needs some way to collect the work their members are planning to be assigned to, we use the `~group::` labels to do so. + +Normally there is a 1:1 relationship between Stage labels and Group labels. In the spirit of "Everyone can contribute", +any issue can be picked up by any group, depending on current priorities. For example, an issue labeled ~"devops::create" may be picked up by the ~"group::access" group. + +We also use stage and group labels to help quantify our [throughput](https://about.gitlab.com/handbook/engineering/management/throughput). +Please read [Stage and Group labels in Throughtput](https://about.gitlab.com/handbook/engineering/management/throughput/#stage-and-group-labels-in-throughput) for more information on how the labels are used in this context. [structure-groups]: https://about.gitlab.com/company/team/structure/#groups [product-categories]: https://about.gitlab.com/handbook/product/categories/ diff --git a/doc/development/testing_guide/end_to_end/quick_start_guide.md b/doc/development/testing_guide/end_to_end/quick_start_guide.md index 14a169dcc1d..e1df8be8b6f 100644 --- a/doc/development/testing_guide/end_to_end/quick_start_guide.md +++ b/doc/development/testing_guide/end_to_end/quick_start_guide.md @@ -110,7 +110,7 @@ end ``` > Notice that the test itself is simple. The most challenging part is the creation of the application state, which will be covered later. - +> > The exemplified test case's MVC is not enough for the change to be merged, but it helps to build up the test logic. The reason is that we do not want to use locators directly in the tests, and tests **must** use [Page Objects] before they can be merged. This way we better separate the responsibilities, where the Page Objects encapsulate elements and methods that allow us to interact with pages, while the spec files describe the test cases in more business-related language. Below are the steps that the test covers: @@ -211,7 +211,7 @@ A pre-condition for the entire test suite is defined in the `before :context` bl > For our test suite, due to the need of the tests being completely independent of each other, we won't use the `before :context` block. The `before :context` block would make the tests dependent on each other because the first test changes the label of the issue, and the second one depends on the `'animal::fox'` label being set. -> **Tip:** In case of a test suite with only one `it` block it's ok to use only the `before` block (see below) with all the test's pre-conditions. +TIP: **Tip:** In case of a test suite with only one `it` block it's ok to use only the `before` block (see below) with all the test's pre-conditions. #### `before` @@ -274,11 +274,11 @@ end In the `before` block we create all the application state needed for the tests to run. We do that by using the `Runtime::Browser.visit` method to go to the login page, by performing a `sign_in_using_credentials` from the `Login` Page Object, by fabricating resources via APIs (`issue`, and `Resource::Label`), and by using the `issue.visit!` to visit the issue page. > A project is created in the background by creating the `issue` resource. - +> > When creating the [Resources], notice that when calling the `fabricate_via_api` method, we pass some attribute:values, like `title`, and `labels` for the `issue` resource; and `project` and `title` for the `label` resource. - +> > What's important to understand here is that by creating the application state mostly using the public APIs we save a lot of time in the test suite setup stage. - +> > Soon we will cover the use of the already existing resources' methods and the creation of your own `fabricate_via_api` methods for resources where this is still not available, but first, let's optimize our implementation. ### 6. Optimization @@ -362,7 +362,7 @@ First, in the [issue resource](https://gitlab.com/gitlab-org/gitlab-ee/blob/d358 Add the following `attribute :id` and `attribute :labels` right above the [`attribute :title`](https://gitlab.com/gitlab-org/gitlab-ee/blob/d3584e80b4236acdf393d815d604801573af72cc/qa/qa/resource/issue.rb#L15). > This line is needed to allow for the issue fabrication, and for labels to be automatically added to the issue when fabricating it via API. - +> > We add the attributes above the existing attribute to keep them alphabetically organized. Then, let's initialize an instance variable for labels to allow an empty array as default value when such information is not passed during the resource fabrication, since this optional. [Between the attributes and the `fabricate!` method](https://gitlab.com/gitlab-org/gitlab-ee/blob/1a1f1408728f19b2aa15887cd20bddab7e70c8bd/qa/qa/resource/issue.rb#L18), add the following: @@ -437,7 +437,7 @@ By defining the `resource_web_url(resource)` method, we override the one from th By defining the `api_get_path` method, we **would** allow for the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to get a single label, but since there's no path available for that in the publich API, we raise a `NotImplementedError` instead. -By defining the `api_post_path` method, we allow for the [`ApiFabricator `](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to create a new label in a specific project. +By defining the `api_post_path` method, we allow for the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to create a new label in a specific project. By defining the `api_post_body` method, we we allow for the [`ApiFabricator.api_post`](https://gitlab.com/gitlab-org/gitlab-ee/blob/a9177ca1812bac57e2b2fa4560e1d5dd8ffac38b/qa/qa/resource/api_fabricator.rb#L68) method to know which data to send when making the `POST` request. @@ -580,7 +580,7 @@ filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", > `data-qa-*` data attributes and CSS classes starting with `qa-` are used solely for the purpose of QA and testing. > By defining these, we add **testability** to the application. - +> > When defining a data attribute like: `qa_selector: 'labels_block'`, it should match the element definition: `element :labels_block`. We use a [sanity test](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page#how-did-we-solve-fragile-tests-problem) to check that defined elements have their respective selectors in the specified views. #### Updates in the `QA::Page::Base` class @@ -599,8 +599,6 @@ This method receives an element (`name`) and the `keys` that it will send to tha As you might remember, in the Issue Page Object we call this method like this: `send_keys_to_element(:dropdown_input_field, [label, :enter])`. -___ - With that, you should be able to start writing end-to-end tests yourself. *Congratulations!* [Page Objects]: page_objects.md diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md index 24edd05da2f..f0da1cc2ddc 100644 --- a/doc/development/what_requires_downtime.md +++ b/doc/development/what_requires_downtime.md @@ -140,7 +140,7 @@ done without requiring downtime. However, this does require that any application changes are deployed _first_. Thus, changing the constraints of a column should happen in a post-deployment migration. NOTE: Avoid using `change_column` as it produces inefficient query because it re-defines -the whole column type. For example, to add a NOT NULL constraint, prefer `change_column_null ` +the whole column type. For example, to add a NOT NULL constraint, prefer `change_column_null` ## Changing Column Types diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 25ab608de3a..ed5b23a122f 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -62,17 +62,19 @@ NOTE: **Note:** Since file system performance may affect GitLab's overall perfor ### CPU +This is the recommended minimum hardware for a handful of example GitLab user base sizes. Your exact needs may be more, depending on your workload. Your workload is influenced by factors such as - but not limited to - how active your users are, how much automation you use, mirroring, and repo/change size. + - 1 core supports up to 100 users but the application can be a bit slower due to having all workers and background jobs running on the same core -- **2 cores** is the **recommended** number of cores and supports up to 500 users -- 4 cores supports up to 2,000 users -- 8 cores supports up to 5,000 users -- 16 cores supports up to 10,000 users -- 32 cores supports up to 20,000 users -- 64 cores supports up to 40,000 users -- More users? Run it on [multiple application servers](https://about.gitlab.com/high-availability/) +- **2 cores** is the **recommended** minimum number of cores and supports up to 100 users +- 4 cores supports up to 500 users +- 8 cores supports up to 1,000 users +- 32 cores supports up to 5,000 users +- More users? Run it high-availability on [multiple application servers](https://about.gitlab.com/high-availability/) ### Memory +This is the recommended minimum hardware for a handful of example GitLab user base sizes. Your exact needs may be more, depending on your workload. Your workload is influenced by factors such as - but not limited to - how active your users are, how much automation you use, mirroring, and repo/change size. + You need at least 8GB of addressable memory (RAM + swap) to install and use GitLab! The operating system and any other running applications will also be using memory so keep in mind that you need at least 4GB available before running GitLab. With @@ -80,13 +82,11 @@ less memory GitLab will give strange errors during the reconfigure run and 500 errors during usage. - 4GB RAM + 4GB swap supports up to 100 users but it will be very slow -- **8GB RAM** is the **recommended** memory size for all installations and supports up to 100 users -- 16GB RAM supports up to 2,000 users -- 32GB RAM supports up to 4,000 users -- 64GB RAM supports up to 8,000 users -- 128GB RAM supports up to 16,000 users -- 256GB RAM supports up to 32,000 users -- More users? Run it on [multiple application servers](https://about.gitlab.com/high-availability/) +- **8GB RAM** is the **recommended** minimum memory size for all installations and supports up to 100 users +- 16GB RAM supports up to 500 users +- 32GB RAM supports up to 1,000 users +- 128GB RAM supports up to 5,000 users +- More users? Run it high-availability on [multiple application servers](https://about.gitlab.com/high-availability/) We recommend having at least [2GB of swap on your server](https://askubuntu.com/a/505344/310789), even if you currently have enough available RAM. Having swap will help reduce the chance of errors occurring diff --git a/doc/security/img/outbound_requests_section.png b/doc/security/img/outbound_requests_section.png Binary files differdeleted file mode 100644 index f7783f34cdd..00000000000 --- a/doc/security/img/outbound_requests_section.png +++ /dev/null diff --git a/doc/security/img/outbound_requests_section_v12_2.png b/doc/security/img/outbound_requests_section_v12_2.png Binary files differnew file mode 100644 index 00000000000..4fd3c7d9fce --- /dev/null +++ b/doc/security/img/outbound_requests_section_v12_2.png diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md index 1194234a295..7ece9407ac0 100644 --- a/doc/security/webhooks.md +++ b/doc/security/webhooks.md @@ -34,15 +34,16 @@ to 127.0.0.1, ::1 and 0.0.0.0, as well as IPv4 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 and IPv6 site-local (ffc0::/10) addresses won't be allowed. This behavior can be overridden by enabling the option *"Allow requests to the -local network from hooks and services"* in the *"Outbound requests"* section +local network from web hooks and services"* in the *"Outbound requests"* section inside the Admin area under **Settings** (`/admin/application_settings/network`): -![Outbound requests admin settings](img/outbound_requests_section.png) +![Outbound requests admin settings](img/outbound_requests_section_v12_2.png) ->**Note:** -*System hooks* are exempt from this protection because they are set up by -admins. +NOTE: **Note:** +*System hooks* are enabled to make requests to local network by default since they are +set up by administrators. However, you can turn this off by disabling the +**Allow requests to the local network from system hooks** option. <!-- ## Troubleshooting diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md index cdcd8215b23..5b227ebebe0 100644 --- a/doc/topics/git/index.md +++ b/doc/topics/git/index.md @@ -48,6 +48,7 @@ The following are resources about version control concepts: The following resources may help you become more efficient at using Git: +- [Useful Git commands](useful_git_commands.md) collected by the GitLab support team. - [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/) - [Eight Tips to help you work better with Git](https://about.gitlab.com/2015/02/19/8-tips-to-help-you-work-better-with-git/) @@ -82,6 +83,8 @@ Git-related queries from GitLab. The following relate to Git Large File Storage: - [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/) -- [GitLab Git LFS documentation](../../workflow/lfs/manage_large_binaries_with_git_lfs.md) +- [Migrate an existing Git repo with Git LFS](migrate_to_git_lfs/index.md) +- [GitLab Git LFS user documentation](../../workflow/lfs/manage_large_binaries_with_git_lfs.md) +- [GitLab Git LFS admin documentation](../../workflow/lfs/lfs_administration.md) - [Git-Annex to Git-LFS migration guide](../../workflow/lfs/migrate_from_git_annex_to_git_lfs.md) - [Towards a production quality open source Git LFS server](https://about.gitlab.com/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/) diff --git a/doc/topics/git/migrate_to_git_lfs/index.md b/doc/topics/git/migrate_to_git_lfs/index.md new file mode 100644 index 00000000000..c879e404997 --- /dev/null +++ b/doc/topics/git/migrate_to_git_lfs/index.md @@ -0,0 +1,174 @@ +--- +type: tutorial, concepts +description: "How to migrate an existing Git repository to Git LFS with BFG." +last_updated: 2019-07-11 +--- + +# Migrate a Git repo into Git LFS with BFG + +Using Git LFS can help you to reduce the size of your Git +repository and improve its performance. + +However, simply adding the +large files that are already in your repository to Git LFS, +will not actually reduce the size of your repository because +the files are still referenced by previous commits. + +Through the method described on this document, first migrate +to Git LFS with [BFG](https://rtyley.github.io/bfg-repo-cleaner/) +through a mirror repo, then clean up the repository's history, +and lastly create LFS tracking rules to prevent new binary files +from being added. + +This tutorial was inspired by the guide +[Use BFG to migrate a repo to Git LFS](https://confluence.atlassian.com/bitbucket/use-bfg-to-migrate-a-repo-to-git-lfs-834233484.html). +For more information on Git LFS, see the [references](#references) +below. + +CAUTION: **Warning:** +The method described on this guide rewrites Git history. Make +sure to back up your repo before beginning and use it at your +own risk. + +## Requirements + +Before beginning, make sure: + +- You have enough LFS storage for the files you want to convert. + Storage is required for the entire history of all files. +- All the team members you share the repository with have pushed all changes. + Branches based on the repository before applying this method cannot be merged. + Branches based on the repo before applying this method cannot be merged. + +To follow this tutorial, you'll need: + +- Maintainer permissions to the existing Git repository + you'd like to migrate to LFS with access through the command line. +- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) + and [Java Runtime Environment](https://www.java.com/en/download/manual.jsp) + (Java 7 or above) installed locally. +- BFG installed locally: + + ```bash + brew install bfg + ``` + +- Git LFS installed locally: + + ```bash + brew install git-lfs + ``` + +NOTE: **Note:** +This guide was tested on macOS Mojave. + +## Steps + +Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs-repo-migration.git`. + +1. Back up your repository: + + Create a copy of your repository so that you can + recover it in case something goes wrong. + +1. Clone `--mirror` the repo: + + Cloning with the mirror flag will create a bare repository. + This ensures you get all the branches within the repo. + + It creates a directory called `<repo-name>.git` + (in our example, `test-git-lfs-repo-migration.git`), + mirroring the upstream project: + + ```bash + git clone --mirror git@gitlab.com:gitlab-tests/test-git-lfs-repo-migration.git + ``` + +1. Convert the Git history with BFG: + + ```bash + bfg --convert-to-git-lfs "*.{png,mp4,jpg,gif}" --no-blob-protection test-git-lfs-repo-migration.git + ``` + + It is scanning all the history, and looking for any files with + that extension, and then converting them to an LFS pointer. + +1. Clean up the repository: + + ```bash + # cd path/to/mirror/repo: + cd test-git-lfs-repo-migration.git + # clean up the repo: + git reflog expire --expire=now --all && git gc --prune=now --aggressive + ``` + + You can also take a look on how to further [clean the repo](../../../user/project/repository/reducing_the_repo_size_using_git.md), + but it's not necessary for the purposes of this guide. + +1. Install Git LFS in the mirror repository: + + ```bash + git lfs install + ``` + +1. [Unprotect the default branch](../../../user/project/protected_branches.md), + so that we can force-push the rewritten repository: + + 1. Navigate to your project's **Settings > Repository** and + expand **Protected Branches**. + 1. Scroll down to locate the protected branches and click + **Unprotect** the default branch. + +1. Force-push to GitLab: + + ```bash + git push --force + ``` + +1. Track the files you want with LFS: + + ```bash + # cd path/to/upstream/repo: + cd test-git-lfs-repo-migration + # You may need to reset your local copy with upstream's `master` after force-pushing from the mirror: + git reset --hard origin/master + # Track the files with LFS: + git lfs track "*.gif" "*.png" "*.jpg" "*.psd" "*.mp4" ".gitattributes" "img/" + ``` + + Now all existing the files you converted, as well as the new + ones you add, will be properly tracked with LFS. + +1. [Re-protect the default branch](../../../user/project/protected_branches.md): + + 1. Navigate to your project's **Settings > Repository** and + expand **Protected Branches**. + 1. Select the default branch from the **Branch** dropdown menu, + and set up the + **Allowed to push** and **Allowed to merge** rules. + 1. Click **Protect**. + +<!-- ## Troubleshooting + +Include any troubleshooting steps that you can foresee. If you know beforehand what issues +one might have when setting this up, or when something is changed, or on upgrading, it's +important to describe those, too. Think of things that may go wrong and include them here. +This is important to minimize requests for support, and to avoid doc comments with +questions that you know someone might ask. + +Each scenario can be a third-level heading, e.g. `### Getting error message X`. +If you have none to add when creating a doc, leave this section in place +but commented out to help encourage others to add to it in the future. --> + +## References + +- [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/) +- [Migrate from Git Annex to Git LFS](../../../workflow/lfs/migrate_from_git_annex_to_git_lfs.md) +- [GitLab's Git LFS user documentation](../../../workflow/lfs/manage_large_binaries_with_git_lfs.md) +- [GitLab's Git LFS administrator documentation](../../../workflow/lfs/lfs_administration.md) +- Alternative method to [migrate an existing repo to Git LFS](https://github.com/git-lfs/git-lfs/wiki/Tutorial#migrating-existing-repository-data-to-lfs) + +<!-- +Test project: +https://gitlab.com/gitlab-tests/test-git-lfs-repo-migration +--> diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md new file mode 100644 index 00000000000..84406805350 --- /dev/null +++ b/doc/topics/git/useful_git_commands.md @@ -0,0 +1,210 @@ +--- +type: reference +--- + +# Useful Git commands + +Here are some useful Git commands collected by the GitLab support team. You may not +need to use often, but they can can come in handy when needed. + +## Remotes + +### Add another URL to a remote, so both remotes get updated on each push + +```sh +git remote set-url --add <remote_name> <remote_url> +``` + +## Staging and reverting changes + +### Remove last commit and leave the changes in unstaged + +```sh +git reset --soft HEAD^ +``` + +### Unstage a certain number of commits from HEAD + +To unstage 3 commits, for example, run: + +```sh +git reset HEAD^3 +``` + +### Unstage changes to a certain file from HEAD + +```sh +git reset <filename> +``` + +### Revert a file to HEAD state and remove changes + +There are two options to revert changes to a file: + +- `git checkout <filename>` +- `git reset --hard <filename>` + +### Undo a previous commit by creating a new replacement commit + +```sh +git revert <commit-sha> +``` + +### Create a new message for last commit + +```sh +git commit --amend +``` + +### Add a file to the last commit + +```sh +git add <filename> +git commit --amend +``` + +Append `--no-edit` to the `commit` command if you do not want to edit the commit +message. + +## Stashing + +### Stash changes + +```sh +git stash save +``` + +The default behavor of `stash` is to save, so you can also use just: + +```sh +git stash +``` + +### Unstash your changes + +```sh +git stash apply +``` + +### Discard your stashed changes + +```sh +git stash drop +``` + +### Apply and drop your stashed changes + +```sh +git stash pop +``` + +## Refs and Log + +### Use reflog to show the log of reference changes to HEAD + +```sh +git reflog +``` + +### Check the Git history of a file + +The basic command to check the git history of a file: + +```sh +git log <file> +``` + +If you get this error message: + +```text +fatal: ambiguous argument <file_name>: unknown revision or path not in the working tree. +Use '--' to separate paths from revisions, like this: +``` + +Use this to check the Git history of the file: + +```sh +git log -- <file> +``` + +### Find the tags that contain a particular SHA + +```sh +git tag --contains <sha> +``` + +### Check the content of each change to a file + +```sh +gitk <file> +``` + +### Check the content of each change to a file, follows it past file renames + +```sh +gitk --follow <file> +``` + +## Debugging + +### Use a custom SSH key for a git command + +```text +GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlabadmin" git <command> +``` + +### Debug cloning + +With SSH: + +```text +GIT_SSH_COMMAND="ssh -vvv" git clone <git@url> +``` + +With HTTPS: + +```text +GIT_TRACE_PACKET=1 GIT_TRACE=2 GIT_CURL_VERBOSE=1 git clone <url> +``` + +## Rebasing + +### Rebase your branch onto master + +The -i flag stands for 'interactive': + +```sh +git rebase -i master +``` + +### Continue the rebase if paused + +```sh +git rebase --continue +``` + +### Use git rerere + +To _reuse_ recorded solutions to the same problems when repeated: + +```sh +git rerere +``` + +To enable `rerere` functionality: + +```sh +git config --global rerere.enabled true +``` + +<!-- ## Troubleshooting + +Include any troubleshooting steps that you can foresee. If you know beforehand what issues +one might have when setting this up, or when something is changed, or on upgrading, it's +important to describe those, too. Think of things that may go wrong and include them here. +This is important to minimize requests for support, and to avoid doc comments with +questions that you know someone might ask. + +Each scenario can be a third-level heading, e.g. `### Getting error message X`. +If you have none to add when creating a doc, leave this section in place +but commented out to help encourage others to add to it in the future. --> diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md index 59835aeba01..cb533538047 100644 --- a/doc/user/application_security/sast/analyzers.md +++ b/doc/user/application_security/sast/analyzers.md @@ -29,6 +29,7 @@ SAST supports the following official analyzers: - [Security Code Scan (.NET)](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) - [TSLint (Typescript)](https://gitlab.com/gitlab-org/security-products/analyzers/tslint) - [Sobelow (Elixir Phoenix)](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow) +- [PMD (Apex only)](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex) The analyzers are published as Docker images that SAST will use to launch dedicated containers for each analysis. @@ -116,24 +117,24 @@ custom analyzer can scan the source code. ## Analyzers Data -| Property \ Tool | Bandit | Brakeman | ESLint security | Find Sec Bugs | Flawfinder | Go AST Scanner | NodeJsScan | Php CS Security Audit | Security code Scan (.NET) | TSLint Security | Sobelow | -| --------------------------------------- | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :---------------------: | :-------------------------: | :-------------: | :----------------: | -| Severity | ✓ | 𐄂 | 𐄂 | ✓ | 𐄂 | ✓ | 𐄂 | ✓ | 𐄂 | ✓ | 𐄂 | -| Title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Description | 𐄂 | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | ✓ | 𐄂 | 𐄂 | ✓ | ✓ | -| File | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Start line | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| End line | ✓ | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | 𐄂 | -| Start column | 𐄂 | 𐄂 | ✓ | ✓ | ✓ | ✓ | 𐄂 | ✓ | ✓ | ✓ | 𐄂 | -| End column | 𐄂 | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | 𐄂 | -| External id (e.g. CVE) | 𐄂 | ⚠ | 𐄂 | ⚠ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | -| URLs | 𐄂 | ✓ | 𐄂 | ⚠ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | -| Internal doc/explanation | ⚠ | ✓ | 𐄂 | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | -| Solution | 𐄂 | 𐄂 | 𐄂 | ⚠ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | -| Confidence | ✓ | ✓ | 𐄂 | ✓ | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | -| Affected item (e.g. class or package) | 𐄂 | ✓ | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | -| Source code extract | ✓ | ✓ | ✓ | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | -| Internal ID | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 𐄂 | ✓ | ✓ | ✓ | ✓ | +| Property \ Tool | Apex | Bandit | Brakeman | ESLint security | Find Sec Bugs | Flawfinder | Go AST Scanner | NodeJsScan | Php CS Security Audit | Security code Scan (.NET) | TSLint Security | Sobelow | +| --------------------------------------- | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :---------------------: | :-------------------------: | :-------------: | :----------------: | +| Severity | ✓ | ✓ | 𐄂 | 𐄂 | ✓ | 𐄂 | ✓ | 𐄂 | ✓ | 𐄂 | ✓ | 𐄂 | +| Title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Description | ✓ | 𐄂 | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | ✓ | 𐄂 | 𐄂 | ✓ | ✓ | +| File | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Start line | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| End line | ✓ | ✓ | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | 𐄂 | +| Start column | ✓ | 𐄂 | 𐄂 | ✓ | ✓ | ✓ | ✓ | 𐄂 | ✓ | ✓ | ✓ | 𐄂 | +| End column | ✓ | 𐄂 | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | 𐄂 | +| External id (e.g. CVE) | 𐄂 | 𐄂 | ⚠ | 𐄂 | ⚠ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | +| URLs | ✓ | 𐄂 | ✓ | 𐄂 | ⚠ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | +| Internal doc/explanation | ✓ | ⚠ | ✓ | 𐄂 | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | +| Solution | ✓ | 𐄂 | 𐄂 | 𐄂 | ⚠ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | +| Confidence | 𐄂 | ✓ | ✓ | 𐄂 | ✓ | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | ✓ | +| Affected item (e.g. class or package) | ✓ | 𐄂 | ✓ | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | +| Source code extract | 𐄂 | ✓ | ✓ | ✓ | 𐄂 | ✓ | ✓ | 𐄂 | 𐄂 | 𐄂 | 𐄂 | 𐄂 | +| Internal ID | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 𐄂 | ✓ | ✓ | ✓ | ✓ | - ✓ => we have that data - ⚠ => we have that data but it's partially reliable, or we need to extract it from unstructured content diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md index aac881112ff..5149f628345 100644 --- a/doc/user/application_security/sast/index.md +++ b/doc/user/application_security/sast/index.md @@ -59,6 +59,7 @@ The following table shows which languages, package managers and frameworks are s |-----------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------| | .NET | [Security Code Scan](https://security-code-scan.github.io) | 11.0 | | Any | [Gitleaks](https://github.com/zricethezav/gitleaks) and [TruffleHog](https://github.com/dxa4481/truffleHog) | 11.9 | +| Apex (Salesforce) | [pmd](https://pmd.github.io/pmd/index.html) | 12.1 | | C/C++ | [Flawfinder](https://www.dwheeler.com/flawfinder/) | 10.7 | | Elixir (Phoenix) | [Sobelow](https://github.com/nccgroup/sobelow) | 11.10 | | Go | [Gosec](https://github.com/securego/gosec) | 10.7 | diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md index 7c24f6db86f..a29df76f4b7 100644 --- a/doc/user/clusters/applications.md +++ b/doc/user/clusters/applications.md @@ -253,6 +253,7 @@ The applications below can be uninstalled. | Application | GitLab version | Notes | | ----------- | -------------- | ----- | | GitLab Runner | 12.2+ | Any running pipelines will be canceled. | +| Helm | 12.2+ | The associated Tiller pod will be deleted and cannot be restored. | | Ingress | 12.1+ | The associated load balancer and IP will be deleted and cannot be restored. Furthermore, it can only be uninstalled if JupyterHub is not installed. | | JupyterHub | 12.1+ | All data not committed to GitLab will be deleted and cannot be restored. | | Knative | 12.1+ | The associated IP will be deleted and cannot be restored. | diff --git a/doc/user/group/bulk_editing/index.md b/doc/user/group/bulk_editing/index.md index 5b5f75c2dd9..c8715577eb2 100644 --- a/doc/user/group/bulk_editing/index.md +++ b/doc/user/group/bulk_editing/index.md @@ -5,22 +5,21 @@ > - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/12719) for merge requests in GitLab [GitLab Premium](https://about.gitlab.com/pricing/) 12.2. -> NOTE: **Note:** -> -> - A permission level of `Reporter` or higher is required in order to manage issues. -> - A permission level of `Developer` or higher is required in order to manage merge requests. - Milestones can be updated simultaneously across multiple issues or merge requests by using the bulk editing feature. ![Bulk editing](img/bulk-editing.png) +NOTE: **Note:** +A permission level of `Reporter` or higher is required in order to manage issues, and +a permission level of `Developer` or higher is required in order to manage merge requests. + To bulk update group issue or merge request milestones: 1. Navigate to the issues or merge requests list. 1. Click the **Edit issues** or **Edit merge requests** button. - - This will open a sidebar on the right-hand side of your screen where an editable field - for milestones will be displayed. - - Checkboxes will also appear beside each issue or merge request. + - This will open a sidebar on the right-hand side of your screen where an editable field + for milestones will be displayed. + - Checkboxes will also appear beside each issue or merge request. 1. Check the checkbox beside each issue to be edited. 1. Select the desired milestone from the sidebar. 1. Click **Update all**. diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md index 9c72fe33d0d..d7178506b64 100644 --- a/doc/user/project/issues/related_issues.md +++ b/doc/user/project/issues/related_issues.md @@ -19,7 +19,7 @@ Issues from a different project require additional information like the group and the project name. For example: - same project: `#44` -- same group: `project#44 ` +- same group: `project#44` - different group: `group/project#44` Valid references will be added to a temporary list that you can review. diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md index 54ecc42d2b9..6a9900d48f9 100644 --- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md +++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md @@ -191,7 +191,7 @@ can use the following setup: 1. In Cloudflare, create a DNS `TXT` record to verify your domain. 1. In GitLab, verify your domain. 1. In Cloudflare, create a DNS `CNAME` record pointing `www` to `domain.com`. -1. In Cloudflare, add a Page Rule pointing `www.domain,com` to `domain.com`: +1. In Cloudflare, add a Page Rule pointing `www.domain.com` to `domain.com`: - Navigate to your domain's dashboard and click **Page Rules** on the top nav. - Click **Create Page Rule**. diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md index b6bba57049d..264372a512d 100644 --- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md +++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md @@ -84,6 +84,10 @@ that are on the remote repository, eg. for a branch from origin: git lfs fetch origin master ``` +### Migrate an existing repo to Git LFS + +Read the documentation on how to [migrate an existing Git repo with Git LFS](../../topics/git/migrate_to_git_lfs/index.md). + ## File Locking > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/35856) in GitLab 10.5. diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 2d6dd18d4ea..2f5ce3d4003 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1162,6 +1162,7 @@ module API attributes = ::ApplicationSettingsHelper.visible_attributes attributes.delete(:performance_bar_allowed_group_path) attributes.delete(:performance_bar_enabled) + attributes.delete(:allow_local_requests_from_hooks_and_services) attributes end @@ -1180,6 +1181,7 @@ module API # support legacy names, can be removed in v5 expose :password_authentication_enabled_for_web, as: :password_authentication_enabled expose :password_authentication_enabled_for_web, as: :signin_enabled + expose :allow_local_requests_from_web_hooks_and_services, as: :allow_local_requests_from_hooks_and_services end # deprecated old Release representation diff --git a/lib/api/settings.rb b/lib/api/settings.rb index aa9e879160d..196ef1fcdfa 100644 --- a/lib/api/settings.rb +++ b/lib/api/settings.rb @@ -124,6 +124,7 @@ module API optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.' optional :instance_statistics_visibility_private, type: Boolean, desc: 'When set to `true` Instance statistics will only be available to admins' optional :local_markdown_version, type: Integer, desc: "Local markdown version, increase this value when any cached markdown should be invalidated" + optional :allow_local_requests_from_hooks_and_services, type: Boolean, desc: 'Deprecated: Use :allow_local_requests_from_web_hooks_and_services instead. Allow requests to the local network from hooks and services.' # support legacy names, can be removed in v5 ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type| optional :"#{type}_key_restriction", @@ -158,6 +159,11 @@ module API attrs[:password_authentication_enabled_for_web] = attrs.delete(:password_authentication_enabled) end + # support legacy names, can be removed in v5 + if attrs.has_key?(:allow_local_requests_from_hooks_and_services) + attrs[:allow_local_requests_from_web_hooks_and_services] = attrs.delete(:allow_local_requests_from_hooks_and_services) + end + attrs = filter_attributes_using_license(attrs) if ApplicationSettings::UpdateService.new(current_settings, current_user, attrs).execute diff --git a/lib/gitlab/blob_helper.rb b/lib/gitlab/blob_helper.rb index d3e15a79a8b..fc579ad8d2a 100644 --- a/lib/gitlab/blob_helper.rb +++ b/lib/gitlab/blob_helper.rb @@ -45,7 +45,7 @@ module Gitlab end def image? - ['.png', '.jpg', '.jpeg', '.gif'].include?(extname.downcase) + ['.png', '.jpg', '.jpeg', '.gif', '.svg'].include?(extname.downcase) end # Internal: Lookup mime type for extension. diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb index fc3223e7442..7e348763e81 100644 --- a/lib/gitlab/ci/ansi2html.rb +++ b/lib/gitlab/ci/ansi2html.rb @@ -194,16 +194,10 @@ module Gitlab end def handle_new_line - css_classes = [] - - if @sections.any? - css_classes = %w[section line] + sections.map { |section| "s_#{section}" } - end - write_in_tag %{<br/>} - write_raw %{<span class="#{css_classes.join(' ')}"></span>} if css_classes.any? + + close_open_tags if @sections.any? && @lineno_in_section == 0 @lineno_in_section += 1 - open_new_tag end def handle_section(scanner) @@ -310,11 +304,24 @@ module Gitlab if @sections.any? css_classes << "section" - css_classes << "js-section-header section-header" if @lineno_in_section == 0 + + css_classes << if @lineno_in_section == 0 + "js-section-header section-header" + else + "line" + end + css_classes += sections.map { |section| "js-s-#{section}" } end - @out << %{<span class="#{css_classes.join(' ')}">} + close_open_tags + + @out << if css_classes.any? + %{<span class="#{css_classes.join(' ')}">} + else + %{<span>} + end + @n_open_tags += 1 end diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb index d8296940a04..ab0d4c38ab6 100644 --- a/lib/gitlab/ci/pipeline/seed/build.rb +++ b/lib/gitlab/ci/pipeline/seed/build.rb @@ -9,9 +9,10 @@ module Gitlab delegate :dig, to: :@attributes - def initialize(pipeline, attributes) + def initialize(pipeline, attributes, previous_stages) @pipeline = pipeline @attributes = attributes + @previous_stages = previous_stages @only = Gitlab::Ci::Build::Policy .fabricate(attributes.delete(:only)) @@ -19,10 +20,15 @@ module Gitlab .fabricate(attributes.delete(:except)) end + def name + dig(:name) + end + def included? strong_memoize(:inclusion) do - @only.all? { |spec| spec.satisfied_by?(@pipeline, self) } && - @except.none? { |spec| spec.satisfied_by?(@pipeline, self) } + all_of_only? && + none_of_except? && + all_of_needs? end end @@ -42,6 +48,25 @@ module Gitlab @attributes.to_h.dig(:options, :trigger).present? end + def all_of_only? + @only.all? { |spec| spec.satisfied_by?(@pipeline, self) } + end + + def none_of_except? + @except.none? { |spec| spec.satisfied_by?(@pipeline, self) } + end + + def all_of_needs? + return true unless Feature.enabled?(:ci_dag_support, @pipeline.project) + return true if dig(:needs_attributes).nil? + + dig(:needs_attributes).all? do |need| + @previous_stages.any? do |stage| + stage.seeds_names.include?(need[:name]) + end + end + end + def to_resource strong_memoize(:resource) do if bridge? diff --git a/lib/gitlab/ci/pipeline/seed/stage.rb b/lib/gitlab/ci/pipeline/seed/stage.rb index 9c15064756a..7c737027445 100644 --- a/lib/gitlab/ci/pipeline/seed/stage.rb +++ b/lib/gitlab/ci/pipeline/seed/stage.rb @@ -10,12 +10,13 @@ module Gitlab delegate :size, to: :seeds delegate :dig, to: :seeds - def initialize(pipeline, attributes) + def initialize(pipeline, attributes, previous_stages) @pipeline = pipeline @attributes = attributes + @previous_stages = previous_stages @builds = attributes.fetch(:builds).map do |attributes| - Seed::Build.new(@pipeline, attributes) + Seed::Build.new(@pipeline, attributes, previous_stages) end end @@ -32,6 +33,12 @@ module Gitlab end end + def seeds_names + strong_memoize(:seeds_names) do + seeds.map(&:name).to_set + end + end + def included? seeds.any? end @@ -39,13 +46,7 @@ module Gitlab def to_resource strong_memoize(:stage) do ::Ci::Stage.new(attributes).tap do |stage| - seeds.each do |seed| - if seed.bridge? - stage.bridges << seed.to_resource - else - stage.builds << seed.to_resource - end - end + stage.statuses = seeds.map(&:to_resource) end end end diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml index 5ad624bb15f..c963d6ed1c4 100644 --- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml @@ -5,6 +5,7 @@ container_scanning: image: docker:stable variables: DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" # Defining two new variables based on GitLab's CI/CD predefined variables # https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG @@ -22,8 +23,8 @@ container_scanning: DOCKER_SERVICE: docker DOCKER_HOST: tcp://${DOCKER_SERVICE}:2375/ # https://hub.docker.com/r/arminc/clair-local-scan/tags - CLAIR_LOCAL_SCAN_VERSION: v2.0.8_fe9b059d930314b54c78f75afe265955faf4fdc1 - CLAIR_EXECUTABLE_VERSION: v11 + CLAIR_LOCAL_SCAN_VERSION: v2.0.8_0ed98e9ead65a51ba53f7cc53fa5e80c92169207 + CLAIR_EXECUTABLE_VERSION: v12 ## Disable the proxy for clair-local-scan, otherwise Container Scanning will ## fail when a proxy is used. NO_PROXY: ${DOCKER_SERVICE},localhost diff --git a/lib/gitlab/http_connection_adapter.rb b/lib/gitlab/http_connection_adapter.rb index 41eab3658bc..84eb60f3a5d 100644 --- a/lib/gitlab/http_connection_adapter.rb +++ b/lib/gitlab/http_connection_adapter.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # This class is part of the Gitlab::HTTP wrapper. Depending on the value -# of the global setting allow_local_requests_from_hooks_and_services this adapter +# of the global setting allow_local_requests_from_web_hooks_and_services this adapter # will allow/block connection to internal IPs and/or urls. # # This functionality can be overridden by providing the setting the option @@ -38,7 +38,7 @@ module Gitlab end def allow_settings_local_requests? - Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services? + Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services? end end end diff --git a/lib/gitlab/kubernetes/helm/delete_command.rb b/lib/gitlab/kubernetes/helm/delete_command.rb index aeba4a54b6d..dcf22e7abb6 100644 --- a/lib/gitlab/kubernetes/helm/delete_command.rb +++ b/lib/gitlab/kubernetes/helm/delete_command.rb @@ -43,17 +43,6 @@ module Gitlab command.shelljoin end - - def optional_tls_flags - return [] unless files.key?(:'ca.pem') - - [ - '--tls', - '--tls-ca-cert', "#{files_dir}/ca.pem", - '--tls-cert', "#{files_dir}/cert.pem", - '--tls-key', "#{files_dir}/key.pem" - ] - end end end end diff --git a/lib/gitlab/kubernetes/helm/reset_command.rb b/lib/gitlab/kubernetes/helm/reset_command.rb new file mode 100644 index 00000000000..37e1d8573ab --- /dev/null +++ b/lib/gitlab/kubernetes/helm/reset_command.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module Gitlab + module Kubernetes + module Helm + class ResetCommand + include BaseCommand + include ClientCommand + + attr_reader :name, :files + + def initialize(name:, rbac:, files:) + @name = name + @files = files + @rbac = rbac + end + + def generate_script + super + [ + reset_helm_command, + delete_tiller_replicaset + ].join("\n") + end + + def rbac? + @rbac + end + + def pod_name + "uninstall-#{name}" + end + + private + + # This method can be delete once we upgrade Helm to > 12.13.0 + # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27096#note_159695900 + # + # Tracking this method to be removed here: + # https://gitlab.com/gitlab-org/gitlab-ce/issues/52791#note_199374155 + def delete_tiller_replicaset + command = %w[kubectl delete replicaset -n gitlab-managed-apps -l name=tiller] + + command.shelljoin + end + + def reset_helm_command + command = %w[helm reset] + optional_tls_flags + + command.shelljoin + end + end + end + end +end diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb index 1350924cd76..64317225ec6 100644 --- a/lib/gitlab/kubernetes/kube_client.rb +++ b/lib/gitlab/kubernetes/kube_client.rb @@ -128,7 +128,7 @@ module Gitlab private def validate_url! - return if Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services? + return if Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services? Gitlab::UrlBlocker.validate!(api_prefix, allow_local_network: false) end diff --git a/lib/gitlab/octokit/middleware.rb b/lib/gitlab/octokit/middleware.rb index 2f762957d1b..2dd7d08a58b 100644 --- a/lib/gitlab/octokit/middleware.rb +++ b/lib/gitlab/octokit/middleware.rb @@ -16,7 +16,7 @@ module Gitlab private def allow_local_requests? - Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services? + Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services? end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 5e9e371a5fc..d462bb03adf 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -948,6 +948,12 @@ msgstr "" msgid "Allow requests to the local network from hooks and services." msgstr "" +msgid "Allow requests to the local network from system hooks" +msgstr "" + +msgid "Allow requests to the local network from web hooks and services" +msgstr "" + msgid "Allow this key to push to repository as well? (Default only allows pull access.)" msgstr "" @@ -2647,7 +2653,7 @@ msgstr "" msgid "ClusterIntegration|Kubernetes cluster name" msgstr "" -msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details" +msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine." msgstr "" msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way." @@ -2818,6 +2824,9 @@ msgstr "" msgid "ClusterIntegration|The associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications." msgstr "" +msgid "ClusterIntegration|The associated Tiller pod will be deleted and cannot be restored." +msgstr "" + msgid "ClusterIntegration|The associated certifcate will be deleted and cannot be restored." msgstr "" diff --git a/package.json b/package.json index f0a7f3e47af..ebaa3811295 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@babel/preset-env": "^7.4.4", "@gitlab/csslab": "^1.9.0", "@gitlab/svgs": "^1.67.0", - "@gitlab/ui": "^5.11.1", + "@gitlab/ui": "5.12.0", "apollo-cache-inmemory": "^1.5.1", "apollo-client": "^2.5.1", "apollo-link": "^1.2.11", @@ -101,7 +101,7 @@ "monaco-editor-webpack-plugin": "^1.7.0", "mousetrap": "^1.4.6", "pdfjs-dist": "^2.0.943", - "pikaday": "^1.6.1", + "pikaday": "^1.8.0", "popper.js": "^1.14.7", "prismjs": "^1.6.0", "prosemirror-markdown": "^1.3.0", diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 0f885d776e1..fab47aa4701 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -251,15 +251,13 @@ describe Projects::IssuesController do end end - describe 'Redirect after sign in' do + # This spec runs as a request-style spec in order to invoke the + # Rails router. A controller-style spec matches the wrong route, and + # session['user_return_to'] becomes incorrect. + describe 'Redirect after sign in', type: :request do context 'with an AJAX request' do it 'does not store the visited URL' do - get :show, params: { - format: :json, - namespace_id: project.namespace, - project_id: project, - id: issue.iid - }, xhr: true + get project_issue_path(project, issue), xhr: true expect(session['user_return_to']).to be_blank end @@ -267,14 +265,9 @@ describe Projects::IssuesController do context 'without an AJAX request' do it 'stores the visited URL' do - get :show, - params: { - namespace_id: project.namespace.to_param, - project_id: project, - id: issue.iid - } + get project_issue_path(project, issue) - expect(session['user_return_to']).to eq("/#{project.namespace.to_param}/#{project.to_param}/issues/#{issue.iid}") + expect(session['user_return_to']).to eq(project_issue_path(project, issue)) end end end diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index 39ebf02dcf5..f076a5e769f 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -546,7 +546,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do expect(response).to have_gitlab_http_status(:ok) expect(json_response['id']).to eq job.id expect(json_response['status']).to eq job.status - expect(json_response['html']).to eq('<span class="">BUILD TRACE</span>') + expect(json_response['html']).to eq('<span>BUILD TRACE</span>') end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index c77605f3869..ddd87404003 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -338,14 +338,17 @@ describe 'Admin updates settings' do visit network_admin_application_settings_path page.within('.as-outbound') do - check 'Allow requests to the local network from hooks and services' + check 'Allow requests to the local network from web hooks and services' + # Enabled by default + uncheck 'Allow requests to the local network from system hooks' # Enabled by default uncheck 'Enforce DNS rebinding attack protection' click_button 'Save changes' end expect(page).to have_content "Application settings saved successfully" - expect(current_settings.allow_local_requests_from_hooks_and_services).to be true + expect(current_settings.allow_local_requests_from_web_hooks_and_services).to be true + expect(current_settings.allow_local_requests_from_system_hooks).to be false expect(current_settings.dns_rebinding_protection_enabled).to be false end end diff --git a/spec/features/projects/clusters/applications_spec.rb b/spec/features/projects/clusters/applications_spec.rb index de97c8a8bc0..8cfd23d16df 100644 --- a/spec/features/projects/clusters/applications_spec.rb +++ b/spec/features/projects/clusters/applications_spec.rb @@ -22,9 +22,8 @@ describe 'Clusters Applications', :js do let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) } it 'user is unable to install applications' do - page.within('.js-cluster-application-row-helm') do - expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Install') - end + expect(page).not_to have_css('.js-cluster-application-row-helm') + expect(page).not_to have_css('.js-cluster-application-install-button') end end @@ -63,7 +62,8 @@ describe 'Clusters Applications', :js do Clusters::Cluster.last.application_helm.make_installed! - expect(page).to have_css('.js-cluster-application-install-button[disabled]', exact_text: 'Installed') + expect(page).not_to have_css('.js-cluster-application-install-button') + expect(page).to have_css('.js-cluster-application-uninstall-button:not([disabled])', exact_text: 'Uninstall') end expect(page).to have_content('Helm Tiller was successfully installed on your Kubernetes cluster') diff --git a/spec/features/snippets/user_edits_snippet_spec.rb b/spec/features/snippets/user_edits_snippet_spec.rb index 92e34a1f510..5ff12c37aff 100644 --- a/spec/features/snippets/user_edits_snippet_spec.rb +++ b/spec/features/snippets/user_edits_snippet_spec.rb @@ -34,7 +34,7 @@ describe 'User edits snippet', :js do click_button('Save changes') wait_for_requests - link = find('a.no-attachment-icon img[alt="banana_sample"]')['src'] + link = find('a.no-attachment-icon img:not(.lazy)[alt="banana_sample"]')['src'] expect(link).to match(%r{/uploads/-/system/personal_snippet/#{snippet.id}/\h{32}/banana_sample\.gif\z}) end diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js index 6de06a9e2d5..80816faa5fc 100644 --- a/spec/frontend/clusters/clusters_bundle_spec.js +++ b/spec/frontend/clusters/clusters_bundle_spec.js @@ -147,47 +147,80 @@ describe('Clusters', () => { }); describe('updateContainer', () => { + const { location } = window; + + beforeEach(() => { + delete window.location; + window.location = { + reload: jest.fn(), + hash: location.hash, + }; + }); + + afterEach(() => { + window.location = location; + }); + describe('when creating cluster', () => { it('should show the creating container', () => { cluster.updateContainer(null, 'creating'); expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy(); - expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy(); - expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy(); + expect(window.location.reload).not.toHaveBeenCalled(); }); it('should continue to show `creating` banner with subsequent updates of the same status', () => { + cluster.updateContainer(null, 'creating'); cluster.updateContainer('creating', 'creating'); expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy(); - expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy(); - expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy(); + expect(window.location.reload).not.toHaveBeenCalled(); }); }); describe('when cluster is created', () => { - it('should show the success container and fresh the page', () => { - cluster.updateContainer(null, 'created'); + it('should hide the "creating" banner and refresh the page', () => { + jest.spyOn(cluster, 'setClusterNewlyCreated'); + cluster.updateContainer(null, 'creating'); + cluster.updateContainer('creating', 'created'); expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy(); + expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy(); + expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy(); + expect(window.location.reload).toHaveBeenCalled(); + expect(cluster.setClusterNewlyCreated).toHaveBeenCalledWith(true); + }); - expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy(); + it('when the page is refreshed, it should show the "success" banner', () => { + jest.spyOn(cluster, 'setClusterNewlyCreated'); + jest.spyOn(cluster, 'isClusterNewlyCreated').mockReturnValue(true); + + cluster.updateContainer(null, 'created'); + cluster.updateContainer('created', 'created'); + expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy(); + expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy(); expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy(); + expect(window.location.reload).not.toHaveBeenCalled(); + expect(cluster.setClusterNewlyCreated).toHaveBeenCalledWith(false); }); it('should not show a banner when status is already `created`', () => { + jest.spyOn(cluster, 'setClusterNewlyCreated'); + jest.spyOn(cluster, 'isClusterNewlyCreated').mockReturnValue(false); + + cluster.updateContainer(null, 'created'); cluster.updateContainer('created', 'created'); expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy(); - expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy(); - expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy(); + expect(window.location.reload).not.toHaveBeenCalled(); + expect(cluster.setClusterNewlyCreated).not.toHaveBeenCalled(); }); }); diff --git a/spec/javascripts/persistent_user_callout_spec.js b/spec/javascripts/persistent_user_callout_spec.js index 2fdfff3db03..d15758be5d2 100644 --- a/spec/javascripts/persistent_user_callout_spec.js +++ b/spec/javascripts/persistent_user_callout_spec.js @@ -22,6 +22,24 @@ describe('PersistentUserCallout', () => { return fixture; } + function createDeferredLinkFixture() { + const fixture = document.createElement('div'); + fixture.innerHTML = ` + <div + class="container" + data-dismiss-endpoint="${dismissEndpoint}" + data-feature-id="${featureName}" + data-defer-links="true" + > + <button type="button" class="js-close"></button> + <a href="/somewhere-pleasant" target="_blank" class="deferred-link">A link</a> + <a href="/somewhere-else" target="_blank" class="normal-link">Another link</a> + </div> + `; + + return fixture; + } + describe('dismiss', () => { let button; let mockAxios; @@ -74,6 +92,75 @@ describe('PersistentUserCallout', () => { }); }); + describe('deferred links', () => { + let button; + let deferredLink; + let normalLink; + let mockAxios; + let persistentUserCallout; + let windowSpy; + + beforeEach(() => { + const fixture = createDeferredLinkFixture(); + const container = fixture.querySelector('.container'); + button = fixture.querySelector('.js-close'); + deferredLink = fixture.querySelector('.deferred-link'); + normalLink = fixture.querySelector('.normal-link'); + mockAxios = new MockAdapter(axios); + persistentUserCallout = new PersistentUserCallout(container); + spyOn(persistentUserCallout.container, 'remove'); + windowSpy = spyOn(window, 'open').and.callFake(() => {}); + }); + + afterEach(() => { + mockAxios.restore(); + }); + + it('defers loading of a link until callout is dismissed', done => { + const { href, target } = deferredLink; + mockAxios.onPost(dismissEndpoint).replyOnce(200); + + deferredLink.click(); + + setTimeoutPromise() + .then(() => { + expect(windowSpy).toHaveBeenCalledWith(href, target); + expect(persistentUserCallout.container.remove).toHaveBeenCalled(); + expect(mockAxios.history.post[0].data).toBe( + JSON.stringify({ feature_name: featureName }), + ); + }) + .then(done) + .catch(done.fail); + }); + + it('does not dismiss callout on non-deferred links', done => { + normalLink.click(); + + setTimeoutPromise() + .then(() => { + expect(windowSpy).not.toHaveBeenCalled(); + expect(persistentUserCallout.container.remove).not.toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + it('does not follow link when notification is closed', done => { + mockAxios.onPost(dismissEndpoint).replyOnce(200); + + button.click(); + + setTimeoutPromise() + .then(() => { + expect(windowSpy).not.toHaveBeenCalled(); + expect(persistentUserCallout.container.remove).toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + }); + describe('factory', () => { it('returns an instance of PersistentUserCallout with the provided container property', () => { const fixture = createFixture(); diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb index 651fdaaabca..eaf06ed8992 100644 --- a/spec/lib/gitlab/ci/ansi2html_spec.rb +++ b/spec/lib/gitlab/ci/ansi2html_spec.rb @@ -6,11 +6,11 @@ describe Gitlab::Ci::Ansi2html do subject { described_class } it "prints non-ansi as-is" do - expect(convert_html("Hello")).to eq('<span class="">Hello</span>') + expect(convert_html("Hello")).to eq('<span>Hello</span>') end it "strips non-color-changing control sequences" do - expect(convert_html("Hello \e[2Kworld")).to eq('<span class="">Hello world</span>') + expect(convert_html("Hello \e[2Kworld")).to eq('<span>Hello world</span>') end it "prints simply red" do @@ -34,7 +34,7 @@ describe Gitlab::Ci::Ansi2html do end it "resets colors after red on blue" do - expect(convert_html("\e[31;44mHello\e[0m world")).to eq('<span class="term-fg-red term-bg-blue">Hello</span><span class=""> world</span>') + expect(convert_html("\e[31;44mHello\e[0m world")).to eq('<span class="term-fg-red term-bg-blue">Hello</span><span> world</span>') end it "performs color change from red/blue to yellow/blue" do @@ -46,11 +46,11 @@ describe Gitlab::Ci::Ansi2html do end it "performs color change from red/blue to reset to yellow/green" do - expect(convert_html("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello</span><span class=""> </span><span class="term-fg-yellow term-bg-green">world</span>') + expect(convert_html("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello</span><span> </span><span class="term-fg-yellow term-bg-green">world</span>') end it "ignores unsupported codes" do - expect(convert_html("\e[51mHello\e[0m")).to eq('<span class="">Hello</span>') + expect(convert_html("\e[51mHello\e[0m")).to eq('<span>Hello</span>') end it "prints light red" do @@ -74,8 +74,8 @@ describe Gitlab::Ci::Ansi2html do end it "resets bold text" do - expect(convert_html("\e[1mHello\e[21m world")).to eq('<span class="term-bold">Hello</span><span class=""> world</span>') - expect(convert_html("\e[1mHello\e[22m world")).to eq('<span class="term-bold">Hello</span><span class=""> world</span>') + expect(convert_html("\e[1mHello\e[21m world")).to eq('<span class="term-bold">Hello</span><span> world</span>') + expect(convert_html("\e[1mHello\e[22m world")).to eq('<span class="term-bold">Hello</span><span> world</span>') end it "prints italic text" do @@ -83,7 +83,7 @@ describe Gitlab::Ci::Ansi2html do end it "resets italic text" do - expect(convert_html("\e[3mHello\e[23m world")).to eq('<span class="term-italic">Hello</span><span class=""> world</span>') + expect(convert_html("\e[3mHello\e[23m world")).to eq('<span class="term-italic">Hello</span><span> world</span>') end it "prints underlined text" do @@ -91,7 +91,7 @@ describe Gitlab::Ci::Ansi2html do end it "resets underlined text" do - expect(convert_html("\e[4mHello\e[24m world")).to eq('<span class="term-underline">Hello</span><span class=""> world</span>') + expect(convert_html("\e[4mHello\e[24m world")).to eq('<span class="term-underline">Hello</span><span> world</span>') end it "prints concealed text" do @@ -99,7 +99,7 @@ describe Gitlab::Ci::Ansi2html do end it "resets concealed text" do - expect(convert_html("\e[8mHello\e[28m world")).to eq('<span class="term-conceal">Hello</span><span class=""> world</span>') + expect(convert_html("\e[8mHello\e[28m world")).to eq('<span class="term-conceal">Hello</span><span> world</span>') end it "prints crossed-out text" do @@ -107,7 +107,7 @@ describe Gitlab::Ci::Ansi2html do end it "resets crossed-out text" do - expect(convert_html("\e[9mHello\e[29m world")).to eq('<span class="term-cross">Hello</span><span class=""> world</span>') + expect(convert_html("\e[9mHello\e[29m world")).to eq('<span class="term-cross">Hello</span><span> world</span>') end it "can print 256 xterm fg colors" do @@ -139,15 +139,15 @@ describe Gitlab::Ci::Ansi2html do end it "prints <" do - expect(convert_html("<")).to eq('<span class=""><</span>') + expect(convert_html("<")).to eq('<span><</span>') end it "replaces newlines with line break tags" do - expect(convert_html("\n")).to eq('<span class=""><br/><span class=""></span></span>') + expect(convert_html("\n")).to eq('<span><br/></span>') end it "groups carriage returns with newlines" do - expect(convert_html("\r\n")).to eq('<span class=""><br/><span class=""></span></span>') + expect(convert_html("\r\n")).to eq('<span><br/></span>') end describe "incremental update" do @@ -184,7 +184,7 @@ describe Gitlab::Ci::Ansi2html do context "with partial sequence" do let(:pre_text) { "Hello\e" } - let(:pre_html) { "<span class=\"\">Hello</span>" } + let(:pre_html) { "<span>Hello</span>" } let(:text) { "[1m World" } let(:html) { "<span class=\"term-bold\"> World</span>" } @@ -193,9 +193,9 @@ describe Gitlab::Ci::Ansi2html do context 'with new line' do let(:pre_text) { "Hello\r" } - let(:pre_html) { "<span class=\"\">Hello\r</span>" } + let(:pre_html) { "<span>Hello\r</span>" } let(:text) { "\nWorld" } - let(:html) { "<span class=\"\"><br/><span class=\"\">World</span></span>" } + let(:html) { "<span><br/>World</span>" } it_behaves_like 'stateable converter' end @@ -222,7 +222,7 @@ describe Gitlab::Ci::Ansi2html do text = "#{section_start}Some text#{section_end}" class_name_start = section_start.gsub("\033[0K", '').gsub('<', '<') class_name_end = section_end.gsub("\033[0K", '').gsub('<', '<') - html = %{<span class="">#{class_name_start}Some text#{class_name_end}</span>} + html = %{<span>#{class_name_start}Some text#{class_name_end}</span>} expect(convert_html(text)).to eq(html) end @@ -232,12 +232,11 @@ describe Gitlab::Ci::Ansi2html do let(:text) { "#{section_start}Some text#{section_end}" } it 'prints light red' do - text = "#{section_start}\e[91mHello\e[0m\n#{section_end}" + text = "#{section_start}\e[91mHello\e[0m\nLine 1\nLine 2\nLine 3\n#{section_end}" header = %{<span class="term-fg-l-red section js-section-header section-header js-s-#{class_name(section_name)}">Hello</span>} line_break = %{<span class="section js-section-header section-header js-s-#{class_name(section_name)}"><br/></span>} - line = %{<span class="section line s_#{class_name(section_name)}"></span>} - empty_line = %{<span class="section js-s-#{class_name(section_name)}"></span>} - html = "#{section_start_html}#{header}#{line_break}#{line}#{empty_line}#{section_end_html}" + output_line = %{<span class="section line js-s-#{class_name(section_name)}">Line 1<br/>Line 2<br/>Line 3<br/></span>} + html = "#{section_start_html}#{header}#{line_break}#{output_line}#{section_end_html}" expect(convert_html(text)).to eq(html) end diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb index 417a2d119ff..9bccd5be4fe 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb @@ -38,8 +38,8 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do it 'populates pipeline with stages' do expect(pipeline.stages).to be_one expect(pipeline.stages.first).not_to be_persisted - expect(pipeline.stages.first.builds).to be_one - expect(pipeline.stages.first.builds.first).not_to be_persisted + expect(pipeline.stages.first.statuses).to be_one + expect(pipeline.stages.first.statuses.first).not_to be_persisted end it 'correctly assigns user' do @@ -191,8 +191,8 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do step.perform! expect(pipeline.stages.size).to eq 1 - expect(pipeline.stages.first.builds.size).to eq 1 - expect(pipeline.stages.first.builds.first.name).to eq 'rspec' + expect(pipeline.stages.first.statuses.size).to eq 1 + expect(pipeline.stages.first.statuses.first.name).to eq 'rspec' end end diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb index 46ea0d7554b..762025f9bd9 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb @@ -6,8 +6,9 @@ describe Gitlab::Ci::Pipeline::Seed::Build do let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_empty_pipeline, project: project) } let(:attributes) { { name: 'rspec', ref: 'master' } } + let(:previous_stages) { [] } - let(:seed_build) { described_class.new(pipeline, attributes) } + let(:seed_build) { described_class.new(pipeline, attributes, previous_stages) } describe '#attributes' do subject { seed_build.attributes } @@ -381,4 +382,39 @@ describe Gitlab::Ci::Pipeline::Seed::Build do end end end + + describe 'applying needs: dependency' do + subject { seed_build } + + let(:attributes) do + { + name: 'rspec', + needs_attributes: [{ + name: 'build' + }] + } + end + + context 'when build job is not present in prior stages' do + it { is_expected.not_to be_included } + end + + context 'when build job is part of prior stages' do + let(:stage_attributes) do + { + name: 'build', + index: 0, + builds: [{ name: 'build' }] + } + end + + let(:stage_seed) do + Gitlab::Ci::Pipeline::Seed::Stage.new(pipeline, stage_attributes, []) + end + + let(:previous_stages) { [stage_seed] } + + it { is_expected.to be_included } + end + end end diff --git a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb index ad864d0d56e..6fba9f37d91 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' describe Gitlab::Ci::Pipeline::Seed::Stage do let(:project) { create(:project, :repository) } let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let(:previous_stages) { [] } let(:attributes) do { name: 'test', @@ -15,7 +16,7 @@ describe Gitlab::Ci::Pipeline::Seed::Stage do end subject do - described_class.new(pipeline, attributes) + described_class.new(pipeline, attributes, previous_stages) end describe '#size' do @@ -109,6 +110,17 @@ describe Gitlab::Ci::Pipeline::Seed::Stage do end end + describe '#seeds_names' do + it 'returns all job names' do + expect(subject.seeds_names).to contain_exactly( + 'rspec', 'spinach') + end + + it 'returns a set' do + expect(subject.seeds_names).to be_a(Set) + end + end + describe '#to_resource' do it 'builds a valid stage object with all builds' do subject.to_resource.save! diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb index 35250632e86..af519f4bae6 100644 --- a/spec/lib/gitlab/ci/trace/stream_spec.rb +++ b/spec/lib/gitlab/ci/trace/stream_spec.rb @@ -65,9 +65,9 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do result = stream.html expect(result).to eq( - "<span class=\"\">ヾ(´༎ຶД༎ຶ`)ノ<br/><span class=\"\"></span></span>"\ - "<span class=\"term-fg-green\">許功蓋</span><span class=\"\"><br/>"\ - "<span class=\"\"></span></span>") + "<span>ヾ(´༎ຶД༎ຶ`)ノ<br/></span>"\ + "<span class=\"term-fg-green\">許功蓋</span>"\ + "<span><br/></span>") expect(result.encoding).to eq(Encoding.default_external) end end @@ -253,7 +253,7 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do it 'returns html content with state' do result = stream.html_with_state - expect(result.html).to eq("<span class=\"\">1234</span>") + expect(result.html).to eq("<span>1234</span>") end context 'follow-up state' do @@ -269,7 +269,7 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do result = stream.html_with_state(last_result.state) expect(result.append).to be_truthy - expect(result.html).to eq("<span class=\"\">5678</span>") + expect(result.html).to eq("<span>5678</span>") end end end @@ -305,13 +305,11 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do describe '#html' do shared_examples_for 'htmls' do it "returns html" do - expect(stream.html).to eq( - "<span class=\"\">12<br/><span class=\"\">34<br/>"\ - "<span class=\"\">56</span></span></span>") + expect(stream.html).to eq("<span>12<br/>34<br/>56</span>") end it "returns html for last line only" do - expect(stream.html(last_lines: 1)).to eq("<span class=\"\">56</span>") + expect(stream.html(last_lines: 1)).to eq("<span>56</span>") end end diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb index 158f77cab2c..d3f9be845dd 100644 --- a/spec/lib/gitlab/http_spec.rb +++ b/spec/lib/gitlab/http_spec.rb @@ -23,14 +23,14 @@ describe Gitlab::HTTP do end end - describe 'allow_local_requests_from_hooks_and_services is' do + describe 'allow_local_requests_from_web_hooks_and_services is' do before do WebMock.stub_request(:get, /.*/).to_return(status: 200, body: 'Success') end context 'disabled' do before do - allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_hooks_and_services?).and_return(false) + allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(false) end it 'deny requests to localhost' do @@ -52,7 +52,7 @@ describe Gitlab::HTTP do context 'enabled' do before do - allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_hooks_and_services?).and_return(true) + allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_web_hooks_and_services?).and_return(true) end it 'allow requests to localhost' do diff --git a/spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb new file mode 100644 index 00000000000..d49d4779735 --- /dev/null +++ b/spec/lib/gitlab/kubernetes/helm/reset_command_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Kubernetes::Helm::ResetCommand do + let(:rbac) { true } + let(:name) { 'helm' } + let(:files) { {} } + let(:reset_command) { described_class.new(name: name, rbac: rbac, files: files) } + + subject { reset_command } + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS + helm reset + kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller + EOS + end + end + + context 'when there is a ca.pem file' do + let(:files) { { 'ca.pem': 'some file content' } } + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS1.squish + "\n" + <<~EOS2 + helm reset + --tls + --tls-ca-cert /data/helm/helm/config/ca.pem + --tls-cert /data/helm/helm/config/cert.pem + --tls-key /data/helm/helm/config/key.pem + EOS1 + kubectl delete replicaset -n gitlab-managed-apps -l name\\=tiller + EOS2 + end + end + end + + describe '#pod_resource' do + subject { reset_command.pod_resource } + + context 'rbac is enabled' do + let(:rbac) { true } + + it 'generates a pod that uses the tiller serviceAccountName' do + expect(subject.spec.serviceAccountName).to eq('tiller') + end + end + + context 'rbac is not enabled' do + let(:rbac) { false } + + it 'generates a pod that uses the default serviceAccountName' do + expect(subject.spec.serviceAcccountName).to be_nil + end + end + end + + describe '#pod_name' do + subject { reset_command.pod_name } + + it { is_expected.to eq('uninstall-helm') } + end +end diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb index 97ebb5f1554..f49d4e23e39 100644 --- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb +++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb @@ -58,7 +58,7 @@ describe Gitlab::Kubernetes::KubeClient do context 'when local requests are allowed' do before do - stub_application_setting(allow_local_requests_from_hooks_and_services: true) + stub_application_setting(allow_local_requests_from_web_hooks_and_services: true) end it 'allows local addresses' do diff --git a/spec/lib/gitlab/octokit/middleware_spec.rb b/spec/lib/gitlab/octokit/middleware_spec.rb index 7f2b523f5b7..43f6d13f7ba 100644 --- a/spec/lib/gitlab/octokit/middleware_spec.rb +++ b/spec/lib/gitlab/octokit/middleware_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::Octokit::Middleware do context 'when localhost requests are not allowed' do before do - stub_application_setting(allow_local_requests_from_hooks_and_services: false) + stub_application_setting(allow_local_requests_from_web_hooks_and_services: false) end it_behaves_like 'Local URL' @@ -38,7 +38,7 @@ describe Gitlab::Octokit::Middleware do context 'when localhost requests are allowed' do before do - stub_application_setting(allow_local_requests_from_hooks_and_services: true) + stub_application_setting(allow_local_requests_from_web_hooks_and_services: true) end it_behaves_like 'Public URL' @@ -50,7 +50,7 @@ describe Gitlab::Octokit::Middleware do context 'when local network requests are not allowed' do before do - stub_application_setting(allow_local_requests_from_hooks_and_services: false) + stub_application_setting(allow_local_requests_from_web_hooks_and_services: false) end it_behaves_like 'Local URL' @@ -58,7 +58,7 @@ describe Gitlab::Octokit::Middleware do context 'when local network requests are allowed' do before do - stub_application_setting(allow_local_requests_from_hooks_and_services: true) + stub_application_setting(allow_local_requests_from_web_hooks_and_services: true) end it_behaves_like 'Public URL' diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 8768e914284..b7e005e3883 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -208,6 +208,22 @@ describe Ci::Build do end end + describe '.without_needs' do + let!(:build) { create(:ci_build) } + + subject { described_class.without_needs } + + context 'when no build_need is created' do + it { is_expected.to contain_exactly(build) } + end + + context 'when a build_need is created' do + let!(:need_a) { create(:ci_build_need, build: build) } + + it { is_expected.to be_empty } + end + end + describe '#enqueue' do let(:build) { create(:ci_build, :created) } @@ -630,12 +646,17 @@ describe Ci::Build do create(:ci_build, pipeline: pipeline, name: 'final', stage_idx: 3, stage: 'deploy', options: { - dependencies: dependencies, - needs: needs + dependencies: dependencies } ) end + before do + needs.to_a.each do |need| + create(:ci_build_need, build: final, name: need) + end + end + subject { final.dependencies } context 'when depedencies are defined' do @@ -648,6 +669,14 @@ describe Ci::Build do let(:needs) { %w(build rspec staging) } it { is_expected.to contain_exactly(build, rspec_test, staging) } + + context 'when ci_dag_support is disabled' do + before do + stub_feature_flags(ci_dag_support: false) + end + + it { is_expected.to contain_exactly(build, rspec_test, rubocop_test, staging) } + end end context 'when needs and dependencies are defined' do diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb index 6ea6c110d62..d4f8b552088 100644 --- a/spec/models/clusters/applications/helm_spec.rb +++ b/spec/models/clusters/applications/helm_spec.rb @@ -19,11 +19,27 @@ describe Clusters::Applications::Helm do end describe '#can_uninstall?' do - let(:helm) { create(:clusters_applications_helm) } + context "with other existing applications" do + Clusters::Cluster::APPLICATIONS.keys.each do |application_name| + next if application_name == 'helm' + + it do + cluster_application = create("clusters_applications_#{application_name}".to_sym) + + helm = cluster_application.cluster.application_helm - subject { helm.can_uninstall? } + expect(helm.allowed_to_uninstall?).to be_falsy + end + end + end - it { is_expected.to be_falsey } + context "without other existing applications" do + subject { helm.can_uninstall? } + + let(:helm) { create(:clusters_applications_helm) } + + it { is_expected.to be_truthy } + end end describe '#issue_client_cert' do @@ -73,4 +89,41 @@ describe Clusters::Applications::Helm do end end end + + describe '#uninstall_command' do + let(:helm) { create(:clusters_applications_helm) } + + subject { helm.uninstall_command } + + it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::ResetCommand) } + + it 'has name' do + expect(subject.name).to eq('helm') + end + + it 'has cert files' do + expect(subject.files[:'ca.pem']).to be_present + expect(subject.files[:'ca.pem']).to eq(helm.ca_cert) + + expect(subject.files[:'cert.pem']).to be_present + expect(subject.files[:'key.pem']).to be_present + + cert = OpenSSL::X509::Certificate.new(subject.files[:'cert.pem']) + expect(cert.not_after).to be > 999.years.from_now + end + + describe 'rbac' do + context 'rbac cluster' do + it { expect(subject).to be_rbac } + end + + context 'non rbac cluster' do + before do + helm.cluster.platform_kubernetes.abac! + end + + it { expect(subject).not_to be_rbac } + end + end + end end diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb index 342ed907854..334f10526cb 100644 --- a/spec/models/clusters/applications/knative_spec.rb +++ b/spec/models/clusters/applications/knative_spec.rb @@ -91,7 +91,7 @@ describe Clusters::Applications::Knative do end it 'does not install metrics for prometheus' do - expect(subject.postinstall).to be_nil + expect(subject.postinstall).to be_empty end context 'with prometheus installed' do @@ -101,7 +101,7 @@ describe Clusters::Applications::Knative do subject { knative.install_command } it 'installs metrics' do - expect(subject.postinstall).not_to be_nil + expect(subject.postinstall).not_to be_empty expect(subject.postinstall.length).to be(1) expect(subject.postinstall[0]).to eql("kubectl apply -f #{Clusters::Applications::Knative::METRICS_CONFIG}") end diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index 26267c64112..d9f31c46f59 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -142,7 +142,7 @@ describe Clusters::Applications::Prometheus do end it 'does not install knative metrics' do - expect(subject.postinstall).to be_nil + expect(subject.postinstall).to be_empty end context 'with knative installed' do diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index 471769e4aab..5811016ea4d 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -106,7 +106,7 @@ describe Clusters::Platforms::Kubernetes do before do allow(ApplicationSetting) .to receive(:current) - .and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: true)) + .and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_web_hooks_and_services: true)) end it { expect(kubernetes.save).to be_truthy } diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index e76186fb280..7b35c2ffd36 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -556,6 +556,7 @@ eos it 'returns the URI type at the given path' do expect(commit.uri_type('files/html')).to be(:tree) expect(commit.uri_type('files/images/logo-black.png')).to be(:raw) + expect(commit.uri_type('files/images/wm.svg')).to be(:raw) expect(project.commit('video').uri_type('files/videos/intro.mp4')).to be(:raw) expect(commit.uri_type('files/js/application.js')).to be(:blob) end diff --git a/spec/models/lfs_download_object_spec.rb b/spec/models/lfs_download_object_spec.rb index effd8b08124..8b53effe98f 100644 --- a/spec/models/lfs_download_object_spec.rb +++ b/spec/models/lfs_download_object_spec.rb @@ -50,7 +50,7 @@ describe LfsDownloadObject do before do allow(ApplicationSetting) .to receive(:current) - .and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: setting)) + .and_return(ApplicationSetting.build_from_defaults(allow_local_requests_from_web_hooks_and_services: setting)) end context 'are allowed' do diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb index db3e4902c64..a164ed9bbea 100644 --- a/spec/models/project_statistics_spec.rb +++ b/spec/models/project_statistics_spec.rb @@ -140,18 +140,7 @@ describe ProjectStatistics do let(:namespace) { create(:group) } let(:project) { create(:project, namespace: namespace) } - context 'when the feature flag is off' do - it 'does not schedule the aggregation worker' do - stub_feature_flags(update_statistics_namespace: false, namespace: namespace) - - expect(Namespaces::ScheduleAggregationWorker) - .not_to receive(:perform_async) - - statistics.refresh!(only: [:lfs_objects_size]) - end - end - - context 'when the feature flag is on' do + context 'when arguments are passed' do it 'schedules the aggregation worker' do expect(Namespaces::ScheduleAggregationWorker) .to receive(:perform_async) diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 8a60980fe80..184c00a356a 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -25,6 +25,9 @@ describe API::Settings, 'Settings' do expect(json_response['ed25519_key_restriction']).to eq(0) expect(json_response['performance_bar_allowed_group_id']).to be_nil expect(json_response['instance_statistics_visibility_private']).to be(false) + expect(json_response['allow_local_requests_from_hooks_and_services']).to be(false) + expect(json_response['allow_local_requests_from_web_hooks_and_services']).to be(false) + expect(json_response['allow_local_requests_from_system_hooks']).to be(true) expect(json_response).not_to have_key('performance_bar_allowed_group_path') expect(json_response).not_to have_key('performance_bar_enabled') end @@ -67,7 +70,9 @@ describe API::Settings, 'Settings' do instance_statistics_visibility_private: true, diff_max_patch_bytes: 150_000, default_branch_protection: ::Gitlab::Access::PROTECTION_DEV_CAN_MERGE, - local_markdown_version: 3 + local_markdown_version: 3, + allow_local_requests_from_web_hooks_and_services: true, + allow_local_requests_from_system_hooks: false } expect(response).to have_gitlab_http_status(200) @@ -95,6 +100,8 @@ describe API::Settings, 'Settings' do expect(json_response['diff_max_patch_bytes']).to eq(150_000) expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_DEV_CAN_MERGE) expect(json_response['local_markdown_version']).to eq(3) + expect(json_response['allow_local_requests_from_web_hooks_and_services']).to eq(true) + expect(json_response['allow_local_requests_from_system_hooks']).to eq(false) end end @@ -117,6 +124,14 @@ describe API::Settings, 'Settings' do expect(json_response['performance_bar_allowed_group_id']).to be_nil end + it 'supports legacy allow_local_requests_from_hooks_and_services' do + put api("/application/settings", admin), + params: { allow_local_requests_from_hooks_and_services: true } + + expect(response).to have_gitlab_http_status(200) + expect(json_response['allow_local_requests_from_hooks_and_services']).to eq(true) + end + context 'external policy classification settings' do let(:settings) do { diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb index f38a18fcf59..76ecca06522 100644 --- a/spec/serializers/cluster_application_entity_spec.rb +++ b/spec/serializers/cluster_application_entity_spec.rb @@ -22,7 +22,7 @@ describe ClusterApplicationEntity do end it 'has can_uninstall' do - expect(subject[:can_uninstall]).to be_falsey + expect(subject[:can_uninstall]).to be_truthy end context 'non-helm application' do diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb index d9b61dfe503..7e2f311a065 100644 --- a/spec/services/ci/create_pipeline_service_spec.rb +++ b/spec/services/ci/create_pipeline_service_spec.rb @@ -1099,6 +1099,62 @@ describe Ci::CreatePipelineService do end end end + + context 'when needs is used' do + let(:pipeline) { execute_service } + + let(:config) do + { + build_a: { + stage: "build", + script: "ls", + only: %w[master] + }, + test_a: { + stage: "test", + script: "ls", + only: %w[master feature tags], + needs: %w[build_a] + }, + deploy: { + stage: "deploy", + script: "ls", + only: %w[tags] + } + } + end + + before do + stub_ci_pipeline_yaml_file(YAML.dump(config)) + end + + context 'when pipeline on master is created' do + let(:ref_name) { 'refs/heads/master' } + + it 'creates a pipeline with build_a and test_a' do + expect(pipeline).to be_persisted + expect(pipeline.builds.map(&:name)).to contain_exactly("build_a", "test_a") + end + end + + context 'when pipeline on feature is created' do + let(:ref_name) { 'refs/heads/feature' } + + it 'does not create a pipeline as test_a depends on build_a' do + expect(pipeline).not_to be_persisted + expect(pipeline.builds).to be_empty + end + end + + context 'when pipeline on v1.0.0 is created' do + let(:ref_name) { 'refs/tags/v1.0.0' } + + it 'does create a pipeline only with deploy' do + expect(pipeline).to be_persisted + expect(pipeline.builds.map(&:name)).to contain_exactly("deploy") + end + end + end end describe '#execute!' do diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index 77f108b6ab8..1b28d2d4d02 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -786,6 +786,50 @@ describe Ci::ProcessPipelineService, '#execute' do expect(builds.pending).to contain_exactly(deploy) end end + + context 'when one of the jobs is run on a failure' do + let!(:linux_notify) { create_build('linux:notify', stage: 'deploy', stage_idx: 2, when: 'on_failure') } + + let!(:linux_notify_on_build) { create(:ci_build_need, build: linux_notify, name: 'linux:build') } + + context 'when another job in build phase fails first' do + context 'when ci_dag_support is enabled' do + it 'does skip linux:notify' do + expect(process_pipeline).to be_truthy + + mac_build.reset.drop! + linux_build.reset.success! + + expect(linux_notify.reset).to be_skipped + end + end + + context 'when ci_dag_support is disabled' do + before do + stub_feature_flags(ci_dag_support: false) + end + + it 'does run linux:notify' do + expect(process_pipeline).to be_truthy + + mac_build.reset.drop! + linux_build.reset.success! + + expect(linux_notify.reset).to be_pending + end + end + end + + context 'when linux:build job fails first' do + it 'does run linux:notify' do + expect(process_pipeline).to be_truthy + + linux_build.reset.drop! + + expect(linux_notify.reset).to be_pending + end + end + end end def process_pipeline diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb index 75d534c59bf..970e82e7107 100644 --- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb @@ -17,7 +17,7 @@ describe Projects::LfsPointers::LfsDownloadService do before do ApplicationSetting.create_from_defaults - stub_application_setting(allow_local_requests_from_hooks_and_services: local_request_setting) + stub_application_setting(allow_local_requests_from_web_hooks_and_services: local_request_setting) allow(project).to receive(:lfs_enabled?).and_return(true) end diff --git a/spec/services/self_monitoring/project/create_service_spec.rb b/spec/services/self_monitoring/project/create_service_spec.rb index a1e7aaf45f2..7d4faba526b 100644 --- a/spec/services/self_monitoring/project/create_service_spec.rb +++ b/spec/services/self_monitoring/project/create_service_spec.rb @@ -37,7 +37,7 @@ describe SelfMonitoring::Project::CreateService do allow(ApplicationSetting) .to receive(:current) .and_return( - ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: true) + ApplicationSetting.build_from_defaults(allow_local_requests_from_web_hooks_and_services: true) ) end @@ -95,7 +95,7 @@ describe SelfMonitoring::Project::CreateService do allow(ApplicationSetting) .to receive(:current) .and_return( - ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: false) + ApplicationSetting.build_from_defaults(allow_local_requests_from_web_hooks_and_services: false) ) end diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb index 37bafc0c002..50167a2e059 100644 --- a/spec/services/web_hook_service_spec.rb +++ b/spec/services/web_hook_service_spec.rb @@ -19,17 +19,37 @@ describe WebHookService do let(:service_instance) { described_class.new(project_hook, data, :push_hooks) } describe '#initialize' do - it 'allow_local_requests is true if hook is a SystemHook' do - instance = described_class.new(build(:system_hook), data, :system_hook) - expect(instance.request_options[:allow_local_requests]).to be_truthy + before do + stub_application_setting(setting_name => setting) end - it 'allow_local_requests is false if hook is not a SystemHook' do - %i(project_hook service_hook web_hook_log).each do |hook| - instance = described_class.new(build(hook), data, hook) - expect(instance.request_options[:allow_local_requests]).to be_falsey + shared_examples_for 'respects outbound network setting' do + context 'when local requests are allowed' do + let(:setting) { true } + + it { expect(hook.request_options[:allow_local_requests]).to be_truthy } + end + + context 'when local requests are not allowed' do + let(:setting) { false } + + it { expect(hook.request_options[:allow_local_requests]).to be_falsey } end end + + context 'when SystemHook' do + let(:setting_name) { :allow_local_requests_from_system_hooks } + let(:hook) { described_class.new(build(:system_hook), data, :system_hook) } + + include_examples 'respects outbound network setting' + end + + context 'when ProjectHook' do + let(:setting_name) { :allow_local_requests_from_web_hooks_and_services } + let(:hook) { described_class.new(build(:project_hook), data, :project_hook) } + + include_examples 'respects outbound network setting' + end end describe '#execute' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6994b6687fc..bcc133790d1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -148,9 +148,9 @@ RSpec.configure do |config| Gitlab::ThreadMemoryCache.cache_backend.clear end - config.around(:example, :quarantine) do + config.around(:example, :quarantine) do |example| # Skip tests in quarantine unless we explicitly focus on them. - skip('In quarantine') unless config.inclusion_filter[:quarantine] + example.run if config.inclusion_filter[:quarantine] end config.before(:example, :request_store) do diff --git a/spec/support/shared_examples/ci_trace_shared_examples.rb b/spec/support/shared_examples/ci_trace_shared_examples.rb index 6fd4b14d51d..e2b4b50d41d 100644 --- a/spec/support/shared_examples/ci_trace_shared_examples.rb +++ b/spec/support/shared_examples/ci_trace_shared_examples.rb @@ -7,11 +7,11 @@ shared_examples_for 'common trace features' do end it "returns formatted html" do - expect(trace.html).to eq("<span class=\"\">12<br/><span class=\"\">34</span></span>") + expect(trace.html).to eq("<span>12<br/>34</span>") end it "returns last line of formatted html" do - expect(trace.html(last_lines: 1)).to eq("<span class=\"\">34</span>") + expect(trace.html(last_lines: 1)).to eq("<span>34</span>") end end diff --git a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb index aad63982e7a..e03435cafe8 100644 --- a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb +++ b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb @@ -32,19 +32,6 @@ shared_examples_for 'UpdateProjectStatistics' do subject.save! end - - context 'when feature flag is disabled for the namespace' do - it 'does not schedules a namespace statistics worker' do - namespace = subject.project.root_ancestor - - stub_feature_flags(update_statistics_namespace: false, namespace: namespace) - - expect(Namespaces::ScheduleAggregationWorker) - .not_to receive(:perform_async) - - subject.save! - end - end end context 'when updating' do @@ -87,20 +74,6 @@ shared_examples_for 'UpdateProjectStatistics' do subject.save! end.not_to exceed_query_limit(control_count) end - - context 'when the feature flag is disabled for the namespace' do - it 'does not schedule a namespace statistics worker' do - namespace = subject.project.root_ancestor - - stub_feature_flags(update_statistics_namespace: false, namespace: namespace) - - expect(Namespaces::ScheduleAggregationWorker) - .not_to receive(:perform_async) - - subject.write_attribute(statistic_attribute, read_attribute + delta) - subject.save! - end - end end context 'when destroying' do @@ -144,18 +117,5 @@ shared_examples_for 'UpdateProjectStatistics' do project.destroy! end end - - context 'when feature flag is disabled for the namespace' do - it 'does not schedule a namespace statistics worker' do - namespace = subject.project.root_ancestor - - stub_feature_flags(update_statistics_namespace: false, namespace: namespace) - - expect(Namespaces::ScheduleAggregationWorker) - .not_to receive(:perform_async) - - subject.destroy! - end - end end end diff --git a/spec/support/shared_examples/url_validator_examples.rb b/spec/support/shared_examples/url_validator_examples.rb index 16fceddb605..c5a775fefb6 100644 --- a/spec/support/shared_examples/url_validator_examples.rb +++ b/spec/support/shared_examples/url_validator_examples.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true RSpec.shared_examples 'url validator examples' do |schemes| - let(:validator) { described_class.new(attributes: [:link_url], **options) } - let!(:badge) { build(:badge, link_url: 'http://www.example.com') } + describe '#validate' do + let(:validator) { described_class.new(attributes: [:link_url], **options) } + let(:badge) { build(:badge, link_url: 'http://www.example.com') } - subject { validator.validate(badge) } + subject { validator.validate(badge) } - describe '#validate' do context 'with no options' do let(:options) { {} } @@ -42,3 +42,52 @@ RSpec.shared_examples 'url validator examples' do |schemes| end end end + +RSpec.shared_examples 'public url validator examples' do |setting| + let(:validator) { described_class.new(attributes: [:link_url]) } + let(:badge) { build(:badge, link_url: 'http://www.example.com') } + + subject { validator.validate(badge) } + + context 'by default' do + it 'blocks urls pointing to localhost' do + badge.link_url = 'https://127.0.0.1' + + subject + + expect(badge.errors).to be_present + end + + it 'blocks urls pointing to the local network' do + badge.link_url = 'https://192.168.1.1' + + subject + + expect(badge.errors).to be_present + end + end + + context 'when local requests are allowed' do + let!(:settings) { create(:application_setting) } + + before do + stub_application_setting(setting) + end + + it 'does not block urls pointing to localhost' do + badge.link_url = 'https://127.0.0.1' + + subject + + expect(badge.errors).not_to be_present + end + + it 'does not block urls pointing to the local network' do + badge.link_url = 'https://192.168.1.1' + + subject + + expect(badge.errors).not_to be_present + end + end +end diff --git a/spec/validators/public_url_validator_spec.rb b/spec/validators/public_url_validator_spec.rb index f6364fb1dd5..3cbf1002730 100644 --- a/spec/validators/public_url_validator_spec.rb +++ b/spec/validators/public_url_validator_spec.rb @@ -2,27 +2,5 @@ require 'spec_helper' describe PublicUrlValidator do include_examples 'url validator examples', AddressableUrlValidator::DEFAULT_OPTIONS[:schemes] - - context 'by default' do - let(:validator) { described_class.new(attributes: [:link_url]) } - let!(:badge) { build(:badge, link_url: 'http://www.example.com') } - - subject { validator.validate(badge) } - - it 'blocks urls pointing to localhost' do - badge.link_url = 'https://127.0.0.1' - - subject - - expect(badge.errors).to be_present - end - - it 'blocks urls pointing to the local network' do - badge.link_url = 'https://192.168.1.1' - - subject - - expect(badge.errors).to be_present - end - end + include_examples 'public url validator examples', allow_local_requests_from_web_hooks_and_services: true end diff --git a/spec/validators/system_hook_url_validator_spec.rb b/spec/validators/system_hook_url_validator_spec.rb new file mode 100644 index 00000000000..02384bbd1ce --- /dev/null +++ b/spec/validators/system_hook_url_validator_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SystemHookUrlValidator do + include_examples 'url validator examples', AddressableUrlValidator::DEFAULT_OPTIONS[:schemes] + include_examples 'public url validator examples', allow_local_requests_from_system_hooks: true +end diff --git a/spec/workers/namespaces/root_statistics_worker_spec.rb b/spec/workers/namespaces/root_statistics_worker_spec.rb index 8dd74b96d49..6bbdfe03ceb 100644 --- a/spec/workers/namespaces/root_statistics_worker_spec.rb +++ b/spec/workers/namespaces/root_statistics_worker_spec.rb @@ -74,15 +74,4 @@ describe Namespaces::RootStatisticsWorker, '#perform' do worker.perform(group.id) end end - - context 'when update_statistics_namespace is off' do - it 'does not create a new one' do - stub_feature_flags(update_statistics_namespace: false, namespace: group) - - expect_any_instance_of(Namespaces::StatisticsRefresherService) - .not_to receive(:execute) - - worker.perform(group.id) - end - end end diff --git a/spec/workers/namespaces/schedule_aggregation_worker_spec.rb b/spec/workers/namespaces/schedule_aggregation_worker_spec.rb index d4a49a3f53a..be722f451e0 100644 --- a/spec/workers/namespaces/schedule_aggregation_worker_spec.rb +++ b/spec/workers/namespaces/schedule_aggregation_worker_spec.rb @@ -31,16 +31,6 @@ describe Namespaces::ScheduleAggregationWorker, '#perform', :clean_gitlab_redis_ expect(group.aggregation_schedule).to be_present end end - - context 'when update_statistics_namespace is off' do - it 'does not create a new one' do - stub_feature_flags(update_statistics_namespace: false, namespace: group) - - expect do - worker.perform(group.id) - end.not_to change(Namespace::AggregationSchedule, :count) - end - end end context 'when group is not the root ancestor' do diff --git a/yarn.lock b/yarn.lock index 221ffa27f6c..11e51d7690d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -996,10 +996,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.67.0.tgz#c7b94eca13b99fd3aaa737fb6dcc0abc41d3c579" integrity sha512-hJOmWEs6RkjzyKkb1vc9wwKGZIBIP0coHkxu/KgOoxhBVudpGk4CH7xJ6UuB2TKpb0SEh5CC1CzRZfBYaFhsaA== -"@gitlab/ui@^5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-5.11.1.tgz#10ee8a4410eb249032142f85f6180b6c465c48d7" - integrity sha512-bxIB3//aaYZIT6fpDKhIW60gvVvOCbw6inqC8xffQmklFYFKgcZjEIBu3RH5oJ6t3zFxeelcPQG7+t2F+p3bIg== +"@gitlab/ui@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-5.12.0.tgz#e44a227de3df287c63eb36162361fb451e344f69" + integrity sha512-QCKG3gaO4UL5yqGNqcioPPFz3rJl6J22tt8DwgARAFREGu20KK0VChHEY0xOyShCU595mKz0XgJZF+8NuxXUtw== dependencies: "@babel/standalone" "^7.0.0" "@gitlab/vue-toasted" "^1.2.1" @@ -8354,7 +8354,7 @@ moment-mini@^2.22.1: resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.22.1.tgz#bc32d73e43a4505070be6b53494b17623183420d" integrity sha512-OUCkHOz7ehtNMYuZjNciXUfwTuz8vmF1MTbAy59ebf+ZBYZO5/tZKuChVWCX+uDo+4idJBpGltNfV8st+HwsGw== -moment@2.x, moment@^2.10.2: +moment@^2.10.2: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -9308,12 +9308,10 @@ pify@^4.0.0, pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pikaday@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.6.1.tgz#b91bcb9b8539cedd8d6d08e4e7465e12095671b0" - integrity sha512-B+pxVcSGuzLblMe4dnhCF3dnI2zkyj5GAqanGX9cVcOk90fp2ULo1OZFUPRXQXUE5tmcimnk1tPOFs8tUHQetQ== - optionalDependencies: - moment "2.x" +pikaday@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.8.0.tgz#ce930e257042e852e6aadee1115e01554b2d71c5" + integrity sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA== pinkie-promise@^2.0.0: version "2.0.1" |