Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-01-31 03:08:13 +00:00
parent 13ddda5208
commit 25805c1633
25 changed files with 376 additions and 38 deletions

View File

@ -167,7 +167,6 @@ variables:
RETRY_FAILED_TESTS_IN_NEW_PROCESS: "true"
# Run with decomposed databases by default
DECOMPOSED_DB: "true"
GITLAB_ALLOW_SEPARATE_CI_DATABASE: "true"
DOCS_REVIEW_APPS_DOMAIN: "docs.gitlab-review.app"
DOCS_GITLAB_REPO_SUFFIX: "ee"

View File

@ -47,10 +47,9 @@ cache-assets:test as-if-foss:
- .as-if-foss
cache-assets:production:
extends: .cache-assets-base
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
extends:
- .cache-assets-base
- .production
packages-cleanup:
extends:

View File

@ -33,10 +33,8 @@
compile-production-assets:
extends:
- .compile-assets-base
- .production
- .frontend:rules:compile-production-assets
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
artifacts:
name: webpack-report
expire_in: 31d

View File

@ -21,6 +21,12 @@
- !reference [.default-utils-before_script, before_script]
- source scripts/prepare_build.sh
.production:
variables:
RAILS_ENV: "production"
NODE_ENV: "production"
GITLAB_ALLOW_SEPARATE_CI_DATABASE: "true"
.ruby-gems-cache: &ruby-gems-cache
key: "ruby-gems-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}"
paths:

View File

@ -19,12 +19,11 @@
memory-on-boot:
extends:
- .only-code-memory-job-base
- .production
- .use-pg12
stage: test
needs: ["setup-test-env", "compile-test-assets"]
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
SETUP_DB: "true"
MEMORY_ON_BOOT_FILE_PREFIX: "tmp/memory_on_boot_"
TEST_COUNT: 5

View File

@ -198,7 +198,7 @@ gem 'asciidoctor-kroki', '~> 0.7.0', require: false
gem 'rouge', '~> 3.30.0'
gem 'truncato', '~> 0.7.12'
gem 'bootstrap_form', '~> 4.2.0'
gem 'nokogiri', '~> 1.14.0'
gem 'nokogiri', '~> 1.14.1'
# Calendar rendering
gem 'icalendar'

View File

@ -364,17 +364,17 @@
{"name":"nio4r","version":"2.5.8","platform":"java","checksum":"b2b1800f6bf7ce4b797ca8b639ad278a99c9c904fb087a91d944f38e4bd71401"},
{"name":"nio4r","version":"2.5.8","platform":"ruby","checksum":"3becb4ad95ab8ac0a9bd2e1b16466869402be62848082bf6329ae9091f276676"},
{"name":"no_proxy_fix","version":"0.1.2","platform":"ruby","checksum":"4e9b4c31bb146de7fcf347dc1087bb13ac2039b56d50aa019e61036256abcd00"},
{"name":"nokogiri","version":"1.14.0","platform":"aarch64-linux","checksum":"c87564f5f8fbfb72fbcb7ed9781f6472ceabe2f288ede6b9c37071dc32320ba6"},
{"name":"nokogiri","version":"1.14.0","platform":"arm-linux","checksum":"33617e8a94993b8130a50bd59d6141a8d4d2aa4d4053f5c7874c71608e6e6dcc"},
{"name":"nokogiri","version":"1.14.0","platform":"arm64-darwin","checksum":"5c0cd4eeb8501526e7e2aaba93b60ebf3dda37bfda665691196d4e9bb87adb1a"},
{"name":"nokogiri","version":"1.14.0","platform":"java","checksum":"772936bf635b33b99bc89828de8e7077de47009638fe5ff11795f8b1d578465c"},
{"name":"nokogiri","version":"1.14.0","platform":"ruby","checksum":"55ca6e87ae85e944a5901dd5a6cacbb961eaaf8b8dd3901b57475665396914bb"},
{"name":"nokogiri","version":"1.14.0","platform":"x64-mingw-ucrt","checksum":"ee11c092b2cf2b137e71f623746162c578b53483dccf4c6209c80f5ba47927fe"},
{"name":"nokogiri","version":"1.14.0","platform":"x64-mingw32","checksum":"9b91eede6155eb8891d7d95d8087d514f3007dd19813982104ed77452a2a7ace"},
{"name":"nokogiri","version":"1.14.0","platform":"x86-linux","checksum":"649019d961b0ea8aee1bc8aa2573ab8ffb77d3f5e9c333aa2462a79fc56745fc"},
{"name":"nokogiri","version":"1.14.0","platform":"x86-mingw32","checksum":"40985fc46315ea3d33ed900a649c0bb77484035ea882b7c9e55aef436b1958a8"},
{"name":"nokogiri","version":"1.14.0","platform":"x86_64-darwin","checksum":"5d328c0d0c5f6f37a26c75b0282f9014c9686d4c10578ec8dfbbfcbea7da8b95"},
{"name":"nokogiri","version":"1.14.0","platform":"x86_64-linux","checksum":"faa88b2bca46adaa3420c6e27eb8eb71f5b8d9f454ed7488a194a00c5ef52fbe"},
{"name":"nokogiri","version":"1.14.1","platform":"aarch64-linux","checksum":"99594e8b94f576644ac640a223d74c79e840218948e963aa635f0254927bff10"},
{"name":"nokogiri","version":"1.14.1","platform":"arm-linux","checksum":"1dc9b7821e1fa1f3fda40659662e51a4b3692acc4ee6342ee34a6a537fc1d5d8"},
{"name":"nokogiri","version":"1.14.1","platform":"arm64-darwin","checksum":"1a693df86da8c4c97b01d614470f9c3e10b9c755de8803fbfcfffe0f9dff522a"},
{"name":"nokogiri","version":"1.14.1","platform":"java","checksum":"c1f87a8f7bc56028deb2aecbb29e9b318405f7c468b29047aede78b41bc735a2"},
{"name":"nokogiri","version":"1.14.1","platform":"ruby","checksum":"b2db3af7769c29cd77d5f39cd3d0b65ab10975bdecf04be71d683f9c9abe2663"},
{"name":"nokogiri","version":"1.14.1","platform":"x64-mingw-ucrt","checksum":"2463a1ae0be5f06a10f3f3b374c2b743bff6280db993d488511a19bb7bc7cb7c"},
{"name":"nokogiri","version":"1.14.1","platform":"x64-mingw32","checksum":"f3a2b0ceedf51d776b39dc759ce191a4df842d7d4f5900c64f33d4753db39877"},
{"name":"nokogiri","version":"1.14.1","platform":"x86-linux","checksum":"f395d6c28c822b0877cfb0c71781f05243c034b4823359ab25b3288a73b9fc82"},
{"name":"nokogiri","version":"1.14.1","platform":"x86-mingw32","checksum":"be34b32fe74e82bffca5b1f3df8727c8fdc828762b6dddab53a11cd8f8515785"},
{"name":"nokogiri","version":"1.14.1","platform":"x86_64-darwin","checksum":"9b14091f77086c4f0f09451ba3acd1b5f7e0076fb34fc536682170fa9f1a5074"},
{"name":"nokogiri","version":"1.14.1","platform":"x86_64-linux","checksum":"21d234c51582b292e2e1e02e6c30eea9188894348985d6910aa8e993749c0aff"},
{"name":"notiffany","version":"0.1.3","platform":"ruby","checksum":"d37669605b7f8dcb04e004e6373e2a780b98c776f8eb503ac9578557d7808738"},
{"name":"numerizer","version":"0.2.0","platform":"ruby","checksum":"e58076d5ee5370417b7e52d9cb25836d62acd1b8d9a194c308707986c1705d7b"},
{"name":"oauth","version":"0.5.6","platform":"ruby","checksum":"4085fe28e0c5e2434135e00a6555294fd2a4ff96a98d1bdecdcd619fc6368dff"},

View File

@ -942,7 +942,7 @@ GEM
netrc (0.11.0)
nio4r (2.5.8)
no_proxy_fix (0.1.2)
nokogiri (1.14.0)
nokogiri (1.14.1)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
notiffany (0.1.3)
@ -1742,7 +1742,7 @@ DEPENDENCIES
multi_json (~> 1.14.1)
net-ldap (~> 0.17.1)
net-ntp
nokogiri (~> 1.14.0)
nokogiri (~> 1.14.1)
oauth2 (~> 2.0)
octokit (~> 4.15)
ohai (~> 16.10)

View File

@ -262,9 +262,11 @@ module UsersHelper
if with_schema_markup
job_title = '<span itemprop="jobTitle">'.html_safe + job_title + "</span>".html_safe
organization = '<span itemprop="worksFor">'.html_safe + organization + "</span>".html_safe
end
html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization }
html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization }
else
s_('Profile|%{job_title} at %{organization}') % { job_title: job_title, organization: organization }
end
end
def user_table_headers

View File

@ -10878,6 +10878,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="boardepicancestorsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="boardepicancestorsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="boardepicancestorsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="boardepicancestorsor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="boardepicancestorssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="boardepicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="boardepicancestorsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@ -10916,6 +10917,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="boardepicchildrenmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="boardepicchildrenmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="boardepicchildrennot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="boardepicchildrenor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="boardepicchildrensearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="boardepicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="boardepicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@ -12947,6 +12949,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="epicancestorsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="epicancestorsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="epicancestorsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="epicancestorsor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="epicancestorssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="epicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="epicancestorsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@ -12985,6 +12988,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="epicchildrenmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="epicchildrenmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="epicchildrennot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="epicchildrenor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="epicchildrensearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="epicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="epicchildrenstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@ -14004,6 +14008,7 @@ Returns [`Epic`](#epic).
| <a id="groupepicmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="groupepicmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="groupepicnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="groupepicor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="groupepicsearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="groupepicsort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="groupepicstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@ -14054,6 +14059,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupepicsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="groupepicsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="groupepicsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="groupepicsor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="groupepicssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="groupepicssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="groupepicsstartdate"></a>`startDate` **{warning-solid}** | [`Time`](#time) | **Deprecated** in 13.5. Use timeframe.start. |
@ -25444,6 +25450,14 @@ A time-frame defined as a closed inclusive range of two dates.
| <a id="timeframeend"></a>`end` | [`Date!`](#date) | End of the range. |
| <a id="timeframestart"></a>`start` | [`Date!`](#date) | Start of the range. |
### `UnionedEpicFilterInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="unionedepicfilterinputlabelname"></a>`labelName` | [`[String!]`](#string) | Filters epics that have at least one of the given labels. Ignored unless `or_issuable_queries` flag is enabled. |
### `UnionedIssueFilterInput`
#### Arguments

View File

@ -25,8 +25,7 @@ Only three directives are applicable for the `Strict-Transport-Security` header.
Note that invalid directives, or the `Strict-Transport-Security` header appearing more than once (if the values are
different) is considered invalid.
Prior to adding to this security configuration to your website, it is recommended you review the hstspreload.org
[Deployment Recommendations](https://hstspreload.org/#deployment-recommendations).
Prior to adding to this security configuration to your website, it is recommended you review the hstspreload.org [Deployment Recommendations](https://hstspreload.org/#deployment-recommendations).
## Details

View File

@ -8,12 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Description
A `Content-Security-Policy` (CSP) was identified on the target site. CSP can aid in hardening
a website against various client side attacks such as Cross-Site Scripting (XSS).
A missing or invalid `Content-Security-Policy` (CSP) was identified on the target site. CSP can aid in
hardening a website against various client side attacks such as Cross-Site Scripting (XSS).
## Remediation
Follow the recommendations to determine if any actions are necessary to harden this `Content-Security-Policy`.
If the target site is missing a CSP, please investigate the relevant URLs for enabling CSP. Otherwise,
follow the recommendations to determine if any actions are necessary.
## Details

View File

@ -126,7 +126,7 @@ The [DAST browser-based crawler](../browser_based.md) provides a number of vulne
| [798.94](798.94.md) | Exposure of confidential secret or token Private Key | High | Passive |
| [798.95](798.95.md) | Exposure of confidential secret or token Pulumi API token | High | Passive |
| [798.96](798.96.md) | Exposure of confidential secret or token PyPI upload token | High | Passive |
| [798.97](798.97.md) | Exposure of confidential secret or token RubyGem API token | High | Passive |
| [798.97](798.97.md) | Exposure of confidential secret or token RubyGems API token | High | Passive |
| [798.98](798.98.md) | Exposure of confidential secret or token RapidAPI Access Token | High | Passive |
| [798.99](798.99.md) | Exposure of confidential secret or token Sendbird Access ID | High | Passive |
| [798.100](798.100.md) | Exposure of confidential secret or token Sendbird Access Token | High | Passive |

9
qa/lib/slack.rb Normal file
View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
require 'chemlab/library'
module Slack
include Chemlab::Library
self.base_url = 'https://slack.com'
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
module Slack
module Mixins
module Browser
def browser
::Chemlab.configuration.browser.session.engine
end
end
end
end

View File

@ -0,0 +1,52 @@
# frozen_string_literal: true
module Slack
module Mixins
module GitlabApp
# @param [QA::Resource::Project] project
# @param [String] channel
# @param [String] title
# @param [String] description
def create_issue(project, channel:, title:, description:)
lines = [
"/staging-gitlab #{project.path_with_namespace} issue new #{title}",
description
]
send_message_to_channel(lines, channel: channel)
end
# @param [QA::Resource::Project] project
# @param [QA::Resource::Project] target
# @param [String] id
# @param [String] channel
def move_issue(project, target, id:, channel:)
line = "/staging-gitlab #{project.path_with_namespace} issue move #{id} to #{target.path_with_namespace}"
send_message_to_channel([line], channel: channel)
end
# @param [QA::Resource::Project] project
# @param [String] id
# @param [String] channel
def show_issue(project, id:, channel:)
send_message_to_channel(["/staging-gitlab #{project.path_with_namespace} issue show #{id}"], channel: channel)
end
# @param [QA::Resource::Project] project
# @param [String] id
# @param [String] channel
def close_issue(project, id:, channel:)
send_message_to_channel(["/staging-gitlab #{project.path_with_namespace} issue close #{id}"], channel: channel)
end
# @param [QA::Resource::Project] project
# @param [String] channel
# @param [String] id
# @param [String] comment
def comment_on_issue(project, channel:, id:, comment:)
command = "/staging-gitlab #{project.path_with_namespace} issue comment #{id}"
send_message_to_channel([command, comment], channel: channel)
end
end
end
end

68
qa/lib/slack/page/chat.rb Normal file
View File

@ -0,0 +1,68 @@
# frozen_string_literal: true
module Slack
module Page
class Chat < Chemlab::Page
include Mixins::Browser
include Mixins::GitlabApp
div :message_field, data_qa: 'message_input'
button :connect_gitlab_button, visible_text: /Connect your GitLab account/
button :skip_download_slack_button, data_qa: 'continue_in_browser'
def skip_download_screen
wait_for_text('download the Slack app')
skip_download_slack_button_element.click if skip_download_slack_button_element.exists?
end
# @param [Array<String>] lines - messages to send
# @param [String] channel to send message to
def send_message_to_channel(lines, channel:)
go_to_channel(channel)
message_field_element.focus
message_field_element.click
while line = lines.shift
browser.send_keys(line)
wait_for_text(line)
browser.send_keys([:shift, :enter]) unless lines.empty?
end
browser.send_keys(:enter)
end
def wait_for_text(line)
QA::Support::Waiter.wait_until(max_duration: 3, raise_on_failure: false) do
browser.text.include?(line)
end
end
def go_to_channel(channel)
menu_item = messages.find do |div|
div.text == channel
end
menu_item.click
end
def click_connect_account_link
divs = messages(visible_text: /connect your GitLab account/i)
el = divs.last.a(href: /staging-ref/)
el.scroll.to(:top)
el.click
end
def messages(**opts)
browser.divs(data_qa: 'virtual-list-item', **opts)
end
def gitlab_app_home
browser.divs(data_qa: 'channel_item_container').find do |el|
el.text == 'GitLab'
end
end
end
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
module Slack
module Page
class Login < Chemlab::Page
path '/workspace-signin'
text_field :workspace_field, data_qa: 'signin_domain_input'
button :continue_button, data_qa: 'submit_team_domain_button'
link :sign_in_with_password_link, data_qa: 'sign_in_password_link'
text_field :email_address_field, data_qa: 'login_email'
text_field :password_field, data_qa: 'login_password', type: 'password'
button :sign_in_button, data_qa: 'signin_button'
def sign_in
navigate_to_workspace
# sign into with password if needed
sign_in_with_password_link_element.click if sign_in_with_password_link_element.exists?
finish_sign_in
end
def navigate_to_workspace
self.workspace_field = ::QA::Runtime::Env.slack_workspace
continue_button
end
def finish_sign_in
return unless email_address_field_element.exists?
self.email_address_field = ::QA::Runtime::Env.slack_email
self.password_field = ::QA::Runtime::Env.slack_password
sign_in_button
end
end
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
module Slack
module Page
class Oauth < Chemlab::Page
button :submit_oauth, data_qa: 'oauth_submit_button'
end
end
end

View File

@ -0,0 +1,54 @@
# frozen_string_literal: true
module QA
module Flow
module Integrations
module Slack
extend self
# Need to sign in for this method
# @param [QA::Resource::Project]
def start_slack_install(project)
project.visit!
Page::Project::Menu.perform do |project_menu_page|
project_menu_page.click_project
project_menu_page.go_to_integrations_settings
end
Page::Project::Settings::Integrations.perform(&:click_slack_application_link)
EE::Page::Project::Settings::Services::Slack.perform(&:start_slack_install)
::Slack::Page::Oauth.perform(&:submit_oauth)
end
# @param [QA::Resource::Project] project
# @option [String | Nil] channel
# @return [Boolean] is this account already authorized?
def start_gitlab_connect(project, channel: nil)
::Slack::Page::Chat.perform do |chat_page|
# sometimes Slack will present a blocking page
# for downloading the app instead of using a browser
chat_page.skip_download_screen
lines = ["/staging-gitlab #{project.path_with_namespace} issue show 1"]
chat_page.send_message_to_channel(lines, channel: channel)
# The only way to know if we are authorized is to send a slash command to the channel.
# If the account / chat_name is already authorized, the Slack app will try to look up the issue
# and return a 404 because it doesn't exist
QA::Support::Waiter.wait_until(max_duration: 4, raise_on_failure: false) do
chat_page.messages.last.text =~ /connect your GitLab account|404 not found!/i
end
break(true) if chat_page.messages.last.text =~ /404 not found!/i
chat_page.click_connect_account_link
false
end
end
end
end
end
end

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
module QA
module Page
module Profile
module ChatNames
class New < Chemlab::Page
button :authorize, value: /Authorize/i
end
end
end
end
end

View File

@ -10,6 +10,7 @@ module QA
element :prometheus_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :jira_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :pipelines_email_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :gitlab_slack_application_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
end
def click_on_prometheus_integration
@ -27,6 +28,10 @@ module QA
def click_jenkins_ci_link
click_element :jenkins_link
end
def click_slack_application_link
click_element :gitlab_slack_application_link
end
end
end
end

View File

@ -104,7 +104,7 @@ module QA
# Specify the user-agent to allow challenges to be bypassed
# See https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11938
if QA::Runtime::Env.user_agent
unless QA::Runtime::Env.user_agent.blank?
capabilities['goog:chromeOptions'][:args] << "user-agent=#{QA::Runtime::Env.user_agent}"
end
@ -117,6 +117,38 @@ module QA
capabilities['goog:chromeOptions'][:args] << 'window-size=1480,2200'
end
# Slack tries to open an external URL handler
# The test needs to default the handler to always open Slack
# to prevent a blocking popup.
if QA::Runtime::Env.slack_workspace
slack_default_preference = {
'protocol_handler' => {
'allowed_origin_protocol_pairs' => {
"https://#{QA::Runtime::Env.slack_workspace}.slack.com" => {
'slack' => true
}
}
}
}
default_profile = File.join("#{chrome_profile_location}/Default")
FileUtils.mkdir_p(default_profile) unless Dir.exist?(default_profile)
preferences = slack_default_preference
# mutate the preferences if it exists
# else write a new file
if File.exist?("#{default_profile}/Preferences")
begin
preferences = JSON.parse(File.read("#{default_profile}/Preferences"))
preferences.deep_merge!(slack_default_preference)
rescue JSON::ParserError => _
end
end
File.write("#{default_profile}/Preferences", preferences.to_json)
append_chrome_profile_to_capabilities(capabilities)
end
when :safari
if QA::Runtime::Env.remote_mobile_device_name
capabilities['platformName'] = 'iOS'
@ -131,10 +163,7 @@ module QA
# Use the same profile on QA runs if CHROME_REUSE_PROFILE is true.
# Useful to speed up local QA.
if QA::Runtime::Env.reuse_chrome_profile?
qa_profile_dir = ::File.expand_path('../../tmp/qa-profile', __dir__)
capabilities['goog:chromeOptions'][:args] << "user-data-dir=#{qa_profile_dir}"
end
append_chrome_profile_to_capabilities(capabilities) if QA::Runtime::Env.reuse_chrome_profile?
selenium_options = {
browser: QA::Runtime::Env.browser,
@ -193,6 +222,16 @@ module QA
end
# rubocop: enable Metrics/AbcSize
def self.append_chrome_profile_to_capabilities(capabilities)
return if capabilities['goog:chromeOptions'][:args].include?(chrome_profile_location)
capabilities['goog:chromeOptions'][:args] << "user-data-dir=#{chrome_profile_location}"
end
def self.chrome_profile_location
::File.expand_path('../../tmp/qa-profile', __dir__)
end
class Session
include Capybara::DSL

View File

@ -293,6 +293,18 @@ module QA
ENV['JIRA_HOSTNAME']
end
def slack_workspace
ENV['QA_SLACK_WORKSPACE']
end
def slack_email
ENV['QA_SLACK_EMAIL']
end
def slack_password
ENV['QA_SLACK_PASSWORD']
end
def jenkins_admin_username
ENV.fetch('QA_JENKINS_USER', 'administrator')
end
@ -502,6 +514,15 @@ module QA
ENV['DEFAULT_CHROME_DOWNLOAD_PATH'] || Dir.tmpdir
end
def require_slack_env!
missing_env = %i[slack_workspace slack_email slack_password].select do |method|
::QA::Runtime::Env.public_send(method).nil?
end
return unless missing_env.any?
raise "Missing Slack env: #{missing_env.map(&:upcase).join(', ')}"
end
private
def remote_grid_credentials

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GroupsController, factory_default: :keep do
RSpec.describe GroupsController, factory_default: :keep, feature_category: :code_review_workflow do
include ExternalAuthorizationServiceHelpers
include AdminModeHelper