Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-08-31 15:10:41 +00:00
parent 729eabcb41
commit 2368893df7
159 changed files with 1335 additions and 330 deletions

View File

@ -43,7 +43,7 @@ review-build-cng:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
REVIEW_APPS_DOMAIN: "temp.gitlab-review.app" # FIXME: using temporary domain
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "v4.1.3"
GITLAB_HELM_CHART_REF: "v4.3.0"
environment:
name: review/${CI_COMMIT_REF_NAME}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}

View File

@ -18,7 +18,13 @@ module Projects
if environment
render 'projects/environments/metrics'
elsif default_environment
redirect_to project_metrics_dashboard_path(project, environment: default_environment)
redirect_to project_metrics_dashboard_path(
project,
**permitted_params
.to_h
.symbolize_keys
.merge(environment: default_environment)
)
else
render 'projects/environments/empty_metrics'
end
@ -26,9 +32,14 @@ module Projects
private
def permitted_params
@permitted_params ||= params.permit(:dashboard_path, :environment, :page)
end
def environment
strong_memoize(:environment) do
project.environments.find(params[:environment]) if params[:environment]
env = permitted_params[:environment]
project.environments.find(env) if env
end
end

View File

@ -17,6 +17,7 @@
# without_projects: boolean
# sort: string
# id: integer
# non_internal: boolean
#
class UsersFinder
include CreatedAtFilter
@ -42,6 +43,7 @@ class UsersFinder
users = by_created_at(users)
users = by_without_projects(users)
users = by_custom_attributes(users)
users = by_non_internal(users)
order(users)
end
@ -112,6 +114,12 @@ class UsersFinder
users.without_projects
end
def by_non_internal(users)
return users unless params[:non_internal]
users.non_internal
end
# rubocop: disable CodeReuse/ActiveRecord
def order(users)
return users unless params[:sort]

View File

@ -51,6 +51,11 @@ module Mutations
snippet = service_response.payload[:snippet]
# Only when the user is not an api user and the operation was successful
if !api_user? && service_response.success?
::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
end
{
snippet: service_response.success? ? snippet : nil,
errors: errors_on_object(snippet)

View File

@ -34,6 +34,11 @@ module Mutations
update_params(args)).execute(snippet)
snippet = result.payload[:snippet]
# Only when the user is not an api user and the operation was successful
if !api_user? && result.success?
::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
end
{
snippet: result.success? ? snippet : snippet.reset,
errors: errors_on_object(snippet)

View File

@ -83,9 +83,9 @@ module RelativePositioning
if gap_width < MIN_GAP
raise NoSpaceLeft
elsif gap_width > MAX_GAP
if pos_before == MIN_POSITION
if pos_before <= MIN_POSITION
pos_after - IDEAL_DISTANCE
elsif pos_after == MAX_POSITION
elsif pos_after >= MAX_POSITION
pos_before + IDEAL_DISTANCE
else
midpoint

View File

@ -2,7 +2,16 @@
class Namespace::RootStorageStatistics < ApplicationRecord
SNIPPETS_SIZE_STAT_NAME = 'snippets_size'.freeze
STATISTICS_ATTRIBUTES = %W(storage_size repository_size wiki_size lfs_objects_size build_artifacts_size packages_size #{SNIPPETS_SIZE_STAT_NAME}).freeze
STATISTICS_ATTRIBUTES = %W(
storage_size
repository_size
wiki_size
lfs_objects_size
build_artifacts_size
packages_size
#{SNIPPETS_SIZE_STAT_NAME}
pipeline_artifacts_size
).freeze
self.primary_key = :namespace_id
@ -40,7 +49,8 @@ class Namespace::RootStorageStatistics < ApplicationRecord
'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size',
'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size',
'COALESCE(SUM(ps.packages_size), 0) AS packages_size',
"COALESCE(SUM(ps.snippets_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}"
"COALESCE(SUM(ps.snippets_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}",
'COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size'
)
end

View File

@ -107,7 +107,7 @@ class User < ApplicationRecord
has_many :group_deploy_keys
has_many :gpg_keys
has_many :emails, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :emails
has_many :personal_access_tokens, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :identities, dependent: :destroy, autosave: true # rubocop:disable Cop/ActiveRecordDependent
has_many :u2f_registrations, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent

View File

@ -42,7 +42,7 @@ module Git
push_service_class = push_service_class_for(ref_type)
create_bulk_push_event = changes.size > Gitlab::CurrentSettings.push_event_activities_limit
merge_request_branches = merge_request_branches_for(changes)
merge_request_branches = merge_request_branches_for(ref_type, changes)
changes.each do |change|
push_service_class.new(
@ -74,8 +74,10 @@ module Git
Git::BranchPushService
end
def merge_request_branches_for(changes)
@merge_requests_branches ||= MergeRequests::PushedBranchesService.new(project, current_user, changes: changes).execute
def merge_request_branches_for(ref_type, changes)
return [] if ref_type == :tag
MergeRequests::PushedBranchesService.new(project, current_user, changes: changes).execute
end
end
end

View File

@ -2,12 +2,12 @@
.user-callout{ data: { uid: 'dev_ops_score_intro_callout_dismissed' } }
.bordered-box.landing.content-block
%button.btn.btn-default.close.js-close-callout{ type: 'button',
'aria-label' => _('Dismiss DevOps Score introduction') }
'aria-label' => _('Dismiss DevOps Report introduction') }
= icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
.user-callout-copy
%h4
= _('Introducing Your DevOps Score')
= _('Introducing Your DevOps Report')
%p
= _('Your DevOps Score gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers.')
= _('Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers.')
.svg-container.devops
= custom_icon('dev_ops_score_overview')

View File

@ -4,4 +4,4 @@
%h4= _('Data is still calculating...')
%p
= _('In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index.')
= link_to _('Learn more'), help_page_path('user/admin_area/analytics/dev_ops_score'), target: '_blank'
= link_to _('Learn more'), help_page_path('user/admin_area/analytics/dev_ops_report'), target: '_blank'

View File

@ -1,4 +1,4 @@
- page_title _('DevOps Score')
- page_title _('DevOps Report')
- usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled
.container
@ -16,10 +16,10 @@
%h2.devops-header-title{ class: "devops-#{score_level(@metric.average_percentage_score)}-score" }
= number_to_percentage(@metric.average_percentage_score, precision: 1)
.devops-header-subtitle
= _('index')
= _('DevOps')
%br
= _('score')
= link_to icon('question-circle', 'aria-hidden' => 'true'), help_page_path('user/admin_area/analytics/dev_ops_score')
= _('Score')
= link_to icon('question-circle', 'aria-hidden' => 'true'), help_page_path('user/admin_area/analytics/dev_ops_report')
.devops-cards.board-card-container
- @metric.cards.each do |card|

View File

@ -62,9 +62,9 @@
= _('Analytics')
%li.divider.fly-out-top-item
= nav_link(controller: :dev_ops_score) do
= link_to admin_dev_ops_score_path, title: _('DevOps Score') do
= link_to admin_dev_ops_score_path, title: _('DevOps Report') do
%span
= _('DevOps Score')
= _('DevOps Report')
= nav_link(controller: :cohorts) do
= link_to admin_cohorts_path, title: _('Cohorts') do
%span

View File

@ -0,0 +1,5 @@
---
title: Fix Metrics dashboard embeds when using new URLs
merge_request: 39876
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Track snippet editor actions
merge_request: 40277
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add filter to exclude non internal users in REST API
merge_request: 40372
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add emails user_id foreign key with cascade delete
merge_request: 39899
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Fix wrong caching logic in ProcessRefChangesService
merge_request: 40821
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Rename DevOps Score to DevOps Report
merge_request: 39953
author:
type: changed

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class AddEmailsUserIdForeignKey < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
CONSTRAINT_NAME = 'fk_emails_user_id'
def up
with_lock_retries do
add_foreign_key :emails, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME
end
end
def down
with_lock_retries do
remove_foreign_key_if_exists :emails, column: :user_id, name: CONSTRAINT_NAME
end
end
end

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class RemoveOrphanedEmails < ActiveRecord::Migration[6.0]
DOWNTIME = false
def up
execute <<~SQL
DELETE FROM emails
WHERE not exists (
SELECT 1 FROM users WHERE users.id = emails.user_id
);
SQL
execute 'DELETE FROM emails WHERE user_id IS NULL;'
end
def down
# no-op
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class ValidateEmailsUserIdForeignKey < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
CONSTRAINT_NAME = 'fk_emails_user_id'
def up
validate_foreign_key :emails, :user_id, name: CONSTRAINT_NAME
end
def down
# no op
end
end

View File

@ -0,0 +1 @@
5a5278fdd9539d33a6de226a84ed39b7c5a26929cec68ec5e8d193afb3cfafa2

View File

@ -0,0 +1 @@
476bce9b18177f37b31e15d42f5a1391c0bfbbd312a513c1d5b43085b90afb3e

View File

@ -0,0 +1 @@
5e2dfdf725ad0a3d90b240ced74cf5a872f7126b716847f9f9e99b4ad2a22109

View File

@ -22016,6 +22016,9 @@ ALTER TABLE ONLY public.events
ALTER TABLE ONLY public.vulnerabilities
ADD CONSTRAINT fk_efb96ab1e2 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.emails
ADD CONSTRAINT fk_emails_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.clusters
ADD CONSTRAINT fk_f05c5e5a42 FOREIGN KEY (management_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;

View File

@ -1725,11 +1725,73 @@ type ClusterAgentDeletePayload {
errors: [String!]!
}
type ClusterAgentToken {
"""
Cluster agent this token is associated with
"""
clusterAgent: ClusterAgent
"""
Timestamp the token was created
"""
createdAt: Time
"""
Global ID of the token
"""
id: ClustersAgentTokenID!
}
"""
Autogenerated input type of ClusterAgentTokenCreate
"""
input ClusterAgentTokenCreateInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Global ID of the cluster agent that will be associated with the new token
"""
clusterAgentId: ClustersAgentID!
}
"""
Autogenerated return type of ClusterAgentTokenCreate
"""
type ClusterAgentTokenCreatePayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
"""
Token secret value. Make sure you save it - you won't be able to access it again
"""
secret: String
"""
Token created after mutation
"""
token: ClusterAgentToken
}
"""
Identifier of Clusters::Agent
"""
scalar ClustersAgentID
"""
Identifier of Clusters::AgentToken
"""
scalar ClustersAgentTokenID
type Commit {
"""
Author of the commit
@ -8547,6 +8609,11 @@ type MergeRequest implements Noteable {
"""
allowCollaboration: Boolean
"""
Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured.
"""
approved: Boolean!
"""
Users who approved the merge request
"""
@ -9792,6 +9859,7 @@ type Mutation {
boardListCreate(input: BoardListCreateInput!): BoardListCreatePayload
boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload
clusterAgentDelete(input: ClusterAgentDeleteInput!): ClusterAgentDeletePayload
clusterAgentTokenCreate(input: ClusterAgentTokenCreateInput!): ClusterAgentTokenCreatePayload
commitCreate(input: CommitCreateInput!): CommitCreatePayload
configureSast(input: ConfigureSastInput!): ConfigureSastPayload
createAlertIssue(input: CreateAlertIssueInput!): CreateAlertIssuePayload

View File

@ -4729,6 +4729,181 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ClusterAgentToken",
"description": null,
"fields": [
{
"name": "clusterAgent",
"description": "Cluster agent this token is associated with",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "ClusterAgent",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createdAt",
"description": "Timestamp the token was created",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Time",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": "Global ID of the token",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ClustersAgentTokenID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "ClusterAgentTokenCreateInput",
"description": "Autogenerated input type of ClusterAgentTokenCreate",
"fields": null,
"inputFields": [
{
"name": "clusterAgentId",
"description": "Global ID of the cluster agent that will be associated with the new token",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ClustersAgentID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ClusterAgentTokenCreatePayload",
"description": "Autogenerated return type of ClusterAgentTokenCreate",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "secret",
"description": "Token secret value. Make sure you save it - you won't be able to access it again",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "token",
"description": "Token created after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "ClusterAgentToken",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "ClustersAgentID",
@ -4739,6 +4914,16 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "ClustersAgentTokenID",
"description": "Identifier of Clusters::AgentToken",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Commit",
@ -23818,6 +24003,24 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "approved",
"description": "Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "approvedBy",
"description": "Users who approved the merge request",
@ -27729,6 +27932,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "clusterAgentTokenCreate",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "ClusterAgentTokenCreateInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "ClusterAgentTokenCreatePayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "commitCreate",
"description": null,

View File

@ -295,6 +295,25 @@ Autogenerated return type of ClusterAgentDelete
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
## ClusterAgentToken
| Name | Type | Description |
| --- | ---- | ---------- |
| `clusterAgent` | ClusterAgent | Cluster agent this token is associated with |
| `createdAt` | Time | Timestamp the token was created |
| `id` | ClustersAgentTokenID! | Global ID of the token |
## ClusterAgentTokenCreatePayload
Autogenerated return type of ClusterAgentTokenCreate
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `secret` | String | Token secret value. Make sure you save it - you won't be able to access it again |
| `token` | ClusterAgentToken | Token created after mutation |
## Commit
| Name | Type | Description |
@ -1319,6 +1338,7 @@ Autogenerated return type of MarkAsSpamSnippet
| Name | Type | Description |
| --- | ---- | ---------- |
| `allowCollaboration` | Boolean | Indicates if members of the target project can push to the fork |
| `approved` | Boolean! | Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured. |
| `author` | User | User who created this merge request |
| `commitCount` | Int | Number of commits in the merge request |
| `createdAt` | Time! | Timestamp of when the merge request was created |

View File

@ -61,6 +61,15 @@ GET /users?active=true
GET /users?blocked=true
```
GitLab supports bot users such as the [alert bot](../operations/incident_management/generic_alerts.md)
or the [support bot](../user/project/service_desk.md#support-bot-user).
To exclude these users from the users' list, you can use the parameter `exclude_internal=true`
([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241144) in GitLab 13.4).
```plaintext
GET /users?exclude_internal=true
```
NOTE: **Note:**
Username search is case insensitive.

View File

@ -43,7 +43,7 @@ Most issues will have labels for at least one of the following:
- Type: `~feature`, `~bug`, `~tooling`, `~documentation`, etc.
- Stage: `~"devops::plan"`, `~"devops::create"`, etc.
- Group: `~"group::source code"`, `~"group::knowledge"`, `~"group::editor"`, etc.
- Category: `~"Category:Code Analytics"`, `~"Category:DevOps Score"`, `~"Category:Templates"`, etc.
- Category: `~"Category:Code Analytics"`, `~"Category:DevOps Reports"`, `~"Category:Templates"`, etc.
- Feature: `~wiki`, `~ldap`, `~api`, `~issues`, `~"merge requests"`, etc.
- Department: `~UX`, `~Quality`
- Team: `~"Technical Writing"`, `~Delivery`
@ -188,9 +188,9 @@ their color is `#428BCA`.
`<Category Name>` is the category name as it is in the single source of truth for categories at
<https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml>.
For instance, the "DevOps Score" category is represented by the
~"Category:DevOps Score" label in the `gitlab-org` group since its
`devops_score.name` value is "DevOps Score".
For instance, the "DevOps Report" category is represented by the
~"Category:DevOps Reports" label in the `gitlab-org` group since its
`devops_score.name` value is "DevOps Reports".
If a category's label doesn't respect this naming convention, it should be specified
with [the `label` attribute](https://about.gitlab.com/handbook/marketing/website/#category-attributes)

View File

@ -750,3 +750,64 @@ code review. For docs changes in merge requests, whenever a change to files unde
is made, Danger Bot leaves a comment with further instructions about the documentation
process. This is configured in the `Dangerfile` in the GitLab repository under
[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation).
## Automatic screenshot generator
You can now set up an automatic screenshot generator to take and compress screenshots, with the
help of a configuration file known as **screenshot generator**.
### Use the tool
To run the tool on an existing screenshot generator, take the following steps:
1. Set up the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
1. Navigate to the subdirectory with your cloned GitLab repository, typically `gdk/gitlab`.
1. Make sure that your GDK database is fully migrated: `bin/rake db:migrate RAILS_ENV=development`.
1. Install pngquant, see the tool website for more info: [`pngquant`](https://pngquant.org/)
1. Run `scripts/docs_screenshots.rb spec/docs_screenshots/<name_of_screenshot_generator>.rb <milestone-version>`.
1. Identify the location of the screenshots, based on the `gitlab/doc` location defined by the `it` parameter in your script.
1. Commit the newly created screenshots.
### Extending the tool
To add an additional **screenshot generator**, take the following steps:
- Locate the `spec/docs_screenshots` directory.
- Add a new file with a `_docs.rb` extension.
- Be sure to include the following bits in the file:
```ruby
require 'spec_helper'
RSpec.describe '<What I am taking screenshots of>', :js do
include DocsScreenshotHelpers # Helper that enables the screenshots taking mechanism
before do
page.driver.browser.manage.window.resize_to(1366, 1024) # length and width of the page
end
```
- In addition, every `it` block must include the path where the screenshot is saved
```ruby
it 'user/packages/container_registry/img/project_image_repositories_list'
```
#### Full page screenshots
To take a full page screenshot simply `visit the page` and perform any expectation on real content (to have capybara wait till the page is ready and not take a white screenshot).
#### Element screenshot
To have the screenshot focuses few more steps are needed:
- **find the area**: `screenshot_area = find('#js-registry-policies')`
- **scroll the area in focus**: `scroll_to screenshot_area`
- **wait for the content**: `expect(screenshot_area).to have_content 'Expiration interval'`
- **set the crop area**: `set_crop_data(screenshot_area, 20)`
In particular `set_crop_data` accepts as arguments: a `DOM` element and a padding, the padding will be added around the element enlarging the screenshot area.
#### Live example
Please use `spec/docs_screenshots/container_registry_docs.rb` as a guide and as an example to create your own scripts.

View File

@ -37,7 +37,7 @@ More useful links:
- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions.
- As a benefit of having the usage ping active, GitLab lets you analyze the users activities over time of your GitLab installation.
- As a benefit of having the usage ping active, GitLab provides you with The DevOps Score,which gives you an overview of your entire instances adoption of Concurrent DevOps from planning to monitoring.
- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instances adoption of Concurrent DevOps from planning to monitoring.
- You will get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value)
- You will get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization?
- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes.
@ -108,7 +108,7 @@ sequenceDiagram
S3 Bucket->>Snowflake DW: Import data
Snowflake DW->>Snowflake DW: Transform data using dbt
Snowflake DW->>Sisense Dashboards: Data available for querying
Versions Application->>GitLab Instance: DevOps Score (Conversational Development Index)
Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index)
```
## How Usage Ping works

View File

@ -20,15 +20,28 @@ metrics to others, and you want to have relevant information directly available.
NOTE: **Note:**
Requires [Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.md) metrics.
Note: **Note:**
In GitLab versions 13.3 and earlier, metrics dashboard links were in the form
`https://<root_url>/<project>/-/environments/<environment_id>/metrics`. These links
are still supported, and can be used to embed metric charts.
To display metric charts, include a link of the form
`https://<root_url>/<project>/-/environments/<environment_id>/metrics` in a field
`https://<root_url>/<project>/-/metrics?environment=<environment_id>` in a field
that supports GitLab-flavored Markdown:
![Embedded Metrics Markdown](img/embedded_metrics_markdown_v12_8.png)
```markdown
### Summary
**Start time:** 2020-01-21T12:00:31+00:00
### Metrics
https://gitlab.com/gitlab-org/monitor/tanuki-inc/-/metrics?environment=1118134
```
GitLab unfurls the link as an embedded metrics panel:
![Embedded Metrics Rendered](img/embedded_metrics_rendered_v12_8.png)
![Embedded Metrics Rendered](img/embedded_metrics_rendered_v13_4.png)
You can also embed a single chart. To get a link to a chart, click the
**{ellipsis_v}** **More actions** menu in the upper right corner of the chart,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,5 +1,5 @@
---
redirect_to: 'dev_ops_score.md'
redirect_to: 'dev_ops_report.md'
---
This document was moved to [another location](dev_ops_score.md).
This document was moved to [another location](dev_ops_report.md).

View File

@ -1,4 +1,4 @@
# DevOps Score
# DevOps Report
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30469) in GitLab 9.3.
> - [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
@ -6,7 +6,7 @@
NOTE: **Note:**
Your GitLab instance's [usage ping](../settings/usage_statistics.md#usage-ping-core-only) must be activated in order to use this feature.
The DevOps Score gives you an overview of your entire instance's adoption of
The DevOps Report gives you an overview of your entire instance's adoption of
[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
from planning to monitoring.
@ -15,9 +15,9 @@ the last 30 days, averaged over the number of active users in that time period.
provides a Lead score per feature, which is calculated based on GitLab's analysis
of top-performing instances based on [usage ping data](../settings/usage_statistics.md#usage-ping-core-only) that GitLab has
collected. Your score is compared to the lead score of each feature and then expressed as a percentage at the bottom of said feature.
Your overall **index score** is an average of your feature scores. You can use this score to compare your DevOps status to other organizations.
Your overall **DevOps Score** is an average of your feature scores. You can use this score to compare your DevOps status to other organizations.
![DevOps Score](img/dev_ops_score_v12_6.png)
![DevOps Report](img/dev_ops_report_v13_4.png)
The page also provides helpful links to articles and GitLab docs, to help you
improve your scores.

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

View File

@ -6,5 +6,5 @@ Administrators have access to instance-wide analytics, as shown in **Admin Area
There are two kinds of statistics:
- [Dev Ops Score](dev_ops_score.md): Provides an overview of your entire instance's feature usage.
- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time.

View File

@ -1,5 +1,5 @@
---
redirect_to: '../analytics/dev_ops_score.md'
redirect_to: '../analytics/dev_ops_report.md'
---
Conversational Development Index was renamed to [DevOps Score](../analytics/dev_ops_score.md) in GitLab 12.6.
Conversational Development Index was renamed to [DevOps Report](../analytics/dev_ops_report.md) in GitLab 12.6.

View File

@ -1,5 +1,5 @@
---
redirect_to: '../analytics/dev_ops_score.md'
redirect_to: '../analytics/dev_ops_report.md'
---
This document was moved to [another location](../analytics/dev_ops_score.md).
This document was moved to [another location](../analytics/dev_ops_report.md).

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -8,7 +8,7 @@ You can use sign-up restrictions to:
- Disable new signups.
- Require user email confirmation.
- Blacklist or whitelist email addresses belonging to specific domains.
- Denylist or allowlist email addresses belonging to specific domains.
NOTE: **Note:**
These restrictions are only applied during sign-up from an external user. An admin is
@ -31,7 +31,7 @@ consider disabling new signups if you do not expect public users to sign up for
account.
Alternatively, you could also consider setting up a
[whitelist](#whitelist-email-domains) or [blacklist](#blacklist-email-domains) on
[allowlist](#allowlist-email-domains) or [denylist](#denylist-email-domains) on
email domains to prevent malicious users from creating accounts.
## Require email confirmation
@ -48,14 +48,14 @@ their email address before they are allowed to sign in.
You can [change](../../../security/password_length_limits.md#modify-minimum-password-length-using-gitlab-ui)
the minimum number of characters a user must have in their password using the GitLab UI.
## Whitelist email domains
## Allowlist email domains
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/598) in GitLab 7.11.0
You can restrict users to only sign up using email addresses matching the given
domains list.
## Blacklist email domains
## Denylist email domains
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5259) in GitLab 8.10.
@ -71,17 +71,17 @@ To access this feature:
1. Navigate to the **Admin Area > Settings > General**.
1. Expand the **Sign-up restrictions** section.
For the blacklist, you can enter the list manually or upload a `.txt` file that
For the denylist, you can enter the list manually or upload a `.txt` file that
contains list entries.
For the whitelist, you must enter the list manually.
For the allowlist, you must enter the list manually.
Both the whitelist and blacklist accept wildcards. For example, you can use
Both the allowlist and denylist accept wildcards. For example, you can use
`*.company.com` to accept every `company.com` subdomain, or `*.io` to block all
domains ending in `.io`. Domains should be separated by a whitespace,
semicolon, comma, or a new line.
![Domain Blacklist](img/domain_blacklist.png)
![Domain Denylist](img/domain_denylist.png)
<!-- ## Troubleshooting

View File

@ -84,6 +84,7 @@ module API
optional :created_after, type: DateTime, desc: 'Return users created after the specified time'
optional :created_before, type: DateTime, desc: 'Return users created before the specified time'
optional :without_projects, type: Boolean, default: false, desc: 'Filters only users without projects'
optional :exclude_internal, as: :non_internal, type: Boolean, default: false, desc: 'Filters only non internal users'
all_or_none_of :extern_uid, :provider
use :sort_params

View File

@ -10,7 +10,6 @@ module Banzai
# the cost of doing a full regex match.
def xpath_search
"descendant-or-self::a[contains(@href,'metrics') and \
contains(@href,'environments') and \
starts-with(@href, '#{gitlab_domain}')]"
end
@ -29,7 +28,7 @@ module Banzai
params['project'],
params['environment'],
embedded: true,
**query_params(params['url'])
**query_params(params['url']).except(:environment)
)
end
end

View File

@ -10,20 +10,23 @@ module Gitlab
QUERY_PATTERN = '(?<query>\?[a-zA-Z0-9%.()+_=-]+(&[a-zA-Z0-9%.()+_=-]+)*)?'
ANCHOR_PATTERN = '(?<anchor>\#[a-z0-9_-]+)?'
OPTIONAL_DASH_PATTERN = '(?:/-)?'
DASH_PATTERN = '(?:/-)'
# Matches urls for a metrics dashboard. This could be
# either the /metrics endpoint or the /metrics_dashboard
# endpoint.
# Matches urls for a metrics dashboard.
# This regex needs to match the old metrics URL, the new metrics URL,
# and the dashboard URL (inline_metrics_redactor_filter.rb
# uses this regex to match against the dashboard URL.)
#
# EX - https://<host>/<namespace>/<project>/environments/<env_id>/metrics
# EX - Old URL: https://<host>/<namespace>/<project>/environments/<env_id>/metrics
# OR
# New URL: https://<host>/<namespace>/<project>/-/metrics?environment=<env_id>
# OR
# dashboard URL: https://<host>/<namespace>/<project>/environments/<env_id>/metrics_dashboard
def metrics_regex
strong_memoize(:metrics_regex) do
regex_for_project_metrics(
%r{
/environments
/(?<environment>\d+)
/(metrics_dashboard|metrics)
( #{environment_metrics_regex} ) | ( #{non_environment_metrics_regex} )
}x
)
end
@ -36,6 +39,7 @@ module Gitlab
strong_memoize(:grafana_regex) do
regex_for_project_metrics(
%r{
#{DASH_PATTERN}?
/grafana
/metrics_dashboard
}x
@ -44,16 +48,22 @@ module Gitlab
end
# Matches dashboard urls for a metric chart embed
# for cluster metrics
# for cluster metrics.
# This regex needs to match the dashboard URL as well, not just the trigger URL.
# The inline_metrics_redactor_filter.rb uses this regex to match against
# the dashboard URL.
#
# EX - https://<host>/<namespace>/<project>/-/clusters/<cluster_id>/?group=Cluster%20Health&title=Memory%20Usage&y_label=Memory%20(GiB)
# dashboard URL - https://<host>/<namespace>/<project>/-/clusters/<cluster_id>/metrics_dashboard?group=Cluster%20Health&title=Memory%20Usage&y_label=Memory%20(GiB)
def clusters_regex
strong_memoize(:clusters_regex) do
regex_for_project_metrics(
%r{
#{DASH_PATTERN}?
/clusters
/(?<cluster_id>\d+)
/?
( (/metrics) | ( /metrics_dashboard\.json ) )?
}x
)
end
@ -67,10 +77,11 @@ module Gitlab
strong_memoize(:alert_regex) do
regex_for_project_metrics(
%r{
#{DASH_PATTERN}?
/prometheus
/alerts
/(?<alert>\d+)
/metrics_dashboard
/metrics_dashboard(\.json)?
}x
)
end
@ -95,16 +106,37 @@ module Gitlab
private
def environment_metrics_regex
%r{
#{DASH_PATTERN}?
/environments
/(?<environment>\d+)
/(metrics_dashboard|metrics)
}x
end
def non_environment_metrics_regex
%r{
#{DASH_PATTERN}
/metrics
(?= # Lookahead to ensure there is an environment query param
\?
.*
environment=(?<environment>\d+)
.*
)
}x
end
def regex_for_project_metrics(path_suffix_pattern)
%r{
(?<url>
^(?<url>
#{gitlab_host_pattern}
#{project_path_pattern}
#{OPTIONAL_DASH_PATTERN}
#{path_suffix_pattern}
#{QUERY_PATTERN}
#{ANCHOR_PATTERN}
)
)$
}x
end

View File

@ -2,10 +2,10 @@ return if Rails.env.production?
require 'png_quantizator'
require 'parallel'
require_relative '../../tooling/lib/tooling/images'
# The amount of variance (in bytes) allowed in
# file size when testing for compression size
TOLERANCE = 10000
namespace :pngquant do
# Returns an array of all images eligible for compression
@ -13,55 +13,13 @@ namespace :pngquant do
Dir.glob('doc/**/*.png', File::FNM_CASEFOLD)
end
# Runs pngquant on an image and optionally
# writes the result to disk
def compress_image(file, overwrite_original)
compressed_file = "#{file}.compressed"
FileUtils.copy(file, compressed_file)
pngquant_file = PngQuantizator::Image.new(compressed_file)
# Run the image repeatedly through pngquant until
# the change in file size is within TOLERANCE
loop do
before = File.size(compressed_file)
pngquant_file.quantize!
after = File.size(compressed_file)
break if before - after <= TOLERANCE
end
savings = File.size(file) - File.size(compressed_file)
is_uncompressed = savings > TOLERANCE
if is_uncompressed && overwrite_original
FileUtils.copy(compressed_file, file)
end
FileUtils.remove(compressed_file)
[is_uncompressed, savings]
end
# Ensures pngquant is available and prints an error if not
def check_executable
unless system('pngquant --version', out: File::NULL)
warn(
'Error: pngquant executable was not detected in the system.'.color(:red),
'Download pngquant at https://pngquant.org/ and place the executable in /usr/local/bin'.color(:green)
)
abort
end
end
desc 'GitLab | Pngquant | Compress all documentation PNG images using pngquant'
task :compress do
check_executable
files = doc_images
puts "Compressing #{files.size} PNG files in doc/**"
Parallel.each(files) do |file|
was_uncompressed, savings = compress_image(file, true)
was_uncompressed, savings = Tooling::Image.compress_image(file)
if was_uncompressed
puts "#{file} was reduced by #{savings} bytes"
@ -71,13 +29,11 @@ namespace :pngquant do
desc 'GitLab | Pngquant | Checks that all documentation PNG images have been compressed with pngquant'
task :lint do
check_executable
files = doc_images
puts "Checking #{files.size} PNG files in doc/**"
uncompressed_files = Parallel.map(files) do |file|
is_uncompressed, _ = compress_image(file, false)
is_uncompressed, _ = Tooling::Image.compress_image(file, true)
if is_uncompressed
puts "Uncompressed file detected: ".color(:red) + file
file

View File

@ -5156,6 +5156,9 @@ msgstr ""
msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
@ -8583,7 +8586,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
msgid "DevOps Score"
msgid "DevOps"
msgstr ""
msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@ -8729,7 +8735,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
msgid "Dismiss DevOps Score introduction"
msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@ -13318,7 +13324,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
msgid "Introducing Your DevOps Score"
msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@ -21469,6 +21475,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
msgid "Score"
msgstr ""
msgid "Scroll down"
msgstr ""
@ -28572,7 +28581,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
msgid "Your DevOps Score gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@ -29323,9 +29332,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
msgid "index"
msgstr ""
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@ -29997,9 +30003,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
msgid "score"
msgstr ""
msgid "security Reports|There was an error creating the merge request"
msgstr ""

View File

@ -21,7 +21,7 @@ module RuboCop
private
def acceptable_file_path?(path)
File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path)
File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path) || File.fnmatch?('*/docs_screenshots/*_docs.rb', path)
end
def shared_example?(node)

60
scripts/docs_screenshots.rb Executable file
View File

@ -0,0 +1,60 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'png_quantizator'
require 'open3'
require 'parallel'
require_relative '../tooling/lib/tooling/images.rb'
generator = ARGV[0]
milestone = ARGV[1]
unless generator
warn('Error: missing generator, please supply one')
abort
end
unless milestone
warn('Error: missing milestone, please supply one')
abort
end
def rename_image(file, milestone)
path = File.dirname(file)
basename = File.basename(file)
final_name = File.join(path, "#{basename}_v#{milestone}.png")
FileUtils.mv(file, final_name)
end
system('spring', 'rspec', generator)
files = []
Open3.popen3("git diff --name-only -- '*.png'") do |stdin, stdout, stderr, thread|
files.concat stdout.read.chomp.split("\n")
end
Open3.popen3("git status --porcelain -- '*.png'") do |stdin, stdout, stderr, thread|
files.concat stdout.read.chomp.split("?? ")
end
files.reject!(&:empty?)
if files.empty?
puts "No file generated, did you select the right screenshot generator?"
else
puts "Compressing newly generated screenshots"
Parallel.each(files) do |file|
file_path = File.join(Dir.pwd, file.to_s.strip)
was_uncompressed, savings = Tooling::Image.compress_image(file_path)
rename_image(file_path, milestone)
if was_uncompressed
puts "#{file} was reduced by #{savings} bytes."
else
puts "Skipping already compressed file: #{file}."
end
end
end

View File

@ -44,7 +44,7 @@ RSpec.describe Projects::GraphsController do
context 'when anonymous users can read build report results' do
it 'sets the daily coverage options' do
Timecop.freeze do
freeze_time do
get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' })
expect(assigns[:daily_coverage_options]).to eq(

View File

@ -6,9 +6,9 @@ RSpec.describe Projects::IssuesController do
include ProjectForksHelper
include_context 'includes Spam constants'
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:issue) { create(:issue, project: project) }
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:user, reload: true) { create(:user) }
let(:issue) { create(:issue, project: project) }
describe "GET #index" do
context 'external issue tracker' do
@ -39,8 +39,8 @@ RSpec.describe Projects::IssuesController do
end
context 'when project has moved' do
let(:new_project) { create(:project) }
let(:issue) { create(:issue, project: new_project) }
let_it_be(:new_project) { create(:project) }
let_it_be(:issue) { create(:issue, project: new_project) }
before do
project.route.destroy
@ -297,6 +297,7 @@ RSpec.describe Projects::IssuesController do
project.add_developer(developer)
end
let_it_be(:issue) { create(:issue, project: project) }
let(:developer) { user }
let(:params) do
{
@ -401,7 +402,7 @@ RSpec.describe Projects::IssuesController do
end
context 'when moving issue to another private project' do
let(:another_project) { create(:project, :private) }
let_it_be(:another_project) { create(:project, :private) }
context 'when user has access to move issue' do
before do
@ -438,10 +439,10 @@ RSpec.describe Projects::IssuesController do
end
describe 'PUT #reorder' do
let(:group) { create(:group, projects: [project]) }
let!(:issue1) { create(:issue, project: project, relative_position: 10) }
let!(:issue2) { create(:issue, project: project, relative_position: 20) }
let!(:issue3) { create(:issue, project: project, relative_position: 30) }
let_it_be(:group) { create(:group, projects: [project]) }
let_it_be(:issue1) { create(:issue, project: project, relative_position: 10) }
let_it_be(:issue2) { create(:issue, project: project, relative_position: 20) }
let_it_be(:issue3) { create(:issue, project: project, relative_position: 30) }
before do
sign_in(user)
@ -657,15 +658,15 @@ RSpec.describe Projects::IssuesController do
end
describe 'Confidential Issues' do
let(:project) { create(:project_empty_repo, :public) }
let(:assignee) { create(:assignee) }
let(:author) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:admin) { create(:admin) }
let!(:issue) { create(:issue, project: project) }
let!(:unescaped_parameter_value) { create(:issue, :confidential, project: project, author: author) }
let!(:request_forgery_timing_attack) { create(:issue, :confidential, project: project, assignees: [assignee]) }
let_it_be(:project) { create(:project_empty_repo, :public) }
let_it_be(:assignee) { create(:assignee) }
let_it_be(:author) { create(:user) }
let_it_be(:non_member) { create(:user) }
let_it_be(:member) { create(:user) }
let_it_be(:admin) { create(:admin) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:unescaped_parameter_value) { create(:issue, :confidential, project: project, author: author) }
let_it_be(:request_forgery_timing_attack) { create(:issue, :confidential, project: project, assignees: [assignee]) }
describe 'GET #index' do
it 'does not list confidential issues for guests' do
@ -1077,7 +1078,7 @@ RSpec.describe Projects::IssuesController do
end
context 'resolving discussions in MergeRequest' do
let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
let_it_be(:discussion) { create(:diff_note_on_merge_request).to_discussion }
let(:merge_request) { discussion.noteable }
let(:project) { merge_request.source_project }
@ -1376,9 +1377,9 @@ RSpec.describe Projects::IssuesController do
end
context "when the user is owner" do
let(:owner) { create(:user) }
let(:namespace) { create(:namespace, owner: owner) }
let(:project) { create(:project, namespace: namespace) }
let_it_be(:owner) { create(:user) }
let_it_be(:namespace) { create(:namespace, owner: owner) }
let_it_be(:project) { create(:project, namespace: namespace) }
before do
sign_in(owner)
@ -1461,7 +1462,8 @@ RSpec.describe Projects::IssuesController do
describe 'POST create_merge_request' do
let(:target_project_id) { nil }
let(:project) { create(:project, :repository, :public) }
let_it_be(:project) { create(:project, :repository, :public) }
before do
project.add_developer(user)
@ -1539,7 +1541,7 @@ RSpec.describe Projects::IssuesController do
end
describe 'POST #import_csv' do
let(:project) { create(:project, :public) }
let_it_be(:project) { create(:project, :public) }
let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
context 'unauthorized' do
@ -1621,7 +1623,7 @@ RSpec.describe Projects::IssuesController do
end
context 'when not logged in' do
let(:project) { create(:project_empty_repo, :public) }
let(:empty_project) { create(:project_empty_repo, :public) }
it 'redirects to the sign in page' do
request_csv
@ -1738,7 +1740,7 @@ RSpec.describe Projects::IssuesController do
end
context 'with cross-reference system note', :request_store do
let(:new_issue) { create(:issue) }
let_it_be(:new_issue) { create(:issue) }
let(:cross_reference) { "mentioned in #{new_issue.to_reference(issue.project)}" }
before do
@ -1836,7 +1838,7 @@ RSpec.describe Projects::IssuesController do
end
context 'private project with token authentication' do
let(:private_project) { create(:project, :private) }
let_it_be(:private_project) { create(:project, :private) }
it_behaves_like 'authenticates sessionless user', :index, :atom, ignore_incrementing: true do
before do
@ -1856,7 +1858,7 @@ RSpec.describe Projects::IssuesController do
end
context 'public project with token authentication' do
let(:public_project) { create(:project, :public) }
let_it_be(:public_project) { create(:project, :public) }
it_behaves_like 'authenticates sessionless user', :index, :atom, public: true do
before do

View File

@ -98,7 +98,7 @@ RSpec.describe Projects::NotesController do
let(:page_2_boundary) { microseconds(page_2.last.updated_at + NotesFinder::FETCH_OVERLAP) }
around do |example|
Timecop.freeze do
freeze_time do
example.run
end
end

View File

@ -35,7 +35,6 @@ RSpec.describe 'Database schema' do
deploy_keys_projects: %w[deploy_key_id],
deployments: %w[deployable_id environment_id user_id],
draft_notes: %w[discussion_id commit_id],
emails: %w[user_id],
epics: %w[updated_by_id last_edited_by_id state_id],
events: %w[target_id],
forked_project_links: %w[forked_from_project_id],

View File

@ -0,0 +1,87 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Container Registry', :js do
include DocsScreenshotHelpers
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:project) { create(:project, namespace: group) }
before do
page.driver.browser.manage.window.resize_to(1366, 1024)
group.add_owner(user)
sign_in(user)
stub_container_registry_config(enabled: true)
stub_container_registry_tags(repository: :any, tags: [])
end
context 'expiration policy settings' do
it 'user/packages/container_registry/img/expiration_policy_form' do
visit project_settings_ci_cd_path(project)
screenshot_area = find('#js-registry-policies')
scroll_to screenshot_area
expect(screenshot_area).to have_content 'Expiration interval'
set_crop_data(screenshot_area, 20)
end
end
context 'project container_registry' do
it 'user/packages/container_registry/img/project_empty_page' do
visit_project_container_registry
expect(page).to have_content _('There are no container images stored for this project')
end
context 'with a list of repositories' do
before do
stub_container_registry_tags(repository: %r{my/image}, tags: %w[latest], with_manifest: true)
create_list(:container_repository, 12, project: project)
end
it 'user/packages/container_registry/img/project_image_repositories_list' do
visit_project_container_registry
expect(page).to have_content 'Image Repositories'
end
it 'user/packages/container_registry/img/project_image_repositories_list_with_commands_open' do
visit_project_container_registry
click_on 'CLI Commands'
end
end
end
context 'group container_registry' do
it 'user/packages/container_registry/img/group_empty_page' do
visit_group_container_registry
expect(page).to have_content 'There are no container images available in this group'
end
context 'with a list of repositories' do
before do
stub_container_registry_tags(repository: %r{my/image}, tags: %w[latest], with_manifest: true)
create_list(:container_repository, 12, project: project)
end
it 'user/packages/container_registry/img/group_image_repositories_list' do
visit_group_container_registry
expect(page).to have_content 'Image Repositories'
end
end
end
def visit_project_container_registry
visit project_container_registry_index_path(project)
end
def visit_group_container_registry
visit group_container_registries_path(group)
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'DevOps Score page' do
RSpec.describe 'DevOps Report page' do
before do
sign_in(create(:admin))
end
@ -10,11 +10,11 @@ RSpec.describe 'DevOps Score page' do
it 'has dismissable intro callout', :js do
visit admin_dev_ops_score_path
expect(page).to have_content 'Introducing Your DevOps Score'
expect(page).to have_content 'Introducing Your DevOps Report'
find('.js-close-callout').click
expect(page).not_to have_content 'Introducing Your DevOps Score'
expect(page).not_to have_content 'Introducing Your DevOps Report'
end
context 'when usage ping is disabled' do
@ -31,7 +31,7 @@ RSpec.describe 'DevOps Score page' do
it 'hides the intro callout' do
visit admin_dev_ops_score_path
expect(page).not_to have_content 'Introducing Your DevOps Score'
expect(page).not_to have_content 'Introducing Your DevOps Report'
end
end

View File

@ -23,7 +23,7 @@ RSpec.describe 'Issue Boards', :js do
let(:application_settings) { {} }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
before do

View File

@ -8,7 +8,7 @@ RSpec.describe 'Group milestones' do
let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
before do

View File

@ -112,7 +112,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
let!(:group) { create(:group) }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
before do

View File

@ -503,7 +503,7 @@ RSpec.describe 'Login' do
context 'within the grace period' do
it 'redirects to two-factor configuration page' do
Timecop.freeze do
freeze_time do
expect(authentication_metrics)
.to increment(:user_authenticated_counter)

View File

@ -12,7 +12,7 @@ RSpec.describe UsersFinder do
it 'returns all users' do
users = described_class.new(user).execute
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user)
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
end
it 'filters by username' do
@ -54,7 +54,7 @@ RSpec.describe UsersFinder do
it 'returns no external users' do
users = described_class.new(user, external: true).execute
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user)
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
end
it 'filters by created_at' do
@ -68,19 +68,25 @@ RSpec.describe UsersFinder do
expect(users.map(&:username)).not_to include([filtered_user_before.username, filtered_user_after.username])
end
it 'filters by non internal users' do
users = described_class.new(user, non_internal: true).execute
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user)
end
it 'does not filter by custom attributes' do
users = described_class.new(
user,
custom_attributes: { foo: 'bar' }
).execute
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user)
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
end
it 'orders returned results' do
users = described_class.new(user, sort: 'id_asc').execute
expect(users).to eq([normal_user, blocked_user, omniauth_user, user])
expect(users).to eq([normal_user, blocked_user, omniauth_user, internal_user, user])
end
end
@ -96,13 +102,14 @@ RSpec.describe UsersFinder do
it 'returns all users' do
users = described_class.new(admin).execute
expect(users).to contain_exactly(admin, normal_user, blocked_user, external_user, omniauth_user)
expect(users).to contain_exactly(admin, normal_user, blocked_user, external_user, omniauth_user, internal_user)
end
it 'filters by custom attributes' do
create :user_custom_attribute, user: normal_user, key: 'foo', value: 'foo'
create :user_custom_attribute, user: normal_user, key: 'bar', value: 'bar'
create :user_custom_attribute, user: blocked_user, key: 'foo', value: 'foo'
create :user_custom_attribute, user: internal_user, key: 'foo', value: 'foo'
users = described_class.new(
admin,

View File

@ -27,7 +27,10 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
total_time_spent reference author merged_at commit_count
]
expected_fields << 'approved_by' if Gitlab.ee?
if Gitlab.ee?
expected_fields << 'approved'
expected_fields << 'approved_by'
end
expect(described_class).to have_graphql_fields(*expected_fields)
end

View File

@ -5,25 +5,68 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::InlineMetricsFilter do
include FilterSpecHelper
let(:params) { ['foo', 'bar', 12] }
let(:query_params) { {} }
let(:trigger_url) { urls.metrics_namespace_project_environment_url(*params, query_params) }
let(:environment_id) { 12 }
let(:dashboard_url) { urls.metrics_dashboard_namespace_project_environment_url(*params, **query_params, embedded: true) }
it_behaves_like 'a metrics embed filter'
let(:query_params) do
{
dashboard: 'config/prometheus/common_metrics.yml',
group: 'System metrics (Kubernetes)',
title: 'Core Usage (Pod Average)',
y_label: 'Cores per Pod'
}
end
context 'with query params specified' do
let(:query_params) do
{
dashboard: 'config/prometheus/common_metrics.yml',
group: 'System metrics (Kubernetes)',
title: 'Core Usage (Pod Average)',
y_label: 'Cores per Pod'
}
context 'with /-/environments/:environment_id/metrics URL' do
let(:params) { ['group', 'project', environment_id] }
let(:trigger_url) { urls.metrics_namespace_project_environment_url(*params, **query_params) }
context 'with no query params' do
let(:query_params) { {} }
it_behaves_like 'a metrics embed filter'
end
it_behaves_like 'a metrics embed filter'
context 'with query params' do
it_behaves_like 'a metrics embed filter'
end
end
context 'with /-/metrics?environment=:environment_id URL' do
let(:params) { %w(group project) }
let(:trigger_url) { urls.namespace_project_metrics_dashboard_url(*params, **query_params) }
let(:dashboard_url) do
urls.metrics_dashboard_namespace_project_environment_url(
*params.append(environment_id),
**query_params.except(:environment),
embedded: true
)
end
context 'with query params' do
it_behaves_like 'a metrics embed filter' do
before do
query_params.merge!(environment: environment_id)
end
end
end
context 'with only environment in query params' do
let(:query_params) { { environment: environment_id } }
it_behaves_like 'a metrics embed filter'
end
context 'with no query params' do
let(:query_params) { {} }
it 'ignores metrics URL without environment parameter' do
input = %(<a href="#{trigger_url}">example</a>)
filtered_input = filter(input).to_s
expect(CGI.unescape_html(filtered_input)).to eq(input)
end
end
end
it 'leaves links to other dashboards unchanged' do

View File

@ -22,6 +22,13 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
it_behaves_like 'redacts the embed placeholder'
it_behaves_like 'retains the embed placeholder when applicable'
context 'with /-/metrics?environment=:environment_id URL' do
let(:url) { urls.project_metrics_dashboard_url(project, embedded: true, environment: 1) }
it_behaves_like 'redacts the embed placeholder'
it_behaves_like 'retains the embed placeholder when applicable'
end
context 'for a grafana dashboard' do
let(:url) { urls.project_grafana_api_metrics_dashboard_url(project, embedded: true) }
@ -33,7 +40,7 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
let_it_be(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [project]) }
let(:params) { [project.namespace.path, project.path, cluster.id] }
let(:query_params) { { group: 'Cluster Health', title: 'CPU Usage', y_label: 'CPU (cores)' } }
let(:url) { urls.metrics_dashboard_namespace_project_cluster_url(*params, **query_params) }
let(:url) { urls.metrics_dashboard_namespace_project_cluster_url(*params, **query_params, format: :json) }
context 'with user who can read cluster' do
it_behaves_like 'redacts the embed placeholder'

View File

@ -45,7 +45,7 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
let(:current_time) { Time.current.utc }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
subject { parsed_payload.starts_at }

View File

@ -17,7 +17,7 @@ RSpec.describe Gitlab::AppTextLogger do
end
it 'logs time in UTC with ISO8601.3 standard' do
Timecop.freeze do
freeze_time do
expect(subject.format_message('INFO', Time.now, nil, string_message))
.to include(Time.now.utc.iso8601(3))
end

View File

@ -20,7 +20,7 @@ RSpec.describe Gitlab::Ci::Jwt do
subject(:payload) { described_class.new(build, ttl: 30).payload }
it 'has correct values for the standard JWT attributes' do
Timecop.freeze do
freeze_time do
now = Time.now.to_i
aggregate_failures do

View File

@ -85,7 +85,7 @@ RSpec.describe Gitlab::ConanToken do
it 'returns the encoded JWT' do
allow(SecureRandom).to receive(:uuid).and_return('u-u-i-d')
Timecop.freeze do
freeze_time do
jwt = build_jwt(access_token_id: 123, user_id: 456)
token = described_class.new(access_token_id: 123, user_id: 456)

View File

@ -34,7 +34,7 @@ RSpec.describe Gitlab::CycleAnalytics::CodeStage do
describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@ -76,7 +76,7 @@ RSpec.describe Gitlab::CycleAnalytics::CodeStage do
describe '#group_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do

View File

@ -29,7 +29,7 @@ RSpec.describe Gitlab::CycleAnalytics::IssueStage do
describe '#median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@ -65,7 +65,7 @@ RSpec.describe Gitlab::CycleAnalytics::IssueStage do
describe '#group_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@ -87,7 +87,7 @@ RSpec.describe Gitlab::CycleAnalytics::IssueStage do
describe '#group_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do

View File

@ -29,7 +29,7 @@ RSpec.describe Gitlab::CycleAnalytics::PlanStage do
describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@ -67,7 +67,7 @@ RSpec.describe Gitlab::CycleAnalytics::PlanStage do
describe '#group_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do

View File

@ -27,7 +27,7 @@ RSpec.describe Gitlab::CycleAnalytics::ReviewStage do
describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@ -70,7 +70,7 @@ RSpec.describe Gitlab::CycleAnalytics::ReviewStage do
describe '#group_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do

View File

@ -231,7 +231,7 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
context 'when `from` and `to` are within a day' do
it 'returns the number of deployments made on that day' do
Timecop.freeze(Time.now) do
freeze_time do
create(:deployment, :success, project: project)
options[:from] = options[:to] = Time.now

View File

@ -32,7 +32,7 @@ RSpec.describe Gitlab::CycleAnalytics::StagingStage do
describe '#project_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@ -79,7 +79,7 @@ RSpec.describe Gitlab::CycleAnalytics::StagingStage do
describe '#group_median' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do

View File

@ -37,7 +37,7 @@ RSpec.describe Gitlab::CycleAnalytics::TestStage do
end
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'counts median from issues with metrics' do

View File

@ -86,7 +86,7 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
let!(:id3) { create(:user).id }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
before do

View File

@ -7,7 +7,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
describe '#loaded?' do
it 'is `true` when it was loaded recently' do
Timecop.freeze do
freeze_time do
allow(access).to receive(:loaded_at).and_return(5.minutes.ago)
expect(access).to be_loaded
@ -19,7 +19,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'is `false` when there the result was loaded a long time ago' do
Timecop.freeze do
freeze_time do
allow(access).to receive(:loaded_at).and_return(2.weeks.ago)
expect(access).not_to be_loaded
@ -70,7 +70,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'stores the result in redis' do
Timecop.freeze do
freeze_time do
fake_cache = double
expect(fake_cache).to receive(:store).with(true, nil, Time.now)
expect(access).to receive(:cache).and_return(fake_cache)
@ -118,7 +118,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'does not load from the webservice' do
Timecop.freeze do
freeze_time do
expect(fake_cache).to receive(:load).and_return([true, nil, Time.now])
expect(access).to receive(:load_from_cache).and_call_original
@ -129,7 +129,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'loads from the webservice when the cached result was too old' do
Timecop.freeze do
freeze_time do
expect(fake_cache).to receive(:load).and_return([true, nil, 2.days.ago])
expect(access).to receive(:load_from_cache).and_call_original

View File

@ -22,7 +22,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Cache, :clean_gitlab_redis_cache d
describe '#load' do
it 'reads stored info from redis' do
Timecop.freeze do
freeze_time do
set_in_redis(:access, false)
set_in_redis(:reason, 'Access denied for now')
set_in_redis(:refreshed_at, Time.now)
@ -38,7 +38,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Cache, :clean_gitlab_redis_cache d
describe '#store' do
it 'sets the values in redis' do
Timecop.freeze do
freeze_time do
cache.store(true, 'the reason', Time.now)
expect(read_from_redis(:access)).to eq('true')

View File

@ -38,7 +38,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelLinksImporter do
.to receive(:find_target_id)
.and_return(1)
Timecop.freeze do
freeze_time do
expect(Gitlab::Database)
.to receive(:bulk_insert)
.with(

View File

@ -85,13 +85,13 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_red
end
it 'includes the created timestamp' do
Timecop.freeze do
freeze_time do
expect(label_hash[:created_at]).to eq(Time.zone.now)
end
end
it 'includes the updated timestamp' do
Timecop.freeze do
freeze_time do
expect(label_hash[:updated_at]).to eq(Time.zone.now)
end
end

View File

@ -164,7 +164,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
.to receive(:increment)
.and_call_original
Timecop.freeze do
freeze_time do
importer.update_repository
expect(project.last_repository_updated_at).to be_like_time(Time.zone.now)

View File

@ -261,7 +261,7 @@ RSpec.describe Gitlab::GithubImport::Importer::RepositoryImporter do
describe '#update_clone_time' do
it 'sets the timestamp for when the cloning process finished' do
Timecop.freeze do
freeze_time do
expect(project)
.to receive(:update_column)
.with(:last_repository_updated_at, Time.zone.now)

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'timecop'
RSpec.describe Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription do
describe '#to_s' do
@ -50,7 +49,7 @@ RSpec.describe Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription d
let(:created_at) { nil }
it 'description contains current time in UTC' do
Timecop.freeze do
freeze_time do
now = Time.current.utc.strftime('%d %B %Y, %-l:%M%p (%Z)')
expect(to_s).to include(

View File

@ -8,7 +8,7 @@ RSpec.describe Gitlab::LogTimestampFormatter do
let(:formatted_timestamp) { Time.now.utc.iso8601(3) }
it 'logs the timestamp in UTC and ISO8601.3 format' do
Timecop.freeze(Time.now) do
freeze_time do
expect(subject.call('', Time.now, '', '')).to include formatted_timestamp
end
end

View File

@ -6,11 +6,12 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
include Gitlab::Routing.url_helpers
describe '#metrics_regex' do
let(:environment_id) { 1 }
let(:url_params) do
[
'foo',
'bar',
1,
environment_id,
{
start: '2019-08-02T05:43:09.000Z',
dashboard: 'config/prometheus/common_metrics.yml',
@ -33,12 +34,42 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
subject { described_class.metrics_regex }
context 'for metrics route' do
context 'for /-/environments/:environment_id/metrics route' do
let(:url) { metrics_namespace_project_environment_url(*url_params) }
it_behaves_like 'regex which matches url when expected'
end
context 'for /-/metrics?environment=:environment_id route' do
let(:url) { namespace_project_metrics_dashboard_url(*url_params) }
let(:url_params) do
[
'namespace1',
'project1',
{
environment: environment_id,
start: '2019-08-02T05:43:09.000Z',
dashboard: 'config/prometheus/common_metrics.yml',
group: 'awesome group',
anchor: 'title'
}
]
end
let(:expected_params) do
{
'url' => url,
'namespace' => 'namespace1',
'project' => 'project1',
'environment' => "#{environment_id}",
'query' => "?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&environment=#{environment_id}&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z",
'anchor' => '#title'
}
end
it_behaves_like 'regex which matches url when expected'
end
context 'for metrics_dashboard route' do
let(:url) { metrics_dashboard_namespace_project_environment_url(*url_params) }
@ -47,16 +78,19 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
end
describe '#clusters_regex' do
let(:url) do
Gitlab::Routing.url_helpers.namespace_project_cluster_url(
let(:url) { Gitlab::Routing.url_helpers.namespace_project_cluster_url(*url_params) }
let(:url_params) do
[
'foo',
'bar',
'1',
group: 'Cluster Health',
title: 'Memory Usage',
y_label: 'Memory 20(GiB)',
anchor: 'title'
)
{
group: 'Cluster Health',
title: 'Memory Usage',
y_label: 'Memory 20(GiB)',
anchor: 'title'
}
]
end
let(:expected_params) do
@ -73,6 +107,27 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
subject { described_class.clusters_regex }
it_behaves_like 'regex which matches url when expected'
context 'for metrics_dashboard route' do
let(:url) do
metrics_dashboard_namespace_project_cluster_url(
*url_params, cluster_type: :project, embedded: true, format: :json
)
end
let(:expected_params) do
{
'url' => url,
'namespace' => 'foo',
'project' => 'bar',
'cluster_id' => '1',
'query' => '?cluster_type=project&embedded=true',
'anchor' => nil
}
end
it_behaves_like 'regex which matches url when expected'
end
end
describe '#grafana_regex' do
@ -103,15 +158,18 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
end
describe '#alert_regex' do
let(:url) do
Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_prometheus_alert_url(
let(:url) { Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_prometheus_alert_url(*url_params) }
let(:url_params) do
[
'foo',
'bar',
'1',
start: '2020-02-10T12:59:49.938Z',
end: '2020-02-10T20:59:49.938Z',
anchor: "anchor"
)
{
start: '2020-02-10T12:59:49.938Z',
end: '2020-02-10T20:59:49.938Z',
anchor: "anchor"
}
]
end
let(:expected_params) do
@ -128,6 +186,21 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
subject { described_class.alert_regex }
it_behaves_like 'regex which matches url when expected'
it_behaves_like 'regex which matches url when expected' do
let(:url) { Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_prometheus_alert_url(*url_params, format: :json) }
let(:expected_params) do
{
'url' => url,
'namespace' => 'foo',
'project' => 'bar',
'alert' => '1',
'query' => nil,
'anchor' => nil
}
end
end
end
describe '#build_dashboard_url' do

View File

@ -30,7 +30,7 @@ RSpec.describe Gitlab::Metrics::MethodCall do
end
around do |example|
Timecop.freeze do
freeze_time do
example.run
end
end

View File

@ -12,7 +12,7 @@ RSpec.describe Gitlab::Metrics::Samplers::RubySampler do
describe '#initialize' do
it 'sets process_start_time_seconds' do
Timecop.freeze do
freeze_time do
expect(sampler.metrics[:process_start_time_seconds].get).to eq(Time.now.to_i)
end
end

View File

@ -50,7 +50,7 @@ RSpec.describe Gitlab::PhabricatorImport::Cache::Map, :clean_gitlab_redis_cache
describe '#set_gitlab_model' do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'sets the class and id in redis with a ttl' do

View File

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Prometheus::Queries::AdditionalMetricsEnvironmentQuery do
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
include_examples 'additional metrics query' do

View File

@ -28,7 +28,7 @@ RSpec.describe Gitlab::Prometheus::Queries::ValidateQuery do
let(:error_message) { "invalid parameter 'query': 1:9: parse error: unexpected identifier \"query\"" }
it 'returns invalid' do
Timecop.freeze do
freeze_time do
stub_prometheus_query_error(
prometheus_query_with_time_url(query, Time.now),
error_message
@ -53,7 +53,7 @@ RSpec.describe Gitlab::Prometheus::Queries::ValidateQuery do
end
it 'catches exception and returns invalid' do
Timecop.freeze do
freeze_time do
expect(subject.query(query)).to eq(valid: false, error: message)
end
end

View File

@ -136,7 +136,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_with_time_url(prometheus_query, Time.now.utc) }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
context 'when request returns vector results' do
@ -195,7 +195,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_with_time_url(query, Time.now.utc) }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
context 'when request returns vector results' do
@ -228,7 +228,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_series_url('series_name', 'other_service') }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
it 'calls endpoint and returns list of series' do
@ -259,7 +259,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_range_url(prometheus_query) }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
context 'when non utc time is passed' do
@ -358,7 +358,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_url(prometheus_query) }
around do |example|
Timecop.freeze { example.run }
freeze_time { example.run }
end
context 'when response status code is 200' do

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'timecop'
RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting do
let(:fake_duplicate_job) do
@ -77,7 +76,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecut
context 'scheduled in the future' do
it 'adds the jid of the existing job to the job hash' do
Timecop.freeze do
freeze_time do
allow(fake_duplicate_job).to receive(:scheduled?).twice.and_return(true)
allow(fake_duplicate_job).to receive(:scheduled_at).and_return(Time.now + time_diff)
allow(fake_duplicate_job).to receive(:options).and_return({ including_scheduled: true })

View File

@ -15,7 +15,7 @@ RSpec.describe Gitlab::UpdatedNotesPaginator do
let(:page_1_boundary) { page_1.last.updated_at + NotesFinder::FETCH_OVERLAP }
around do |example|
Timecop.freeze do
freeze_time do
example.run
end
end

View File

@ -52,7 +52,7 @@ RSpec.describe MigrateIssueTrackersData do
it 'schedules background migrations at correct time' do
Sidekiq::Testing.fake! do
Timecop.freeze do
freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_service.id)

View File

@ -19,7 +19,7 @@ RSpec.describe BackfillProjectSettings, :sidekiq, schema: 20200114113341 do
it 'schedules BackfillProjectSettings background jobs' do
Sidekiq::Testing.fake! do
Timecop.freeze do
freeze_time do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)

View File

@ -53,7 +53,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
describe "#up" do
it 'schedules background migrations at correct time' do
Sidekiq::Testing.fake! do
Timecop.freeze do
freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_service.id)

View File

@ -27,7 +27,7 @@ RSpec.describe BackfillDeploymentClustersFromDeployments, :migration, :sidekiq,
batch_2_end = create_deployment(**deployment_data)
Sidekiq::Testing.fake! do
Timecop.freeze do
freeze_time do
migrate!
# batch 1

Some files were not shown because too many files have changed in this diff Show More