diff options
73 files changed, 825 insertions, 173 deletions
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml index abda6fad9aa..6525d8abcf5 100644 --- a/.gitlab/ci/reports.gitlab-ci.yml +++ b/.gitlab/ci/reports.gitlab-ci.yml @@ -28,7 +28,7 @@ code_quality: variables: SAST_BRAKEMAN_LEVEL: 2 # GitLab-specific SAST_EXCLUDED_PATHS: "qa, spec, doc, ee/spec, config/gitlab.yml.example, tmp" # GitLab-specific - SAST_EXCLUDED_ANALYZERS: bandit, flawfinder, phpcs-security-audit, pmd-apex, security-code-scan, spotbugs, eslint + SAST_EXCLUDED_ANALYZERS: bandit, flawfinder, phpcs-security-audit, pmd-apex, security-code-scan, spotbugs, eslint, nodejs-scan brakeman-sast: rules: !reference [".reports:rules:brakeman-sast", rules] diff --git a/app/assets/javascripts/integrations/constants.js b/app/assets/javascripts/integrations/constants.js index 1644f35459b..8a8d38b295c 100644 --- a/app/assets/javascripts/integrations/constants.js +++ b/app/assets/javascripts/integrations/constants.js @@ -1,5 +1,23 @@ +import { s__ } from '~/locale'; + export const TEST_INTEGRATION_EVENT = 'testIntegration'; export const SAVE_INTEGRATION_EVENT = 'saveIntegration'; export const GET_JIRA_ISSUE_TYPES_EVENT = 'getJiraIssueTypes'; export const TOGGLE_INTEGRATION_EVENT = 'toggleIntegration'; export const VALIDATE_INTEGRATION_FORM_EVENT = 'validateIntegrationForm'; + +export const integrationLevels = { + GROUP: 'group', + INSTANCE: 'instance', +}; + +export const defaultIntegrationLevel = integrationLevels.INSTANCE; + +export const overrideDropdownDescriptions = { + [integrationLevels.GROUP]: s__( + 'Integrations|Default settings are inherited from the group level.', + ), + [integrationLevels.INSTANCE]: s__( + 'Integrations|Default settings are inherited from the instance level.', + ), +}; diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue index 707666f11d2..ba1aeb28616 100644 --- a/app/assets/javascripts/integrations/edit/components/integration_form.vue +++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue @@ -2,8 +2,11 @@ import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; import { mapState, mapActions, mapGetters } from 'vuex'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import { TEST_INTEGRATION_EVENT, SAVE_INTEGRATION_EVENT } from '~/integrations/constants'; -import { integrationLevels } from '../constants'; +import { + TEST_INTEGRATION_EVENT, + SAVE_INTEGRATION_EVENT, + integrationLevels, +} from '~/integrations/constants'; import eventHub from '../event_hub'; import ActiveCheckbox from './active_checkbox.vue'; diff --git a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue index 7b3a067b186..63650400bb7 100644 --- a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue +++ b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue @@ -2,7 +2,7 @@ import { GlDropdown, GlDropdownItem, GlLink } from '@gitlab/ui'; import { mapState } from 'vuex'; import { s__ } from '~/locale'; -import { defaultIntegrationLevel, overrideDropdownDescriptions } from '../constants'; +import { defaultIntegrationLevel, overrideDropdownDescriptions } from '~/integrations/constants'; const dropdownOptions = [ { diff --git a/app/assets/javascripts/integrations/edit/constants.js b/app/assets/javascripts/integrations/edit/constants.js deleted file mode 100644 index b74ae209eb7..00000000000 --- a/app/assets/javascripts/integrations/edit/constants.js +++ /dev/null @@ -1,17 +0,0 @@ -import { s__ } from '~/locale'; - -export const integrationLevels = { - GROUP: 'group', - INSTANCE: 'instance', -}; - -export const defaultIntegrationLevel = integrationLevels.INSTANCE; - -export const overrideDropdownDescriptions = { - [integrationLevels.GROUP]: s__( - 'Integrations|Default settings are inherited from the group level.', - ), - [integrationLevels.INSTANCE]: s__( - 'Integrations|Default settings are inherited from the instance level.', - ), -}; diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue new file mode 100644 index 00000000000..195ff7af583 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue @@ -0,0 +1,151 @@ +<script> +import { GlButton, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import ListItem from '~/vue_shared/components/registry/list_item.vue'; +import { + PACKAGE_ERROR_STATUS, + PACKAGE_DEFAULT_STATUS, +} from '~/packages_and_registries/package_registry/constants'; +import { getPackageTypeLabel } from '~/packages/shared/utils'; +import PackagePath from '~/packages/shared/components/package_path.vue'; +import PackageTags from '~/packages/shared/components/package_tags.vue'; +import PublishMethod from '~/packages_and_registries/package_registry/components/list/publish_method.vue'; +import PackageIconAndName from '~/packages/shared/components/package_icon_and_name.vue'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; + +export default { + name: 'PackageListRow', + components: { + GlButton, + GlLink, + GlSprintf, + GlTruncate, + PackageTags, + PackagePath, + PublishMethod, + ListItem, + PackageIconAndName, + TimeagoTooltip, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + inject: ['isGroupPage'], + props: { + packageEntity: { + type: Object, + required: true, + }, + }, + computed: { + packageType() { + return getPackageTypeLabel(this.packageEntity.packageType.toLowerCase()); + }, + packageLink() { + const { project, id } = this.packageEntity; + return `${project?.webUrl}/-/packages/${getIdFromGraphQLId(id)}`; + }, + pipeline() { + return this.packageEntity?.pipelines?.nodes[0]; + }, + pipelineUser() { + return this.pipeline?.user?.name; + }, + showWarningIcon() { + return this.packageEntity.status === PACKAGE_ERROR_STATUS; + }, + showTags() { + return Boolean(this.packageEntity.tags?.nodes?.length); + }, + disabledRow() { + return this.packageEntity.status && this.packageEntity.status !== PACKAGE_DEFAULT_STATUS; + }, + }, + i18n: { + erroredPackageText: s__('PackageRegistry|Invalid Package: failed metadata extraction'), + }, +}; +</script> + +<template> + <list-item data-qa-selector="package_row" :disabled="disabledRow"> + <template #left-primary> + <div class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0"> + <gl-link + :href="packageLink" + class="gl-text-body gl-min-w-0" + data-qa-selector="package_link" + :disabled="disabledRow" + > + <gl-truncate :text="packageEntity.name" /> + </gl-link> + + <gl-button + v-if="showWarningIcon" + v-gl-tooltip="{ title: $options.i18n.erroredPackageText }" + class="gl-hover-bg-transparent!" + icon="warning" + category="tertiary" + data-testid="warning-icon" + :aria-label="__('Warning')" + /> + + <package-tags + v-if="showTags" + class="gl-ml-3" + :tags="packageEntity.tags.nodes" + hide-label + :tag-display-limit="1" + /> + </div> + </template> + <template #left-secondary> + <div class="gl-display-flex" data-testid="left-secondary-infos"> + <span>{{ packageEntity.version }}</span> + + <div v-if="pipelineUser" class="gl-display-none gl-sm-display-flex gl-ml-2"> + <gl-sprintf :message="s__('PackageRegistry|published by %{author}')"> + <template #author>{{ pipelineUser }}</template> + </gl-sprintf> + </div> + + <package-icon-and-name> + {{ packageType }} + </package-icon-and-name> + + <package-path + v-if="isGroupPage" + :path="packageEntity.project.fullPath" + :disabled="disabledRow" + /> + </div> + </template> + + <template #right-primary> + <publish-method :pipeline="pipeline" /> + </template> + + <template #right-secondary> + <span> + <gl-sprintf :message="__('Created %{timestamp}')"> + <template #timestamp> + <timeago-tooltip :time="packageEntity.createdAt" /> + </template> + </gl-sprintf> + </span> + </template> + + <template v-if="!disabledRow" #right-action> + <gl-button + data-testid="action-delete" + icon="remove" + category="secondary" + variant="danger" + :title="s__('PackageRegistry|Remove package')" + :aria-label="s__('PackageRegistry|Remove package')" + @click="$emit('packageToDelete', packageEntity)" + /> + </template> + </list-item> +</template> diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/publish_method.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/publish_method.vue new file mode 100644 index 00000000000..8ecf433f3ab --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/publish_method.vue @@ -0,0 +1,61 @@ +<script> +import { GlIcon, GlLink } from '@gitlab/ui'; +import { __, s__ } from '~/locale'; +import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; + +export default { + name: 'PublishMethod', + components: { + ClipboardButton, + GlIcon, + GlLink, + }, + props: { + pipeline: { + type: Object, + required: false, + default: null, + }, + }, + computed: { + hasPipeline() { + return Boolean(this.pipeline); + }, + packageShaShort() { + return this.pipeline?.sha?.substring(0, 8); + }, + }, + i18n: { + COPY_COMMIT_SHA: __('Copy commit SHA'), + MANUALLY_PUBLISHED: s__('PackageRegistry|Manually Published'), + }, +}; +</script> + +<template> + <div class="gl-display-flex gl-align-items-center"> + <template v-if="hasPipeline"> + <gl-icon name="git-merge" class="gl-mr-2" /> + <span data-testid="pipeline-ref" class="gl-mr-2">{{ pipeline.ref }}</span> + + <gl-icon name="commit" class="gl-mr-2" /> + <gl-link data-testid="pipeline-sha" :href="pipeline.commitPath" class="gl-mr-2">{{ + packageShaShort + }}</gl-link> + + <clipboard-button + :text="pipeline.sha" + :title="$options.i18n.COPY_COMMIT_SHA" + category="tertiary" + size="small" + /> + </template> + + <template v-else> + <gl-icon name="upload" class="gl-mr-2" /> + <span data-testid="manually-published"> + {{ $options.i18n.MANUALLY_PUBLISHED }} + </span> + </template> + </div> +</template> diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql index 101115c96ff..aaf0eb54aff 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql +++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql @@ -1,4 +1,27 @@ fragment PackageData on Package { id name + version + packageType + createdAt + status + tags { + nodes { + name + } + } + pipelines { + nodes { + sha + ref + commitPath + user { + name + } + } + } + project { + fullPath + webUrl + } } diff --git a/app/helpers/hooks_helper.rb b/app/helpers/hooks_helper.rb index 2725d28c47c..c1dfd2b2cda 100644 --- a/app/helpers/hooks_helper.rb +++ b/app/helpers/hooks_helper.rb @@ -36,6 +36,15 @@ module HooksHelper admin_hook_path(hook) end end + + def hook_log_path(hook, hook_log) + case hook + when ProjectHook + hook_log.present.details_path + when SystemHook + admin_hook_hook_log_path(hook, hook_log) + end + end end HooksHelper.prepend_mod_with('HooksHelper') diff --git a/app/views/admin/hook_logs/_index.html.haml b/app/views/admin/hook_logs/_index.html.haml index a7f947f96ea..4c0a908be93 100644 --- a/app/views/admin/hook_logs/_index.html.haml +++ b/app/views/admin/hook_logs/_index.html.haml @@ -4,34 +4,4 @@ = _('Recent Deliveries') %p= _('When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong.') .col-lg-9 - - if hook_logs.present? - %table.table - %thead - %tr - %th= _('Status') - %th= _('Trigger') - %th= _('URL') - %th= _('Elapsed time') - %th= _('Request time') - %th - - hook_logs.each do |hook_log| - %tr - %td - = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log } - %td.d-none.d-sm-block - %span.badge.badge-gray.deploy-project-label - = hook_log.trigger.singularize.titleize - %td - = truncate(hook_log.url, length: 50) - %td.light - #{number_with_precision(hook_log.execution_duration, precision: 2)} sec - %td.light - = time_ago_with_tooltip(hook_log.created_at) - %td - = link_to _('View details'), admin_hook_hook_log_path(hook, hook_log) - - = paginate hook_logs, theme: 'gitlab' - - - else - .settings-message.text-center - = _("You don't have any webhooks deliveries") + = render partial: 'shared/hook_logs/recent_deliveries_table', locals: { hook: hook, hook_logs: hook_logs } diff --git a/app/views/projects/hook_logs/_index.html.haml b/app/views/projects/hook_logs/_index.html.haml index ee4dbf5c05c..4c0a908be93 100644 --- a/app/views/projects/hook_logs/_index.html.haml +++ b/app/views/projects/hook_logs/_index.html.haml @@ -1,37 +1,7 @@ -.row.gl-mt-7.gl-mb-3 +.row.gl-mt-3.gl-mb-3 .col-lg-3 %h4.gl-mt-0 - Recent Deliveries - %p When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong. + = _('Recent Deliveries') + %p= _('When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong.') .col-lg-9 - - if hook_logs.present? - %table.table - %thead - %tr - %th Status - %th Trigger - %th URL - %th Elapsed time - %th Request time - %th - - hook_logs.each do |hook_log| - %tr - %td - = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log } - %td.d-none.d-sm-block - %span.badge.badge-gray.deploy-project-label - = hook_log.trigger.singularize.titleize - %td - = truncate(hook_log.url, length: 50) - %td.light - #{number_with_precision(hook_log.execution_duration, precision: 2)} sec - %td.light - = time_ago_with_tooltip(hook_log.created_at) - %td - = link_to 'View details', hook_log.present.details_path - - = paginate hook_logs, theme: 'gitlab' - - - else - .settings-message.text-center - You don't have any webhooks deliveries + = render partial: 'shared/hook_logs/recent_deliveries_table', locals: { hook: hook, hook_logs: hook_logs } diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml index ebe179c3454..86dfa1929d6 100644 --- a/app/views/projects/hook_logs/show.html.haml +++ b/app/views/projects/hook_logs/show.html.haml @@ -5,8 +5,8 @@ .row.gl-mt-3.gl-mb-3 .col-lg-3 %h4.gl-mt-0 - Request details + = _("Request details") .col-lg-9 - = link_to 'Resend Request', @hook_log.present.retry_path, method: :post, class: "btn gl-button btn-default float-right gl-ml-3" + = link_to _('Resend Request'), @hook_log.present.retry_path, method: :post, class: "btn gl-button btn-default float-right gl-ml-3" = render partial: 'shared/hook_logs/content', locals: { hook_log: @hook_log } diff --git a/app/views/shared/hook_logs/_recent_deliveries_table.html.haml b/app/views/shared/hook_logs/_recent_deliveries_table.html.haml new file mode 100644 index 00000000000..1f64af16d08 --- /dev/null +++ b/app/views/shared/hook_logs/_recent_deliveries_table.html.haml @@ -0,0 +1,31 @@ +- if hook_logs.present? + %table.table + %thead + %tr + %th= _('Status') + %th.d-none.d-sm-table-cell= _('Trigger') + %th= _('URL') + %th= _('Elapsed time') + %th= _('Request time') + %th + - hook_logs.each do |hook_log| + %tr + %td + = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log } + %td.d-none.d-sm-table-cell + %span.badge.badge-gray.deploy-project-label + = hook_log.trigger.singularize.titleize + %td + = truncate(hook_log.url, length: 50) + %td + #{number_with_precision(hook_log.execution_duration, precision: 2)} sec + %td + = time_ago_with_tooltip(hook_log.created_at) + %td + = link_to _('View details'), hook_log_path(hook, hook_log) + + = paginate hook_logs, theme: 'gitlab' + +- else + .settings-message.text-center + = _("You don't have any webhooks deliveries") diff --git a/bin/background_jobs b/bin/background_jobs index 6aebc8126c6..f9b42b97e06 100755 --- a/bin/background_jobs +++ b/bin/background_jobs @@ -3,6 +3,7 @@ cd $(dirname $0)/.. app_root=$(pwd) sidekiq_workers=${SIDEKIQ_WORKERS:-1} +sidekiq_queues=${SIDEKIQ_QUEUES:-*} # Queues to listen to; default to `*` (all) sidekiq_pidfile="$app_root/tmp/pids/sidekiq-cluster.pid" sidekiq_logfile="$app_root/log/sidekiq.log" gitlab_user=$(ls -l config.ru | awk '{print $3}') @@ -37,8 +38,7 @@ restart() stop fi - warn "Sidekiq output will be written to $sidekiq_logfile" - start_sidekiq "$@" >> $sidekiq_logfile 2>&1 + start_sidekiq "$@" } start_sidekiq() @@ -50,13 +50,13 @@ start_sidekiq() cmd="${cmd} ${chpst} -P" fi - # sidekiq-cluster expects '*' '*' arguments (one wildcard for each process). + # sidekiq-cluster expects an argument per process. for (( i=1; i<=$sidekiq_workers; i++ )) do - processes_args+=("*") + processes_args+=("${sidekiq_queues}") done - ${cmd} bin/sidekiq-cluster "${processes_args[@]}" -P $sidekiq_pidfile -e $RAILS_ENV "$@" + ${cmd} bin/sidekiq-cluster "${processes_args[@]}" -P $sidekiq_pidfile -e $RAILS_ENV "$@" 2>&1 | tee -a $sidekiq_logfile } action="$1" diff --git a/config/metrics/counts_all/20210216175627_templates_asana_active.yml b/config/metrics/counts_all/20210216175627_templates_asana_active.yml index 48025516d32..3575f359f99 100644 --- a/config/metrics/counts_all/20210216175627_templates_asana_active.yml +++ b/config/metrics/counts_all/20210216175627_templates_asana_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175638_templates_assembla_active.yml b/config/metrics/counts_all/20210216175638_templates_assembla_active.yml index 1ab0d42a5ee..d0f203e12c5 100644 --- a/config/metrics/counts_all/20210216175638_templates_assembla_active.yml +++ b/config/metrics/counts_all/20210216175638_templates_assembla_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml b/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml index 85b10732ae8..2e97c4bf1be 100644 --- a/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml +++ b/config/metrics/counts_all/20210216175649_templates_bamboo_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml b/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml index bc5a1238010..6d26fbfb8dd 100644 --- a/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml +++ b/config/metrics/counts_all/20210216175701_templates_bugzilla_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml b/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml index 16287a4e71a..8218ae10cae 100644 --- a/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml +++ b/config/metrics/counts_all/20210216175712_templates_buildkite_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175723_templates_campfire_active.yml b/config/metrics/counts_all/20210216175723_templates_campfire_active.yml index 728d3d0af48..2e8b09e4997 100644 --- a/config/metrics/counts_all/20210216175723_templates_campfire_active.yml +++ b/config/metrics/counts_all/20210216175723_templates_campfire_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175734_templates_confluence_active.yml b/config/metrics/counts_all/20210216175734_templates_confluence_active.yml index bb2d9976110..2287415e83c 100644 --- a/config/metrics/counts_all/20210216175734_templates_confluence_active.yml +++ b/config/metrics/counts_all/20210216175734_templates_confluence_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml b/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml index c1c63d0529a..343c4c887aa 100644 --- a/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml +++ b/config/metrics/counts_all/20210216175745_templates_custom_issue_tracker_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175756_templates_discord_active.yml b/config/metrics/counts_all/20210216175756_templates_discord_active.yml index d0663da787f..9f057665e3a 100644 --- a/config/metrics/counts_all/20210216175756_templates_discord_active.yml +++ b/config/metrics/counts_all/20210216175756_templates_discord_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml b/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml index 6a764f64ab6..edec715a037 100644 --- a/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml +++ b/config/metrics/counts_all/20210216175807_templates_drone_ci_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml b/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml index f709aff9f07..057e3b3056b 100644 --- a/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml +++ b/config/metrics/counts_all/20210216175818_templates_emails_on_push_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml b/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml index 35bbce95380..31a270395fb 100644 --- a/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml +++ b/config/metrics/counts_all/20210216175829_templates_external_wiki_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml b/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml index dc1466d2bef..74d085a4447 100644 --- a/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml +++ b/config/metrics/counts_all/20210216175840_templates_flowdock_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml b/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml index b676501db10..fb007335b2d 100644 --- a/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml +++ b/config/metrics/counts_all/20210216175902_templates_hangouts_chat_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175924_templates_irker_active.yml b/config/metrics/counts_all/20210216175924_templates_irker_active.yml index fc3ed89b6e8..c3491169a7e 100644 --- a/config/metrics/counts_all/20210216175924_templates_irker_active.yml +++ b/config/metrics/counts_all/20210216175924_templates_irker_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml b/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml index 542671304b0..96938d84aee 100644 --- a/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml +++ b/config/metrics/counts_all/20210216175935_templates_jenkins_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175946_templates_jira_active.yml b/config/metrics/counts_all/20210216175946_templates_jira_active.yml index 83d3669b7f2..964aef061d2 100644 --- a/config/metrics/counts_all/20210216175946_templates_jira_active.yml +++ b/config/metrics/counts_all/20210216175946_templates_jira_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml b/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml index 460c5e808d8..9e472a1cb54 100644 --- a/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml +++ b/config/metrics/counts_all/20210216175957_templates_mattermost_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml b/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml index 927710d918c..97a8dccd834 100644 --- a/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml +++ b/config/metrics/counts_all/20210216180008_templates_mattermost_slash_commands_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml b/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml index fb35802c2b7..1fed89e7932 100644 --- a/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml +++ b/config/metrics/counts_all/20210216180019_templates_microsoft_teams_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180030_templates_packagist_active.yml b/config/metrics/counts_all/20210216180030_templates_packagist_active.yml index aa56cf08028..75c4f0f2428 100644 --- a/config/metrics/counts_all/20210216180030_templates_packagist_active.yml +++ b/config/metrics/counts_all/20210216180030_templates_packagist_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml b/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml index 2d81cf582e9..74629749687 100644 --- a/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml +++ b/config/metrics/counts_all/20210216180041_templates_pipelines_email_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml b/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml index 7c869361d05..abc6227f431 100644 --- a/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml +++ b/config/metrics/counts_all/20210216180052_templates_pivotaltracker_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180104_templates_pushover_active.yml b/config/metrics/counts_all/20210216180104_templates_pushover_active.yml index 572b5da07d4..9580fe01068 100644 --- a/config/metrics/counts_all/20210216180104_templates_pushover_active.yml +++ b/config/metrics/counts_all/20210216180104_templates_pushover_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180115_templates_redmine_active.yml b/config/metrics/counts_all/20210216180115_templates_redmine_active.yml index a85417cbc2c..47ba5ed946b 100644 --- a/config/metrics/counts_all/20210216180115_templates_redmine_active.yml +++ b/config/metrics/counts_all/20210216180115_templates_redmine_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180126_templates_slack_active.yml b/config/metrics/counts_all/20210216180126_templates_slack_active.yml index dffa673cd47..792c965216e 100644 --- a/config/metrics/counts_all/20210216180126_templates_slack_active.yml +++ b/config/metrics/counts_all/20210216180126_templates_slack_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml b/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml index e044d6cf1dd..38bc6959318 100644 --- a/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml +++ b/config/metrics/counts_all/20210216180137_templates_slack_slash_commands_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml b/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml index b3a37ebc578..63e8285e220 100644 --- a/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml +++ b/config/metrics/counts_all/20210216180148_templates_teamcity_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml b/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml index 39facfb237e..10c7b23a308 100644 --- a/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml +++ b/config/metrics/counts_all/20210216180159_templates_unify_circuit_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml b/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml index 185b538a228..1e41a8170d4 100644 --- a/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml +++ b/config/metrics/counts_all/20210216180210_templates_webex_teams_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml b/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml index a6c11918ce2..edd5aa07f59 100644 --- a/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml +++ b/config/metrics/counts_all/20210216180221_templates_youtrack_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216180934_templates_prometheus_active.yml b/config/metrics/counts_all/20210216180934_templates_prometheus_active.yml index 4bf8911c666..9f8a24488ad 100644 --- a/config/metrics/counts_all/20210216180934_templates_prometheus_active.yml +++ b/config/metrics/counts_all/20210216180934_templates_prometheus_active.yml @@ -7,7 +7,8 @@ product_stage: monitor product_group: group::monitor product_category: metrics value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216182551_templates_datadog_active.yml b/config/metrics/counts_all/20210216182551_templates_datadog_active.yml index d2df07b8d21..975bc2164bc 100644 --- a/config/metrics/counts_all/20210216182551_templates_datadog_active.yml +++ b/config/metrics/counts_all/20210216182551_templates_datadog_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/config/metrics/counts_all/20210216182618_templates_ewm_active.yml b/config/metrics/counts_all/20210216182618_templates_ewm_active.yml index 1ace369980b..be61177d818 100644 --- a/config/metrics/counts_all/20210216182618_templates_ewm_active.yml +++ b/config/metrics/counts_all/20210216182618_templates_ewm_active.yml @@ -7,7 +7,8 @@ product_stage: ecosystem product_group: group::integrations product_category: integrations value_type: number -status: active +status: removed +milestone_removed: '14.4' time_frame: all data_source: database distribution: diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md index 7eef9a97539..45b94781adc 100644 --- a/doc/administration/integration/terminal.md +++ b/doc/administration/integration/terminal.md @@ -50,8 +50,8 @@ detail below. ## Enabling and disabling terminal support NOTE: -AWS Elastic Load Balancers (ELBs) do not support web sockets. -If you want web terminals to work, use AWS Application Load Balancers (ALBs). +AWS Classic Load Balancers (CLBs) do not support web sockets. +If you want web terminals to work, use AWS Network Load Balancers (NLBs). Read [AWS Elastic Load Balancing Product Comparison](https://aws.amazon.com/elasticloadbalancing/features/#compare) for more information. diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index 52dfc89dc73..1d275010556 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -119,12 +119,15 @@ The following metrics are available: | `action_cable_pool_largest_size` | Gauge | 13.4 | Largest number of worker threads observed so far in ActionCable thread pool | `server_mode` | | `action_cable_pool_pending_tasks` | Gauge | 13.4 | Number of tasks waiting to be executed in ActionCable thread pool | `server_mode` | | `action_cable_pool_tasks_total` | Gauge | 13.4 | Total number of tasks executed in ActionCable thread pool | `server_mode` | +| `gitlab_ci_trace_operations_total` | Counter | 13.4 | Total amount of different operations on a build trace | `operation` | +| `gitlab_ci_trace_bytes_total` | Counter | 13.4 | Total amount of build trace bytes transferred | | | `action_cable_single_client_transmissions_total` | Counter | 13.10 | The number of ActionCable messages transmitted to any client in any channel | `server_mode` | | `action_cable_subscription_confirmations_total` | Counter | 13.10 | The number of ActionCable subscriptions from clients confirmed | `server_mode` | | `action_cable_subscription_rejections_total` | Counter | 13.10 | The number of ActionCable subscriptions from clients rejected | `server_mode` | | `action_cable_transmitted_bytes` | Histogram | 14.1 | Message size, in bytes, transmitted over action cable | `operation`, `channel` | | `gitlab_issuable_fast_count_by_state_total` | Counter | 13.5 | Total number of row count operations on issue/merge request list pages | | | `gitlab_issuable_fast_count_by_state_failures_total` | Counter | 13.5 | Number of soft-failed row count operations on issue/merge request list pages | | +| `gitlab_ci_trace_finalize_duration_seconds` | Histogram | 13.6 | Duration of build trace chunks migration to object storage | | | `gitlab_external_http_total` | Counter | 13.8 | Total number of HTTP calls to external systems | `controller`, `action` | | `gitlab_external_http_duration_seconds` | Counter | 13.8 | Duration in seconds spent on each HTTP call to external systems | | | `gitlab_external_http_exception_total` | Counter | 13.8 | Total number of exceptions raised when making external HTTP calls | | diff --git a/doc/update/package/index.md b/doc/update/package/index.md index 6f5d3d973b6..776a7111188 100644 --- a/doc/update/package/index.md +++ b/doc/update/package/index.md @@ -14,7 +14,7 @@ GitLab package. - Decide when to upgrade by viewing the [supported upgrade paths](../index.md#upgrade-paths). You can't directly skip major versions (for example, go from 10.3 to 12.7 in one step). - If you are upgrading from a non-package installation to a GitLab package installation, see - [Upgrading from a non-package installation to a GitLab package installation](https://docs.gitlab.com/omnibus/convert_to_omnibus.html). + [Upgrading from a non-package installation to a GitLab package installation](https://docs.gitlab.com/omnibus/update/convert_to_omnibus.html). - Ensure that any [background migrations](../index.md#checking-for-background-migrations-before-upgrading) are fully completed. Upgrading diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md index 7ddddfc5e53..b5294bb265d 100644 --- a/doc/user/admin_area/analytics/dev_ops_report.md +++ b/doc/user/admin_area/analytics/dev_ops_report.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # DevOps Report **(FREE SELF)** -> [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6. +> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) from Conversational Development Index in GitLab 12.6. The DevOps Report gives you an overview of your entire instance's adoption of [Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/) diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md index 98e241ba3bd..674eee5e80a 100644 --- a/doc/user/application_security/configuration/index.md +++ b/doc/user/application_security/configuration/index.md @@ -38,7 +38,7 @@ Select **Configuration history** to see the `.gitlab-ci.yml` file's history. You can configure the following security controls: -- Static Application Security Testing (SAST) +- Static Application Security Testing (SAST) **(FREE)** - Select **Enable SAST** to configure SAST for the current project. For more details, read [Configure SAST in the UI](../sast/index.md#configure-sast-in-the-ui). - Dynamic Application Security Testing (DAST) **(ULTIMATE)** diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index cdbab1bc2e9..4d10110efa9 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -227,7 +227,7 @@ When a user tries to sign in with Group SSO, GitLab attempts to find or create a To link SAML to your existing GitLab.com account: -1. Sign in to your GitLab.com account. +1. Sign in to your GitLab.com account. [Reset your password](https://gitlab.com/users/password/new) if necessary. 1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group owner can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the identity provider. 1. Select **Authorize**. 1. Enter your credentials on the identity provider if prompted. diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md index 600c9ecce03..d75d91f087d 100644 --- a/doc/user/workspace/index.md +++ b/doc/user/workspace/index.md @@ -22,6 +22,17 @@ Our goal is to reach feature parity between SaaS and self-managed installations, NOTE: Workspace is currently in development. +## Demo: New hierarchy concept for groups and projects for epics + +The following demo introduces the new hierarchy concept for groups and projects for epics. + +<div class="video-fallback"> + See the video: <a href="https://www.youtube.com/embed/fE74lsG_8yM">Consolidating groups and projects update (2021-08-23)</a>. +</div> +<figure class="video-container"> + <iframe src="https://www.youtube.com/embed/fE74lsG_8yM" frameborder="0" allowfullscreen="true"> </iframe> +</figure> + ## Concept previews The following provide a preview to the Workspace concept. diff --git a/lib/gitlab/performance_bar/stats.rb b/lib/gitlab/performance_bar/stats.rb index a7a1bdb2ac6..e90c7358845 100644 --- a/lib/gitlab/performance_bar/stats.rb +++ b/lib/gitlab/performance_bar/stats.rb @@ -37,9 +37,7 @@ module Gitlab end def log_queries(id, data, type) - json_path = ['data', type, 'details'] - - queries_by_location(data, json_path).each do |location, queries| + queries_by_location(data, type).each do |location, queries| next unless location duration = queries.sum { |query| query['duration'].to_f } @@ -56,8 +54,8 @@ module Gitlab end end - def queries_by_location(data, path) - return [] unless queries = data.dig(*path) + def queries_by_location(data, type) + return [] unless queries = data.dig('data', type, 'details') queries.group_by do |query| parse_backtrace(query['backtrace']) diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 306b903a837..21d98a3ef8a 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -404,7 +404,6 @@ module Gitlab response[:"projects_#{name}_active"] = count(Integration.active.where.not(project: nil).where(type: type)) response[:"groups_#{name}_active"] = count(Integration.active.where.not(group: nil).where(type: type)) - response[:"templates_#{name}_active"] = count(Integration.active.where(template: true, type: type)) response[:"instances_#{name}_active"] = count(Integration.active.where(instance: true, type: type)) response[:"projects_inheriting_#{name}_active"] = count(Integration.active.where.not(project: nil).where.not(inherit_from_id: nil).where(type: type)) response[:"groups_inheriting_#{name}_active"] = count(Integration.active.where.not(group: nil).where.not(inherit_from_id: nil).where(type: type)) diff --git a/spec/frontend/access_tokens/components/projects_token_selector_spec.js b/spec/frontend/access_tokens/components/projects_token_selector_spec.js index 09f52fe9a5f..40aaf16d41f 100644 --- a/spec/frontend/access_tokens/components/projects_token_selector_spec.js +++ b/spec/frontend/access_tokens/components/projects_token_selector_spec.js @@ -11,7 +11,7 @@ import produce from 'immer'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; -import { getJSONFixture } from 'helpers/fixtures'; +import getProjectsQueryResponse from 'test_fixtures/graphql/projects/access_tokens/get_projects.query.graphql.json'; import createMockApollo from 'helpers/mock_apollo_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -20,9 +20,6 @@ import getProjectsQuery from '~/access_tokens/graphql/queries/get_projects.query import { getIdFromGraphQLId } from '~/graphql_shared/utils'; describe('ProjectsTokenSelector', () => { - const getProjectsQueryResponse = getJSONFixture( - 'graphql/projects/access_tokens/get_projects.query.graphql.json', - ); const getProjectsQueryResponsePage2 = produce( getProjectsQueryResponse, (getProjectsQueryResponseDraft) => { diff --git a/spec/frontend/deploy_keys/components/action_btn_spec.js b/spec/frontend/deploy_keys/components/action_btn_spec.js index 307a0b6d8b0..6ac68061518 100644 --- a/spec/frontend/deploy_keys/components/action_btn_spec.js +++ b/spec/frontend/deploy_keys/components/action_btn_spec.js @@ -1,10 +1,10 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import data from 'test_fixtures/deploy_keys/keys.json'; import actionBtn from '~/deploy_keys/components/action_btn.vue'; import eventHub from '~/deploy_keys/eventhub'; describe('Deploy keys action btn', () => { - const data = getJSONFixture('deploy_keys/keys.json'); const deployKey = data.enabled_keys[0]; let wrapper; diff --git a/spec/frontend/deploy_keys/components/app_spec.js b/spec/frontend/deploy_keys/components/app_spec.js index a72b2b00776..598b7a0f173 100644 --- a/spec/frontend/deploy_keys/components/app_spec.js +++ b/spec/frontend/deploy_keys/components/app_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import data from 'test_fixtures/deploy_keys/keys.json'; import waitForPromises from 'helpers/wait_for_promises'; import { TEST_HOST } from 'spec/test_constants'; import deployKeysApp from '~/deploy_keys/components/app.vue'; @@ -10,7 +11,6 @@ import axios from '~/lib/utils/axios_utils'; const TEST_ENDPOINT = `${TEST_HOST}/dummy/`; describe('Deploy keys app component', () => { - const data = getJSONFixture('deploy_keys/keys.json'); let wrapper; let mock; diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js index 5420f9a01f9..511b9d6ef55 100644 --- a/spec/frontend/deploy_keys/components/key_spec.js +++ b/spec/frontend/deploy_keys/components/key_spec.js @@ -1,4 +1,5 @@ import { mount } from '@vue/test-utils'; +import data from 'test_fixtures/deploy_keys/keys.json'; import key from '~/deploy_keys/components/key.vue'; import DeployKeysStore from '~/deploy_keys/store'; import { getTimeago } from '~/lib/utils/datetime_utility'; @@ -7,8 +8,6 @@ describe('Deploy keys key', () => { let wrapper; let store; - const data = getJSONFixture('deploy_keys/keys.json'); - const findTextAndTrim = (selector) => wrapper.find(selector).text().trim(); const createComponent = (propsData) => { diff --git a/spec/frontend/deploy_keys/components/keys_panel_spec.js b/spec/frontend/deploy_keys/components/keys_panel_spec.js index d6419356166..f3b907e5450 100644 --- a/spec/frontend/deploy_keys/components/keys_panel_spec.js +++ b/spec/frontend/deploy_keys/components/keys_panel_spec.js @@ -1,9 +1,9 @@ import { mount } from '@vue/test-utils'; +import data from 'test_fixtures/deploy_keys/keys.json'; import deployKeysPanel from '~/deploy_keys/components/keys_panel.vue'; import DeployKeysStore from '~/deploy_keys/store'; describe('Deploy keys panel', () => { - const data = getJSONFixture('deploy_keys/keys.json'); let wrapper; const findTableRowHeader = () => wrapper.find('.table-row-header'); diff --git a/spec/frontend/diffs/mock_data/diff_with_commit.js b/spec/frontend/diffs/mock_data/diff_with_commit.js index f3b39bd3577..a261f5cda8c 100644 --- a/spec/frontend/diffs/mock_data/diff_with_commit.js +++ b/spec/frontend/diffs/mock_data/diff_with_commit.js @@ -1,5 +1,5 @@ -const FIXTURE = 'merge_request_diffs/with_commit.json'; +import fixture from 'test_fixtures/merge_request_diffs/with_commit.json'; export default function getDiffWithCommit() { - return getJSONFixture(FIXTURE); + return fixture; } diff --git a/spec/frontend/filtered_search/visual_token_value_spec.js b/spec/frontend/filtered_search/visual_token_value_spec.js index 7185f382fc1..8ac5b6fbea6 100644 --- a/spec/frontend/filtered_search/visual_token_value_spec.js +++ b/spec/frontend/filtered_search/visual_token_value_spec.js @@ -1,4 +1,5 @@ import { escape } from 'lodash'; +import labelData from 'test_fixtures/labels/project_labels.json'; import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper'; import { TEST_HOST } from 'helpers/test_constants'; import DropdownUtils from '~/filtered_search/dropdown_utils'; @@ -132,15 +133,8 @@ describe('Filtered Search Visual Tokens', () => { }); describe('updateLabelTokenColor', () => { - const jsonFixtureName = 'labels/project_labels.json'; const dummyEndpoint = '/dummy/endpoint'; - let labelData; - - beforeAll(() => { - labelData = getJSONFixture(jsonFixtureName); - }); - const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken( 'label', '=', diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js index ff602327592..0a9cbadb249 100644 --- a/spec/frontend/integrations/edit/components/integration_form_spec.js +++ b/spec/frontend/integrations/edit/components/integration_form_spec.js @@ -11,7 +11,7 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue'; import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue'; import TriggerFields from '~/integrations/edit/components/trigger_fields.vue'; -import { integrationLevels } from '~/integrations/edit/constants'; +import { integrationLevels } from '~/integrations/constants'; import { createStore } from '~/integrations/edit/store'; describe('IntegrationForm', () => { diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js index eb43d940f5e..90facaff1f9 100644 --- a/spec/frontend/integrations/edit/components/override_dropdown_spec.js +++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js @@ -2,7 +2,7 @@ import { GlDropdown, GlLink } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue'; -import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants'; +import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/constants'; import { createStore } from '~/integrations/edit/store'; describe('OverrideDropdown', () => { diff --git a/spec/frontend/packages/shared/components/package_list_row_spec.js b/spec/frontend/packages/shared/components/package_list_row_spec.js index bd15d48c4eb..5f2fc8ddfbd 100644 --- a/spec/frontend/packages/shared/components/package_list_row_spec.js +++ b/spec/frontend/packages/shared/components/package_list_row_spec.js @@ -1,5 +1,5 @@ import { GlLink } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import PackagesListRow from '~/packages/shared/components/package_list_row.vue'; @@ -19,14 +19,14 @@ describe('packages_list_row', () => { const InfrastructureIconAndName = { name: 'InfrastructureIconAndName', template: '<div></div>' }; const PackageIconAndName = { name: 'PackageIconAndName', template: '<div></div>' }; - const findPackageTags = () => wrapper.find(PackageTags); - const findPackagePath = () => wrapper.find(PackagePath); - const findDeleteButton = () => wrapper.find('[data-testid="action-delete"]'); - const findPackageIconAndName = () => wrapper.find(PackageIconAndName); + const findPackageTags = () => wrapper.findComponent(PackageTags); + const findPackagePath = () => wrapper.findComponent(PackagePath); + const findDeleteButton = () => wrapper.findByTestId('action-delete'); + const findPackageIconAndName = () => wrapper.findComponent(PackageIconAndName); const findInfrastructureIconAndName = () => wrapper.findComponent(InfrastructureIconAndName); const findListItem = () => wrapper.findComponent(ListItem); const findPackageLink = () => wrapper.findComponent(GlLink); - const findWarningIcon = () => wrapper.find('[data-testid="warning-icon"]'); + const findWarningIcon = () => wrapper.findByTestId('warning-icon'); const mountComponent = ({ isGroup = false, @@ -35,7 +35,7 @@ describe('packages_list_row', () => { disableDelete = false, provide, } = {}) => { - wrapper = shallowMount(PackagesListRow, { + wrapper = shallowMountExtended(PackagesListRow, { store, provide, stubs: { diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap new file mode 100644 index 00000000000..2f2be797251 --- /dev/null +++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`packages_list_row renders 1`] = ` +<div + class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1 gl-border-t-transparent gl-border-b-gray-100" + data-qa-selector="package_row" +> + <div + class="gl-display-flex gl-align-items-center gl-py-3 gl-px-5" + > + <!----> + + <div + class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1" + > + <div + class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1" + > + <div + class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0" + > + <div + class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0" + > + <gl-link-stub + class="gl-text-body gl-min-w-0" + data-qa-selector="package_link" + href="http://gdk.test:3000/gitlab-org/gitlab-test/-/packages/111" + > + <gl-truncate-stub + position="end" + text="@gitlab-org/package-15" + /> + </gl-link-stub> + + <!----> + + <!----> + </div> + + <!----> + </div> + + <div + class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1" + > + <div + class="gl-display-flex" + data-testid="left-secondary-infos" + > + <span> + 1.0.0 + </span> + + <!----> + + <package-icon-and-name-stub> + + npm + + </package-icon-and-name-stub> + + <!----> + </div> + </div> + </div> + + <div + class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500 gl-flex-shrink-0" + > + <div + class="gl-display-flex gl-align-items-center gl-sm-text-body gl-sm-font-weight-bold gl-min-h-6" + > + <publish-method-stub /> + </div> + + <div + class="gl-display-flex gl-align-items-center gl-min-h-6" + > + <span> + Created + <timeago-tooltip-stub + cssclass="" + time="2020-08-17T14:23:32Z" + tooltipplacement="top" + /> + </span> + </div> + </div> + </div> + + <div + class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1" + > + <gl-button-stub + aria-label="Remove package" + buttontextclasses="" + category="secondary" + data-testid="action-delete" + icon="remove" + size="medium" + title="Remove package" + variant="danger" + /> + </div> + </div> + + <div + class="gl-display-flex" + > + <div + class="gl-w-7" + /> + + <!----> + + <div + class="gl-w-9" + /> + </div> +</div> +`; diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap new file mode 100644 index 00000000000..919dbe25ffe --- /dev/null +++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`publish_method renders 1`] = ` +<div + class="gl-display-flex gl-align-items-center" +> + <gl-icon-stub + class="gl-mr-2" + name="git-merge" + size="16" + /> + + <span + class="gl-mr-2" + data-testid="pipeline-ref" + > + master + </span> + + <gl-icon-stub + class="gl-mr-2" + name="commit" + size="16" + /> + + <gl-link-stub + class="gl-mr-2" + data-testid="pipeline-sha" + href="/namespace14/project14/-/commit/b83d6e391c22777fca1ed3012fce84f633d7fed0" + > + b83d6e39 + </gl-link-stub> + + <clipboard-button-stub + category="tertiary" + size="small" + text="b83d6e391c22777fca1ed3012fce84f633d7fed0" + title="Copy commit SHA" + tooltipplacement="top" + /> +</div> +`; diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js new file mode 100644 index 00000000000..a276db104d7 --- /dev/null +++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js @@ -0,0 +1,156 @@ +import { GlLink, GlSprintf } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; + +import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue'; +import PackagePath from '~/packages/shared/components/package_path.vue'; +import PackageTags from '~/packages/shared/components/package_tags.vue'; +import PackageIconAndName from '~/packages/shared/components/package_icon_and_name.vue'; +import { PACKAGE_ERROR_STATUS } from '~/packages_and_registries/package_registry/constants'; + +import ListItem from '~/vue_shared/components/registry/list_item.vue'; +import { packageData, packagePipelines, packageProject, packageTags } from '../../mock_data'; + +describe('packages_list_row', () => { + let wrapper; + + const defaultProvide = { + isGroupPage: false, + }; + + const packageWithoutTags = { ...packageData(), project: packageProject() }; + const packageWithTags = { ...packageWithoutTags, tags: { nodes: packageTags() } }; + + const findPackageTags = () => wrapper.find(PackageTags); + const findPackagePath = () => wrapper.find(PackagePath); + const findDeleteButton = () => wrapper.findByTestId('action-delete'); + const findPackageIconAndName = () => wrapper.find(PackageIconAndName); + const findListItem = () => wrapper.findComponent(ListItem); + const findPackageLink = () => wrapper.findComponent(GlLink); + const findWarningIcon = () => wrapper.findByTestId('warning-icon'); + const findLeftSecondaryInfos = () => wrapper.findByTestId('left-secondary-infos'); + + const mountComponent = ({ + packageEntity = packageWithoutTags, + provide = defaultProvide, + } = {}) => { + wrapper = shallowMountExtended(PackagesListRow, { + provide, + stubs: { + ListItem, + GlSprintf, + }, + propsData: { + packageEntity, + }, + directives: { + GlTooltip: createMockDirective(), + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders', () => { + mountComponent(); + expect(wrapper.element).toMatchSnapshot(); + }); + + describe('tags', () => { + it('renders package tags when a package has tags', () => { + mountComponent({ packageEntity: packageWithTags }); + + expect(findPackageTags().exists()).toBe(true); + }); + + it('does not render when there are no tags', () => { + mountComponent(); + + expect(findPackageTags().exists()).toBe(false); + }); + }); + + describe('when it is group', () => { + it('has a package path component', () => { + mountComponent({ provide: { isGroupPage: true } }); + + expect(findPackagePath().exists()).toBe(true); + expect(findPackagePath().props()).toMatchObject({ path: 'gitlab-org/gitlab-test' }); + }); + }); + + describe('delete button', () => { + it('exists and has the correct props', () => { + mountComponent({ packageEntity: packageWithoutTags }); + + expect(findDeleteButton().exists()).toBe(true); + expect(findDeleteButton().attributes()).toMatchObject({ + icon: 'remove', + category: 'secondary', + variant: 'danger', + title: 'Remove package', + }); + }); + + it('emits the packageToDelete event when the delete button is clicked', async () => { + mountComponent({ packageEntity: packageWithoutTags }); + + findDeleteButton().vm.$emit('click'); + + await wrapper.vm.$nextTick(); + expect(wrapper.emitted('packageToDelete')).toBeTruthy(); + expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]); + }); + }); + + describe(`when the package is in ${PACKAGE_ERROR_STATUS} status`, () => { + beforeEach(() => { + mountComponent({ packageEntity: { ...packageWithoutTags, status: PACKAGE_ERROR_STATUS } }); + }); + + it('list item has a disabled prop', () => { + expect(findListItem().props('disabled')).toBe(true); + }); + + it('details link is disabled', () => { + expect(findPackageLink().attributes('disabled')).toBe('true'); + }); + + it('has a warning icon', () => { + const icon = findWarningIcon(); + const tooltip = getBinding(icon.element, 'gl-tooltip'); + expect(icon.props('icon')).toBe('warning'); + expect(tooltip.value).toMatchObject({ + title: 'Invalid Package: failed metadata extraction', + }); + }); + + it('delete button does not exist', () => { + expect(findDeleteButton().exists()).toBe(false); + }); + }); + + describe('secondary left info', () => { + it('has the package version', () => { + mountComponent(); + + expect(findLeftSecondaryInfos().text()).toContain(packageWithoutTags.version); + }); + + it('if the pipeline exists show the author message', () => { + mountComponent({ + packageEntity: { ...packageWithoutTags, pipelines: { nodes: packagePipelines() } }, + }); + + expect(findLeftSecondaryInfos().text()).toContain('published by Administrator'); + }); + + it('has icon and name component', () => { + mountComponent(); + + expect(findPackageIconAndName().text()).toBe(packageWithoutTags.packageType.toLowerCase()); + }); + }); +}); diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js new file mode 100644 index 00000000000..fcbd7cc6a50 --- /dev/null +++ b/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js @@ -0,0 +1,47 @@ +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import PublishMethod from '~/packages_and_registries/package_registry/components/list/publish_method.vue'; +import { packagePipelines } from '../../mock_data'; + +const [pipelineData] = packagePipelines(); + +describe('publish_method', () => { + let wrapper; + + const findPipelineRef = () => wrapper.findByTestId('pipeline-ref'); + const findPipelineSha = () => wrapper.findByTestId('pipeline-sha'); + const findManualPublish = () => wrapper.findByTestId('manually-published'); + + const mountComponent = (pipeline = pipelineData) => { + wrapper = shallowMountExtended(PublishMethod, { + propsData: { + pipeline, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders', () => { + mountComponent(); + expect(wrapper.element).toMatchSnapshot(); + }); + + describe('pipeline information', () => { + it('displays branch and commit when pipeline info exists', () => { + mountComponent(); + + expect(findPipelineRef().exists()).toBe(true); + expect(findPipelineSha().exists()).toBe(true); + }); + + it('does not show any pipeline details when no information exists', () => { + mountComponent(null); + + expect(findPipelineRef().exists()).toBe(false); + expect(findPipelineSha().exists()).toBe(false); + expect(findManualPublish().text()).toBe(PublishMethod.i18n.MANUALLY_PUBLISHED); + }); + }); +}); diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js index 8b1ac377531..70fc096fa44 100644 --- a/spec/frontend/packages_and_registries/package_registry/mock_data.js +++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js @@ -86,6 +86,12 @@ export const dependencyLinks = () => [ }, ]; +export const packageProject = () => ({ + fullPath: 'gitlab-org/gitlab-test', + webUrl: 'http://gdk.test:3000/gitlab-org/gitlab-test', + __typename: 'Project', +}); + export const packageVersions = () => [ { createdAt: '2021-08-10T09:33:54Z', @@ -257,14 +263,18 @@ export const packagesListQuery = (type = 'group') => ({ count: 2, nodes: [ { - __typename: 'Package', - id: 'gid://gitlab/Packages::Package/247', - name: 'version_test1', + ...packageData(), + project: packageProject(), + tags: { nodes: packageTags() }, + pipelines: { + nodes: packagePipelines(), + }, }, { - __typename: 'Package', - id: 'gid://gitlab/Packages::Package/246', - name: 'version_test1', + ...packageData(), + project: packageProject(), + tags: { nodes: [] }, + pipelines: { nodes: [] }, }, ], __typename: 'PackageConnection', diff --git a/spec/helpers/hooks_helper_spec.rb b/spec/helpers/hooks_helper_spec.rb index 92e082c4974..3b23d705790 100644 --- a/spec/helpers/hooks_helper_spec.rb +++ b/spec/helpers/hooks_helper_spec.rb @@ -6,9 +6,10 @@ RSpec.describe HooksHelper do let(:project) { create(:project) } let(:project_hook) { create(:project_hook, project: project) } let(:system_hook) { create(:system_hook) } - let(:trigger) { 'push_events' } describe '#link_to_test_hook' do + let(:trigger) { 'push_events' } + it 'returns project namespaced link' do expect(helper.link_to_test_hook(project_hook, trigger)) .to include("href=\"#{test_project_hook_path(project, project_hook, trigger: trigger)}\"") @@ -19,4 +20,24 @@ RSpec.describe HooksHelper do .to include("href=\"#{test_admin_hook_path(system_hook, trigger: trigger)}\"") end end + + describe '#hook_log_path' do + context 'with a project hook' do + let(:web_hook_log) { create(:web_hook_log, web_hook: project_hook) } + + it 'returns project-namespaced link' do + expect(helper.hook_log_path(project_hook, web_hook_log)) + .to eq(web_hook_log.present.details_path) + end + end + + context 'with a system hook' do + let(:web_hook_log) { create(:web_hook_log, web_hook: system_hook) } + + it 'returns admin-namespaced link' do + expect(helper.hook_log_path(system_hook, web_hook_log)) + .to eq(admin_hook_hook_log_path(system_hook, web_hook_log)) + end + end + end end |