Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
cce8cf03d3
commit
eaea945e03
42 changed files with 459 additions and 242 deletions
|
@ -392,9 +392,7 @@ RSpec/RepeatedExample:
|
|||
- 'spec/features/merge_request/user_posts_diff_notes_spec.rb'
|
||||
- 'spec/features/projects/files/template_type_dropdown_spec.rb'
|
||||
- 'spec/finders/environments_finder_spec.rb'
|
||||
- 'spec/frontend/fixtures/merge_requests.rb'
|
||||
- 'spec/helpers/users_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/closing_issue_extractor_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
|
||||
- 'spec/services/notification_service_spec.rb'
|
||||
- 'spec/services/web_hook_service_spec.rb'
|
||||
|
|
|
@ -1 +1 @@
|
|||
8.29.0
|
||||
8.30.0
|
||||
|
|
|
@ -23,6 +23,8 @@ const popoverStates = {
|
|||
},
|
||||
};
|
||||
export default {
|
||||
dismissTrackValue: 10,
|
||||
clickTrackValue: 'click_button',
|
||||
components: {
|
||||
GlPopover,
|
||||
GlSprintf,
|
||||
|
@ -109,7 +111,16 @@ export default {
|
|||
<template #title>
|
||||
<span v-html="suggestTitle"></span>
|
||||
<span class="ml-auto">
|
||||
<gl-deprecated-button :aria-label="__('Close')" class="btn-blank" @click="onDismiss">
|
||||
<gl-deprecated-button
|
||||
:aria-label="__('Close')"
|
||||
class="btn-blank"
|
||||
name="dismiss"
|
||||
:data-track-property="humanAccess"
|
||||
:data-track-value="$options.dismissTrackValue"
|
||||
:data-track-event="$options.clickTrackValue"
|
||||
:data-track-label="trackLabel"
|
||||
@click="onDismiss"
|
||||
>
|
||||
<gl-icon name="close" aria-hidden="true" />
|
||||
</gl-deprecated-button>
|
||||
</span>
|
||||
|
|
48
app/services/projects/prometheus/metrics/base_service.rb
Normal file
48
app/services/projects/prometheus/metrics/base_service.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
module Prometheus
|
||||
module Metrics
|
||||
class BaseService
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
def initialize(metric, params = {})
|
||||
@metric = metric
|
||||
@project = metric.project
|
||||
@params = params.dup
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_reader :metric, :project, :params
|
||||
|
||||
def application
|
||||
alert.environment.cluster_prometheus_adapter
|
||||
end
|
||||
|
||||
def schedule_alert_update
|
||||
return unless alert
|
||||
return unless alert.environment
|
||||
|
||||
::Clusters::Applications::ScheduleUpdateService.new(
|
||||
alert.environment.cluster_prometheus_adapter, project).execute
|
||||
end
|
||||
|
||||
def alert
|
||||
strong_memoize(:alert) { find_alert(metric) }
|
||||
end
|
||||
|
||||
def find_alert(metric)
|
||||
Projects::Prometheus::AlertsFinder
|
||||
.new(project: project, metric: metric)
|
||||
.execute
|
||||
.first
|
||||
end
|
||||
|
||||
def has_alert?
|
||||
alert.present?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
14
app/services/projects/prometheus/metrics/destroy_service.rb
Normal file
14
app/services/projects/prometheus/metrics/destroy_service.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
module Prometheus
|
||||
module Metrics
|
||||
class DestroyService < Metrics::BaseService
|
||||
def execute
|
||||
schedule_alert_update if has_alert?
|
||||
metric.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
29
app/services/projects/prometheus/metrics/update_service.rb
Normal file
29
app/services/projects/prometheus/metrics/update_service.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
module Prometheus
|
||||
module Metrics
|
||||
class UpdateService < Metrics::BaseService
|
||||
def execute
|
||||
metric.update!(params)
|
||||
schedule_alert_update if requires_alert_update?
|
||||
metric
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def requires_alert_update?
|
||||
has_alert? && (changing_title? || changing_query?)
|
||||
end
|
||||
|
||||
def changing_title?
|
||||
metric.previous_changes.include?(:title)
|
||||
end
|
||||
|
||||
def changing_query?
|
||||
metric.previous_changes.include?(:query)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,4 +16,5 @@
|
|||
|
||||
- if @commit
|
||||
.network-graph{ data: { url: @url, commit_url: @commit_url, ref: @ref, commit_id: @commit.id } }
|
||||
= spinner nil, true
|
||||
.text-center.prepend-top-default
|
||||
.spinner.spinner-md
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Migrate .fa-spinner to .spinner for app/views/projects/network
|
||||
merge_request: 25050
|
||||
author: nuwe1
|
||||
type: other
|
5
changelogs/unreleased/closing-issue-spec.yml
Normal file
5
changelogs/unreleased/closing-issue-spec.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Remove duplicate spec from closing issue spec
|
||||
merge_request: 28803
|
||||
author: Rajendra Kadam
|
||||
type: added
|
5
changelogs/unreleased/merge-requests.yml
Normal file
5
changelogs/unreleased/merge-requests.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix duplciate spec in merge requests
|
||||
merge_request: 28856
|
||||
author: Rajendra Kadam
|
||||
type: added
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPartialIndexOnIdToCiJobArtifacts < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
INDEX_NAME = 'index_ci_job_artifacts_file_store_is_null'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :ci_job_artifacts, :id, where: 'file_store IS NULL', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPartialIndexOnIdToLfsObjects < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
INDEX_NAME = 'index_lfs_objects_file_store_is_null'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :lfs_objects, :id, where: 'file_store IS NULL', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :lfs_objects, INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPartialIndexOnIdToUploads < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
INDEX_NAME = 'index_uploads_store_is_null'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :uploads, :id, where: 'store IS NULL', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :uploads, INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -8708,6 +8708,8 @@ CREATE INDEX index_ci_daily_report_results_on_last_pipeline_id ON public.ci_dail
|
|||
|
||||
CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key ON public.ci_group_variables USING btree (group_id, key);
|
||||
|
||||
CREATE INDEX index_ci_job_artifacts_file_store_is_null ON public.ci_job_artifacts USING btree (id) WHERE (file_store IS NULL);
|
||||
|
||||
CREATE INDEX index_ci_job_artifacts_on_expire_at_and_job_id ON public.ci_job_artifacts USING btree (expire_at, job_id);
|
||||
|
||||
CREATE INDEX index_ci_job_artifacts_on_file_store ON public.ci_job_artifacts USING btree (file_store);
|
||||
|
@ -9328,6 +9330,8 @@ CREATE UNIQUE INDEX index_lfs_file_locks_on_project_id_and_path ON public.lfs_fi
|
|||
|
||||
CREATE INDEX index_lfs_file_locks_on_user_id ON public.lfs_file_locks USING btree (user_id);
|
||||
|
||||
CREATE INDEX index_lfs_objects_file_store_is_null ON public.lfs_objects USING btree (id) WHERE (file_store IS NULL);
|
||||
|
||||
CREATE INDEX index_lfs_objects_on_file_store ON public.lfs_objects USING btree (file_store);
|
||||
|
||||
CREATE UNIQUE INDEX index_lfs_objects_on_oid ON public.lfs_objects USING btree (oid);
|
||||
|
@ -10094,6 +10098,8 @@ CREATE INDEX index_uploads_on_store ON public.uploads USING btree (store);
|
|||
|
||||
CREATE INDEX index_uploads_on_uploader_and_path ON public.uploads USING btree (uploader, path);
|
||||
|
||||
CREATE INDEX index_uploads_store_is_null ON public.uploads USING btree (id) WHERE (store IS NULL);
|
||||
|
||||
CREATE INDEX index_user_agent_details_on_subject_id_and_subject_type ON public.user_agent_details USING btree (subject_id, subject_type);
|
||||
|
||||
CREATE INDEX index_user_callouts_on_user_id ON public.user_callouts USING btree (user_id);
|
||||
|
@ -12929,5 +12935,8 @@ COPY "schema_migrations" (version) FROM STDIN;
|
|||
20200330123739
|
||||
20200330132913
|
||||
20200331220930
|
||||
20200403184110
|
||||
20200403185127
|
||||
20200403185422
|
||||
\.
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ future GitLab releases.**
|
|||
| `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. |
|
||||
| `CI_PIPELINE_ID` | 8.10 | all | The unique id of the current pipeline that GitLab CI/CD uses internally |
|
||||
| `CI_PIPELINE_IID` | 11.0 | all | The unique id of the current pipeline scoped to project |
|
||||
| `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `trigger`, `schedule`, `api`, `pipeline`, `external`, `chat`, `merge_request_event`, and `external_pull_request_event`. For pipelines created before GitLab 9.5, this will show as `unknown` |
|
||||
| `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `trigger`, `schedule`, `api`, `pipeline`, `parent_pipeline`, `external`, `chat`, `merge_request_event`, and `external_pull_request_event`. For pipelines created before GitLab 9.5, this will show as `unknown` |
|
||||
| `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md) |
|
||||
| `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL |
|
||||
| `CI_PROJECT_DIR` | all | all | The full path where the repository is cloned and where the job is run. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see [Advanced configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) for GitLab Runner. |
|
||||
|
|
|
@ -468,7 +468,7 @@ helped us with overall code quality (using delegation, `&.` those
|
|||
types of things), and making the code more robust.
|
||||
|
||||
**["Support multiple assignees for merge requests"](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10161)**:
|
||||
A good example of collaboration on an MR touching multiple parts of the codebase. Nick pointed out interesting edge cases, James Lopes also joined in raising concerns on import/export feature.
|
||||
A good example of collaboration on an MR touching multiple parts of the codebase. Nick pointed out interesting edge cases, James Lopez also joined in raising concerns on import/export feature.
|
||||
|
||||
### Credits
|
||||
|
||||
|
|
|
@ -410,7 +410,7 @@ merge request with new or changed docs is submitted, are:
|
|||
- If any code or the `doc/README.md` file is changed, a full pipeline will run, which
|
||||
runs tests for [`/help`](#gitlab-help-tests).
|
||||
|
||||
### Running tests & lint checks locally
|
||||
### Running tests
|
||||
|
||||
Apart from [previewing your changes locally](#previewing-the-changes-live), you can also run all lint checks
|
||||
and Nanoc tests locally.
|
||||
|
@ -462,62 +462,20 @@ The output should be similar to:
|
|||
Note that this requires you to either have the required lint tools installed on your machine,
|
||||
or a working Docker installation, in which case an image with these tools pre-installed will be used.
|
||||
|
||||
For more information on available linters refer to the [linting](#linting) section.
|
||||
|
||||
### Linting
|
||||
### Local linting
|
||||
|
||||
To help adhere to the [documentation style guidelines](styleguide.md), and improve the content
|
||||
added to documentation, consider locally installing and running documentation linters. This will
|
||||
help you catch common issues before raising merge requests for review of documentation.
|
||||
|
||||
The following are some suggested linters you can install locally and sample configuration:
|
||||
Running the following locally allows you to match the checks in the build pipeline:
|
||||
|
||||
- [`proselint`](#proselint)
|
||||
- [markdownlint](#markdownlint), which is the same as the test run in [`docs-lint`](#testing)
|
||||
- [Vale](#vale), for English language grammar and syntax suggestions
|
||||
- [markdownlint](#markdownlint).
|
||||
- [Vale](#vale).
|
||||
|
||||
NOTE: **Note:**
|
||||
This list does not limit what other linters you can add to your local documentation writing toolchain.
|
||||
|
||||
#### `proselint`
|
||||
|
||||
`proselint` checks for common problems with English prose. It provides a
|
||||
[plethora of checks](http://proselint.com/checks/) that are helpful for technical writing.
|
||||
|
||||
`proselint` can be used [on the command line](http://proselint.com/utility/), either on a single
|
||||
Markdown file or on all Markdown files in a project. For example, to run `proselint` on all
|
||||
documentation in the [`gitlab` project](https://gitlab.com/gitlab-org/gitlab), run the
|
||||
following commands from within the `gitlab` project:
|
||||
|
||||
```shell
|
||||
cd doc
|
||||
proselint **/*.md
|
||||
```
|
||||
|
||||
`proselint` can also be run from within editors using plugins. For example, the following plugins
|
||||
are available:
|
||||
|
||||
- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-proselint)
|
||||
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=PatrykPeszko.vscode-proselint)
|
||||
- [Others](https://github.com/amperser/proselint#plugins-for-other-software)
|
||||
|
||||
##### Sample `proselint` configuration
|
||||
|
||||
All of the checks are good to use. However, excluding the `typography.symbols` and `misc.phrasal_adjectives` checks will reduce
|
||||
noise. The following sample `proselint` configuration disables these checks:
|
||||
|
||||
```json
|
||||
{
|
||||
"checks": {
|
||||
"typography.symbols": false,
|
||||
"misc.phrasal_adjectives": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A file with `proselint` configuration must be placed in a
|
||||
[valid location](https://github.com/amperser/proselint#checks). For example, `~/.config/proselint/config`.
|
||||
|
||||
#### markdownlint
|
||||
|
||||
[markdownlint](https://github.com/DavidAnson/markdownlint) checks that Markdown
|
||||
|
@ -596,8 +554,6 @@ You can also
|
|||
[configure the text editor of your choice](https://errata-ai.github.io/vale/#local-use-by-a-single-writer)
|
||||
to display the results.
|
||||
|
||||
Vale's test results are not currently displayed in CI, but may be displayed in the future.
|
||||
|
||||
## Danger Bot
|
||||
|
||||
GitLab uses [Danger](https://github.com/danger/danger) for some elements in
|
||||
|
|
|
@ -8,7 +8,7 @@ This document defines the standards for GitLab's documentation content and files
|
|||
|
||||
For broader information about the documentation, see the [Documentation guidelines](index.md).
|
||||
|
||||
For programmatic help adhering to the guidelines, see [linting](index.md#linting).
|
||||
For programmatic help adhering to the guidelines, see [Testing](index.md#testing).
|
||||
|
||||
See the GitLab handbook for further [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines)
|
||||
that apply to all GitLab content, not just documentation.
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
module Gitlab
|
||||
module Database
|
||||
module BatchCount
|
||||
def batch_count(relation, column = nil, batch_size: nil)
|
||||
BatchCounter.new(relation, column: column).count(batch_size: batch_size)
|
||||
def batch_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)
|
||||
BatchCounter.new(relation, column: column).count(batch_size: batch_size, start: start, finish: finish)
|
||||
end
|
||||
|
||||
def batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)
|
||||
|
|
|
@ -240,9 +240,9 @@ module Gitlab
|
|||
{} # augmented in EE
|
||||
end
|
||||
|
||||
def count(relation, column = nil, fallback: -1, batch: true)
|
||||
def count(relation, column = nil, fallback: -1, batch: true, start: nil, finish: nil)
|
||||
if batch && Feature.enabled?(:usage_ping_batch_counter, default_enabled: true)
|
||||
Gitlab::Database::BatchCount.batch_count(relation, column)
|
||||
Gitlab::Database::BatchCount.batch_count(relation, column, start: start, finish: finish)
|
||||
else
|
||||
relation.count
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
context 'Release' do
|
||||
context 'Release', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/213222', type: :flaky } do
|
||||
describe 'Deploy token creation' do
|
||||
it 'user adds a deploy token' do
|
||||
Flow::Login.sign_in
|
||||
|
|
|
@ -3,23 +3,14 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Asana' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Asana')
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Asana')
|
||||
fill_in('Api key', with: 'verySecret')
|
||||
fill_in('Restrict to branch', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_then_save_integration
|
||||
|
||||
expect(page).to have_content('Asana activated.')
|
||||
end
|
||||
|
|
|
@ -3,22 +3,17 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Assembla' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Assembla')
|
||||
stub_request(:post, /.*atlas.assembla.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Assembla')
|
||||
fill_in('Token', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Assembla activated.')
|
||||
end
|
||||
|
|
|
@ -3,31 +3,26 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Atlassian Bamboo CI' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Atlassian Bamboo CI')
|
||||
stub_request(:get, /.*bamboo.example.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Atlassian Bamboo CI')
|
||||
fill_in('Bamboo url', with: 'http://bamboo.example.com')
|
||||
fill_in('Build key', with: 'KEY')
|
||||
fill_in('Username', with: 'user')
|
||||
fill_in('Password', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Atlassian Bamboo CI activated.')
|
||||
|
||||
# Password field should not be filled in.
|
||||
click_link('Atlassian Bamboo CI')
|
||||
|
||||
expect(find_field('Enter new password').value).to be_nil
|
||||
expect(find_field('Enter new password').value).to be_blank
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,22 +3,13 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Emails on push' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Emails on push')
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Emails on push')
|
||||
fill_in('Recipients', with: 'qa@company.name')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Emails on push activated.')
|
||||
end
|
||||
|
|
|
@ -3,22 +3,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Flowdock' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Flowdock')
|
||||
include_context 'project service activation' do
|
||||
let(:project) { create(:project, :repository) }
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
before do
|
||||
stub_request(:post, /.*api.flowdock.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Flowdock')
|
||||
fill_in('Token', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Flowdock activated.')
|
||||
end
|
||||
|
|
|
@ -2,37 +2,37 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'User activates HipChat' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('HipChat')
|
||||
end
|
||||
describe 'User activates HipChat', :js do
|
||||
include_context 'project service activation'
|
||||
|
||||
context 'with standart settings' do
|
||||
before do
|
||||
stub_request(:post, /.*api.hipchat.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
visit_project_integration('HipChat')
|
||||
fill_in('Room', with: 'gitlab')
|
||||
fill_in('Token', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('HipChat activated.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with custom settings' do
|
||||
before do
|
||||
stub_request(:post, /.*chat.example.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
visit_project_integration('HipChat')
|
||||
fill_in('Room', with: 'gitlab_custom')
|
||||
fill_in('Token', with: 'secretCustom')
|
||||
fill_in('Server', with: 'https://chat.example.com')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('HipChat activated.')
|
||||
end
|
||||
|
|
|
@ -3,23 +3,14 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Irker (IRC gateway)' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Irker (IRC gateway)')
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Irker (IRC gateway)')
|
||||
check('Colorize messages')
|
||||
fill_in('Recipients', with: 'irc://chat.freenode.net/#commits')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Irker (IRC gateway) activated.')
|
||||
end
|
||||
|
|
|
@ -3,27 +3,22 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates JetBrains TeamCity CI' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('JetBrains TeamCity CI')
|
||||
stub_request(:post, /.*teamcity.example.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('JetBrains TeamCity CI')
|
||||
check('Push')
|
||||
check('Merge request')
|
||||
fill_in('Teamcity url', with: 'http://teamcity.example.com')
|
||||
fill_in('Build type', with: 'GitlabTest_Build')
|
||||
fill_in('Username', with: 'user')
|
||||
fill_in('Password', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('JetBrains TeamCity CI activated.')
|
||||
end
|
||||
|
|
|
@ -3,23 +3,18 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Packagist' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Packagist')
|
||||
stub_request(:post, /.*packagist.org.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Packagist')
|
||||
fill_in('Username', with: 'theUser')
|
||||
fill_in('Token', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_then_save_integration
|
||||
|
||||
expect(page).to have_content('Packagist activated.')
|
||||
end
|
||||
|
|
|
@ -3,22 +3,17 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates PivotalTracker' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('PivotalTracker')
|
||||
stub_request(:post, /.*www.pivotaltracker.com.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('PivotalTracker')
|
||||
fill_in('Token', with: 'verySecret')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('PivotalTracker activated.')
|
||||
end
|
||||
|
|
|
@ -3,21 +3,17 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Prometheus' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Prometheus')
|
||||
stub_request(:get, /.*prometheus.example.com.*/)
|
||||
end
|
||||
|
||||
it 'does not activate service and informs about deprecation' do
|
||||
it 'does not activate service and informs about deprecation', :js do
|
||||
visit_project_integration('Prometheus')
|
||||
check('Active')
|
||||
fill_in('API URL', with: 'http://prometheus.example.com')
|
||||
|
||||
click_button('Save changes')
|
||||
|
||||
expect(page).not_to have_content('Prometheus activated.')
|
||||
|
|
|
@ -3,26 +3,21 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Pushover' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
include_context 'project service activation'
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Pushover')
|
||||
stub_request(:post, /.*api.pushover.net.*/)
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
visit_project_integration('Pushover')
|
||||
fill_in('Api key', with: 'verySecret')
|
||||
fill_in('User key', with: 'verySecret')
|
||||
fill_in('Device', with: 'myDevice')
|
||||
select('High Priority', from: 'Priority')
|
||||
select('Bike', from: 'Sound')
|
||||
click_button('Save')
|
||||
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Pushover activated.')
|
||||
end
|
||||
|
|
|
@ -3,32 +3,26 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User activates Slack notifications' do
|
||||
let(:user) { create(:user) }
|
||||
let(:service) { SlackService.new }
|
||||
let(:project) { create(:project, slack_service: service) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
end
|
||||
include_context 'project service activation'
|
||||
|
||||
context 'when service is not configured yet' do
|
||||
before do
|
||||
visit(project_settings_integrations_path(project))
|
||||
|
||||
click_link('Slack notifications')
|
||||
visit_project_integration('Slack notifications')
|
||||
end
|
||||
|
||||
it 'activates service' do
|
||||
check('Active')
|
||||
it 'activates service', :js do
|
||||
fill_in('Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685')
|
||||
click_button('Save')
|
||||
|
||||
click_test_then_save_integration
|
||||
|
||||
expect(page).to have_content('Slack notifications activated.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when service is already configured' do
|
||||
let(:service) { SlackService.new }
|
||||
let(:project) { create(:project, slack_service: service) }
|
||||
|
||||
before do
|
||||
service.fields
|
||||
service.update(
|
||||
|
|
|
@ -3,17 +3,11 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'User views services' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
|
||||
visit(project_settings_integrations_path(project))
|
||||
end
|
||||
include_context 'project service activation'
|
||||
|
||||
it 'shows the list of available services' do
|
||||
visit_project_integrations
|
||||
|
||||
expect(page).to have_content('Integrations')
|
||||
expect(page).to have_content('Campfire')
|
||||
expect(page).to have_content('HipChat')
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import Popover from '~/blob/suggest_gitlab_ci_yml/components/popover.vue';
|
||||
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
|
||||
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
|
||||
import * as utils from '~/lib/utils/common_utils';
|
||||
import { GlDeprecatedButton } from '@gitlab/ui';
|
||||
|
||||
jest.mock('~/lib/utils/common_utils', () => ({
|
||||
...jest.requireActual('~/lib/utils/common_utils'),
|
||||
|
@ -27,6 +28,9 @@ describe('Suggest gitlab-ci.yml Popover', () => {
|
|||
dismissKey,
|
||||
humanAccess,
|
||||
},
|
||||
stubs: {
|
||||
'gl-popover': '<div><slot name="title"></slot><slot></slot></div>',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -88,6 +92,22 @@ describe('Suggest gitlab-ci.yml Popover', () => {
|
|||
property: expectedProperty,
|
||||
});
|
||||
});
|
||||
|
||||
it('sends a tracking event when the popover is dismissed', () => {
|
||||
const expectedLabel = commitTrackLabel;
|
||||
const expectedAction = 'click_button';
|
||||
const expectedProperty = 'owner';
|
||||
const expectedValue = '10';
|
||||
const dismissButton = wrapper.find(GlDeprecatedButton);
|
||||
|
||||
triggerEvent(dismissButton.element);
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith('_category_', expectedAction, {
|
||||
label: expectedLabel,
|
||||
property: expectedProperty,
|
||||
value: expectedValue,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the popover is mounted with the trackLabel of the Confirm button popover at the bottom of the page', () => {
|
||||
|
|
|
@ -94,7 +94,7 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
|
|||
end
|
||||
|
||||
it 'merge_requests/discussions.json' do
|
||||
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
|
||||
create(:discussion_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
|
||||
render_discussions_json(merge_request)
|
||||
end
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ describe Gitlab::ClosingIssueExtractor do
|
|||
end
|
||||
|
||||
it do
|
||||
message = "Awesome commit (Fixes: #{reference})"
|
||||
message = "Awesome commit (fixes: #{reference})"
|
||||
expect(subject.closed_by_message(message)).to eq([issue])
|
||||
end
|
||||
|
||||
|
@ -396,7 +396,7 @@ describe Gitlab::ClosingIssueExtractor do
|
|||
end
|
||||
|
||||
it 'allows mixed comma-separated and non-comma-separated issue numbers in single line message' do
|
||||
message = "Closes #{reference}, #{reference2} and #{reference3}"
|
||||
message = "Closes #{reference}, #{reference2} #{reference3}"
|
||||
|
||||
expect(subject.closed_by_message(message))
|
||||
.to match_array([issue, other_issue, third_issue])
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Database::BatchCount do
|
||||
let_it_be(:fallback) { ::Gitlab::Database::BatchCounter::FALLBACK }
|
||||
let_it_be(:small_batch_size) { ::Gitlab::Database::BatchCounter::MIN_REQUIRED_BATCH_SIZE - 1 }
|
||||
let(:model) { Issue }
|
||||
let(:column) { :author_id }
|
||||
|
||||
|
@ -37,9 +39,8 @@ describe Gitlab::Database::BatchCount do
|
|||
expect(described_class.batch_count(model, batch_size: 50_000)).to eq(5)
|
||||
end
|
||||
|
||||
it 'will not count table with batch_size 1K' do
|
||||
fallback = ::Gitlab::Database::BatchCounter::FALLBACK
|
||||
expect(described_class.batch_count(model, batch_size: fallback / 2)).to eq(fallback)
|
||||
it 'will not count table with a batch size less than allowed' do
|
||||
expect(described_class.batch_count(model, batch_size: small_batch_size)).to eq(fallback)
|
||||
end
|
||||
|
||||
it 'counts with a small edge case batch_sizes than result' do
|
||||
|
@ -57,6 +58,25 @@ describe Gitlab::Database::BatchCount do
|
|||
end.to raise_error 'BatchCount can not be run inside a transaction'
|
||||
end
|
||||
end
|
||||
|
||||
it 'counts with a start and finish' do
|
||||
expect(described_class.batch_count(model, start: model.minimum(:id), finish: model.maximum(:id))).to eq(5)
|
||||
end
|
||||
|
||||
context 'disallowed configurations' do
|
||||
it 'returns fallback if start is bigger than finish' do
|
||||
expect(described_class.batch_count(model, start: 1, finish: 0)).to eq(fallback)
|
||||
end
|
||||
|
||||
it 'returns fallback if loops more than allowed' do
|
||||
large_finish = Gitlab::Database::BatchCounter::MAX_ALLOWED_LOOPS * Gitlab::Database::BatchCounter::DEFAULT_BATCH_SIZE + 1
|
||||
expect(described_class.batch_count(model, start: 1, finish: large_finish)).to eq(fallback)
|
||||
end
|
||||
|
||||
it 'returns fallback if batch size is less than min required' do
|
||||
expect(described_class.batch_count(model, batch_size: small_batch_size)).to eq(fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#batch_distinct_count' do
|
||||
|
@ -80,9 +100,8 @@ describe Gitlab::Database::BatchCount do
|
|||
expect(described_class.batch_distinct_count(model, column, batch_size: 50_000)).to eq(2)
|
||||
end
|
||||
|
||||
it 'will not count table with batch_size 1K' do
|
||||
fallback = ::Gitlab::Database::BatchCounter::FALLBACK
|
||||
expect(described_class.batch_distinct_count(model, column, batch_size: fallback / 2)).to eq(fallback)
|
||||
it 'will not count table with a batch size less than allowed' do
|
||||
expect(described_class.batch_distinct_count(model, column, batch_size: small_batch_size)).to eq(fallback)
|
||||
end
|
||||
|
||||
it 'counts with a small edge case batch_sizes than result' do
|
||||
|
@ -98,5 +117,20 @@ describe Gitlab::Database::BatchCount do
|
|||
it 'counts with User min and max as start and finish' do
|
||||
expect(described_class.batch_distinct_count(model, column, start: User.minimum(:id), finish: User.maximum(:id))).to eq(2)
|
||||
end
|
||||
|
||||
context 'disallowed configurations' do
|
||||
it 'returns fallback if start is bigger than finish' do
|
||||
expect(described_class.batch_distinct_count(model, column, start: 1, finish: 0)).to eq(fallback)
|
||||
end
|
||||
|
||||
it 'returns fallback if loops more than allowed' do
|
||||
large_finish = Gitlab::Database::BatchCounter::MAX_ALLOWED_LOOPS * Gitlab::Database::BatchCounter::DEFAULT_DISTINCT_BATCH_SIZE + 1
|
||||
expect(described_class.batch_distinct_count(model, column, start: 1, finish: large_finish)).to eq(fallback)
|
||||
end
|
||||
|
||||
it 'returns fallback if batch size is less than min required' do
|
||||
expect(described_class.batch_distinct_count(model, column, batch_size: small_batch_size)).to eq(fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Projects::Prometheus::Metrics::DestroyService do
|
||||
let(:metric) { create(:prometheus_metric) }
|
||||
|
||||
subject { described_class.new(metric) }
|
||||
|
||||
it 'destroys metric' do
|
||||
subject.execute
|
||||
|
||||
expect(PrometheusMetric.find_by(id: metric.id)).to be_nil
|
||||
end
|
||||
|
||||
context 'when metric has a prometheus alert associated' do
|
||||
it 'schedules a prometheus alert update' do
|
||||
create(:prometheus_alert, project: metric.project, prometheus_metric: metric)
|
||||
|
||||
schedule_update_service = spy
|
||||
allow(::Clusters::Applications::ScheduleUpdateService).to receive(:new).and_return(schedule_update_service)
|
||||
|
||||
subject.execute
|
||||
|
||||
expect(schedule_update_service).to have_received(:execute)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Projects::Prometheus::Metrics::UpdateService do
|
||||
let(:metric) { create(:prometheus_metric) }
|
||||
|
||||
it 'updates the prometheus metric' do
|
||||
expect do
|
||||
described_class.new(metric, { title: "bar" }).execute
|
||||
end.to change { metric.reload.title }.to("bar")
|
||||
end
|
||||
|
||||
context 'when metric has a prometheus alert associated' do
|
||||
let(:schedule_update_service) { spy }
|
||||
|
||||
before do
|
||||
create(:prometheus_alert, project: metric.project, prometheus_metric: metric)
|
||||
allow(::Clusters::Applications::ScheduleUpdateService).to receive(:new).and_return(schedule_update_service)
|
||||
end
|
||||
|
||||
context 'when updating title' do
|
||||
it 'schedules a prometheus alert update' do
|
||||
described_class.new(metric, { title: "bar" }).execute
|
||||
|
||||
expect(schedule_update_service).to have_received(:execute)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when updating query' do
|
||||
it 'schedules a prometheus alert update' do
|
||||
described_class.new(metric, { query: "sum(bar)" }).execute
|
||||
|
||||
expect(schedule_update_service).to have_received(:execute)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not schedule a prometheus alert update without title nor query being changed' do
|
||||
described_class.new(metric, { y_label: "bar" }).execute
|
||||
|
||||
expect(schedule_update_service).not_to have_received(:execute)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
shared_context 'project service activation' do
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
def visit_project_integrations
|
||||
visit project_settings_integrations_path(project)
|
||||
end
|
||||
|
||||
def visit_project_integration(name)
|
||||
visit_project_integrations
|
||||
click_link(name)
|
||||
end
|
||||
|
||||
def click_test_integration
|
||||
click_button('Test settings and save changes')
|
||||
end
|
||||
|
||||
def click_test_then_save_integration
|
||||
click_test_integration
|
||||
|
||||
expect(page).to have_content('Test failed.')
|
||||
|
||||
click_link('Save anyway')
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue