diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-30 15:10:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-30 15:10:51 +0300 |
commit | a10d237d37e78cbe84f72fffaeff74dc73f1e68f (patch) | |
tree | a3a820c7d67801605dcbb419d3f38513ee61044c | |
parent | afa3d4e0666ea2cddcf995fadac75c35a75c9b64 (diff) |
Add latest changes from gitlab-org/gitlab@master
75 files changed, 653 insertions, 344 deletions
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index d2d32691dba..d4875d7e89c 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -189,22 +189,6 @@ Rails/SaveBang: - 'spec/controllers/omniauth_callbacks_controller_spec.rb' - 'spec/controllers/profiles/emails_controller_spec.rb' - 'spec/controllers/profiles/notifications_controller_spec.rb' - - 'spec/controllers/projects/artifacts_controller_spec.rb' - - 'spec/controllers/projects/cycle_analytics/events_controller_spec.rb' - - 'spec/controllers/projects/cycle_analytics_controller_spec.rb' - - 'spec/controllers/projects/discussions_controller_spec.rb' - - 'spec/controllers/projects/forks_controller_spec.rb' - - 'spec/controllers/projects/group_links_controller_spec.rb' - - 'spec/controllers/projects/imports_controller_spec.rb' - - 'spec/controllers/projects/issues_controller_spec.rb' - - 'spec/controllers/projects/labels_controller_spec.rb' - - 'spec/controllers/projects/milestones_controller_spec.rb' - - 'spec/controllers/projects/notes_controller_spec.rb' - - 'spec/controllers/projects/pipelines_controller_spec.rb' - - 'spec/controllers/projects/releases/evidences_controller_spec.rb' - - 'spec/controllers/projects/runners_controller_spec.rb' - - 'spec/controllers/projects/starrers_controller_spec.rb' - - 'spec/controllers/projects/uploads_controller_spec.rb' - 'spec/controllers/projects_controller_spec.rb' - 'spec/controllers/sent_notifications_controller_spec.rb' - 'spec/controllers/sessions_controller_spec.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index b6707734a9a..1ac9f38e3db 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -cc879cfb5db4ed342c4f0ea744dbbfdc9649b35f +79003389aa5098a6ef37e73298cafbad4d9e6b79 diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue new file mode 100644 index 00000000000..98190d716c9 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue @@ -0,0 +1,105 @@ +<script> +import { + GlFilteredSearchToken, + GlFilteredSearchSuggestion, + GlDropdownDivider, + GlLoadingIcon, +} from '@gitlab/ui'; +import { debounce } from 'lodash'; + +import { deprecatedCreateFlash as createFlash } from '~/flash'; +import { __ } from '~/locale'; + +import { DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY, DEBOUNCE_DELAY } from '../constants'; +import { stripQuotes } from '../filtered_search_utils'; + +export default { + components: { + GlFilteredSearchToken, + GlFilteredSearchSuggestion, + GlDropdownDivider, + GlLoadingIcon, + }, + props: { + config: { + type: Object, + required: true, + }, + value: { + type: Object, + required: true, + }, + }, + data() { + return { + emojis: this.config.initialEmojis || [], + defaultEmojis: this.config.defaultEmojis || [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY], + loading: true, + }; + }, + computed: { + currentValue() { + return this.value.data.toLowerCase(); + }, + activeEmoji() { + return this.emojis.find( + (emoji) => emoji.name.toLowerCase() === stripQuotes(this.currentValue), + ); + }, + }, + methods: { + fetchEmojiBySearchTerm(searchTerm) { + this.loading = true; + this.config + .fetchEmojis(searchTerm) + .then((res) => { + this.emojis = Array.isArray(res) ? res : res.data; + }) + .catch(() => createFlash(__('There was a problem fetching emojis.'))) + .finally(() => { + this.loading = false; + }); + }, + searchEmojis: debounce(function debouncedSearch({ data }) { + this.fetchEmojiBySearchTerm(data); + }, DEBOUNCE_DELAY), + }, +}; +</script> + +<template> + <gl-filtered-search-token + :config="config" + v-bind="{ ...$props, ...$attrs }" + v-on="$listeners" + @input="searchEmojis" + > + <template #view="{ inputValue }"> + <gl-emoji v-if="activeEmoji" :data-name="activeEmoji.name" /> + <span v-else>{{ inputValue }}</span> + </template> + <template #suggestions> + <gl-filtered-search-suggestion + v-for="emoji in defaultEmojis" + :key="emoji.value" + :value="emoji.value" + > + {{ emoji.value }} + </gl-filtered-search-suggestion> + <gl-dropdown-divider v-if="defaultEmojis.length" /> + <gl-loading-icon v-if="loading" /> + <template v-else> + <gl-filtered-search-suggestion + v-for="emoji in emojis" + :key="emoji.name" + :value="emoji.name" + > + <div class="gl-display-flex"> + <gl-emoji :data-name="emoji.name" /> + <span class="gl-ml-3">{{ emoji.name }}</span> + </div> + </gl-filtered-search-suggestion> + </template> + </template> + </gl-filtered-search-token> +</template> diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index 8f6d94a172a..2ab23064353 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -260,7 +260,7 @@ export default { :line-content="lineContent" :can-suggest="canSuggest" :show-suggest-popover="showSuggestPopover" - :suggestion-start-index="lines.length" + :suggestion-start-index="lines.length - 1" @preview-markdown="showPreviewTab" @write-markdown="showWriteTab" @handleSuggestDismissed="() => $emit('handleSuggestDismissed')" diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb index c3816116e2b..91a5109c748 100644 --- a/app/graphql/types/milestone_type.rb +++ b/app/graphql/types/milestone_type.rb @@ -14,6 +14,9 @@ module Types field :id, GraphQL::ID_TYPE, null: false, description: 'ID of the milestone.' + field :iid, GraphQL::ID_TYPE, null: false, + description: "Internal ID of the milestone." + field :title, GraphQL::STRING_TYPE, null: false, description: 'Title of the milestone.' diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb index 17b5a202922..08e9f06a6a1 100644 --- a/app/models/packages/package.rb +++ b/app/models/packages/package.rb @@ -5,6 +5,8 @@ class Packages::Package < ApplicationRecord include UsageStatistics include Gitlab::Utils::StrongMemoize + DISPLAYABLE_STATUSES = [:default, :error].freeze + belongs_to :project belongs_to :creator, class_name: 'User' @@ -70,7 +72,7 @@ class Packages::Package < ApplicationRecord composer: 6, generic: 7, golang: 8, debian: 9, rubygems: 10 } - enum status: { default: 0, hidden: 1, processing: 2 } + enum status: { default: 0, hidden: 1, processing: 2, error: 3 } scope :with_name, ->(name) { where(name: name) } scope :with_name_like, ->(name) { where(arel_table[:name].matches(name)) } @@ -80,7 +82,7 @@ class Packages::Package < ApplicationRecord scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) } scope :with_package_type, ->(package_type) { where(package_type: package_type) } scope :with_status, ->(status) { where(status: status) } - scope :displayable, -> { with_status(:default) } + scope :displayable, -> { with_status(DISPLAYABLE_STATUSES) } scope :including_build_info, -> { includes(pipelines: :user) } scope :including_project_route, -> { includes(project: { namespace: :route }) } scope :including_tags, -> { includes(:tags) } diff --git a/app/models/project.rb b/app/models/project.rb index b21d9818953..30741e117bf 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1370,9 +1370,9 @@ class Project < ApplicationRecord end def disabled_services - return %w(datadog) unless Feature.enabled?(:datadog_ci_integration, self) + return %w[datadog hipchat] unless Feature.enabled?(:datadog_ci_integration, self) - [] + %w[hipchat] end def find_or_initialize_service(name) diff --git a/app/models/service.rb b/app/models/service.rb index b0bad81d584..ff69327ab61 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -12,7 +12,7 @@ class Service < ApplicationRecord SERVICE_NAMES = %w[ asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog discord - drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat hipchat irker jira + drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat irker jira mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack ].freeze diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index 0d819dc5b47..fd35574a64c 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -3,15 +3,15 @@ .table-mobile-header{ role: 'rowheader' }= _('Type') .table-mobile-content - if runner.instance_type? - %span.badge.badge-success shared + %span.badge.badge-pill.gl-badge.sm.badge-success shared - elsif runner.group_type? - %span.badge.badge-success group + %span.badge.badge-pill.gl-badge.sm.badge-success group - else - %span.badge.badge-info specific + %span.badge.badge-pill.gl-badge.sm.badge-info specific - if runner.locked? - %span.badge.badge-warning locked + %span.badge.badge-pill.gl-badge.sm.badge-warning locked - unless runner.active? - %span.badge.badge-danger paused + %span.badge.badge-pill.gl-badge.sm.badge-danger paused .table-section.section-10 .table-mobile-header{ role: 'rowheader' }= _('Runner token') diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index aca50de3852..0ad9173b9ff 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -1,19 +1,11 @@ - add_page_specific_style 'page_bundles/ci_status' -= content_for :title do - %h3.project-title - Runner ##{@runner.id} - .float-right - - if @runner.instance_type? - %span.runner-state.runner-state-shared - Shared - - else - %span.runner-state.runner-state-specific - Specific - - page_title @runner.short_sha -- add_to_breadcrumbs _("Runners"), admin_runners_path -- breadcrumb_title "##{@runner.id}" +- add_to_breadcrumbs _('Runners'), admin_runners_path +- breadcrumb_title page_title + +%h2.page-title + = sprintf(s_('Runners|Runner #%{runner_id}'), {runner_id: @runner.id}) - if @runner.instance_type? .bs-callout.bs-callout-success diff --git a/changelogs/unreleased/27954-remove-hipchat-project-service.yml b/changelogs/unreleased/27954-remove-hipchat-project-service.yml new file mode 100644 index 00000000000..3757d5d6793 --- /dev/null +++ b/changelogs/unreleased/27954-remove-hipchat-project-service.yml @@ -0,0 +1,5 @@ +--- +title: Remove HipChat integration from frontend and docs +merge_request: 57556 +author: +type: removed diff --git a/changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml b/changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml new file mode 100644 index 00000000000..911b8f0d667 --- /dev/null +++ b/changelogs/unreleased/326091-appearance-of-badges-admin-runner-table.yml @@ -0,0 +1,5 @@ +--- +title: Update runner badges look and feel in admin runners table +merge_request: 57566 +author: +type: changed diff --git a/changelogs/unreleased/activerecord_empty_query_default_true.yml b/changelogs/unreleased/activerecord_empty_query_default_true.yml new file mode 100644 index 00000000000..c01d65cf8d3 --- /dev/null +++ b/changelogs/unreleased/activerecord_empty_query_default_true.yml @@ -0,0 +1,5 @@ +--- +title: Use empty-query by default to check database connection +merge_request: 54366 +author: Leandro Gomes @leandrogs +type: performance diff --git a/changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml b/changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml new file mode 100644 index 00000000000..6bf231a5da5 --- /dev/null +++ b/changelogs/unreleased/add_source_project_target_branch_index_to_merge_request.yml @@ -0,0 +1,5 @@ +--- +title: Add TargetProject And SourceBranch Index To MergeRequest +merge_request: 57691 +author: +type: performance diff --git a/changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml b/changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml new file mode 100644 index 00000000000..895439db59c --- /dev/null +++ b/changelogs/unreleased/kassio-graphql-expose-milestone-iid.yml @@ -0,0 +1,5 @@ +--- +title: 'GraphQL: expose milestone iid' +merge_request: 57732 +author: +type: changed diff --git a/changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml b/changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml new file mode 100644 index 00000000000..a4a477abac3 --- /dev/null +++ b/changelogs/unreleased/mrincon-runner-detail-breadcrumb-fix.yml @@ -0,0 +1,5 @@ +--- +title: Add Runner ID as title in Runner details page +merge_request: 57247 +author: +type: changed diff --git a/changelogs/unreleased/rails-save-bang-project-controllers.yml b/changelogs/unreleased/rails-save-bang-project-controllers.yml new file mode 100644 index 00000000000..76b9cc97c23 --- /dev/null +++ b/changelogs/unreleased/rails-save-bang-project-controllers.yml @@ -0,0 +1,5 @@ +--- +title: Fix Rails/SaveBang rubocop offenses in spec/controllers/projects/* +merge_request: 57643 +author: Abdul Wadood @abdulwd +type: fixed diff --git a/config/feature_flags/development/cluster_agent_list.yml b/config/feature_flags/development/cluster_agent_list.yml deleted file mode 100644 index 2c49950620d..00000000000 --- a/config/feature_flags/development/cluster_agent_list.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: cluster_agent_list -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42115 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249596 -milestone: '13.5' -type: development -group: group::configure -default_enabled: true diff --git a/config/initializers/active_record_ping.rb b/config/initializers/active_record_ping.rb index 196f587f565..7088c690a51 100644 --- a/config/initializers/active_record_ping.rb +++ b/config/initializers/active_record_ping.rb @@ -2,6 +2,6 @@ # # frozen_string_literal: true -if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: false) +if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: true) ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Database::PostgresqlAdapter::EmptyQueryPing) end diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml b/config/metrics/aggregates/code_review.yml index a2e931bd217..a2e931bd217 100644 --- a/lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml +++ b/config/metrics/aggregates/code_review.yml diff --git a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml b/config/metrics/aggregates/common.yml index abf04c18e19..15fc6915977 100644 --- a/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml +++ b/config/metrics/aggregates/common.yml @@ -1,4 +1,4 @@ -# Aggregated metrics that include EE only event names within `events:` attribute have to be defined at ee/lib/gitlab/usage_data_counters/aggregated_metrics/common.yml +# Aggregated metrics that include EE only event names within `events:` attribute have to be defined at ee/config/metrics/aggregates/common.yml # instead of this file. #- name: unique name of aggregated metric # operator: aggregation operator. Valid values are: diff --git a/db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb b/db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb new file mode 100644 index 00000000000..d351de6bd77 --- /dev/null +++ b/db/migrate/20210329095548_add_target_project_and_source_branch_index_to_merge_request.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddTargetProjectAndSourceBranchIndexToMergeRequest < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + INDEX_NAME = 'index_merge_requests_on_target_project_id_and_source_branch' + + disable_ddl_transaction! + + def up + add_concurrent_index :merge_requests, [:target_project_id, :source_branch], name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :epic_issues, INDEX_NAME + end +end diff --git a/db/schema_migrations/20210329095548 b/db/schema_migrations/20210329095548 new file mode 100644 index 00000000000..a3f65e8e446 --- /dev/null +++ b/db/schema_migrations/20210329095548 @@ -0,0 +1 @@ +412d0cedef5c933c7de3a70ca2365fe0cfaa4087429ca418854092b6c37904f1
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 96e1a788f31..0fbbd4ea008 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -23090,6 +23090,8 @@ CREATE INDEX index_merge_requests_on_target_project_id_and_iid_and_state_id ON m CREATE INDEX index_merge_requests_on_target_project_id_and_iid_jira_title ON merge_requests USING btree (target_project_id, iid) WHERE ((title)::text ~ '[A-Z][A-Z_0-9]+-\d+'::text); +CREATE INDEX index_merge_requests_on_target_project_id_and_source_branch ON merge_requests USING btree (target_project_id, source_branch); + CREATE INDEX index_merge_requests_on_target_project_id_and_squash_commit_sha ON merge_requests USING btree (target_project_id, squash_commit_sha); CREATE INDEX index_merge_requests_on_target_project_id_and_target_branch ON merge_requests USING btree (target_project_id, target_branch) WHERE ((state_id = 1) AND (merge_when_pipeline_succeeds = true)); diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt index 5025ddfe2dc..4c4bbe96a96 100644 --- a/doc/.vale/gitlab/spelling-exceptions.txt +++ b/doc/.vale/gitlab/spelling-exceptions.txt @@ -245,7 +245,6 @@ Helm Heroku Herokuish Hexo -HipChat hostname hostnames hotfix diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 611520b4e19..ab809e28acb 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -3064,6 +3064,7 @@ Autogenerated return type of GitlabSubscriptionActivate. | `additionalPurchasedStorageSize` | [`Float`](#float) | Additional storage purchased for the root namespace in bytes. | | `autoDevopsEnabled` | [`Boolean`](#boolean) | Indicates whether Auto DevOps is enabled for all projects within this group. | | `avatarUrl` | [`String`](#string) | Avatar URL of the group. | +| `billableMembersCount` | [`Int`](#int) | The number of billable users in the group. | | `board` | [`Board`](#board) | A single board of the group. | | `boards` | [`BoardConnection`](#boardconnection) | Boards of the group. | | `codeCoverageActivities` | [`CodeCoverageActivityConnection`](#codecoverageactivityconnection) | Represents the code coverage activity for this group. | @@ -4167,6 +4168,7 @@ Represents a milestone. | `dueDate` | [`Time`](#time) | Timestamp of the milestone due date. | | `groupMilestone` | [`Boolean!`](#boolean) | Indicates if milestone is at group level. | | `id` | [`ID!`](#id) | ID of the milestone. | +| `iid` | [`ID!`](#id) | Internal ID of the milestone. | | `projectMilestone` | [`Boolean!`](#boolean) | Indicates if milestone is at project level. | | `report` | [`TimeboxReport`](#timeboxreport) | Historically accurate report about the timebox. | | `startDate` | [`Time`](#time) | Timestamp of the milestone start date. | @@ -8013,7 +8015,6 @@ State of a Sentry error. | `FLOWDOCK_SERVICE` | FlowdockService type. | | `GITHUB_SERVICE` | GithubService type. | | `HANGOUTS_CHAT_SERVICE` | HangoutsChatService type. | -| `HIPCHAT_SERVICE` | HipchatService type. | | `IRKER_SERVICE` | IrkerService type. | | `JENKINS_SERVICE` | JenkinsService type. | | `JIRA_SERVICE` | JiraService type. | diff --git a/doc/api/services.md b/doc/api/services.md index 429d824fcb1..2311a5cacb7 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -692,53 +692,6 @@ Get Hangouts Chat service settings for a project. GET /projects/:id/services/hangouts-chat ``` -## HipChat - -Private group chat and IM - -### Create/Edit HipChat service - -Set HipChat service for a project. - -```plaintext -PUT /projects/:id/services/hipchat -``` - -Parameters: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `token` | string | true | Room token | -| `color` | string | false | The room color | -| `notify` | boolean | false | Enable notifications | -| `room` | string | false |Room name or ID | -| `api_version` | string | false | Leave blank for default (v2) | -| `server` | string | false | Leave blank for default. For example, `https://hipchat.example.com`. | -| `push_events` | boolean | false | Enable notifications for push events | -| `issues_events` | boolean | false | Enable notifications for issue events | -| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | -| `merge_requests_events` | boolean | false | Enable notifications for merge request events | -| `tag_push_events` | boolean | false | Enable notifications for tag push events | -| `note_events` | boolean | false | Enable notifications for note events | -| `confidential_note_events` | boolean | false | Enable notifications for confidential note events | -| `pipeline_events` | boolean | false | Enable notifications for pipeline events | - -### Delete HipChat service - -Delete HipChat service for a project. - -```plaintext -DELETE /projects/:id/services/hipchat -``` - -### Get HipChat service settings - -Get HipChat service settings for a project. - -```plaintext -GET /projects/:id/services/hipchat -``` - ## Irker (IRC gateway) Send IRC messages, on update, to a list of recipients through an Irker gateway. diff --git a/doc/development/agent/local.md b/doc/development/agent/local.md index 603364567bf..670315db3a8 100644 --- a/doc/development/agent/local.md +++ b/doc/development/agent/local.md @@ -98,3 +98,58 @@ bazel test //internal/module/gitops/server:server_test - Bazel documentation about [specifying targets to build](https://docs.bazel.build/versions/master/guide.html#specifying-targets-to-build). - [The Bazel query](https://docs.bazel.build/versions/master/query.html) - [Bazel query how to](https://docs.bazel.build/versions/master/query-how-to.html) + +## KAS QA tests + +This section describes how to run KAS tests against different GitLab environments based on the +[GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa). + +### Status + +The `kas` QA tests currently have some limitations. You can run them manually on GDK, but they don't +run automatically with the nightly jobs against the live environment. See the section below +to learn how to run them against different environments. + +### Prepare + +Before performing any of these tests, if you have a `k3s` instance running, make sure to +stop it manually before running them. Otherwise, the tests might fail with the message +`failed to remove k3s cluster`. + +You might need to specify the correct Agent image version that matches the `kas` image version. You can use the `GITLAB_AGENTK_VERSION` local env for this. + +### Against `staging` + +1. Go to your local `qa/qa/service/cluster_provider/k3s.rb` and comment out + [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/5b15540ea78298a106150c3a1d6ed26416109b9d/qa/qa/service/cluster_provider/k3s.rb#L8) and + [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/5b15540ea78298a106150c3a1d6ed26416109b9d/qa/qa/service/cluster_provider/k3s.rb#L36). + We don't allow local connections on `staging` as they require an admin user. +1. Ensure you don't have an `EE_LICENSE` env var set as this would force an admin login. +1. Go to your GDK root folder and `cd gitlab/qa`. +1. Login with your user in staging and create a group to be used as sandbox. + Something like: `username-qa-sandbox`. +1. Create an access token for your user with the `api` permission. +1. Replace the values given below with your own and run: + + ```shell + GITLAB_SANDBOX_NAME="<THE GROUP ID YOU CREATED ON STEP 2>" \ + GITLAB_QA_ACCESS_TOKEN="<THE ACCESS TOKEN YOU CREATED ON STEP 3>" \ + GITLAB_USERNAME="<YOUR STAGING USERNAME>" \ + GITLAB_PASSWORD="<YOUR STAGING PASSWORD>" \ + bundle exec bin/qa Test::Instance::All https://staging.gitlab.com -- --tag quarantine qa/specs/features/ee/api/7_configure/kubernetes/kubernetes_agent_spec.rb + ``` + +### Against GDK + +1. Go to your `qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb` and comment out [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/a55b78532cfd29426cf4e5b4edda81407da9d449/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb#L27) and uncomment [this line](https://gitlab.com/gitlab-org/gitlab/-/blob/a55b78532cfd29426cf4e5b4edda81407da9d449/qa/qa/fixtures/kubernetes_agent/agentk-manifest.yaml.erb#L28). + GDK's `kas` listens on `grpc`, not on `wss`. +1. Go to the GDK's root folder and `cd gitlab/qa`. +1. On the contrary to staging, run the QA test in GDK as admin, which is the default choice. To do so, use the default sandbox group and run the command below. Make sure to adjust your credentials if necessary, otherwise, the test might fail: + + ```shell + GITLAB_USERNAME=root \ + GITLAB_PASSWORD="5iveL\!fe" \ + GITLAB_ADMIN_USERNAME=root \ + GITLAB_ADMIN_PASSWORD="5iveL\!fe" \ + bundle exec bin/qa Test::Instance::All http://gdk.test:3000 -- --tag quarantine qa/specs/features/ee/api/7_configure/kubernetes/kubernetes_agent_spec.rb + ``` diff --git a/doc/development/code_review.md b/doc/development/code_review.md index 083398a840d..f354d7ccbe9 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -409,7 +409,7 @@ When ready to merge: - **Start a new merge request pipeline with the `Run Pipeline` button in the merge request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).** Note that: - If **[master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master), - do not merge the merge request**. Follow these specific [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#maintaining-throughput-during-broken-master). + For other cases, follow these [handbook instructions](https://about.gitlab.com/handbook/engineering/workflow/#merging-during-broken-master). - If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you might merge without starting a new pipeline as the merge request is close enough to `master`. diff --git a/doc/development/usage_ping/index.md b/doc/development/usage_ping/index.md index 38514914fd7..f70eb1a7cbf 100644 --- a/doc/development/usage_ping/index.md +++ b/doc/development/usage_ping/index.md @@ -949,7 +949,7 @@ appear to be associated to any of the services running, because they all appear WARNING: This feature is intended solely for internal GitLab use. -To add data for aggregated metrics into Usage Ping payload you should add corresponding definition at [`lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/) for metrics available at Community Edition and at [`ee/lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/usage_data_counters/aggregated_metrics/) for Enterprise Edition ones. +To add data for aggregated metrics into Usage Ping payload you should add corresponding definition at [`config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/aggregates/) for metrics available at Community Edition and at [`ee/config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/aggregates/) for Enterprise Edition ones. Each aggregate definition includes following parts: @@ -1111,7 +1111,7 @@ end #### Add new aggregated metric definition After all metrics are persisted, you can add an aggregated metric definition at -[`aggregated_metrics/`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/). +[`aggregated_metrics/`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/aggregates/). To declare the aggregate of metrics collected with [Estimated Batch Counters](#estimated-batch-counters), you must fulfill the following requirements: diff --git a/doc/integration/README.md b/doc/integration/README.md index 9c3d39327f8..c725cc08556 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -63,7 +63,7 @@ or [Kroki](../administration/integration/kroki.md) to use diagrams in AsciiDoc a ## Integrations -Integration with services such as Campfire, Flowdock, HipChat, Pivotal Tracker, and Slack are available as [Integrations](../user/project/integrations/overview.md). +Integration with services such as Campfire, Flowdock, Jira, Pivotal Tracker, and Slack are available as [Integrations](../user/project/integrations/overview.md). ## Troubleshooting diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md index 933e963c628..861246a065a 100644 --- a/doc/user/clusters/agent/index.md +++ b/doc/user/clusters/agent/index.md @@ -4,7 +4,7 @@ group: Configure info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# GitLab Kubernetes Agent **(PREMIUM SELF)** +# GitLab Kubernetes Agent **(PREMIUM)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4. > - [In GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/300960), KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program. diff --git a/doc/user/index.md b/doc/user/index.md index b1daea5d579..c99c64a4852 100644 --- a/doc/user/index.md +++ b/doc/user/index.md @@ -70,7 +70,7 @@ With GitLab Enterprise Edition, you can also: - Leverage continuous delivery method with [Canary Deployments](project/canary_deployments.md). - Scan your code for vulnerabilities and [display them in merge requests](application_security/sast/index.md). -You can also [integrate](project/integrations/overview.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, Jira, and a lot more. +You can also [integrate](project/integrations/overview.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, Trello, Slack, Bamboo CI, Jira, and a lot more. ## User types diff --git a/doc/user/project/integrations/hipchat.md b/doc/user/project/integrations/hipchat.md deleted file mode 100644 index 5bb226b0efd..00000000000 --- a/doc/user/project/integrations/hipchat.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -stage: Create -group: Ecosystem -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments ---- - -# Atlassian HipChat **(FREE)** - -WARNING: -This feature, and the integration for it, were -[deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57434) in -GitLab 13.11. The HipChat integration no longer sends any notifications to HipChat. - -GitLab provides a way to send HipChat notifications upon a number of events, -such as when a user pushes code, creates a branch or tag, adds a comment, and -creates a merge request. - -## Setup - -GitLab requires the use of a HipChat v2 API token to work. v1 tokens are -not supported at this time. Note the differences between v1 and v2 tokens: - -HipChat v1 API (legacy) supports "API Auth Tokens" in the Group API menu. A v1 -token is allowed to send messages to *any* room. - -HipChat v2 API has tokens that are can be created using the Integrations tab -in the Group or Room administration page. By design, these are lightweight tokens that -allow GitLab to send messages only to *one* room. - -### Complete these steps in HipChat - -1. Go to: `https://admin.hipchat.com/admin` -1. Click on "Group Admin" -> "Integrations". -1. Find "Build Your Own!" and click "Create". -1. Select the desired room, name the integration "GitLab", and click "Create". -1. In the "Send messages to this room by posting this URL" column, you should - see a URL in the format: - -```plaintext -https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token> -``` - -HipChat is now ready to accept messages from GitLab. Next, set up the HipChat -service in GitLab. - -### Complete these steps in GitLab - -1. Navigate to the project you want to configure for notifications. -1. Navigate to the [Integrations page](overview.md#accessing-integrations) -1. Click "HipChat". -1. Ensure that the **Active** toggle is enabled. -1. Insert the `token` field from the URL into the `Token` field on the Web page. -1. Insert the `room` field from the URL into the `Room` field on the Web page. -1. Save or optionally click "Test Settings". - -## Troubleshooting - -If you do not see notifications, make sure you are using a HipChat v2 API -token, not a v1 token. - -Note that the v2 token is tied to a specific room. If you want to be able to -specify arbitrary rooms, you can create an API token for a specific user in -HipChat under "Account settings" and "API access". Use the `XXX` value under -`auth_token=XXX`. diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md index 69b7e8a51d3..3775719a8a4 100644 --- a/doc/user/project/integrations/overview.md +++ b/doc/user/project/integrations/overview.md @@ -41,7 +41,6 @@ Click on the service links to see further configuration instructions and details | [Generic alerts](../../../operations/incident_management/integrations.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No | | [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No | | [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No | -| [HipChat](hipchat.md) | Private group chat and IM | No | | [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway | No | | [Jira](jira.md) | Jira issue tracker | No | | [Jenkins](../../../integration/jenkins.md) **(STARTER)** | An extendable open source continuous integration server | Yes | diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md index d11f02addea..1c4423fb7b0 100644 --- a/doc/user/search/advanced_search.md +++ b/doc/user/search/advanced_search.md @@ -91,7 +91,7 @@ Examples: ### Excluding filters -[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31684) in GitLab Starter 13.3. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31684) in GitLab 13.3. Filters can be inverted to **filter out** results from the result set, by prefixing the filter name with a `-` (hyphen) character, such as: diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 6247895a2dd..f4ad4cfcd41 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -112,7 +112,6 @@ module API end def delete_group(group) - Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/22226') destroy_conditionally!(group) do |group| ::Groups::DestroyService.new(group, current_user).async_execute end diff --git a/lib/gitlab/kas.rb b/lib/gitlab/kas.rb index 329c0f221b5..7a674cb5c21 100644 --- a/lib/gitlab/kas.rb +++ b/lib/gitlab/kas.rb @@ -27,7 +27,7 @@ module Gitlab def included_in_gitlab_com_rollout?(project) return true unless ::Gitlab.com? - Feature.enabled?(:kubernetes_agent_on_gitlab_com, project) + Feature.enabled?(:kubernetes_agent_on_gitlab_com, project, default_enabled: :yaml) end end end diff --git a/lib/gitlab/usage/metric_definition.rb b/lib/gitlab/usage/metric_definition.rb index a134b7bf37c..3807967844b 100644 --- a/lib/gitlab/usage/metric_definition.rb +++ b/lib/gitlab/usage/metric_definition.rb @@ -56,7 +56,7 @@ module Gitlab class << self def paths - @paths ||= [Rails.root.join('config', 'metrics', '**', '*.yml')] + @paths ||= [Rails.root.join('config', 'metrics', '[^agg]*', '*.yml')] end def definitions(skip_validation: false) diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb index 1aeca87d849..f77c8cab39c 100644 --- a/lib/gitlab/usage/metrics/aggregates/aggregate.rb +++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb @@ -7,7 +7,7 @@ module Gitlab UNION_OF_AGGREGATED_METRICS = 'OR' INTERSECTION_OF_AGGREGATED_METRICS = 'AND' ALLOWED_METRICS_AGGREGATIONS = [UNION_OF_AGGREGATED_METRICS, INTERSECTION_OF_AGGREGATED_METRICS].freeze - AGGREGATED_METRICS_PATH = Rails.root.join('lib/gitlab/usage_data_counters/aggregated_metrics/*.yml') + AGGREGATED_METRICS_PATH = Rails.root.join('config/metrics/aggregates/*.yml') AggregatedMetricError = Class.new(StandardError) UnknownAggregationOperator = Class.new(AggregatedMetricError) UnknownAggregationSource = Class.new(AggregatedMetricError) diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb index 84ca661b7a7..b130358a27a 100644 --- a/lib/gitlab/usage/metrics/names_suggestions/generator.rb +++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb @@ -6,6 +6,7 @@ module Gitlab module NamesSuggestions class Generator < ::Gitlab::UsageData FREE_TEXT_METRIC_NAME = "<please fill metric name>" + CONSTRAINTS_PROMPT_TEMPLATE = "<adjective describing: '%{constraints}'>" class << self def generate(key_path) @@ -76,15 +77,20 @@ module Gitlab # count_environment_id_from_clusters_with_deployments actual_source = parse_source(relation, arel_column) - if constraints.include?(actual_source) - parts << "<adjective describing: '#{constraints}'>" - end + append_constraints_prompt(actual_source, [constraints], parts) parts << actual_source - parts += process_joined_relations(actual_source, arel, relation) + parts += process_joined_relations(actual_source, arel, relation, constraints) parts.compact.join('_') end + def append_constraints_prompt(target, constraints, parts) + applicable_constraints = constraints.select { |constraint| constraint.include?(target) } + return unless applicable_constraints.any? + + parts << CONSTRAINTS_PROMPT_TEMPLATE % { constraints: applicable_constraints.join(' AND ') } + end + def parse_constraints(relation:, arel:) connection = relation.connection ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Constraints @@ -94,7 +100,7 @@ module Gitlab end # TODO: joins with `USING` keyword - def process_joined_relations(actual_source, arel, relation) + def process_joined_relations(actual_source, arel, relation, where_constraints) joins = parse_joins(connection: relation.connection, arel: arel) return [] unless joins.any? @@ -109,7 +115,7 @@ module Gitlab build_relations_tree(joins + [{ source: relation.table_name }], actual_source, source_key: :target, target_key: :source) end - collect_join_parts(relations[actual_source]) + collect_join_parts(relations: relations[actual_source], joins: joins, wheres: where_constraints) end def parse_joins(connection:, arel:) @@ -128,7 +134,11 @@ module Gitlab join_cond_regex = /(#{source_regex}\s+=\s+#{target_regex})|(#{target_regex}\s+=\s+#{source_regex})/i matched = join_cond_regex.match(join[:constraints]) - join[:target] = matched[:target] if matched + if matched + join[:target] = matched[:target] + join[:constraints].gsub!(/#{join_cond_regex}(\s+(and|or))*/i, '') + end + join end end @@ -147,13 +157,15 @@ module Gitlab tree end - def collect_join_parts(joined_relations, parts = [], conjunctions = %w[with having including].cycle) + def collect_join_parts(relations:, joins:, wheres:, parts: [], conjunctions: %w[with having including].cycle) conjunction = conjunctions.next - joined_relations.each do |subtree| + relations.each do |subtree| subtree.each do |parent, children| parts << "<#{conjunction}>" + join_constraints = joins.find { |join| join[:source] == parent }&.dig(:constraints) + append_constraints_prompt(parent, [wheres, join_constraints].compact, parts) parts << parent - collect_join_parts(children, parts, conjunctions) + collect_join_parts(relations: children, joins: joins, wheres: wheres, parts: parts, conjunctions: conjunctions) end end parts diff --git a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb index c2662a74432..6f5f878501f 100644 --- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb +++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb @@ -34,120 +34,120 @@ module Gitlab ISSUE_COMMENT_REMOVED = 'g_project_management_issue_comment_removed' class << self - def track_issue_created_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_CREATED, author, time) + def track_issue_created_action(author:) + track_unique_action(ISSUE_CREATED, author) end - def track_issue_title_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_TITLE_CHANGED, author, time) + def track_issue_title_changed_action(author:) + track_unique_action(ISSUE_TITLE_CHANGED, author) end - def track_issue_description_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_DESCRIPTION_CHANGED, author, time) + def track_issue_description_changed_action(author:) + track_unique_action(ISSUE_DESCRIPTION_CHANGED, author) end - def track_issue_assignee_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_ASSIGNEE_CHANGED, author, time) + def track_issue_assignee_changed_action(author:) + track_unique_action(ISSUE_ASSIGNEE_CHANGED, author) end - def track_issue_made_confidential_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_MADE_CONFIDENTIAL, author, time) + def track_issue_made_confidential_action(author:) + track_unique_action(ISSUE_MADE_CONFIDENTIAL, author) end - def track_issue_made_visible_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_MADE_VISIBLE, author, time) + def track_issue_made_visible_action(author:) + track_unique_action(ISSUE_MADE_VISIBLE, author) end - def track_issue_closed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_CLOSED, author, time) + def track_issue_closed_action(author:) + track_unique_action(ISSUE_CLOSED, author) end - def track_issue_reopened_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_REOPENED, author, time) + def track_issue_reopened_action(author:) + track_unique_action(ISSUE_REOPENED, author) end - def track_issue_label_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_LABEL_CHANGED, author, time) + def track_issue_label_changed_action(author:) + track_unique_action(ISSUE_LABEL_CHANGED, author) end - def track_issue_milestone_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_MILESTONE_CHANGED, author, time) + def track_issue_milestone_changed_action(author:) + track_unique_action(ISSUE_MILESTONE_CHANGED, author) end - def track_issue_cross_referenced_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_CROSS_REFERENCED, author, time) + def track_issue_cross_referenced_action(author:) + track_unique_action(ISSUE_CROSS_REFERENCED, author) end - def track_issue_moved_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_MOVED, author, time) + def track_issue_moved_action(author:) + track_unique_action(ISSUE_MOVED, author) end - def track_issue_related_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_RELATED, author, time) + def track_issue_related_action(author:) + track_unique_action(ISSUE_RELATED, author) end - def track_issue_unrelated_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_UNRELATED, author, time) + def track_issue_unrelated_action(author:) + track_unique_action(ISSUE_UNRELATED, author) end - def track_issue_marked_as_duplicate_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_MARKED_AS_DUPLICATE, author, time) + def track_issue_marked_as_duplicate_action(author:) + track_unique_action(ISSUE_MARKED_AS_DUPLICATE, author) end - def track_issue_locked_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_LOCKED, author, time) + def track_issue_locked_action(author:) + track_unique_action(ISSUE_LOCKED, author) end - def track_issue_unlocked_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_UNLOCKED, author, time) + def track_issue_unlocked_action(author:) + track_unique_action(ISSUE_UNLOCKED, author) end - def track_issue_designs_added_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_DESIGNS_ADDED, author, time) + def track_issue_designs_added_action(author:) + track_unique_action(ISSUE_DESIGNS_ADDED, author) end - def track_issue_designs_modified_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_DESIGNS_MODIFIED, author, time) + def track_issue_designs_modified_action(author:) + track_unique_action(ISSUE_DESIGNS_MODIFIED, author) end - def track_issue_designs_removed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_DESIGNS_REMOVED, author, time) + def track_issue_designs_removed_action(author:) + track_unique_action(ISSUE_DESIGNS_REMOVED, author) end - def track_issue_due_date_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_DUE_DATE_CHANGED, author, time) + def track_issue_due_date_changed_action(author:) + track_unique_action(ISSUE_DUE_DATE_CHANGED, author) end - def track_issue_time_estimate_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_TIME_ESTIMATE_CHANGED, author, time) + def track_issue_time_estimate_changed_action(author:) + track_unique_action(ISSUE_TIME_ESTIMATE_CHANGED, author) end - def track_issue_time_spent_changed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_TIME_SPENT_CHANGED, author, time) + def track_issue_time_spent_changed_action(author:) + track_unique_action(ISSUE_TIME_SPENT_CHANGED, author) end - def track_issue_comment_added_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_COMMENT_ADDED, author, time) + def track_issue_comment_added_action(author:) + track_unique_action(ISSUE_COMMENT_ADDED, author) end - def track_issue_comment_edited_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_COMMENT_EDITED, author, time) + def track_issue_comment_edited_action(author:) + track_unique_action(ISSUE_COMMENT_EDITED, author) end - def track_issue_comment_removed_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_COMMENT_REMOVED, author, time) + def track_issue_comment_removed_action(author:) + track_unique_action(ISSUE_COMMENT_REMOVED, author) end - def track_issue_cloned_action(author:, time: Time.zone.now) - track_unique_action(ISSUE_CLONED, author, time) + def track_issue_cloned_action(author:) + track_unique_action(ISSUE_CLONED, author) end private - def track_unique_action(action, author, time) + def track_unique_action(action, author) return unless author - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id, time: time) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id) end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 02443a28b12..45aa67b0b15 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -26554,6 +26554,9 @@ msgstr "" msgid "Runners|Revision" msgstr "" +msgid "Runners|Runner #%{runner_id}" +msgstr "" + msgid "Runners|Shared" msgstr "" @@ -30690,6 +30693,9 @@ msgstr "" msgid "There was a problem fetching branches." msgstr "" +msgid "There was a problem fetching emojis." +msgstr "" + msgid "There was a problem fetching groups." msgstr "" @@ -32190,7 +32196,7 @@ msgstr "" msgid "Trials|You can apply your trial to a new group or an existing group." msgstr "" -msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'" +msgid "Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'" msgstr "" msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)" diff --git a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb index 9aba86cdaf2..9aba86cdaf2 100644 --- a/spec/lib/gitlab/usage_data_counters/aggregated_metrics_spec.rb +++ b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb index 69ab9873b90..754b0ddfb94 100644 --- a/spec/controllers/projects/artifacts_controller_spec.rb +++ b/spec/controllers/projects/artifacts_controller_spec.rb @@ -448,7 +448,7 @@ RSpec.describe Projects::ArtifactsController do context 'with regular branch' do before do - pipeline.update(ref: 'master', + pipeline.update!(ref: 'master', sha: project.commit('master').sha) get :latest_succeeded, params: params_from_ref('master') @@ -459,7 +459,7 @@ RSpec.describe Projects::ArtifactsController do context 'with branch name containing slash' do before do - pipeline.update(ref: 'improve/awesome', + pipeline.update!(ref: 'improve/awesome', sha: project.commit('improve/awesome').sha) get :latest_succeeded, params: params_from_ref('improve/awesome') @@ -470,7 +470,7 @@ RSpec.describe Projects::ArtifactsController do context 'with branch name and path containing slashes' do before do - pipeline.update(ref: 'improve/awesome', + pipeline.update!(ref: 'improve/awesome', sha: project.commit('improve/awesome').sha) get :latest_succeeded, params: params_from_ref('improve/awesome', job.name, 'file/README.md') diff --git a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb index f940da7ea35..6bbdda89b14 100644 --- a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb +++ b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb @@ -26,7 +26,7 @@ RSpec.describe Projects::CycleAnalytics::EventsController do let(:issue) { create(:issue, project: project, created_at: 9.days.ago) } before do - issue.update(milestone: milestone) + issue.update!(milestone: milestone) end it 'is not empty' do diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb index 8a793e29bfa..0c8677ea4b9 100644 --- a/spec/controllers/projects/discussions_controller_spec.rb +++ b/spec/controllers/projects/discussions_controller_spec.rb @@ -85,7 +85,7 @@ RSpec.describe Projects::DiscussionsController do context "when the discussion is not resolvable" do before do - note.update(system: true) + note.update!(system: true) end it "returns status 404" do @@ -168,7 +168,7 @@ RSpec.describe Projects::DiscussionsController do context "when the discussion is not resolvable" do before do - note.update(system: true) + note.update!(system: true) end it "returns status 404" do diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index d80d7338d3b..8ca3009e0c7 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -71,7 +71,7 @@ RSpec.describe Projects::ForksController do context 'when fork is internal' do before do - forked_project.update(visibility_level: Project::INTERNAL, group: group) + forked_project.update!(visibility_level: Project::INTERNAL, group: group) end it 'forks counts are correct' do @@ -86,7 +86,7 @@ RSpec.describe Projects::ForksController do context 'when fork is private' do before do - forked_project.update(visibility_level: Project::PRIVATE, group: group) + forked_project.update!(visibility_level: Project::PRIVATE, group: group) end shared_examples 'forks counts' do diff --git a/spec/controllers/projects/group_links_controller_spec.rb b/spec/controllers/projects/group_links_controller_spec.rb index 084a807e162..2fcdfbc2436 100644 --- a/spec/controllers/projects/group_links_controller_spec.rb +++ b/spec/controllers/projects/group_links_controller_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Projects::GroupLinksController do context 'when project is not allowed to be shared with a group' do before do - group.update(share_with_group_lock: false) + group.update!(share_with_group_lock: false) end include_context 'link project to group' diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb index 5e09a50aa36..65a80b9e8ec 100644 --- a/spec/controllers/projects/imports_controller_spec.rb +++ b/spec/controllers/projects/imports_controller_spec.rb @@ -47,7 +47,7 @@ RSpec.describe Projects::ImportsController do context 'when import is in progress' do before do - import_state.update(status: :started) + import_state.update!(status: :started) end it 'renders template' do @@ -65,7 +65,7 @@ RSpec.describe Projects::ImportsController do context 'when import failed' do before do - import_state.update(status: :failed) + import_state.update!(status: :failed) end it 'redirects to new_namespace_project_import_path' do @@ -77,7 +77,7 @@ RSpec.describe Projects::ImportsController do context 'when import finished' do before do - import_state.update(status: :finished) + import_state.update!(status: :finished) end context 'when project is a fork' do @@ -126,7 +126,7 @@ RSpec.describe Projects::ImportsController do context 'when import never happened' do before do - import_state.update(status: :none) + import_state.update!(status: :none) end it 'redirects to namespace_project_path' do diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 474e3a3b009..f8e5dc96489 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -44,7 +44,7 @@ RSpec.describe Projects::IssuesController do let_it_be(:issue) { create(:issue, project: new_project) } before do - project.route.destroy + project.route.destroy! new_project.redirect_routes.create!(path: project.full_path) new_project.add_developer(user) end @@ -711,7 +711,7 @@ RSpec.describe Projects::IssuesController do issue.update!(last_edited_by: deleted_user, last_edited_at: Time.current) - deleted_user.destroy + deleted_user.destroy! sign_in(user) end @@ -1064,10 +1064,10 @@ RSpec.describe Projects::IssuesController do labels = create_list(:label, 10, project: project).map(&:to_reference) issue = create(:issue, project: project, description: 'Test issue') - control_count = ActiveRecord::QueryRecorder.new { issue.update(description: [issue.description, label].join(' ')) }.count + control_count = ActiveRecord::QueryRecorder.new { issue.update!(description: [issue.description, label].join(' ')) }.count # Follow-up to get rid of this `2 * label.count` requirement: https://gitlab.com/gitlab-org/gitlab-foss/issues/52230 - expect { issue.update(description: [issue.description, labels].join(' ')) } + expect { issue.update!(description: [issue.description, labels].join(' ')) } .not_to exceed_query_limit(control_count + 2 * labels.count) end @@ -1923,7 +1923,7 @@ RSpec.describe Projects::IssuesController do before do sign_in(user) - project.route.destroy + project.route.destroy! new_project.redirect_routes.create!(path: project.full_path) new_project.add_developer(user) end diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index f452c22a5ca..35f9d86e71e 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -65,7 +65,7 @@ RSpec.describe Projects::LabelsController do end it 'does not include group labels when project does not belong to a group' do - project.update(namespace: create(:namespace)) + project.update!(namespace: create(:namespace)) list_labels @@ -221,7 +221,7 @@ RSpec.describe Projects::LabelsController do end context 'when requesting a redirected path' do - let_it_be(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') } + let_it_be(:redirect_route) { project.redirect_routes.create!(path: project.full_path + 'old') } it 'redirects to the canonical path' do get :index, params: { namespace_id: project.namespace, project_id: project.to_param + 'old' } @@ -267,7 +267,7 @@ RSpec.describe Projects::LabelsController do end context 'when requesting a redirected path' do - let_it_be(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') } + let_it_be(:redirect_route) { project.redirect_routes.create!(path: project.full_path + 'old') } it 'returns not found' do post :generate, params: { namespace_id: project.namespace, project_id: project.to_param + 'old' } diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index b93f1b41a7e..b62353784b3 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -105,7 +105,7 @@ RSpec.describe Projects::MilestonesController do context 'with a single group ancestor' do before do - project.update(namespace: group) + project.update!(namespace: group) get :index, params: { namespace_id: project.namespace.id, project_id: project.id }, format: :json end @@ -122,7 +122,7 @@ RSpec.describe Projects::MilestonesController do let!(:subgroup_milestone) { create(:milestone, group: subgroup) } before do - project.update(namespace: subgroup) + project.update!(namespace: subgroup) get :index, params: { namespace_id: project.namespace.id, project_id: project.id }, format: :json end @@ -158,7 +158,7 @@ RSpec.describe Projects::MilestonesController do let(:group) { create(:group) } before do - project.update(namespace: group) + project.update!(namespace: group) end context 'when user does not have permission to promote milestone' do @@ -234,7 +234,7 @@ RSpec.describe Projects::MilestonesController do end it 'renders 404' do - project.update(namespace: user.namespace) + project.update!(namespace: user.namespace) post :promote, params: { namespace_id: project.namespace.id, project_id: project.id, id: milestone.iid } @@ -253,7 +253,7 @@ RSpec.describe Projects::MilestonesController do before do project.add_guest(guest_user) sign_in(guest_user) - issue.update(assignee_ids: issue_assignee.id) + issue.update!(assignee_ids: issue_assignee.id) end context "when issue is not confidential" do @@ -269,7 +269,7 @@ RSpec.describe Projects::MilestonesController do context "when issue is confidential" do before do - issue.update(confidential: true) + issue.update!(confidential: true) end it 'shows no milestone participants' do diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index add249e2c74..d92862f0ca3 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -334,7 +334,7 @@ RSpec.describe Projects::NotesController do before do project.update_attribute(:visibility_level, project_visibility) - project.project_feature.update(merge_requests_access_level: merge_requests_access_level) + project.project_feature.update!(merge_requests_access_level: merge_requests_access_level) sign_in(user) end @@ -917,7 +917,7 @@ RSpec.describe Projects::NotesController do context "when the note is not resolvable" do before do - note.update(system: true) + note.update!(system: true) end it "returns status 404" do @@ -980,7 +980,7 @@ RSpec.describe Projects::NotesController do context "when the note is not resolvable" do before do - note.update(system: true) + note.update!(system: true) end it "returns status 404" do diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index e1405660ccb..b060288e205 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Projects::PipelinesController do allow(Sidekiq.logger).to receive(:info) stub_not_protect_default_branch project.add_developer(user) - project.project_feature.update(builds_access_level: feature) + project.project_feature.update!(builds_access_level: feature) sign_in(user) end @@ -702,7 +702,7 @@ RSpec.describe Projects::PipelinesController do before do project.add_developer(user) - project.project_feature.update(builds_access_level: feature) + project.project_feature.update!(builds_access_level: feature) end context 'with a valid .gitlab-ci.yml file' do @@ -777,7 +777,7 @@ RSpec.describe Projects::PipelinesController do before do project.add_developer(user) - project.project_feature.update(builds_access_level: feature) + project.project_feature.update!(builds_access_level: feature) end context 'with a valid .gitlab-ci.yml file' do diff --git a/spec/controllers/projects/releases/evidences_controller_spec.rb b/spec/controllers/projects/releases/evidences_controller_spec.rb index 0ec4cdf2a31..0a83cdb19fe 100644 --- a/spec/controllers/projects/releases/evidences_controller_spec.rb +++ b/spec/controllers/projects/releases/evidences_controller_spec.rb @@ -62,7 +62,7 @@ RSpec.describe Projects::Releases::EvidencesController do context 'when the release was created before evidence existed' do before do - evidence.destroy + evidence.destroy! end it_behaves_like 'not found' diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb index d63d88f8283..3021ad42c9f 100644 --- a/spec/controllers/projects/runners_controller_spec.rb +++ b/spec/controllers/projects/runners_controller_spec.rb @@ -46,7 +46,7 @@ RSpec.describe Projects::RunnersController do describe '#resume' do it 'marks the runner as active and ticks the queue' do - runner.update(active: false) + runner.update!(active: false) expect do post :resume, params: params @@ -61,7 +61,7 @@ RSpec.describe Projects::RunnersController do describe '#pause' do it 'marks the runner as inactive and ticks the queue' do - runner.update(active: true) + runner.update!(active: true) expect do post :pause, params: params diff --git a/spec/controllers/projects/starrers_controller_spec.rb b/spec/controllers/projects/starrers_controller_spec.rb index 66888fa3024..8d03600cd58 100644 --- a/spec/controllers/projects/starrers_controller_spec.rb +++ b/spec/controllers/projects/starrers_controller_spec.rb @@ -170,7 +170,7 @@ RSpec.describe Projects::StarrersController do context 'when project is private' do before do - project.update(visibility_level: Project::PRIVATE) + project.update!(visibility_level: Project::PRIVATE) end it 'starrers are not visible for non logged in users' do diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb index dda58f06a37..c008c7253d8 100644 --- a/spec/controllers/projects/uploads_controller_spec.rb +++ b/spec/controllers/projects/uploads_controller_spec.rb @@ -29,7 +29,7 @@ RSpec.describe Projects::UploadsController do let!(:upload) { create(:upload, :issuable_upload, :with_file, model: model) } let(:project) { model } let(:upload_path) { File.basename(upload.path) } - let!(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') } + let!(:redirect_route) { project.redirect_routes.create!(path: project.full_path + 'old') } it 'redirects to a file with the proper extension' do get :show, params: { namespace_id: project.namespace, project_id: project.to_param + 'old', filename: File.basename(upload.path), secret: upload.secret } diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb index 599b31d9ed5..9edee735af9 100644 --- a/spec/factories/packages.rb +++ b/spec/factories/packages.rb @@ -16,6 +16,10 @@ FactoryBot.define do status { :processing } end + trait :error do + status { :error } + end + factory :maven_package do maven_metadatum diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 4f135b81bdf..fe03f601dd3 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -285,8 +285,16 @@ RSpec.describe "Admin Runners" do end describe 'runner page breadcrumbs' do - it 'contains the current runner’s short sha' do - expect(page.find('h2')).to have_content(runner.short_sha) + it 'contains the current runner token' do + page.within '[data-testid="breadcrumb-links"]' do + expect(page.find('h2')).to have_content(runner.short_sha) + end + end + end + + describe 'runner page title' do + it 'contains the runner id' do + expect(find('.page-title')).to have_content("Runner ##{runner.id}") end end diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/services/disable_triggers_spec.rb index b3a3d7f0622..c1bf640bd79 100644 --- a/spec/features/projects/services/disable_triggers_spec.rb +++ b/spec/features/projects/services/disable_triggers_spec.rb @@ -12,10 +12,10 @@ RSpec.describe 'Disable individual triggers', :js do end context 'service has multiple supported events' do - let(:service_name) { 'HipChat' } + let(:service_name) { 'Jenkins CI' } it 'shows trigger checkboxes' do - event_count = HipchatService.supported_events.count + event_count = JenkinsService.supported_events.count expect(page).to have_content "Trigger" expect(page).to have_css(checkbox_selector, visible: :all, count: event_count) diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb deleted file mode 100644 index cffb780e05d..00000000000 --- a/spec/features/projects/services/user_activates_hipchat_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'User activates HipChat', :js do - include_context 'project service activation' - - context 'with standard settings' do - before do - stub_request(:post, /.*api.hipchat.com.*/) - end - - it 'activates service' do - visit_project_integration('HipChat') - fill_in('Room', with: 'gitlab') - fill_in('Token', with: 'verySecret') - - click_test_then_save_integration(expect_test_to_fail: false) - - expect(page).to have_content('HipChat settings saved and active.') - end - end - - context 'with custom settings' do - before do - stub_request(:post, /.*chat.example.com.*/) - end - - it 'activates service' do - visit_project_integration('HipChat') - fill_in('Room', with: 'gitlab_custom') - fill_in('Token', with: 'secretCustom') - fill_in('Server', with: 'https://chat.example.com') - - click_test_then_save_integration(expect_test_to_fail: false) - - expect(page).to have_content('HipChat settings saved and active.') - end - end -end diff --git a/spec/features/projects/services/user_views_services_spec.rb b/spec/features/projects/services/user_views_services_spec.rb index fef6b7bd991..131971c408f 100644 --- a/spec/features/projects/services/user_views_services_spec.rb +++ b/spec/features/projects/services/user_views_services_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'User views services' do expect(page).to have_content('Integrations') expect(page).to have_content('Campfire') - expect(page).to have_content('HipChat') + expect(page).to have_content('Jira') expect(page).to have_content('Assembla') expect(page).to have_content('Pushover') expect(page).to have_content('Atlassian Bamboo') diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap index 22e206bb483..67b721b2ab0 100644 --- a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap +++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap @@ -29,7 +29,7 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] = > <markdown-header-stub linecontent="" - suggestionstartindex="0" + suggestionstartindex="-1" /> <div diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js index 7606b3bd91c..10910338cb0 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js @@ -3,6 +3,7 @@ import { mockLabels } from 'jest/vue_shared/components/sidebar/labels_select_vue import Api from '~/api'; import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue'; +import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue'; @@ -59,6 +60,16 @@ export const mockMilestones = [ mockEscapedMilestone, ]; +export const mockEmoji1 = { + name: 'thumbsup', +}; + +export const mockEmoji2 = { + name: 'star', +}; + +export const mockEmojis = [mockEmoji1, mockEmoji2]; + export const mockBranchToken = { type: 'source_branch', icon: 'branch', @@ -103,6 +114,16 @@ export const mockMilestoneToken = { fetchMilestones: () => Promise.resolve({ data: mockMilestones }), }; +export const mockReactionEmojiToken = { + type: 'my_reaction_emoji', + icon: 'thumb-up', + title: 'My-Reaction', + unique: true, + token: EmojiToken, + operators: [{ value: '=', description: 'is', default: 'true' }], + fetchEmojis: () => Promise.resolve(mockEmojis), +}; + export const mockMembershipToken = { type: 'with_inherited_permissions', icon: 'group', diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js new file mode 100644 index 00000000000..231f2f01428 --- /dev/null +++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js @@ -0,0 +1,217 @@ +import { + GlFilteredSearchToken, + GlFilteredSearchSuggestion, + GlFilteredSearchTokenSegment, + GlDropdownDivider, +} from '@gitlab/ui'; +import { mount } from '@vue/test-utils'; +import MockAdapter from 'axios-mock-adapter'; +import waitForPromises from 'helpers/wait_for_promises'; +import { deprecatedCreateFlash as createFlash } from '~/flash'; +import axios from '~/lib/utils/axios_utils'; + +import { + DEFAULT_LABEL_NONE, + DEFAULT_LABEL_ANY, +} from '~/vue_shared/components/filtered_search_bar/constants'; +import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue'; + +import { mockReactionEmojiToken, mockEmojis } from '../mock_data'; + +jest.mock('~/flash'); +const GlEmoji = { template: '<img/>' }; +const defaultStubs = { + Portal: true, + GlFilteredSearchSuggestionList: { + template: '<div></div>', + methods: { + getValue: () => '=', + }, + }, + GlEmoji, +}; + +function createComponent(options = {}) { + const { + config = mockReactionEmojiToken, + value = { data: '' }, + active = false, + stubs = defaultStubs, + } = options; + return mount(EmojiToken, { + propsData: { + config, + value, + active, + }, + provide: { + portalName: 'fake target', + alignSuggestions: function fakeAlignSuggestions() {}, + suggestionsListClass: 'custom-class', + }, + stubs, + }); +} + +describe('EmojiToken', () => { + let mock; + let wrapper; + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + wrapper.destroy(); + }); + + describe('computed', () => { + beforeEach(async () => { + wrapper = createComponent({ value: { data: mockEmojis[0].name } }); + + wrapper.setData({ + emojis: mockEmojis, + }); + + await wrapper.vm.$nextTick(); + }); + + describe('currentValue', () => { + it('returns lowercase string for `value.data`', () => { + expect(wrapper.vm.currentValue).toBe(mockEmojis[0].name); + }); + }); + + describe('activeEmoji', () => { + it('returns object for currently present `value.data`', () => { + expect(wrapper.vm.activeEmoji).toEqual(mockEmojis[0]); + }); + }); + }); + + describe('methods', () => { + beforeEach(() => { + wrapper = createComponent(); + }); + + describe('fetchEmojiBySearchTerm', () => { + it('calls `config.fetchEmojis` with provided searchTerm param', () => { + jest.spyOn(wrapper.vm.config, 'fetchEmojis'); + + wrapper.vm.fetchEmojiBySearchTerm('foo'); + + expect(wrapper.vm.config.fetchEmojis).toHaveBeenCalledWith('foo'); + }); + + it('sets response to `emojis` when request is successful', () => { + jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockResolvedValue(mockEmojis); + + wrapper.vm.fetchEmojiBySearchTerm('foo'); + + return waitForPromises().then(() => { + expect(wrapper.vm.emojis).toEqual(mockEmojis); + }); + }); + + it('calls `createFlash` with flash error message when request fails', () => { + jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({}); + + wrapper.vm.fetchEmojiBySearchTerm('foo'); + + return waitForPromises().then(() => { + expect(createFlash).toHaveBeenCalledWith('There was a problem fetching emojis.'); + }); + }); + + it('sets `loading` to false when request completes', () => { + jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({}); + + wrapper.vm.fetchEmojiBySearchTerm('foo'); + + return waitForPromises().then(() => { + expect(wrapper.vm.loading).toBe(false); + }); + }); + }); + }); + + describe('template', () => { + const defaultEmojis = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY]; + + beforeEach(async () => { + wrapper = createComponent({ + value: { data: `"${mockEmojis[0].name}"` }, + }); + + wrapper.setData({ + emojis: mockEmojis, + }); + + await wrapper.vm.$nextTick(); + }); + + it('renders gl-filtered-search-token component', () => { + expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true); + }); + + it('renders token item when value is selected', () => { + const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment); + + expect(tokenSegments).toHaveLength(3); // My Reaction, =, "thumbsup" + expect(tokenSegments.at(2).find(GlEmoji).attributes('data-name')).toEqual('thumbsup'); + }); + + it('renders provided defaultEmojis as suggestions', async () => { + wrapper = createComponent({ + active: true, + config: { ...mockReactionEmojiToken, defaultEmojis }, + stubs: { Portal: true, GlEmoji }, + }); + const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment); + const suggestionsSegment = tokenSegments.at(2); + suggestionsSegment.vm.$emit('activate'); + await wrapper.vm.$nextTick(); + + const suggestions = wrapper.findAll(GlFilteredSearchSuggestion); + + expect(suggestions).toHaveLength(defaultEmojis.length); + defaultEmojis.forEach((emoji, index) => { + expect(suggestions.at(index).text()).toBe(emoji.text); + }); + }); + + it('does not render divider when no defaultEmojis', async () => { + wrapper = createComponent({ + active: true, + config: { ...mockReactionEmojiToken, defaultEmojis: [] }, + stubs: { Portal: true, GlEmoji }, + }); + const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment); + const suggestionsSegment = tokenSegments.at(2); + suggestionsSegment.vm.$emit('activate'); + await wrapper.vm.$nextTick(); + + expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false); + expect(wrapper.find(GlDropdownDivider).exists()).toBe(false); + }); + + it('renders `DEFAULT_LABEL_NONE` and `DEFAULT_LABEL_ANY` as default suggestions', async () => { + wrapper = createComponent({ + active: true, + config: { ...mockReactionEmojiToken }, + stubs: { Portal: true, GlEmoji }, + }); + const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment); + const suggestionsSegment = tokenSegments.at(2); + suggestionsSegment.vm.$emit('activate'); + await wrapper.vm.$nextTick(); + + const suggestions = wrapper.findAll(GlFilteredSearchSuggestion); + + expect(suggestions).toHaveLength(2); + expect(suggestions.at(0).text()).toBe(DEFAULT_LABEL_NONE.text); + expect(suggestions.at(1).text()).toBe(DEFAULT_LABEL_ANY.text); + }); + }); +}); diff --git a/spec/graphql/types/milestone_type_spec.rb b/spec/graphql/types/milestone_type_spec.rb index 806495250ac..5c2ae5cea3c 100644 --- a/spec/graphql/types/milestone_type_spec.rb +++ b/spec/graphql/types/milestone_type_spec.rb @@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['Milestone'] do it 'has the expected fields' do expected_fields = %w[ - id title description state web_path + id iid title description state web_path due_date start_date created_at updated_at project_milestone group_milestone subgroup_milestone stats diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb index 74cbeb85f16..04a43fb8b72 100644 --- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb +++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb @@ -44,7 +44,10 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do # ::Deployment.arel_table[:environment_id] # ) let(:key_path) { 'counts.ingress_modsecurity_logging' } - let(:name_suggestion) { /count_distinct_environment_id_from_<adjective describing\: '\(clusters_applications_ingress\.modsecurity_enabled = TRUE AND clusters_applications_ingress\.modsecurity_mode = \d+ AND clusters.enabled = TRUE AND deployments.status = \d+\)'>_deployments_<with>_clusters_<having>_clusters_applications_ingress/ } + let(:name_suggestion) do + constrains = /'\(clusters_applications_ingress\.modsecurity_enabled = TRUE AND clusters_applications_ingress\.modsecurity_mode = \d+ AND clusters.enabled = TRUE AND deployments.status = \d+\)'/ + /count_distinct_environment_id_from_<adjective describing\: #{constrains}>_deployments_<with>_<adjective describing\: #{constrains}>_clusters_<having>_<adjective describing\: #{constrains}>_clusters_applications_ingress/ + end end end diff --git a/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb b/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb index 664e7938a7e..a1dee442131 100644 --- a/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' # If this spec fails, we need to add the new code review event to the correct aggregated metric RSpec.describe 'Code review events' do it 'the aggregated metrics contain all the code review metrics' do - path = Rails.root.join('lib/gitlab/usage_data_counters/aggregated_metrics/code_review.yml') + path = Rails.root.join('config/metrics/aggregates/code_review.yml') aggregated_events = YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access) code_review_aggregated_events = aggregated_events diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb index f8f6494b92e..1b73e5269d7 100644 --- a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb @@ -3,9 +3,10 @@ require 'spec_helper' RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_gitlab_redis_shared_state do - let(:user1) { build(:user, id: 1) } - let(:user2) { build(:user, id: 2) } - let(:user3) { build(:user, id: 3) } + let_it_be(:user1) { build(:user, id: 1) } + let_it_be(:user2) { build(:user, id: 2) } + let_it_be(:user3) { build(:user, id: 3) } + let(:time) { Time.zone.now } context 'for Issue title edit actions' do @@ -272,10 +273,13 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git described_class.track_issue_title_changed_action(author: user1) described_class.track_issue_description_changed_action(author: user1) described_class.track_issue_assignee_changed_action(author: user1) - described_class.track_issue_title_changed_action(author: user2, time: time - 2.days) - described_class.track_issue_title_changed_action(author: user3, time: time - 3.days) - described_class.track_issue_description_changed_action(author: user3, time: time - 3.days) - described_class.track_issue_assignee_changed_action(author: user3, time: time - 3.days) + + travel_to(2.days.ago) do + described_class.track_issue_title_changed_action(author: user2) + described_class.track_issue_title_changed_action(author: user3) + described_class.track_issue_description_changed_action(author: user3) + described_class.track_issue_assignee_changed_action(author: user3) + end events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(described_class::ISSUE_CATEGORY) today_count = Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: time, end_date: time) diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb index c04f098d875..2ea4c5d8211 100644 --- a/spec/models/packages/package_spec.rb +++ b/spec/models/packages/package_spec.rb @@ -649,10 +649,12 @@ RSpec.describe Packages::Package, type: :model do describe '.displayable' do let_it_be(:hidden_package) { create(:maven_package, :hidden) } let_it_be(:processing_package) { create(:maven_package, :processing) } + let_it_be(:error_package) { create(:maven_package, :error) } subject { described_class.displayable } - it 'does not include hidden packages', :aggregate_failures do + it 'does not include non-displayable packages', :aggregate_failures do + is_expected.to include(error_package) is_expected.not_to include(hidden_package) is_expected.not_to include(processing_package) end diff --git a/spec/services/packages/rubygems/create_gemspec_service_spec.rb b/spec/services/packages/rubygems/create_gemspec_service_spec.rb index 4d5061933e0..198e978a47e 100644 --- a/spec/services/packages/rubygems/create_gemspec_service_spec.rb +++ b/spec/services/packages/rubygems/create_gemspec_service_spec.rb @@ -4,10 +4,10 @@ require 'spec_helper' RSpec.describe Packages::Rubygems::CreateGemspecService do include RubygemsHelpers - let_it_be(:package) { create(:rubygems_package) } let_it_be(:package_file) { create(:package_file, :gem) } let_it_be(:gem) { gem_from_file(package_file.file) } let_it_be(:gemspec) { gem.spec } + let_it_be(:package) { package_file.package } let(:service) { described_class.new(package, gemspec) } diff --git a/spec/services/submodules/update_service_spec.rb b/spec/services/submodules/update_service_spec.rb index e7f92d5ba28..1a53da7b9fe 100644 --- a/spec/services/submodules/update_service_spec.rb +++ b/spec/services/submodules/update_service_spec.rb @@ -90,7 +90,7 @@ RSpec.describe Submodules::UpdateService do let(:submodule) { '../six' } it_behaves_like 'returns error result' do - let(:error_message) { 'Invalid parameters' } + let(:error_message) { 'Invalid submodule path' } end end end diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb index aa6e64a3820..4b956c2b566 100644 --- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb @@ -14,10 +14,6 @@ RSpec.shared_examples 'a daily tracked issuable event' do expect(track_action(author: user1)).to be_truthy expect(track_action(author: user1)).to be_truthy expect(track_action(author: user2)).to be_truthy - expect(track_action(author: user3, time: time - 3.days)).to be_truthy - - expect(count_unique(date_from: time, date_to: time)).to eq(2) - expect(count_unique(date_from: time - 5.days, date_to: 1.day.since(time))).to eq(3) end end |