Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b2eab0d28d
commit
41bea98c57
|
|
@ -201,3 +201,9 @@ body {
|
|||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
.logged-out-marketing-header-candidate {
|
||||
--header-height: 72px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -610,6 +610,14 @@ $pagination-disabled-color: #cdcdcd;
|
|||
*/
|
||||
$status-icon-size: 22px;
|
||||
|
||||
|
||||
/*
|
||||
* Social Icons
|
||||
*/
|
||||
$twitter: #1d9bf0;
|
||||
$skype: #0078d7;
|
||||
$linkedin: #2867b2;
|
||||
|
||||
/*
|
||||
* Award emoji
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -383,3 +383,15 @@ table.u2f-registrations {
|
|||
width: 100%;
|
||||
max-width: $add-to-slack-popup-max-width;
|
||||
}
|
||||
|
||||
.skype-icon {
|
||||
color: $skype;
|
||||
}
|
||||
|
||||
.linkedin-icon {
|
||||
color: $linkedin;
|
||||
}
|
||||
|
||||
.twitter-icon {
|
||||
color: $twitter;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ module ApplicationHelper
|
|||
class_names << 'environment-logs-page' if current_controller?(:logs)
|
||||
class_names << 'with-performance-bar' if performance_bar_enabled?
|
||||
class_names << system_message_class
|
||||
class_names << marketing_header_experiment_class
|
||||
class_names
|
||||
end
|
||||
|
||||
|
|
@ -420,6 +421,16 @@ module ApplicationHelper
|
|||
def appearance
|
||||
::Appearance.current
|
||||
end
|
||||
|
||||
def marketing_header_experiment_class
|
||||
return if current_user
|
||||
|
||||
experiment(:logged_out_marketing_header, actor: nil) do |e|
|
||||
e.candidate { 'logged-out-marketing-header-candidate' }
|
||||
e.control {}
|
||||
e.run
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ApplicationHelper.prepend_mod
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
- request_link_start = '<a href="%{new_user_confirmation_path}">'.html_safe % { new_user_confirmation_path: new_user_confirmation_path }
|
||||
- request_link_end = '</a>'.html_safe
|
||||
- content_for :page_specific_javascripts do
|
||||
= render "layouts/google_tag_manager_head"
|
||||
= render "layouts/one_trust"
|
||||
= render "layouts/google_tag_manager_body"
|
||||
|
||||
.well-confirmation.gl-text-center.gl-mb-6
|
||||
%h1.gl-mt-0
|
||||
|
|
|
|||
|
|
@ -19,8 +19,16 @@
|
|||
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
|
||||
= _('Next')
|
||||
|
||||
.gl-display-none.gl-sm-display-block
|
||||
= render "layouts/nav/top_nav"
|
||||
- if current_user
|
||||
.gl-display-none.gl-sm-display-block
|
||||
= render "layouts/nav/top_nav"
|
||||
- else
|
||||
- experiment(:logged_out_marketing_header, actor: nil) do |e|
|
||||
- e.candidate do
|
||||
= render 'layouts/header/marketing_links'
|
||||
- e.control do
|
||||
.gl-display-none.gl-sm-display-block
|
||||
= render "layouts/nav/top_nav"
|
||||
|
||||
.navbar-collapse.collapse
|
||||
%ul.nav.navbar-nav
|
||||
|
|
@ -104,6 +112,12 @@
|
|||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu.dropdown-menu-right
|
||||
= render 'layouts/header/help_dropdown'
|
||||
- unless current_user
|
||||
- experiment(:logged_out_marketing_header, actor: nil) do |e|
|
||||
- e.candidate do
|
||||
%li.nav-item.gl-display-none.gl-sm-display-block
|
||||
= render "layouts/nav/top_nav"
|
||||
- e.control {}
|
||||
- if header_link?(:user_dropdown)
|
||||
%li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { track_label: "profile_dropdown", track_action: "click_dropdown", track_value: "", qa_selector: 'user_menu' }, class: ('mr-0' if has_impersonation_link) }
|
||||
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
|
||||
|
|
@ -117,10 +131,15 @@
|
|||
= link_to admin_impersonation_path, class: 'nav-link impersonation-btn', method: :delete, title: _('Stop impersonation'), aria: { label: _('Stop impersonation') }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body', qa_selector: 'stop_impersonation_link' } do
|
||||
= sprite_icon('incognito', size: 18)
|
||||
- if header_link?(:sign_in)
|
||||
%li.nav-item
|
||||
%div
|
||||
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
|
||||
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
|
||||
- experiment(:logged_out_marketing_header, actor: nil) do |e|
|
||||
- e.candidate do
|
||||
%li.nav-item.gl-display-none.gl-sm-display-block
|
||||
= link_to _('Sign up now'), new_user_registration_path, class: 'gl-button btn btn-default btn-sign-in'
|
||||
%li.nav-item.gl-display-none.gl-sm-display-block
|
||||
= link_to _('Login'), new_session_path(:user, redirect_to_referer: 'yes')
|
||||
= render 'layouts/header/sign_in_register_button', class: 'gl-sm-display-none'
|
||||
- e.control do
|
||||
= render 'layouts/header/sign_in_register_button'
|
||||
|
||||
%button.navbar-toggler.d-block.d-sm-none{ type: 'button', class: 'gl-border-none!', data: { testid: 'top-nav-responsive-toggle', qa_selector: 'mobile_navbar_button' } }
|
||||
%span.sr-only= _('Toggle navigation')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
%ul.nav.navbar-sub-nav.gl-display-none.gl-lg-display-flex.gl-align-items-center
|
||||
%li.dropdown.gl-mr-3
|
||||
%button{ type: "button", data: { toggle: "dropdown" } }
|
||||
= s_('LoggedOutMarketingHeader|About GitLab')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
.dropdown-menu
|
||||
%ul
|
||||
%li
|
||||
= link_to 'https://about.gitlab.com/stages-devops-lifecycle/' do
|
||||
= s_('LoggedOutMarketingHeader|GitLab: the DevOps platform')
|
||||
%li
|
||||
= link_to explore_root_path do
|
||||
= s_('LoggedOutMarketingHeader|Explore GitLab')
|
||||
%li
|
||||
= link_to 'https://about.gitlab.com/install/' do
|
||||
= s_('LoggedOutMarketingHeader|Install GitLab')
|
||||
%li
|
||||
= link_to 'https://about.gitlab.com/is-it-any-good/' do
|
||||
= s_('LoggedOutMarketingHeader|How GitLab compares')
|
||||
%li
|
||||
= link_to 'https://about.gitlab.com/get-started/' do
|
||||
= s_('LoggedOutMarketingHeader|Get started')
|
||||
%li
|
||||
= link_to 'https://docs.gitlab.com/' do
|
||||
= s_('LoggedOutMarketingHeader|GitLab docs')
|
||||
%li
|
||||
= link_to 'https://about.gitlab.com/learn/' do
|
||||
= s_('LoggedOutMarketingHeader|GitLab Learn')
|
||||
%li.gl-mr-3
|
||||
= link_to 'https://about.gitlab.com/pricing/' do
|
||||
= s_('LoggedOutMarketingHeader|Pricing')
|
||||
%li.gl-mr-3
|
||||
= link_to 'https://about.gitlab.com/sales/' do
|
||||
= s_('LoggedOutMarketingHeader|Talk to an expert')
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
- top_class = local_assigns.fetch(:class, nil)
|
||||
|
||||
%li.nav-item{ class: top_class }
|
||||
%div
|
||||
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
|
||||
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
|
||||
|
|
@ -98,15 +98,15 @@
|
|||
- unless @user.skype.blank?
|
||||
= render 'middle_dot_divider' do
|
||||
= link_to "skype:#{@user.skype}", class: 'gl-hover-text-decoration-none', title: "Skype" do
|
||||
= sprite_icon('skype')
|
||||
= sprite_icon('skype', css_class: 'skype-icon')
|
||||
- unless @user.linkedin.blank?
|
||||
= render 'middle_dot_divider' do
|
||||
= link_to linkedin_url(@user), class: 'gl-hover-text-decoration-none', title: "LinkedIn", target: '_blank', rel: 'noopener noreferrer nofollow' do
|
||||
= sprite_icon('linkedin')
|
||||
= sprite_icon('linkedin', css_class: 'linkedin-icon')
|
||||
- unless @user.twitter.blank?
|
||||
= render 'middle_dot_divider', breakpoint: 'sm' do
|
||||
= link_to twitter_url(@user), class: 'gl-hover-text-decoration-none', title: "Twitter", target: '_blank', rel: 'noopener noreferrer nofollow' do
|
||||
= sprite_icon('twitter')
|
||||
= sprite_icon('twitter', css_class: 'twitter-icon')
|
||||
- unless @user.website_url.blank?
|
||||
= render 'middle_dot_divider', stacking: true do
|
||||
- if Feature.enabled?(:security_auto_fix) && @user.bot?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: logged_out_marketing_header
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76076
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348525
|
||||
milestone: '14.7'
|
||||
type: experiment
|
||||
group: group::activation
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
stage: Manage
|
||||
group: Authentication & Authorization
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Project access tokens API **(FREE)**
|
||||
|
||||
You can read more about [project access tokens](../user/project/settings/project_access_tokens.md).
|
||||
|
||||
## List project access tokens
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
|
||||
|
||||
Get a list of [project access tokens](../user/project/settings/project_access_tokens.md).
|
||||
|
||||
```plaintext
|
||||
GET projects/:id/access_tokens
|
||||
```
|
||||
|
||||
| Attribute | Type | required | Description |
|
||||
|-----------|---------|----------|---------------------|
|
||||
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
|
||||
|
||||
```shell
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
|
||||
```
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"user_id" : 141,
|
||||
"scopes" : [
|
||||
"api"
|
||||
],
|
||||
"name" : "token",
|
||||
"expires_at" : "2021-01-31",
|
||||
"id" : 42,
|
||||
"active" : true,
|
||||
"created_at" : "2021-01-20T22:11:48.151Z",
|
||||
"revoked" : false,
|
||||
"access_level": 40
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Create a project access token
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55408) in GitLab 13.10.
|
||||
|
||||
Create a [project access token](../user/project/settings/project_access_tokens.md).
|
||||
|
||||
```plaintext
|
||||
POST projects/:id/access_tokens
|
||||
```
|
||||
|
||||
| Attribute | Type | required | Description |
|
||||
|-----------|---------|----------|---------------------|
|
||||
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
|
||||
| `name` | String | yes | The name of the project access token |
|
||||
| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
|
||||
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
|
||||
| `expires_at` | Date | no | The token expires at midnight UTC on that date |
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
--header "Content-Type:application/json" \
|
||||
--data '{ "name":"test_token", "scopes":["api", "read_repository"], "expires_at":"2021-01-31", "access_level": 30 }' \
|
||||
"https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"scopes" : [
|
||||
"api",
|
||||
"read_repository"
|
||||
],
|
||||
"active" : true,
|
||||
"name" : "test",
|
||||
"revoked" : false,
|
||||
"created_at" : "2021-01-21T19:35:37.921Z",
|
||||
"user_id" : 166,
|
||||
"id" : 58,
|
||||
"expires_at" : "2021-01-31",
|
||||
"token" : "D4y...Wzr",
|
||||
"access_level": 30
|
||||
}
|
||||
```
|
||||
|
||||
## Revoke a project access token
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
|
||||
|
||||
Revoke a [project access token](../user/project/settings/project_access_tokens.md).
|
||||
|
||||
```plaintext
|
||||
DELETE projects/:id/access_tokens/:token_id
|
||||
```
|
||||
|
||||
| Attribute | Type | required | Description |
|
||||
|-----------|---------|----------|---------------------|
|
||||
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
|
||||
| `token_id` | integer or string | yes | The ID of the project access token |
|
||||
|
||||
```shell
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>"
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
- `204: No Content` if successfully revoked.
|
||||
- `400 Bad Request` or `404 Not Found` if not revoked successfully.
|
||||
|
|
@ -1,112 +1,9 @@
|
|||
---
|
||||
stage: Manage
|
||||
group: Authentication & Authorization
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
redirect_to: 'project_access_tokens.md'
|
||||
remove_date: '2022-04-06'
|
||||
---
|
||||
|
||||
# Project access tokens API **(FREE)**
|
||||
This document was moved to [another location](project_access_tokens.md).
|
||||
|
||||
You can read more about [project access tokens](../user/project/settings/project_access_tokens.md).
|
||||
|
||||
## List project access tokens
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
|
||||
|
||||
Get a list of project access tokens.
|
||||
|
||||
```plaintext
|
||||
GET projects/:id/access_tokens
|
||||
```
|
||||
|
||||
| Attribute | Type | required | Description |
|
||||
|-----------|---------|----------|---------------------|
|
||||
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
|
||||
|
||||
```shell
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
|
||||
```
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"user_id" : 141,
|
||||
"scopes" : [
|
||||
"api"
|
||||
],
|
||||
"name" : "token",
|
||||
"expires_at" : "2021-01-31",
|
||||
"id" : 42,
|
||||
"active" : true,
|
||||
"created_at" : "2021-01-20T22:11:48.151Z",
|
||||
"revoked" : false,
|
||||
"access_level": 40
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Create a project access token
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55408) in GitLab 13.10.
|
||||
|
||||
Create a project access token.
|
||||
|
||||
```plaintext
|
||||
POST projects/:id/access_tokens
|
||||
```
|
||||
|
||||
| Attribute | Type | required | Description |
|
||||
|-----------|---------|----------|---------------------|
|
||||
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
|
||||
| `name` | String | yes | The name of the project access token |
|
||||
| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
|
||||
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
|
||||
| `expires_at` | Date | no | The token expires at midnight UTC on that date |
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
--header "Content-Type:application/json" \
|
||||
--data '{ "name":"test_token", "scopes":["api", "read_repository"], "expires_at":"2021-01-31", "access_level": 30 }' \
|
||||
"https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens"
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"scopes" : [
|
||||
"api",
|
||||
"read_repository"
|
||||
],
|
||||
"active" : true,
|
||||
"name" : "test",
|
||||
"revoked" : false,
|
||||
"created_at" : "2021-01-21T19:35:37.921Z",
|
||||
"user_id" : 166,
|
||||
"id" : 58,
|
||||
"expires_at" : "2021-01-31",
|
||||
"token" : "D4y...Wzr",
|
||||
"access_level": 30
|
||||
}
|
||||
```
|
||||
|
||||
## Revoke a project access token
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9.
|
||||
|
||||
Revoke a project access token.
|
||||
|
||||
```plaintext
|
||||
DELETE projects/:id/access_tokens/:token_id
|
||||
```
|
||||
|
||||
| Attribute | Type | required | Description |
|
||||
|-----------|---------|----------|---------------------|
|
||||
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
|
||||
| `token_id` | integer or string | yes | The ID of the project access token |
|
||||
|
||||
```shell
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/<project_id>/access_tokens/<token_id>"
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
- `204: No Content` if successfully revoked.
|
||||
- `400 Bad Request` or `404 Not Found` if not revoked successfully.
|
||||
<!-- This redirect file can be deleted after <2022-04-06>. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
|
||||
|
|
|
|||
|
|
@ -21429,6 +21429,39 @@ msgstr ""
|
|||
msgid "Locks the discussion."
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|About GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|Explore GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|Get started"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|GitLab Learn"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|GitLab docs"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|How GitLab compares"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|Install GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|Pricing"
|
||||
msgstr ""
|
||||
|
||||
msgid "LoggedOutMarketingHeader|Talk to an expert"
|
||||
msgstr ""
|
||||
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Login with smartcard"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -32902,6 +32935,9 @@ msgstr ""
|
|||
msgid "Sign up"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sign up now"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sign up was successful! Please confirm your email to sign in."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -40776,7 +40812,7 @@ msgstr ""
|
|||
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
|
||||
msgstr ""
|
||||
|
||||
msgid "You have successfully purchased %{product}. You'll receive a receipt by email."
|
||||
msgid "You have successfully purchased %{product}. You'll receive a receipt by email. Your purchase may take a minute to sync, so refresh the page if you don't see it yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../migration_helpers'
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module Migration
|
||||
# Cop that prevents usage of `enable_lock_retries!` within the `disable_ddl_transaction!` method.
|
||||
class PreventGlobalEnableLockRetriesWithDisableDdlTransaction < RuboCop::Cop::Cop
|
||||
include MigrationHelpers
|
||||
|
||||
MSG = '`enable_lock_retries!` cannot be used with `disable_ddl_transaction!`. Use the `with_lock_retries` helper method to define retriable code blocks.'
|
||||
|
||||
def_node_matcher :enable_lock_retries?, <<~PATTERN
|
||||
(send _ :enable_lock_retries! ...)
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :disable_ddl_transaction?, <<~PATTERN
|
||||
(send _ :disable_ddl_transaction! ...)
|
||||
PATTERN
|
||||
|
||||
def on_begin(node)
|
||||
return unless in_migration?(node)
|
||||
|
||||
has_enable_lock_retries = false
|
||||
has_disable_ddl_transaction = false
|
||||
|
||||
node.each_descendant(:send) do |send_node|
|
||||
has_enable_lock_retries = true if enable_lock_retries?(send_node)
|
||||
has_disable_ddl_transaction = true if disable_ddl_transaction?(send_node)
|
||||
|
||||
if has_enable_lock_retries && has_disable_ddl_transaction
|
||||
add_offense(send_node, message: MSG)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe 'User sees experimental lmarketing header' do
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
|
||||
context 'when not logged in' do
|
||||
context 'when experiment candidate' do
|
||||
it 'shows marketing header links', :aggregate_failures do
|
||||
stub_experiments(logged_out_marketing_header: :candidate)
|
||||
|
||||
visit project_path(project)
|
||||
|
||||
expect(page).to have_text "About GitLab"
|
||||
expect(page).to have_text "Pricing"
|
||||
expect(page).to have_text "Talk to an expert"
|
||||
expect(page).to have_text "Sign up now"
|
||||
expect(page).to have_text "Login"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when experiment control' do
|
||||
it 'does not show marketing header links', :aggregate_failures do
|
||||
stub_experiments(logged_out_marketing_header: :control)
|
||||
|
||||
visit project_path(project)
|
||||
|
||||
expect(page).not_to have_text "About GitLab"
|
||||
expect(page).not_to have_text "Pricing"
|
||||
expect(page).not_to have_text "Talk to an expert"
|
||||
expect(page).not_to have_text "Sign up now"
|
||||
expect(page).not_to have_text "Login"
|
||||
expect(page).to have_text "Sign in / Register"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in' do
|
||||
it 'does not show marketing header links', :aggregate_failures do
|
||||
sign_in(create(:user))
|
||||
|
||||
stub_experiments(logged_out_marketing_header: :candidate)
|
||||
|
||||
visit project_path(project)
|
||||
|
||||
expect(page).not_to have_text "About GitLab"
|
||||
expect(page).not_to have_text "Pricing"
|
||||
expect(page).not_to have_text "Talk to an expert"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -477,4 +477,38 @@ RSpec.describe ApplicationHelper do
|
|||
expect(helper).to have_received(:form_for).with(user, expected_options)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#page_class' do
|
||||
context 'when logged_out_marketing_header experiment is enabled' do
|
||||
let_it_be(:expected_class) { 'logged-out-marketing-header-candidate' }
|
||||
|
||||
let(:current_user) { nil }
|
||||
let(:variant) { :candidate }
|
||||
|
||||
subject do
|
||||
helper.page_class.flatten
|
||||
end
|
||||
|
||||
before do
|
||||
stub_experiments(logged_out_marketing_header: variant)
|
||||
allow(helper).to receive(:current_user) { current_user }
|
||||
end
|
||||
|
||||
context 'when candidate' do
|
||||
it { is_expected.to include(expected_class) }
|
||||
end
|
||||
|
||||
context 'when control' do
|
||||
let(:variant) { :control }
|
||||
|
||||
it { is_expected.not_to include(expected_class) }
|
||||
end
|
||||
|
||||
context 'when a user is logged in' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it { is_expected.not_to include(expected_class) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/migration/prevent_global_enable_lock_retries_with_disable_ddl_transaction'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Migration::PreventGlobalEnableLockRetriesWithDisableDdlTransaction do
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context 'when in migration' do
|
||||
before do
|
||||
allow(cop).to receive(:in_migration?).and_return(true)
|
||||
end
|
||||
|
||||
it 'registers an offense when `enable_lock_retries` and `disable_ddl_transaction` is used together' do
|
||||
code = <<~RUBY
|
||||
class SomeMigration < ActiveRecord::Migration[6.0]
|
||||
enable_lock_retries!
|
||||
disable_ddl_transaction!
|
||||
end
|
||||
RUBY
|
||||
|
||||
expect_offense(<<~RUBY, node: code, msg: described_class::MSG)
|
||||
class SomeMigration < ActiveRecord::Migration[6.0]
|
||||
enable_lock_retries!
|
||||
disable_ddl_transaction!
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^ %{msg}
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it 'registers no offense when `enable_lock_retries!` is used' do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class SomeMigration < ActiveRecord::Migration[6.0]
|
||||
enable_lock_retries!
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it 'registers no offense when `disable_ddl_transaction!` is used' do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class SomeMigration < ActiveRecord::Migration[6.0]
|
||||
disable_ddl_transaction!
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context 'when outside of migration' do
|
||||
it 'registers no offense' do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class SomeMigration
|
||||
enable_lock_retries!
|
||||
disable_ddl_transaction!
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue