diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-06 15:08:36 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-06 15:08:36 +0300 |
commit | c1f785fe21ee785618ef3bf0407fee166b6e0ecd (patch) | |
tree | 4807aa3c9dfa10ac1e52554057e407b1af310888 | |
parent | 5d3eac1cf8820b5f95bf2085ccc246ea78f4b4d2 (diff) |
Add latest changes from gitlab-org/gitlab@master
37 files changed, 269 insertions, 967 deletions
diff --git a/.gitpod.yml b/.gitpod.yml index 07cc7f2ecb6..3fb623b9fb6 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -5,6 +5,7 @@ tasks: - name: GDK command: | echo START_TIME_IN_SECONDS="$(date +%s)" | tee /workspace/gitpod_start_time.sh + gp sync-done gitpod-start gp sync-await gdk-copied && cd /workspace/gitlab-development-kit && gdk help - init: | @@ -35,9 +36,10 @@ tasks: ) command: | ( + gp sync-await gitpod-start set -e gp sync-done gdk-copied - source /workspace/gitpod_start_time.sh + [[ -f /workspace/gitpod_start_time.sh ]] && source /workspace/gitpod_start_time.sh SECONDS=0 cd /workspace/gitlab-development-kit # update GDK @@ -72,7 +74,7 @@ tasks: git checkout db/structure.sql cd /workspace/gitlab-development-kit # Waiting for GitLab ... - gp await-port 3000 + gp ports await 3000 printf "Waiting for GitLab at $(gp url 3000) ..." # Check /-/readiness which returns JSON, but we're only interested in the exit code # @@ -84,7 +86,7 @@ tasks: printf "$(date) – GitLab is up (took ~%.1f minutes)\n" "$((10*$SECONDS/60))e-1" | tee -a /workspace/startup.log gp preview $(gp url 3000) || true PREBUILD_LOG=(/workspace/.gitpod/prebuild-log-*) - printf "Took %.1f minutes from https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitpod.yml being executed through to completion %s\n" "$((10*(($(date +%s)-${START_TIME_IN_SECONDS}))/60))e-1" "$([[ -f "$PREBUILD_LOG" ]] && echo "With Prebuilds")" + [[ -f /workspace/gitpod_start_time.sh ]] && printf "Took %.1f minutes from https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitpod.yml being executed through to completion %s\n" "$((10*(($(date +%s)-${START_TIME_IN_SECONDS}))/60))e-1" "$([[ -f "$PREBUILD_LOG" ]] && echo "With Prebuilds")" ) ports: diff --git a/app/assets/javascripts/logs/components/log_control_buttons.vue b/app/assets/javascripts/logs/components/log_control_buttons.vue deleted file mode 100644 index e44b5394fa1..00000000000 --- a/app/assets/javascripts/logs/components/log_control_buttons.vue +++ /dev/null @@ -1,95 +0,0 @@ -<script> -import { GlButton, GlTooltipDirective } from '@gitlab/ui'; - -export default { - components: { - GlButton, - }, - directives: { - GlTooltip: GlTooltipDirective, - }, - props: { - scrollUpButtonDisabled: { - type: Boolean, - required: false, - default: false, - }, - scrollDownButtonDisabled: { - type: Boolean, - required: false, - default: false, - }, - }, - data() { - return { - scrollUpAvailable: Boolean(this.$listeners.scrollUp), - scrollDownAvailable: Boolean(this.$listeners.scrollDown), - }; - }, - methods: { - handleRefreshClick() { - this.$emit('refresh'); - }, - handleScrollUp() { - this.$emit('scrollUp'); - }, - handleScrollDown() { - this.$emit('scrollDown'); - }, - }, -}; -</script> - -<template> - <div> - <div - v-if="scrollUpAvailable" - v-gl-tooltip - class="controllers-buttons" - :title="__('Scroll to top')" - aria-labelledby="scroll-to-top" - > - <gl-button - id="scroll-to-top" - class="js-scroll-to-top gl-mr-2 btn-blank" - :aria-label="__('Scroll to top')" - :disabled="scrollUpButtonDisabled" - icon="scroll_up" - category="primary" - variant="default" - @click="handleScrollUp()" - /> - </div> - <div - v-if="scrollDownAvailable" - v-gl-tooltip - :disabled="scrollUpButtonDisabled" - class="controllers-buttons" - :title="__('Scroll to bottom')" - aria-labelledby="scroll-to-bottom" - > - <gl-button - id="scroll-to-bottom" - class="js-scroll-to-bottom gl-mr-2 btn-blank" - :aria-label="__('Scroll to bottom')" - :v-if="scrollDownAvailable" - :disabled="scrollDownButtonDisabled" - icon="scroll_down" - category="primary" - variant="default" - @click="handleScrollDown()" - /> - </div> - <gl-button - id="refresh-log" - v-gl-tooltip - class="js-refresh-log" - :title="__('Refresh')" - :aria-label="__('Refresh')" - icon="retry" - category="primary" - variant="default" - @click="handleRefreshClick" - /> - </div> -</template> diff --git a/app/assets/javascripts/logs/components/log_simple_filters.vue b/app/assets/javascripts/logs/components/log_simple_filters.vue deleted file mode 100644 index 55bdd5f0088..00000000000 --- a/app/assets/javascripts/logs/components/log_simple_filters.vue +++ /dev/null @@ -1,68 +0,0 @@ -<script> -import { GlDropdown, GlDropdownSectionHeader, GlDropdownItem } from '@gitlab/ui'; -import { mapActions, mapState } from 'vuex'; -import { s__ } from '~/locale'; - -export default { - components: { - GlDropdown, - GlDropdownSectionHeader, - GlDropdownItem, - }, - props: { - disabled: { - type: Boolean, - required: false, - default: false, - }, - }, - data() { - return { - searchQuery: '', - }; - }, - computed: { - ...mapState('environmentLogs', ['pods']), - - podDropdownText() { - return this.pods.current || s__('Environments|No pod selected'); - }, - }, - methods: { - ...mapActions('environmentLogs', ['showPodLogs']), - isCurrentPod(podName) { - return podName === this.pods.current; - }, - }, -}; -</script> -<template> - <div> - <gl-dropdown - ref="podsDropdown" - :text="podDropdownText" - :disabled="disabled" - class="gl-mr-3 gl-mb-3 gl-display-flex gl-md-display-block qa-pods-dropdown" - > - <gl-dropdown-section-header> - {{ s__('Environments|Select pod') }} - </gl-dropdown-section-header> - - <gl-dropdown-item v-if="!pods.options.length" disabled> - <span ref="noPodsMsg" class="text-muted"> - {{ s__('Environments|No pods to display') }} - </span> - </gl-dropdown-item> - <gl-dropdown-item - v-for="podName in pods.options" - :key="podName" - :is-check-item="true" - :is-checked="isCurrentPod(podName)" - class="text-nowrap" - @click="showPodLogs(podName)" - > - {{ podName }} - </gl-dropdown-item> - </gl-dropdown> - </div> -</template> diff --git a/app/assets/javascripts/logs/components/tokens/token_with_loading_state.vue b/app/assets/javascripts/logs/components/tokens/token_with_loading_state.vue deleted file mode 100644 index 4e672c1d121..00000000000 --- a/app/assets/javascripts/logs/components/tokens/token_with_loading_state.vue +++ /dev/null @@ -1,30 +0,0 @@ -<script> -import { GlFilteredSearchToken, GlLoadingIcon } from '@gitlab/ui'; - -export default { - components: { - GlFilteredSearchToken, - GlLoadingIcon, - }, - inheritAttrs: false, - props: { - config: { - type: Object, - required: true, - }, - }, -}; -</script> - -<template> - <gl-filtered-search-token :config="config" v-bind="{ ...$attrs }" v-on="$listeners"> - <template #suggestions> - <div class="m-1"> - <gl-loading-icon v-if="config.loading" size="sm" /> - <div v-else class="py-1 px-2 text-muted"> - {{ config.noOptionsText }} - </div> - </div> - </template> - </gl-filtered-search-token> -</template> diff --git a/app/assets/javascripts/logs/stores/mutation_types.js b/app/assets/javascripts/logs/stores/mutation_types.js deleted file mode 100644 index c1ed65ff48b..00000000000 --- a/app/assets/javascripts/logs/stores/mutation_types.js +++ /dev/null @@ -1,26 +0,0 @@ -export const SET_PROJECT_ENVIRONMENT = 'SET_PROJECT_ENVIRONMENT'; -export const SET_SEARCH = 'SET_SEARCH'; -export const SET_MANAGED_APP = 'SET_MANAGED_APP'; - -export const SET_TIME_RANGE = 'SET_TIME_RANGE'; -export const SHOW_TIME_RANGE_INVALID_WARNING = 'SHOW_TIME_RANGE_INVALID_WARNING'; -export const HIDE_TIME_RANGE_INVALID_WARNING = 'HIDE_TIME_RANGE_INVALID_WARNING'; - -export const SET_CURRENT_POD_NAME = 'SET_CURRENT_POD_NAME'; - -export const REQUEST_ENVIRONMENTS_DATA = 'REQUEST_ENVIRONMENTS_DATA'; -export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCCESS'; -export const RECEIVE_ENVIRONMENTS_DATA_ERROR = 'RECEIVE_ENVIRONMENTS_DATA_ERROR'; -export const HIDE_REQUEST_ENVIRONMENTS_ERROR = 'HIDE_REQUEST_ENVIRONMENTS_ERROR'; - -export const REQUEST_LOGS_DATA = 'REQUEST_LOGS_DATA'; -export const RECEIVE_LOGS_DATA_SUCCESS = 'RECEIVE_LOGS_DATA_SUCCESS'; -export const RECEIVE_LOGS_DATA_ERROR = 'RECEIVE_LOGS_DATA_ERROR'; -export const REQUEST_LOGS_DATA_PREPEND = 'REQUEST_LOGS_DATA_PREPEND'; -export const RECEIVE_LOGS_DATA_PREPEND_SUCCESS = 'RECEIVE_LOGS_DATA_PREPEND_SUCCESS'; -export const RECEIVE_LOGS_DATA_PREPEND_ERROR = 'RECEIVE_LOGS_DATA_PREPEND_ERROR'; -export const HIDE_REQUEST_LOGS_ERROR = 'HIDE_REQUEST_LOGS_ERROR'; -export const REFRESH_POD_LOGS = 'REFRESH_POD_LOGS'; - -export const RECEIVE_PODS_DATA_SUCCESS = 'RECEIVE_PODS_DATA_SUCCESS'; -export const RECEIVE_PODS_DATA_ERROR = 'RECEIVE_PODS_DATA_ERROR'; diff --git a/app/assets/javascripts/logs/stores/mutations.js b/app/assets/javascripts/logs/stores/mutations.js deleted file mode 100644 index 6736d7204b4..00000000000 --- a/app/assets/javascripts/logs/stores/mutations.js +++ /dev/null @@ -1,110 +0,0 @@ -import { convertToFixedRange } from '~/lib/utils/datetime_range'; -import * as types from './mutation_types'; - -const mapLine = ({ timestamp, pod, message }) => ({ - timestamp, - pod, - message, -}); - -export default { - // Search Data - [types.SET_SEARCH](state, searchQuery) { - state.search = searchQuery; - }, - - // Time Range Data - [types.SET_TIME_RANGE](state, timeRange) { - state.timeRange.selected = timeRange; - state.timeRange.current = convertToFixedRange(timeRange); - }, - [types.SHOW_TIME_RANGE_INVALID_WARNING](state) { - state.timeRange.invalidWarning = true; - }, - [types.HIDE_TIME_RANGE_INVALID_WARNING](state) { - state.timeRange.invalidWarning = false; - }, - - // Environments Data - [types.SET_PROJECT_ENVIRONMENT](state, environmentName) { - state.environments.current = environmentName; - - // Clear current pod options - state.pods.current = null; - state.pods.options = []; - }, - [types.REQUEST_ENVIRONMENTS_DATA](state) { - state.environments.options = []; - state.environments.isLoading = true; - }, - [types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS](state, environmentOptions) { - state.environments.options = environmentOptions; - state.environments.isLoading = false; - }, - [types.RECEIVE_ENVIRONMENTS_DATA_ERROR](state) { - state.environments.options = []; - state.environments.isLoading = false; - state.environments.fetchError = true; - }, - [types.HIDE_REQUEST_ENVIRONMENTS_ERROR](state) { - state.environments.fetchError = false; - }, - - // Logs data - [types.REQUEST_LOGS_DATA](state) { - state.timeRange.current = convertToFixedRange(state.timeRange.selected); - - state.logs.lines = []; - state.logs.isLoading = true; - - // start pagination from the beginning - state.logs.cursor = null; - state.logs.isComplete = false; - }, - [types.RECEIVE_LOGS_DATA_SUCCESS](state, { logs = [], cursor }) { - state.logs.lines = logs.map(mapLine); - state.logs.isLoading = false; - state.logs.cursor = cursor; - - if (!cursor) { - state.logs.isComplete = true; - } - }, - [types.RECEIVE_LOGS_DATA_ERROR](state) { - state.logs.lines = []; - state.logs.isLoading = false; - state.logs.fetchError = true; - }, - - [types.REQUEST_LOGS_DATA_PREPEND](state) { - state.logs.isLoading = true; - }, - [types.RECEIVE_LOGS_DATA_PREPEND_SUCCESS](state, { logs = [], cursor }) { - const lines = logs.map(mapLine); - state.logs.lines = lines.concat(state.logs.lines); - state.logs.isLoading = false; - state.logs.cursor = cursor; - - if (!cursor) { - state.logs.isComplete = true; - } - }, - [types.RECEIVE_LOGS_DATA_PREPEND_ERROR](state) { - state.logs.isLoading = false; - state.logs.fetchError = true; - }, - [types.HIDE_REQUEST_LOGS_ERROR](state) { - state.logs.fetchError = false; - }, - - // Pods data - [types.SET_CURRENT_POD_NAME](state, podName) { - state.pods.current = podName; - }, - [types.RECEIVE_PODS_DATA_SUCCESS](state, podOptions) { - state.pods.options = podOptions; - }, - [types.RECEIVE_PODS_DATA_ERROR](state) { - state.pods.options = []; - }, -}; diff --git a/app/assets/javascripts/logs/stores/state.js b/app/assets/javascripts/logs/stores/state.js deleted file mode 100644 index ee17e8ecef2..00000000000 --- a/app/assets/javascripts/logs/stores/state.js +++ /dev/null @@ -1,56 +0,0 @@ -import { convertToFixedRange } from '~/lib/utils/datetime_range'; -import { timeRanges, defaultTimeRange } from '~/vue_shared/constants'; - -export default () => ({ - /** - * Full text search - */ - search: '', - - /** - * Time range (Show last) - */ - timeRange: { - options: timeRanges, - // Selected time range, can be fixed or relative - selected: defaultTimeRange, - // Current time range, must be fixed - current: convertToFixedRange(defaultTimeRange), - - invalidWarning: false, - }, - - /** - * Environments list information - */ - environments: { - options: [], - isLoading: false, - current: null, - fetchError: false, - }, - - /** - * Jobs with logs - */ - logs: { - lines: [], - isLoading: false, - /** - * Logs `cursor` represents the current pagination position, - * Should be sent in next batch (page) of logs to be fetched - */ - cursor: null, - isComplete: false, - - fetchError: false, - }, - - /** - * Pods list information - */ - pods: { - options: [], - current: null, - }, -}); diff --git a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js index 482a3ef2ead..3689199751d 100644 --- a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js +++ b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js @@ -1,7 +1,6 @@ import { GlToast } from '@gitlab/ui'; import Vue from 'vue'; -import { parseBoolean } from '~/lib/utils/common_utils'; import Translate from '~/vue_shared/translate'; import SettingsApp from './components/group_settings_app.vue'; import { apolloProvider } from './graphql'; @@ -20,7 +19,6 @@ export default () => { provide: { groupPath: el.dataset.groupPath, groupDependencyProxyPath: el.dataset.groupDependencyProxyPath, - defaultExpanded: parseBoolean(el.dataset.defaultExpanded), }, render(createElement) { return createElement(SettingsApp); diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue index 4c17b555d1b..59d4f5e24d0 100644 --- a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue +++ b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue @@ -1,7 +1,7 @@ <script> import { GlToggle, GlSprintf, GlLink } from '@gitlab/ui'; import { s__ } from '~/locale'; -import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue'; +import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue'; import updateDependencyProxySettings from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_settings.mutation.graphql'; import updateDependencyProxyImageTtlGroupPolicy from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql'; import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update'; @@ -39,7 +39,7 @@ export default { links: { DEPENDENCY_PROXY_DOCS_PATH, }, - inject: ['defaultExpanded', 'groupPath', 'groupDependencyProxyPath'], + inject: ['groupPath', 'groupDependencyProxyPath'], props: { dependencyProxySettings: { type: Object, @@ -129,10 +129,7 @@ export default { </script> <template> - <settings-block - :default-expanded="defaultExpanded" - data-qa-selector="dependency_proxy_settings_content" - > + <settings-block data-qa-selector="dependency_proxy_settings_content"> <template #title> {{ $options.i18n.DEPENDENCY_PROXY_HEADER }} </template> <template #description> {{ $options.i18n.DEPENDENCY_PROXY_DESCRIPTION }} </template> <template #default> diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue index 14b51a92754..f8c35338262 100644 --- a/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue +++ b/app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue @@ -9,7 +9,7 @@ import { import updateNamespacePackageSettings from '~/packages_and_registries/settings/group/graphql/mutations/update_group_packages_settings.mutation.graphql'; import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update'; import { updateGroupPackagesSettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses'; -import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue'; +import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue'; export default { name: 'PackageSettings', @@ -23,7 +23,7 @@ export default { GenericSettings, DuplicatesSettings, }, - inject: ['defaultExpanded', 'groupPath'], + inject: ['groupPath'], props: { packageSettings: { type: Object, @@ -84,10 +84,7 @@ export default { </script> <template> - <settings-block - :default-expanded="defaultExpanded" - data-qa-selector="package_registry_settings_content" - > + <settings-block data-qa-selector="package_registry_settings_content"> <template #title> {{ $options.i18n.PACKAGE_SETTINGS_HEADER }}</template> <template #description> <span data-testid="description"> diff --git a/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue b/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue new file mode 100644 index 00000000000..5caf95cd050 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue @@ -0,0 +1,17 @@ +<template> + <section class="settings gl-py-7"> + <div class="gl-lg-display-flex"> + <div class="gl-lg-w-half gl-pr-10"> + <h4> + <slot name="title"></slot> + </h4> + <p> + <slot name="description"></slot> + </p> + </div> + <div class="gl-lg-w-half gl-pt-3"> + <slot></slot> + </div> + </div> + </section> +</template> diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index d0f058f6c68..ef6fac8863e 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -28,6 +28,7 @@ &:first-of-type { margin-top: 10px; + padding-top: 0; border: 0; } diff --git a/app/models/concerns/ci/artifactable.rb b/app/models/concerns/ci/artifactable.rb index 78340cf967b..fb4ea4206f4 100644 --- a/app/models/concerns/ci/artifactable.rb +++ b/app/models/concerns/ci/artifactable.rb @@ -30,6 +30,8 @@ module Ci raise NotSupportedAdapterError, 'This file format requires a dedicated adapter' end + ::Gitlab::ApplicationContext.push(artifact: file.model) + file.open do |stream| file_format_adapter_class.new(stream).each_blob(&blk) end diff --git a/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml b/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml index bed671832f3..3e0a8a4f88b 100644 --- a/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml +++ b/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml @@ -2,10 +2,11 @@ - help_path = local_assigns.fetch(:help_path) - label = local_assigns.fetch(:label) - last = local_assigns.fetch(:last, false) -- classes = ["btn btn-confirm gl-button btn-confirm-secondary gl-flex-direction-column gl-w-half"] +- classes = ["btn btn-confirm gl-button btn-confirm-secondary gl-flex-direction-column gl-flex-basis-0 gl-flex-grow-1 gl-min-w-0"] - conditional_classes = [("gl-mr-5" unless last)] = link_to help_path, class: classes + conditional_classes do - .svg-content.gl-p-3= image_tag logo_path, alt: label, class: "gl-w-64 gl-h-64" - %span + %span.gl-display-flex.gl-align-items-center.gl-m-3.gl-h-64 + = image_tag logo_path, alt: label, class: "gl-w-15 gl-max-h-full gl-max-w-full" + %span.gl-white-space-normal = label diff --git a/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml b/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml index e4128ee22a4..7039ce57bd9 100644 --- a/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml +++ b/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml @@ -1,14 +1,18 @@ - gke_label = s_('ClusterIntegration|Google GKE') - eks_label = s_('ClusterIntegration|Amazon EKS') +- civo_label = s_('ClusterIntegration|Civo Kubernetes') - create_cluster_label = s_('ClusterIntegration|Where do you want to create a cluster?') -- eks_help_path = help_page_path('user/infrastructure/clusters/connect/new_eks_cluster') -- gke_help_path = help_page_path('user/infrastructure/clusters/connect/new_gke_cluster') +- eks_help_path = help_page_path('user/infrastructure/clusters/connect/new_eks_cluster.md') +- gke_help_path = help_page_path('user/infrastructure/clusters/connect/new_gke_cluster.md') +- civo_help_path = help_page_path('user/infrastructure/clusters/connect/new_civo_cluster.md') -.gl-p-5 +.gl-py-5.gl-md-pl-5.gl-md-pr-5 %h4.gl-mb-5 = create_cluster_label .gl-display-flex = render partial: 'clusters/clusters/cloud_providers/cloud_provider_button', locals: { label: eks_label, logo_path: 'illustrations/logos/amazon_eks.svg', help_path: eks_help_path } = render partial: 'clusters/clusters/cloud_providers/cloud_provider_button', + locals: { label: civo_label, logo_path: 'illustrations/third-party-logos/civo.svg', help_path: civo_help_path } + = render partial: 'clusters/clusters/cloud_providers/cloud_provider_button', locals: { label: gke_label, logo_path: 'illustrations/logos/google_gke.svg', help_path: gke_help_path, last: true } diff --git a/app/views/groups/settings/packages_and_registries/show.html.haml b/app/views/groups/settings/packages_and_registries/show.html.haml index c4ce76c43ec..888419e463a 100644 --- a/app/views/groups/settings/packages_and_registries/show.html.haml +++ b/app/views/groups/settings/packages_and_registries/show.html.haml @@ -2,6 +2,5 @@ - page_title _('Packages & Registries') - @content_class = 'limit-container-width' unless fluid_layout -%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s, - group_path: @group.full_path, +%section#js-packages-and-registries-settings{ data: { group_path: @group.full_path, group_dependency_proxy_path: group_dependency_proxy_path(@group) } } diff --git a/config/initializers/0_log_deprecations.rb b/config/initializers/0_log_deprecations.rb index 20fb5144937..6ba18ea1136 100644 --- a/config/initializers/0_log_deprecations.rb +++ b/config/initializers/0_log_deprecations.rb @@ -9,11 +9,15 @@ end if log_deprecations? # Log deprecation warnings emitted through Kernel#warn, such as from gems or # the Ruby VM. - Warning.process(/.+is deprecated$/) do |warning| - Gitlab::DeprecationJsonLogger.info(message: warning.strip, source: 'ruby') - # Returning :default means we continue emitting this to stderr as well. - :default - end + actions = { + /.+is deprecated$/ => lambda do |warning| + Gitlab::DeprecationJsonLogger.info(message: warning.strip, source: 'ruby') + # Returning :default means we continue emitting this to stderr as well. + :default + end + } + + Warning.process('', actions) # Log deprecation warnings emitted from Rails (see ActiveSupport::Deprecation). ActiveSupport::Notifications.subscribe('deprecation.rails') do |name, start, finish, id, payload| diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md index 479e78ba0dc..d99e9a0a04b 100644 --- a/doc/administration/sidekiq.md +++ b/doc/administration/sidekiq.md @@ -6,19 +6,91 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Configure an external Sidekiq instance **(FREE SELF)** -You can configure an external Sidekiq instance by using the Sidekiq that's -bundled in the GitLab package. Sidekiq requires connection to the Redis, +You can configure an external Sidekiq instance by using the Sidekiq that's bundled in the GitLab package. Sidekiq requires connection to the Redis, PostgreSQL, and Gitaly instances. -## Required configuration +## Configure TCP access for PostgreSQL, Gitaly, and Redis -To configure Sidekiq: +By default, GitLab uses UNIX sockets and is not set up to communicate via TCP. To change this: + +1. Edit the `/etc/gitlab/gitlab.rb` file on your GitLab instance and add the following: + + ```ruby + + ## PostgreSQL + + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' + postgresql['listen_address'] = '0.0.0.0' + postgresql['port'] = 5432 + + # Add the Sidekiq nodes to PostgreSQL's trusted addresses. + # In the following example, 10.10.1.30/32 is the private IP + # of the Sidekiq server. + postgresql['md5_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32) + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32) + + ## Gitaly + + # Make Gitaly accept connections on all network interfaces + gitaly['listen_addr'] = "0.0.0.0:8075" + ## Set up the Gitaly token as a form of authentication since you are accessing Gitaly over the network + ## https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#about-the-gitaly-token + gitaly['auth_token'] = 'abc123secret' + praefect['auth_token'] = 'abc123secret' + gitlab_rails['gitaly_token'] = 'abc123secret' + + ## Redis configuration + + redis['bind'] = '0.0.0.0' + redis['port'] = 6379 + # Password to Authenticate Redis + redis['password'] = 'redis-password-goes-here' + + gitlab_rails['auto_migrate'] = false + ``` + +1. Run `reconfigure`: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +1. Restart the `PostgreSQL` server: + + ```shell + sudo gitlab-ctl restart postgresql + ``` + +1. After the restart, set `auto_migrate` to `true` or comment to use the default settings: + + ```ruby + gitlab_rails['auto_migrate'] = true + ``` + +1. Run `reconfigure` again: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +## Set up Sidekiq instance 1. SSH into the Sidekiq server. + +1. Confirm that you can access the PostgreSQL, Gitaly, and Redis ports: + + ```shell + telnet <GitLab host> 5432 # PostgreSQL + telnet <GitLab host> 8075 # Gitaly + telnet <GitLab host> 6379 # Redis + ``` + 1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab package using steps 1 and 2. **Do not complete any other steps.** -1. Edit `/etc/gitlab/gitlab.rb` with the following information and make sure - to replace with your values: + +1. Copy the `/etc/gitlab/gitlab.rb` file from the GitLab instance and add the following settings. Make sure + to replace them with your values: <!-- Updates to example must be made at: @@ -59,15 +131,24 @@ Updates to example must be made at: ## external_url 'https://gitlab.example.com' + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + gitlab_rails['internal_api_url'] = 'GITLAB_URL' + gitlab_shell['secret_token'] = 'SHELL_TOKEN' + ######################################## #### Redis ### ######################################## - ## Must be the same in every sentinel node - redis['master_name'] = 'gitlab-redis' - + ## Must be the same in every sentinel node. + redis['master_name'] = 'gitlab-redis' # Required if you have setup redis cluster ## The same password for Redis authentication you set up for the master node. redis['master_password'] = '<redis_master_password>' + + ### If redis is running on the main Gitlab instance and you have opened the TCP port as above add the following + gitlab_rails['redis_host'] = '<gitlab host>' + gitlab_rails['redis_port'] = 6379 ####################################### ### Gitaly ### @@ -78,7 +159,7 @@ Updates to example must be made at: git_data_dirs({ "default" => { "gitaly_address" => "tcp://gitaly:8075", - "gitaly_token" => "<gitaly_token>" + "gitaly_token" => "<gitaly_token>" } }) @@ -90,12 +171,6 @@ Updates to example must be made at: gitlab_rails['db_host'] = '<database_host>' gitlab_rails['db_port'] = '5432' gitlab_rails['db_password'] = '<database_password>' - - # Add the Sidekiq nodes to PostgreSQL's trusted addresses. - # In the following example, 10.10.1.30/32 is the private IP - # of the Sidekiq server. - postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32) - ## Prevent database migrations from running on upgrade automatically gitlab_rails['auto_migrate'] = false @@ -112,13 +187,15 @@ Updates to example must be made at: sidekiq['max_concurrency'] = 10 ``` +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the GitLab instance and replace the file in the Sidekiq instance. + 1. Reconfigure GitLab: ```shell sudo gitlab-ctl reconfigure ``` -1. Restart the Sidekiq nodes after completing the process and finishing the database migrations. +1. Restart the Sidekiq instance after completing the process and finishing the database migrations. ## Configure multiple Sidekiq nodes with shared storage @@ -218,7 +295,7 @@ To make health checks available from `localhost:8092`: 1. Edit `/etc/gitlab/gitlab.rb`: - ```ruby + ```ruby sidekiq['health_checks_enabled'] = true sidekiq['health_checks_listen_address'] = "localhost" sidekiq['health_checks_listen_port'] = "8092" diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb index c284160e539..3e119a39e6d 100644 --- a/lib/gitlab/graphql/pagination/keyset/connection.rb +++ b/lib/gitlab/graphql/pagination/keyset/connection.rb @@ -199,7 +199,7 @@ module Gitlab field_name = field.try(:attribute_name) || field field_value = node[field_name] ordering[field_name] = if field_value.is_a?(Time) - field_value.strftime('%Y-%m-%d %H:%M:%S.%N %Z') + field_value.to_s(:inspect) else field_value.to_s end diff --git a/lib/gitlab/pagination/keyset/order.rb b/lib/gitlab/pagination/keyset/order.rb index eecf74b8d18..0d8e4ea6fee 100644 --- a/lib/gitlab/pagination/keyset/order.rb +++ b/lib/gitlab/pagination/keyset/order.rb @@ -96,7 +96,9 @@ module Gitlab column_definitions.each_with_object({}.with_indifferent_access) do |column_definition, hash| field_value = node[column_definition.attribute_name] hash[column_definition.attribute_name] = if field_value.is_a?(Time) - field_value.strftime('%Y-%m-%d %H:%M:%S.%N %Z') + # use :inspect formatter to provide specific timezone info + # eg 2022-07-05 21:57:56.041499000 +0800 + field_value.to_s(:inspect) elsif field_value.nil? nil elsif lower_named_function?(column_definition) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b7500d308e1..61bbb20d19a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8812,6 +8812,9 @@ msgstr "" msgid "ClusterIntegration|Choose which of your environments will use this cluster." msgstr "" +msgid "ClusterIntegration|Civo Kubernetes" +msgstr "" + msgid "ClusterIntegration|Clear cluster cache" msgstr "" @@ -14665,12 +14668,6 @@ msgstr "" msgid "Environments|No deployments yet" msgstr "" -msgid "Environments|No pod selected" -msgstr "" - -msgid "Environments|No pods to display" -msgstr "" - msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file." msgstr "" @@ -14695,9 +14692,6 @@ msgstr "" msgid "Environments|Rollback environment %{name}?" msgstr "" -msgid "Environments|Select pod" -msgstr "" - msgid "Environments|Show all" msgstr "" @@ -31748,9 +31742,6 @@ msgstr "" msgid "Refine your search criteria (select a %{strong_open}group%{strong_close} and %{strong_open}project%{strong_close} when possible)" msgstr "" -msgid "Refresh" -msgstr "" - msgid "Refresh the page and try again." msgstr "" @@ -34359,7 +34350,7 @@ msgstr "" msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again." msgstr "" -msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects in this group." +msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects and sub-groups in this group." msgstr "" msgid "SecurityOrchestration|All policies" diff --git a/scripts/pipeline_test_report_builder.rb b/scripts/pipeline_test_report_builder.rb index 2101decf59a..5299dba3f97 100755 --- a/scripts/pipeline_test_report_builder.rb +++ b/scripts/pipeline_test_report_builder.rb @@ -72,6 +72,10 @@ class PipelineTestReportBuilder # Please see for more info: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69053#note_709939709 def test_report_for_build(pipeline, build_id) fetch("#{pipeline['web_url']}/tests/suite.json?build_ids[]=#{build_id}") + rescue Net::HTTPServerException => e + raise e unless e.response.code == 404 + + puts "Artifacts not found. They may have expired. Skipping this build." end def build_test_report_json_for_pipeline(pipeline) @@ -92,7 +96,8 @@ class PipelineTestReportBuilder test_report['suites'] ||= [] failed_builds_for_test_stage.each do |failed_build| - test_report['suites'] << test_report_for_build(pipeline, failed_build['id']) + suite = test_report_for_build(pipeline, failed_build['id']) + test_report['suites'] << suite if suite end end diff --git a/spec/features/groups/settings/packages_and_registries_spec.rb b/spec/features/groups/settings/packages_and_registries_spec.rb index d79d9c89999..98dc534f54e 100644 --- a/spec/features/groups/settings/packages_and_registries_spec.rb +++ b/spec/features/groups/settings/packages_and_registries_spec.rb @@ -60,7 +60,6 @@ RSpec.describe 'Group Packages & Registries settings' do visit_settings_page expect(page).to have_content('Duplicate packages') - expect(page).to have_button('Collapse') end it 'automatically saves changes to the server', :js do diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js deleted file mode 100644 index e249272b87d..00000000000 --- a/spec/frontend/logs/components/log_control_buttons_spec.js +++ /dev/null @@ -1,88 +0,0 @@ -import { GlButton } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { nextTick } from 'vue'; -import LogControlButtons from '~/logs/components/log_control_buttons.vue'; - -describe('LogControlButtons', () => { - let wrapper; - - const findScrollToTop = () => wrapper.find('.js-scroll-to-top'); - const findScrollToBottom = () => wrapper.find('.js-scroll-to-bottom'); - const findRefreshBtn = () => wrapper.find('.js-refresh-log'); - - const initWrapper = (opts) => { - wrapper = shallowMount(LogControlButtons, { - listeners: { - scrollUp: () => {}, - scrollDown: () => {}, - }, - ...opts, - }); - }; - - afterEach(() => { - if (wrapper) { - wrapper.destroy(); - } - }); - - it('displays UI elements', () => { - initWrapper(); - - expect(findScrollToTop().is(GlButton)).toBe(true); - expect(findScrollToBottom().is(GlButton)).toBe(true); - expect(findRefreshBtn().is(GlButton)).toBe(true); - }); - - it('emits a `refresh` event on click on `refresh` button', async () => { - initWrapper(); - - // An `undefined` value means no event was emitted - expect(wrapper.emitted('refresh')).toBe(undefined); - - findRefreshBtn().vm.$emit('click'); - - await nextTick(); - expect(wrapper.emitted('refresh')).toHaveLength(1); - }); - - describe('when scrolling actions are enabled', () => { - beforeEach(async () => { - // mock scrolled to the middle of a long page - initWrapper(); - await nextTick(); - }); - - it('click on "scroll to top" scrolls up', () => { - expect(findScrollToTop().attributes('disabled')).toBeUndefined(); - - findScrollToTop().vm.$emit('click'); - - expect(wrapper.emitted('scrollUp')).toHaveLength(1); - }); - - it('click on "scroll to bottom" scrolls down', () => { - expect(findScrollToBottom().attributes('disabled')).toBeUndefined(); - - findScrollToBottom().vm.$emit('click'); - - expect(wrapper.emitted('scrollDown')).toHaveLength(1); - }); - }); - - describe('when scrolling actions are disabled', () => { - beforeEach(async () => { - initWrapper({ listeners: {} }); - await nextTick(); - }); - - it('buttons are disabled', async () => { - await nextTick(); - expect(findScrollToTop().exists()).toBe(false); - expect(findScrollToBottom().exists()).toBe(false); - // This should be enabled when gitlab-ui contains: - // https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1149 - // expect(findScrollToBottom().is('[disabled]')).toBe(true); - }); - }); -}); diff --git a/spec/frontend/logs/components/tokens/token_with_loading_state_spec.js b/spec/frontend/logs/components/tokens/token_with_loading_state_spec.js deleted file mode 100644 index f667a590a36..00000000000 --- a/spec/frontend/logs/components/tokens/token_with_loading_state_spec.js +++ /dev/null @@ -1,71 +0,0 @@ -import { GlFilteredSearchToken, GlLoadingIcon } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; - -import TokenWithLoadingState from '~/logs/components/tokens/token_with_loading_state.vue'; - -describe('TokenWithLoadingState', () => { - let wrapper; - - const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken); - const findLoadingIcon = () => wrapper.find(GlLoadingIcon); - - const initWrapper = (props = {}, options) => { - wrapper = shallowMount(TokenWithLoadingState, { - propsData: { - cursorPosition: 'start', - ...props, - }, - ...options, - }); - }; - - beforeEach(() => {}); - - it('passes entire config correctly', () => { - const config = { - icon: 'pod', - type: 'pod', - title: 'Pod name', - unique: true, - }; - - initWrapper({ config }); - - expect(findFilteredSearchToken().props('config')).toEqual(config); - }); - - describe('suggestions are replaced', () => { - let mockNoOptsText; - let config; - let stubs; - - beforeEach(() => { - mockNoOptsText = 'No suggestions available'; - config = { - loading: false, - noOptionsText: mockNoOptsText, - }; - stubs = { - GlFilteredSearchToken: { - template: `<div><slot name="suggestions"></slot></div>`, - }, - }; - }); - - it('renders a loading icon', () => { - config.loading = true; - - initWrapper({ config }, { stubs }); - - expect(findLoadingIcon().exists()).toBe(true); - expect(wrapper.text()).toBe(''); - }); - - it('renders an empty results message', () => { - initWrapper({ config }, { stubs }); - - expect(findLoadingIcon().exists()).toBe(false); - expect(wrapper.text()).toBe(mockNoOptsText); - }); - }); -}); diff --git a/spec/frontend/logs/mock_data.js b/spec/frontend/logs/mock_data.js deleted file mode 100644 index 14c8f7a2ba2..00000000000 --- a/spec/frontend/logs/mock_data.js +++ /dev/null @@ -1,71 +0,0 @@ -const mockProjectPath = 'root/autodevops-deploy'; - -export const mockEnvName = 'production'; -export const mockEnvironmentsEndpoint = `${mockProjectPath}/environments.json`; -export const mockEnvId = '99'; -export const mockDocumentationPath = '/documentation.md'; -export const mockLogsEndpoint = '/dummy_logs_path.json'; -export const mockCursor = 'MOCK_CURSOR'; -export const mockNextCursor = 'MOCK_NEXT_CURSOR'; - -const makeMockEnvironment = (id, name, advancedQuerying) => ({ - id, - project_path: mockProjectPath, - name, - logs_api_path: mockLogsEndpoint, - enable_advanced_logs_querying: advancedQuerying, -}); - -export const mockEnvironment = makeMockEnvironment(mockEnvId, mockEnvName, true); -export const mockEnvironments = [ - mockEnvironment, - makeMockEnvironment(101, 'staging', false), - makeMockEnvironment(102, 'review/a-feature', false), -]; - -export const mockPodName = 'production-764c58d697-aaaaa'; -export const mockPods = [ - mockPodName, - 'production-764c58d697-bbbbb', - 'production-764c58d697-ccccc', - 'production-764c58d697-ddddd', -]; - -export const mockLogsResult = [ - { - timestamp: '2019-12-13T13:43:18.2760123Z', - message: 'log line 1', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:18.2760123Z', - message: 'log line A', - pod: 'bar', - }, - { - timestamp: '2019-12-13T13:43:26.8420123Z', - message: 'log line 2', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:26.8420123Z', - message: 'log line B', - pod: 'bar', - }, -]; - -export const mockTrace = [ - 'Dec 13 13:43:18.276 | foo | log line 1', - 'Dec 13 13:43:18.276 | bar | log line A', - 'Dec 13 13:43:26.842 | foo | log line 2', - 'Dec 13 13:43:26.842 | bar | log line B', -]; - -export const mockResponse = { - pod_name: mockPodName, - pods: mockPods, - logs: mockLogsResult, - cursor: mockNextCursor, -}; - -export const mockSearch = 'foo +bar'; diff --git a/spec/frontend/logs/stores/mutations_spec.js b/spec/frontend/logs/stores/mutations_spec.js deleted file mode 100644 index 988197a8350..00000000000 --- a/spec/frontend/logs/stores/mutations_spec.js +++ /dev/null @@ -1,257 +0,0 @@ -import * as types from '~/logs/stores/mutation_types'; -import mutations from '~/logs/stores/mutations'; - -import logsPageState from '~/logs/stores/state'; -import { - mockEnvName, - mockEnvironments, - mockPods, - mockPodName, - mockLogsResult, - mockSearch, - mockCursor, - mockNextCursor, -} from '../mock_data'; - -describe('Logs Store Mutations', () => { - let state; - - beforeEach(() => { - state = logsPageState(); - }); - - it('ensures mutation types are correctly named', () => { - Object.keys(types).forEach((k) => { - expect(k).toEqual(types[k]); - }); - }); - - describe('SET_PROJECT_ENVIRONMENT', () => { - it('sets the environment', () => { - mutations[types.SET_PROJECT_ENVIRONMENT](state, mockEnvName); - expect(state.environments.current).toEqual(mockEnvName); - }); - }); - - describe('SET_SEARCH', () => { - it('sets the search', () => { - mutations[types.SET_SEARCH](state, mockSearch); - expect(state.search).toEqual(mockSearch); - }); - }); - - describe('REQUEST_ENVIRONMENTS_DATA', () => { - it('inits data', () => { - mutations[types.REQUEST_ENVIRONMENTS_DATA](state); - expect(state.environments.options).toEqual([]); - expect(state.environments.isLoading).toEqual(true); - }); - }); - - describe('RECEIVE_ENVIRONMENTS_DATA_SUCCESS', () => { - it('receives environments data and stores it as options', () => { - expect(state.environments.options).toEqual([]); - - mutations[types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS](state, mockEnvironments); - - expect(state.environments.options).toEqual(mockEnvironments); - expect(state.environments.isLoading).toEqual(false); - }); - }); - - describe('RECEIVE_ENVIRONMENTS_DATA_ERROR', () => { - it('captures an error loading environments', () => { - mutations[types.RECEIVE_ENVIRONMENTS_DATA_ERROR](state); - - expect(state.environments).toEqual({ - options: [], - isLoading: false, - current: null, - fetchError: true, - }); - }); - }); - - describe('REQUEST_LOGS_DATA', () => { - it('starts loading for logs', () => { - mutations[types.REQUEST_LOGS_DATA](state); - - expect(state.timeRange.current).toEqual({ - start: expect.any(String), - end: expect.any(String), - }); - - expect(state.logs).toEqual({ - lines: [], - cursor: null, - fetchError: false, - isLoading: true, - isComplete: false, - }); - }); - }); - - describe('RECEIVE_LOGS_DATA_SUCCESS', () => { - it('receives logs lines and cursor', () => { - mutations[types.RECEIVE_LOGS_DATA_SUCCESS](state, { - logs: mockLogsResult, - cursor: mockCursor, - }); - - expect(state.logs).toEqual({ - lines: mockLogsResult, - isLoading: false, - cursor: mockCursor, - isComplete: false, - fetchError: false, - }); - }); - - it('receives logs lines and a null cursor to indicate the end', () => { - mutations[types.RECEIVE_LOGS_DATA_SUCCESS](state, { - logs: mockLogsResult, - cursor: null, - }); - - expect(state.logs).toEqual({ - lines: mockLogsResult, - isLoading: false, - cursor: null, - isComplete: true, - fetchError: false, - }); - }); - }); - - describe('RECEIVE_LOGS_DATA_ERROR', () => { - it('receives log data error and stops loading', () => { - mutations[types.RECEIVE_LOGS_DATA_ERROR](state); - - expect(state.logs).toEqual({ - lines: [], - isLoading: false, - cursor: null, - isComplete: false, - fetchError: true, - }); - }); - }); - - describe('REQUEST_LOGS_DATA_PREPEND', () => { - it('receives logs lines and cursor', () => { - mutations[types.REQUEST_LOGS_DATA_PREPEND](state); - - expect(state.logs.isLoading).toBe(true); - }); - }); - - describe('RECEIVE_LOGS_DATA_PREPEND_SUCCESS', () => { - it('receives logs lines and cursor', () => { - mutations[types.RECEIVE_LOGS_DATA_PREPEND_SUCCESS](state, { - logs: mockLogsResult, - cursor: mockCursor, - }); - - expect(state.logs).toEqual({ - lines: mockLogsResult, - isLoading: false, - cursor: mockCursor, - isComplete: false, - fetchError: false, - }); - }); - - it('receives additional logs lines and a new cursor', () => { - mutations[types.RECEIVE_LOGS_DATA_PREPEND_SUCCESS](state, { - logs: mockLogsResult, - cursor: mockCursor, - }); - - mutations[types.RECEIVE_LOGS_DATA_PREPEND_SUCCESS](state, { - logs: mockLogsResult, - cursor: mockNextCursor, - }); - - expect(state.logs).toEqual({ - lines: [...mockLogsResult, ...mockLogsResult], - isLoading: false, - cursor: mockNextCursor, - isComplete: false, - fetchError: false, - }); - }); - - it('receives logs lines and a null cursor to indicate is complete', () => { - mutations[types.RECEIVE_LOGS_DATA_PREPEND_SUCCESS](state, { - logs: mockLogsResult, - cursor: null, - }); - - expect(state.logs).toEqual({ - lines: mockLogsResult, - isLoading: false, - cursor: null, - isComplete: true, - fetchError: false, - }); - }); - }); - - describe('RECEIVE_LOGS_DATA_PREPEND_ERROR', () => { - it('receives logs lines and cursor', () => { - mutations[types.RECEIVE_LOGS_DATA_PREPEND_ERROR](state); - - expect(state.logs.isLoading).toBe(false); - expect(state.logs.fetchError).toBe(true); - }); - }); - - describe('SET_CURRENT_POD_NAME', () => { - it('set current pod name', () => { - mutations[types.SET_CURRENT_POD_NAME](state, mockPodName); - - expect(state.pods.current).toEqual(mockPodName); - }); - }); - - describe('SET_TIME_RANGE', () => { - it('sets a default range', () => { - expect(state.timeRange.selected).toEqual(expect.any(Object)); - expect(state.timeRange.current).toEqual(expect.any(Object)); - }); - - it('sets a time range', () => { - const mockRange = { - start: '2020-01-10T18:00:00.000Z', - end: '2020-01-10T10:00:00.000Z', - }; - mutations[types.SET_TIME_RANGE](state, mockRange); - - expect(state.timeRange.selected).toEqual(mockRange); - expect(state.timeRange.current).toEqual(mockRange); - }); - }); - - describe('RECEIVE_PODS_DATA_SUCCESS', () => { - it('receives pods data success', () => { - mutations[types.RECEIVE_PODS_DATA_SUCCESS](state, mockPods); - - expect(state.pods).toEqual( - expect.objectContaining({ - options: mockPods, - }), - ); - }); - }); - describe('RECEIVE_PODS_DATA_ERROR', () => { - it('receives pods data error', () => { - mutations[types.RECEIVE_PODS_DATA_ERROR](state); - - expect(state.pods).toEqual( - expect.objectContaining({ - options: [], - }), - ); - }); - }); -}); diff --git a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js index 5a836894b51..9d4c7f4737b 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js @@ -38,7 +38,6 @@ describe('DependencyProxySettings', () => { let updateTtlPoliciesMutationResolver; const defaultProvide = { - defaultExpanded: false, groupPath: 'foo_group_path', groupDependencyProxyPath: 'group_dependency_proxy_path', }; @@ -109,12 +108,6 @@ describe('DependencyProxySettings', () => { expect(findSettingsBlock().exists()).toBe(true); }); - it('passes the correct props to settings block', () => { - mountComponent(); - - expect(findSettingsBlock().props('defaultExpanded')).toBe(false); - }); - it('has the correct header text and description', () => { mountComponent(); diff --git a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js index 635195ff0a4..31fc3ad419c 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js @@ -26,7 +26,6 @@ describe('Group Settings App', () => { let show; const defaultProvide = { - defaultExpanded: false, groupPath: 'foo_group_path', }; diff --git a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js index 1a5a35f7af7..274930ce668 100644 --- a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js +++ b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js @@ -31,7 +31,6 @@ describe('Packages Settings', () => { let apolloProvider; const defaultProvide = { - defaultExpanded: false, groupPath: 'foo_group_path', }; @@ -93,12 +92,6 @@ describe('Packages Settings', () => { expect(findSettingsBlock().exists()).toBe(true); }); - it('passes the correct props to settings block', () => { - mountComponent(); - - expect(findSettingsBlock().props('defaultExpanded')).toBe(false); - }); - it('has the correct header text', () => { mountComponent(); diff --git a/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js b/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js new file mode 100644 index 00000000000..a4c1b989dac --- /dev/null +++ b/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js @@ -0,0 +1,43 @@ +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue'; + +describe('SettingsBlock', () => { + let wrapper; + + const mountComponent = (propsData) => { + wrapper = shallowMountExtended(SettingsBlock, { + propsData, + slots: { + title: '<div data-testid="title-slot"></div>', + description: '<div data-testid="description-slot"></div>', + default: '<div data-testid="default-slot"></div>', + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findDefaultSlot = () => wrapper.findByTestId('default-slot'); + const findTitleSlot = () => wrapper.findByTestId('title-slot'); + const findDescriptionSlot = () => wrapper.findByTestId('description-slot'); + + it('has a default slot', () => { + mountComponent(); + + expect(findDefaultSlot().exists()).toBe(true); + }); + + it('has a title slot', () => { + mountComponent(); + + expect(findTitleSlot().exists()).toBe(true); + }); + + it('has a description slot', () => { + mountComponent(); + + expect(findDescriptionSlot().exists()).toBe(true); + }); +}); diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap index 10d250c5ebb..0bf0ef1ded4 100644 --- a/spec/frontend/releases/__snapshots__/util_spec.js.snap +++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap @@ -196,10 +196,10 @@ Object { ], "paginationInfo": Object { "__typename": "PageInfo", - "endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMSJ9", + "endCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTgtMTItMTAgMDA6MDA6MDAuMDAwMDAwMDAwICswMDAwIiwiaWQiOiIxIn0", "hasNextPage": false, "hasPreviousPage": false, - "startCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTktMDEtMTAgMDA6MDA6MDAuMDAwMDAwMDAwIFVUQyIsImlkIjoiMiJ9", + "startCursor": "eyJyZWxlYXNlZF9hdCI6IjIwMTktMDEtMTAgMDA6MDA6MDAuMDAwMDAwMDAwICswMDAwIiwiaWQiOiIyIn0", }, } `; diff --git a/spec/initializers/0_log_deprecations_spec.rb b/spec/initializers/0_log_deprecations_spec.rb index 35bceb2f132..44b277fa9c5 100644 --- a/spec/initializers/0_log_deprecations_spec.rb +++ b/spec/initializers/0_log_deprecations_spec.rb @@ -3,6 +3,10 @@ require 'spec_helper' RSpec.describe '0_log_deprecations' do + def setup_other_deprecations + Warning.process(__FILE__) { :raise } + end + def load_initializer load Rails.root.join('config/initializers/0_log_deprecations.rb') end @@ -11,6 +15,7 @@ RSpec.describe '0_log_deprecations' do before do stub_env('GITLAB_LOG_DEPRECATIONS', env_var) + setup_other_deprecations load_initializer end @@ -20,7 +25,7 @@ RSpec.describe '0_log_deprecations' do ActiveSupport::Notifications.unsubscribe('deprecation.rails') end - context 'for Ruby deprecations' do + describe 'Ruby deprecations' do context 'when catching deprecations through Kernel#warn' do it 'also logs them to deprecation logger' do expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( @@ -32,7 +37,7 @@ RSpec.describe '0_log_deprecations' do end end - context 'for other messages from Kernel#warn' do + describe 'other messages from Kernel#warn' do it 'does not log them to deprecation logger' do expect(Gitlab::DeprecationJsonLogger).not_to receive(:info) @@ -51,7 +56,7 @@ RSpec.describe '0_log_deprecations' do end end - context 'for Rails deprecations' do + describe 'Rails deprecations' do it 'logs them to deprecation logger' do expect(Gitlab::DeprecationJsonLogger).to receive(:info).with( message: match(/^DEPRECATION WARNING: ABC will be removed/), diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb index 97613edee5e..8a2b5ae0d38 100644 --- a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb +++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb @@ -79,7 +79,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_updated_at, column_order_created_at, column_order_id])) } it 'returns the encoded value of the order' do - expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.strftime('%Y-%m-%d %H:%M:%S.%N %Z')) + expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect)) end end end diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb index 61a79d90546..6574b3e3131 100644 --- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb +++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb @@ -92,7 +92,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do let(:nodes) { Project.order(:updated_at) } it 'returns the encoded value of the order' do - expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.strftime('%Y-%m-%d %H:%M:%S.%N %Z')) + expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect)) end it 'includes the :id even when not specified in the order' do @@ -104,7 +104,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do let(:nodes) { Project.order(:updated_at).order(:created_at) } it 'returns the encoded value of the order' do - expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.strftime('%Y-%m-%d %H:%M:%S.%N %Z')) + expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect)) end end @@ -112,7 +112,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do let(:nodes) { Project.order(Arel.sql('projects.updated_at IS NULL')).order(:updated_at).order(:id) } it 'returns the encoded value of the order' do - expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.strftime('%Y-%m-%d %H:%M:%S.%N %Z')) + expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect)) end end end diff --git a/spec/models/concerns/ci/artifactable_spec.rb b/spec/models/concerns/ci/artifactable_spec.rb index b27a4d0dcc1..6af244a5a0f 100644 --- a/spec/models/concerns/ci/artifactable_spec.rb +++ b/spec/models/concerns/ci/artifactable_spec.rb @@ -53,6 +53,15 @@ RSpec.describe Ci::Artifactable do expect { |b| artifact.each_blob(&b) }.to raise_error(described_class::NotSupportedAdapterError) end end + + context 'pushes artifact_size to application context' do + let(:artifact) { create(:ci_job_artifact, :junit) } + + it 'logs artifact size', :aggregate_failures do + expect { |b| artifact.each_blob(&b) }.to yield_control.once + expect(Gitlab::ApplicationContext.current).to include("meta.artifact_size" => artifact.size) + end + end end context 'ActiveRecord scopes' do diff --git a/spec/scripts/pipeline_test_report_builder_spec.rb b/spec/scripts/pipeline_test_report_builder_spec.rb index 8553ada044e..198cdefc530 100644 --- a/spec/scripts/pipeline_test_report_builder_spec.rb +++ b/spec/scripts/pipeline_test_report_builder_spec.rb @@ -103,16 +103,18 @@ RSpec.describe PipelineTestReportBuilder do end describe '#test_report_for_latest_pipeline' do + let(:failed_build_uri) { "#{failed_pipeline_url}/tests/suite.json?build_ids[]=#{failed_build_id}" } + + before do + allow(subject).to receive(:fetch).with(failed_build_uri).and_return(failed_builds_for_pipeline) + end + it 'fetches builds from pipeline related to MR' do - expect(subject).to receive(:fetch).with("#{failed_pipeline_url}/tests/suite.json?build_ids[]=#{failed_build_id}").and_return(failed_builds_for_pipeline) - subject.test_report_for_latest_pipeline + expected = { "suites" => [failed_builds_for_pipeline] }.to_json + expect(subject.test_report_for_latest_pipeline).to eq(expected) end context 'canonical pipeline' do - before do - allow(subject).to receive(:test_report_for_build).and_return(test_report_for_build) - end - context 'no previous pipeline' do let(:mr_pipelines) { [] } @@ -171,6 +173,10 @@ RSpec.describe PipelineTestReportBuilder do end context 'failed pipeline and failed test builds' do + before do + allow(subject).to receive(:fetch).with(failed_build_uri).and_return(test_report_for_build) + end + it 'returns populated test list for suites' do actual = subject.test_report_for_latest_pipeline expected = { @@ -180,6 +186,36 @@ RSpec.describe PipelineTestReportBuilder do expect(actual).to eq(expected) end end + + context 'when receiving a server error' do + let(:response) { instance_double('Net::HTTPResponse') } + let(:error) { Net::HTTPServerException.new('server error', response) } + let(:test_report_for_latest_pipeline) { subject.test_report_for_latest_pipeline } + + before do + allow(response).to receive(:code).and_return(response_code) + allow(subject).to receive(:fetch).with(failed_build_uri).and_raise(error) + end + + context 'when response code is 404' do + let(:response_code) { 404 } + + it 'continues without the missing reports' do + expected = { 'suites' => [] }.to_json + + expect { test_report_for_latest_pipeline }.not_to raise_error + expect(test_report_for_latest_pipeline).to eq(expected) + end + end + + context 'when response code is unexpected' do + let(:response_code) { 500 } + + it 'raises HTTPServerException' do + expect { test_report_for_latest_pipeline }.to raise_error(error) + end + end + end end end end |