Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a94adeb6b2
commit
7b50347823
|
|
@ -1 +1 @@
|
|||
837b920e969e4b707c871be91ab587adcc9a9283
|
||||
43d2f4f949f8a986ecad759c5e02bd01a243ed4f
|
||||
|
|
|
|||
|
|
@ -279,8 +279,6 @@ export function emojiImageTag(name, src) {
|
|||
title: `:${name}:`,
|
||||
alt: `:${name}:`,
|
||||
src,
|
||||
width: '16',
|
||||
height: '16',
|
||||
align: 'absmiddle',
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@ gl-emoji {
|
|||
display: inline-flex;
|
||||
vertical-align: baseline;
|
||||
font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
font-size: 1.2em;
|
||||
line-height: 1;
|
||||
|
||||
img {
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.user-status-emoji {
|
||||
|
|
|
|||
|
|
@ -7,5 +7,17 @@ module Projects
|
|||
(Gitlab.config.pages.external_http || Gitlab.config.pages.external_https) &&
|
||||
project.can_create_custom_domains?
|
||||
end
|
||||
|
||||
def pages_subdomain(project)
|
||||
Gitlab::Pages::UrlBuilder
|
||||
.new(project)
|
||||
.project_namespace
|
||||
end
|
||||
|
||||
def build_pages_url(project, with_unique_domain:)
|
||||
Gitlab::Pages::UrlBuilder
|
||||
.new(project)
|
||||
.pages_url(with_unique_domain: with_unique_domain)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ module Ci
|
|||
class ArtifactBlob
|
||||
include BlobLike
|
||||
|
||||
EXTENSIONS_SERVED_BY_PAGES = %w[.html .htm .txt .json .xml .log].freeze
|
||||
|
||||
attr_reader :entry
|
||||
|
||||
def initialize(entry)
|
||||
|
|
@ -35,31 +33,18 @@ module Ci
|
|||
:build_artifact
|
||||
end
|
||||
|
||||
def external_url(project, job)
|
||||
return unless external_link?(job)
|
||||
|
||||
url_project_path = project.full_path.partition('/').last
|
||||
|
||||
artifact_path = [
|
||||
'-', url_project_path, '-',
|
||||
'jobs', job.id,
|
||||
'artifacts', path
|
||||
].join('/')
|
||||
|
||||
"#{project.pages_namespace_url}/#{artifact_path}"
|
||||
def external_url(job)
|
||||
pages_url_builder(job.project).artifact_url(entry, job)
|
||||
end
|
||||
|
||||
def external_link?(job)
|
||||
pages_config.enabled &&
|
||||
pages_config.artifacts_server &&
|
||||
EXTENSIONS_SERVED_BY_PAGES.include?(File.extname(name)) &&
|
||||
(pages_config.access_control || job.project.public?)
|
||||
pages_url_builder(job.project).artifact_url_available?(entry, job)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def pages_config
|
||||
Gitlab.config.pages
|
||||
def pages_url_builder(project)
|
||||
@pages_url_builder ||= Gitlab::Pages::UrlBuilder.new(project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ module Pages
|
|||
strong_memoize_attr :source
|
||||
|
||||
def prefix
|
||||
if project.pages_namespace_url == project.pages_url
|
||||
if url_builder.namespace_pages?
|
||||
'/'
|
||||
else
|
||||
"#{project.full_path.delete_prefix(trim_prefix)}/"
|
||||
|
|
@ -55,9 +55,7 @@ module Pages
|
|||
strong_memoize_attr :prefix
|
||||
|
||||
def unique_host
|
||||
return unless project.project_setting.pages_unique_domain_enabled?
|
||||
|
||||
project.pages_unique_host
|
||||
url_builder.unique_host
|
||||
end
|
||||
strong_memoize_attr :unique_host
|
||||
|
||||
|
|
@ -76,5 +74,10 @@ module Pages
|
|||
project.pages_metadatum.pages_deployment
|
||||
end
|
||||
strong_memoize_attr :deployment
|
||||
|
||||
def url_builder
|
||||
Gitlab::Pages::UrlBuilder.new(project)
|
||||
end
|
||||
strong_memoize_attr :url_builder
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2218,42 +2218,6 @@ class Project < ApplicationRecord
|
|||
pages_metadatum&.deployed?
|
||||
end
|
||||
|
||||
def pages_url(with_unique_domain: false)
|
||||
return pages_unique_url if with_unique_domain && pages_unique_domain_enabled?
|
||||
|
||||
url = pages_namespace_url
|
||||
url_path = full_path.partition('/').last
|
||||
namespace_url = "#{Settings.pages.protocol}://#{url_path}".downcase
|
||||
|
||||
if Rails.env.development?
|
||||
url_without_port = URI.parse(url)
|
||||
url_without_port.port = nil
|
||||
|
||||
return url if url_without_port.to_s == namespace_url
|
||||
end
|
||||
|
||||
# If the project path is the same as host, we serve it as group page
|
||||
return url if url == namespace_url
|
||||
|
||||
"#{url}/#{url_path}"
|
||||
end
|
||||
|
||||
def pages_unique_url
|
||||
pages_url_for(project_setting.pages_unique_domain)
|
||||
end
|
||||
|
||||
def pages_unique_host
|
||||
URI(pages_unique_url).host
|
||||
end
|
||||
|
||||
def pages_namespace_url
|
||||
pages_url_for(pages_subdomain)
|
||||
end
|
||||
|
||||
def pages_subdomain
|
||||
full_path.partition('/').first
|
||||
end
|
||||
|
||||
def pages_path
|
||||
# TODO: when we migrate Pages to work with new storage types, change here to use disk_path
|
||||
File.join(Settings.pages.path, full_path)
|
||||
|
|
@ -2500,7 +2464,7 @@ class Project < ApplicationRecord
|
|||
break unless pages_enabled?
|
||||
|
||||
variables.append(key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host)
|
||||
variables.append(key: 'CI_PAGES_URL', value: pages_url)
|
||||
variables.append(key: 'CI_PAGES_URL', value: Gitlab::Pages::UrlBuilder.new(self).pages_url)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -3259,18 +3223,6 @@ class Project < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def pages_unique_domain_enabled?
|
||||
Feature.enabled?(:pages_unique_domain, self) &&
|
||||
project_setting.pages_unique_domain_enabled?
|
||||
end
|
||||
|
||||
def pages_url_for(domain)
|
||||
# The host in URL always needs to be downcased
|
||||
Gitlab.config.pages.url.sub(%r{^https?://}) do |prefix|
|
||||
"#{prefix}#{domain}."
|
||||
end.downcase
|
||||
end
|
||||
|
||||
# overridden in EE
|
||||
def project_group_links_with_preload
|
||||
project_group_links
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
- external_url = @blob.external_url(@build)
|
||||
- page_title @path, _('Artifacts'), "#{@build.name} (##{@build.id})", _('Jobs')
|
||||
|
||||
= render "projects/jobs/header"
|
||||
|
|
@ -8,8 +9,8 @@
|
|||
%h2= _("You are being redirected away from GitLab")
|
||||
%p= _("This page is hosted on GitLab pages but contains user-generated content and may contain malicious code. Do not accept unless you trust the author and source.")
|
||||
|
||||
= link_to @blob.external_url(@project, @build),
|
||||
@blob.external_url(@project, @build),
|
||||
= link_to external_url,
|
||||
external_url,
|
||||
target: '_blank',
|
||||
title: _('Opens in a new window'),
|
||||
rel: 'noopener noreferrer'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- if @project.pages_deployed?
|
||||
- pages_url = @project.pages_url(with_unique_domain: true)
|
||||
- pages_url = build_pages_url(@project, with_unique_domain: true)
|
||||
|
||||
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5', data: { qa_selector: 'access_page_container' } }, footer_options: { class: 'gl-alert-warning' }) do |c|
|
||||
- c.with_header do
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
= render 'pages_settings'
|
||||
|
||||
%hr.clearfix
|
||||
= render 'ssl_limitations_warning' if @project.pages_subdomain.include?(".")
|
||||
= render 'ssl_limitations_warning' if pages_subdomain(@project).include?(".")
|
||||
= render 'access'
|
||||
- if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
|
||||
= render 'list'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
|
||||
- dns_record = "#{domain_presenter.domain} ALIAS #{domain_presenter.project.pages_subdomain}.#{Settings.pages.host}."
|
||||
- dns_record = "#{domain_presenter.domain} ALIAS #{pages_subdomain(domain_presenter.project)}.#{Settings.pages.host}."
|
||||
|
||||
.form-group.border-section
|
||||
.row
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ Adding a semicolon(`;`) and a follow-up statement at the end of a statement prev
|
|||
|
||||
```ruby
|
||||
puts ActiveRecord::Base.descendants; :ok
|
||||
Project.select(&:pages_deployed?).each {|p| puts p.pages_url }; true
|
||||
Project.select(&:pages_deployed?).each {|p| puts p.path }; true
|
||||
```
|
||||
|
||||
## Get or store the result of last operation
|
||||
|
|
|
|||
|
|
@ -8516,6 +8516,29 @@ The edge type for [`ComplianceFramework`](#complianceframework).
|
|||
| <a id="complianceframeworkedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="complianceframeworkedgenode"></a>`node` | [`ComplianceFramework`](#complianceframework) | The item at the end of the edge. |
|
||||
|
||||
#### `ComplianceStandardsAdherenceConnection`
|
||||
|
||||
The connection type for [`ComplianceStandardsAdherence`](#compliancestandardsadherence).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="compliancestandardsadherenceconnectionedges"></a>`edges` | [`[ComplianceStandardsAdherenceEdge]`](#compliancestandardsadherenceedge) | A list of edges. |
|
||||
| <a id="compliancestandardsadherenceconnectionnodes"></a>`nodes` | [`[ComplianceStandardsAdherence]`](#compliancestandardsadherence) | A list of nodes. |
|
||||
| <a id="compliancestandardsadherenceconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
|
||||
#### `ComplianceStandardsAdherenceEdge`
|
||||
|
||||
The edge type for [`ComplianceStandardsAdherence`](#compliancestandardsadherence).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="compliancestandardsadherenceedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="compliancestandardsadherenceedgenode"></a>`node` | [`ComplianceStandardsAdherence`](#compliancestandardsadherence) | The item at the end of the edge. |
|
||||
|
||||
#### `ComplianceViolationConnection`
|
||||
|
||||
The connection type for [`ComplianceViolation`](#complianceviolation).
|
||||
|
|
@ -13673,6 +13696,21 @@ Represents a ComplianceFramework associated with a Project.
|
|||
| <a id="complianceframeworkname"></a>`name` | [`String!`](#string) | Name of the compliance framework. |
|
||||
| <a id="complianceframeworkpipelineconfigurationfullpath"></a>`pipelineConfigurationFullPath` | [`String`](#string) | Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hipaa` **(ULTIMATE)**. |
|
||||
|
||||
### `ComplianceStandardsAdherence`
|
||||
|
||||
Compliance standards adherence for a project.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="compliancestandardsadherencecheckname"></a>`checkName` | [`ComplianceStandardsAdherenceCheckName!`](#compliancestandardsadherencecheckname) | Name of the check for the compliance standard. |
|
||||
| <a id="compliancestandardsadherenceid"></a>`id` | [`ID!`](#id) | Compliance standards adherence ID. |
|
||||
| <a id="compliancestandardsadherenceproject"></a>`project` | [`Project!`](#project) | Project adhering to the compliance standard. |
|
||||
| <a id="compliancestandardsadherencestandard"></a>`standard` | [`ComplianceStandardsAdherenceStandard!`](#compliancestandardsadherencestandard) | Name of the compliance standard. |
|
||||
| <a id="compliancestandardsadherencestatus"></a>`status` | [`ComplianceStandardsAdherenceStatus!`](#compliancestandardsadherencestatus) | Status of the compliance standards adherence. |
|
||||
| <a id="compliancestandardsadherenceupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp when the adherence was updated. |
|
||||
|
||||
### `ComplianceViolation`
|
||||
|
||||
Compliance violation associated with a merged merge request.
|
||||
|
|
@ -16609,6 +16647,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| <a id="grouppackagessort"></a>`sort` | [`PackageGroupSort`](#packagegroupsort) | Sort packages by this criteria. |
|
||||
| <a id="grouppackagesstatus"></a>`status` | [`PackageStatus`](#packagestatus) | Filter a package by status. |
|
||||
|
||||
##### `Group.projectComplianceStandardsAdherence`
|
||||
|
||||
Compliance standards adherence for the projects in a group and its subgroups.
|
||||
|
||||
Returns [`ComplianceStandardsAdherenceConnection`](#compliancestandardsadherenceconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#connection-pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, `last: Int`.
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="groupprojectcompliancestandardsadherencefilters"></a>`filters` | [`ComplianceStandardsAdherenceInput`](#compliancestandardsadherenceinput) | Filters applied when retrieving compliance standards adherence. |
|
||||
|
||||
##### `Group.projects`
|
||||
|
||||
Projects within this namespace.
|
||||
|
|
@ -25199,6 +25253,31 @@ ComplianceFramework of a project for filtering.
|
|||
| <a id="complianceframeworkpresencefilterany"></a>`ANY` | Any compliance framework is assigned. |
|
||||
| <a id="complianceframeworkpresencefilternone"></a>`NONE` | No compliance framework is assigned. |
|
||||
|
||||
### `ComplianceStandardsAdherenceCheckName`
|
||||
|
||||
Name of the check for the compliance standard.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="compliancestandardsadherencechecknameprevent_approval_by_merge_request_author"></a>`PREVENT_APPROVAL_BY_MERGE_REQUEST_AUTHOR` | Prevent approval by merge request author. |
|
||||
|
||||
### `ComplianceStandardsAdherenceStandard`
|
||||
|
||||
Name of the compliance standard.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="compliancestandardsadherencestandardgitlab"></a>`GITLAB` | Gitlab. |
|
||||
|
||||
### `ComplianceStandardsAdherenceStatus`
|
||||
|
||||
Status of the compliance standards adherence.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="compliancestandardsadherencestatusfail"></a>`FAIL` | Fail. |
|
||||
| <a id="compliancestandardsadherencestatussuccess"></a>`SUCCESS` | Success. |
|
||||
|
||||
### `ComplianceViolationReason`
|
||||
|
||||
Reason for the compliance violation.
|
||||
|
|
@ -28951,6 +29030,16 @@ Attributes for defining a CI/CD variable.
|
|||
| <a id="complianceframeworkinputname"></a>`name` | [`String`](#string) | New name for the compliance framework. |
|
||||
| <a id="complianceframeworkinputpipelineconfigurationfullpath"></a>`pipelineConfigurationFullPath` | [`String`](#string) | Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hipaa` **(ULTIMATE)**. |
|
||||
|
||||
### `ComplianceStandardsAdherenceInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="compliancestandardsadherenceinputcheckname"></a>`checkName` | [`ComplianceStandardsAdherenceCheckName`](#compliancestandardsadherencecheckname) | Name of the check for the compliance standard. |
|
||||
| <a id="compliancestandardsadherenceinputprojectids"></a>`projectIds` | [`[ProjectID!]`](#projectid) | Filter compliance standards adherence by project. |
|
||||
| <a id="compliancestandardsadherenceinputstandard"></a>`standard` | [`ComplianceStandardsAdherenceStandard`](#compliancestandardsadherencestandard) | Name of the compliance standard. |
|
||||
|
||||
### `ComplianceViolationInput`
|
||||
|
||||
#### Arguments
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ containing:
|
|||
For example, for a component repository located at `gitlab-org/dast` on `gitlab.com`:
|
||||
|
||||
- The path `gitlab.com/gitlab-org/dast` tries to load the `template.yml` from the root directory.
|
||||
- The path `gitalb.com/gitlab-org/dast/api-scan` tries to load the `template.yml` from the `/api-scan` directory.
|
||||
- The path `gitlab.com/gitlab-org/dast/api-scan` tries to load the `template.yml` from the `/api-scan` directory.
|
||||
|
||||
**Additional notes:**
|
||||
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ After the long-term quarantining MR has reached production, you should revert th
|
|||
For Jest specs, you can use the `.skip` method along with the `eslint-disable-next-line` comment to disable the `jest/no-disabled-tests` ESLint rule and include the issue URL. Here's an example:
|
||||
|
||||
```javascript
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/56789
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/56789
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('should throw an error', () => {
|
||||
expect(response).toThrowError(expected_error)
|
||||
|
|
@ -198,6 +198,12 @@ This means it is skipped unless the test suit is run with `--runInBand` Jest com
|
|||
jest --runInBand
|
||||
```
|
||||
|
||||
A list of files with quarantined specs in them can be found with the command:
|
||||
|
||||
```shell
|
||||
yarn jest:quarantine
|
||||
```
|
||||
|
||||
For both test frameworks, make sure to add the `~"quarantined test"` label to the issue.
|
||||
|
||||
Once a test is in quarantine, there are 3 choices:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ module Banzai
|
|||
Filter::SanitizationFilter,
|
||||
Filter::AssetProxyFilter,
|
||||
Filter::EmojiFilter,
|
||||
Filter::CustomEmojiFilter,
|
||||
Filter::AutolinkFilter,
|
||||
Filter::ExternalLinkFilter,
|
||||
*reference_filters
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.36.0'
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.37.0'
|
||||
|
||||
build:
|
||||
stage: build
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.36.0'
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.37.0'
|
||||
|
||||
build:
|
||||
stage: build
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Pages
|
||||
class UrlBuilder
|
||||
attr_reader :project_namespace
|
||||
|
||||
ALLOWED_ARTIFACT_EXTENSIONS = %w[.html .htm .txt .json .xml .log].freeze
|
||||
ARTIFACT_URL = "%{host}/-/%{project_path}/-/jobs/%{job_id}/artifacts/%{artifact_path}"
|
||||
|
||||
def initialize(project)
|
||||
@project = project
|
||||
@project_namespace, _, @project_path = project.full_path.partition('/')
|
||||
end
|
||||
|
||||
def pages_url(with_unique_domain: false)
|
||||
return unique_url if with_unique_domain && unique_domain_enabled?
|
||||
|
||||
project_path_url = "#{config.protocol}://#{project_path}".downcase
|
||||
|
||||
# If the project path is the same as host, we serve it as group page
|
||||
# On development we ignore the URL port to make it work on GDK
|
||||
return namespace_url if Rails.env.development? && portless(namespace_url) == project_path_url
|
||||
# If the project path is the same as host, we serve it as group page
|
||||
return namespace_url if namespace_url == project_path_url
|
||||
|
||||
"#{namespace_url}/#{project_path}"
|
||||
end
|
||||
|
||||
def unique_host
|
||||
return unless unique_domain_enabled?
|
||||
|
||||
URI(unique_url).host
|
||||
end
|
||||
|
||||
def namespace_pages?
|
||||
namespace_url == pages_url
|
||||
end
|
||||
|
||||
def artifact_url(artifact, job)
|
||||
return unless artifact_url_available?(artifact, job)
|
||||
|
||||
format(
|
||||
ARTIFACT_URL,
|
||||
host: namespace_url,
|
||||
project_path: project_path,
|
||||
job_id: job.id,
|
||||
artifact_path: artifact.path)
|
||||
end
|
||||
|
||||
def artifact_url_available?(artifact, job)
|
||||
config.enabled &&
|
||||
config.artifacts_server &&
|
||||
ALLOWED_ARTIFACT_EXTENSIONS.include?(File.extname(artifact.name)) &&
|
||||
(config.access_control || job.project.public?)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :project, :project_path
|
||||
|
||||
def namespace_url
|
||||
@namespace_url ||= url_for(project_namespace)
|
||||
end
|
||||
|
||||
def unique_url
|
||||
@unique_url ||= url_for(project.project_setting.pages_unique_domain)
|
||||
end
|
||||
|
||||
def url_for(subdomain)
|
||||
URI(config.url)
|
||||
.tap { |url| url.port = config.port }
|
||||
.tap { |url| url.host.prepend("#{subdomain}.") }
|
||||
.to_s
|
||||
.downcase
|
||||
end
|
||||
|
||||
def portless(url)
|
||||
URI(url)
|
||||
.tap { |u| u.port = nil }
|
||||
.to_s
|
||||
end
|
||||
|
||||
def unique_domain_enabled?
|
||||
Feature.enabled?(:pages_unique_domain, project) &&
|
||||
project.project_setting.pages_unique_domain_enabled?
|
||||
end
|
||||
|
||||
def config
|
||||
Gitlab.config.pages
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -115,7 +115,7 @@ module Gitlab
|
|||
if Feature.enabled?(:use_metric_definitions_for_events_list)
|
||||
events = Gitlab::Usage::MetricDefinition.not_removed.values.map do |d|
|
||||
d.attributes[:options] && d.attributes[:options][:events]
|
||||
end.flatten.compact
|
||||
end.flatten.compact.uniq
|
||||
|
||||
events.map do |e|
|
||||
{ name: e }.with_indifferent_access
|
||||
|
|
@ -132,7 +132,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def known_events_names
|
||||
known_events.map { |event| event[:name] }
|
||||
@known_events_names ||= known_events.map { |event| event[:name] }
|
||||
end
|
||||
|
||||
def event_for(event_name)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
"jest:ci:predictive": "jest --config jest.config.js --ci --coverage --findRelatedTests $(cat $RSPEC_CHANGED_FILES_PATH) $(cat $RSPEC_MATCHING_JS_FILES_PATH) --passWithNoTests --testSequencer ./scripts/frontend/parallel_ci_sequencer.js",
|
||||
"jest:contract": "PACT_DO_NOT_TRACK=true jest --config jest.config.contract.js --runInBand",
|
||||
"jest:integration": "jest --config jest.config.integration.js",
|
||||
"jest:quarantine": "grep -r 'quarantine:' spec/frontend ee/spec/frontend",
|
||||
"lint:eslint": "node scripts/frontend/eslint.js",
|
||||
"lint:eslint:fix": "node scripts/frontend/eslint.js --fix",
|
||||
"lint:eslint:all": "node scripts/frontend/eslint.js .",
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ RSpec.describe 'User adds pages domain', :js, feature_category: :pages do
|
|||
visit project_pages_path(project)
|
||||
|
||||
within('#content-body') { click_link 'Edit' }
|
||||
expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS #{domain.project.pages_subdomain}.#{Settings.pages.host}."
|
||||
expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS namespace1.example.com."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ describe('gl_emoji', () => {
|
|||
'bomb emoji just with name attribute',
|
||||
'<gl-emoji data-name="bomb"></gl-emoji>',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
|
||||
`<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="16" height="16" align="absmiddle"></gl-emoji>`,
|
||||
`<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" align="absmiddle"></gl-emoji>`,
|
||||
],
|
||||
[
|
||||
'bomb emoji with name attribute and unicode version',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
|
||||
`<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="16" height="16" align="absmiddle"></gl-emoji>`,
|
||||
`<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" align="absmiddle"></gl-emoji>`,
|
||||
],
|
||||
[
|
||||
'bomb emoji with sprite fallback',
|
||||
|
|
@ -77,19 +77,19 @@ describe('gl_emoji', () => {
|
|||
'bomb emoji with image fallback',
|
||||
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb"></gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/bomb.png" width="16" height="16" align="absmiddle"></gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/bomb.png" align="absmiddle"></gl-emoji>',
|
||||
],
|
||||
[
|
||||
'invalid emoji',
|
||||
'<gl-emoji data-name="invalid_emoji"></gl-emoji>',
|
||||
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament">❔</gl-emoji>',
|
||||
`<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" width="16" height="16" align="absmiddle"></gl-emoji>`,
|
||||
`<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" align="absmiddle"></gl-emoji>`,
|
||||
],
|
||||
[
|
||||
'custom emoji with image fallback',
|
||||
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"></gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" width="16" height="16" align="absmiddle"></gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" width="16" height="16" align="absmiddle"></gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" align="absmiddle"></gl-emoji>',
|
||||
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" align="absmiddle"></gl-emoji>',
|
||||
],
|
||||
])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => {
|
||||
it(`renders correctly with emoji support`, async () => {
|
||||
|
|
@ -119,7 +119,7 @@ describe('gl_emoji', () => {
|
|||
await waitForPromises();
|
||||
|
||||
expect(glEmojiElement.outerHTML).toBe(
|
||||
'<gl-emoji data-name=""x="y" onload="alert(document.location.href)"" data-unicode-version="x"><img class="emoji" title=":"x="y" onload="alert(document.location.href)":" alt=":"x="y" onload="alert(document.location.href)":" src="/-/emojis/2/grey_question.png" width="16" height="16" align="absmiddle"></gl-emoji>',
|
||||
'<gl-emoji data-name=""x="y" onload="alert(document.location.href)"" data-unicode-version="x"><img class="emoji" title=":"x="y" onload="alert(document.location.href)":" alt=":"x="y" onload="alert(document.location.href)":" src="/-/emojis/2/grey_question.png" align="absmiddle"></gl-emoji>',
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ describe('AdminRunnersApp', () => {
|
|||
await createComponent({ mountFn: mountExtended });
|
||||
});
|
||||
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/414975
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/414975
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('fetches counts', () => {
|
||||
expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ describe('RelatedIssuesRoot', () => {
|
|||
await createComponent();
|
||||
});
|
||||
|
||||
// Quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/417177
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/417177
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('removes related issue on API success', async () => {
|
||||
mock.onDelete(issuable1.referencePath).reply(HTTP_STATUS_OK, { issues: [] });
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ describe('IssuesDashboardApp component', () => {
|
|||
await waitForPromises();
|
||||
});
|
||||
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/391722
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/391722
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('renders IssuableList component', () => {
|
||||
expect(findIssuableList().props()).toMatchObject({
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const setupHTML = (initialData) => {
|
|||
|
||||
describe('Issue show index', () => {
|
||||
describe('initIssueApp', () => {
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/390368
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/390368
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('should initialize app with no potential XSS attack', async () => {
|
||||
const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {});
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ describe('note_app', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/410409
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/410409
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('should render form comment button as disabled', () => {
|
||||
expect(findCommentButton().props('disabled')).toEqual(true);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ function wrappedDiscussionNote(note) {
|
|||
return `<table><tbody>${note}</tbody></table>`;
|
||||
}
|
||||
|
||||
// the following test is unreliable and failing in main 2-3 times a day
|
||||
// see https://gitlab.com/gitlab-org/gitlab/issues/206906#note_290602581
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/208441
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
describe.skip('Old Notes (~/deprecated_notes.js)', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ describe('MrWidgetOptions', () => {
|
|||
return createComponent();
|
||||
});
|
||||
|
||||
// https://gitlab.com/gitlab-org/gitlab/-/issues/385238
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/385238
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
describe.skip('data', () => {
|
||||
it('should instantiate Store and Service', () => {
|
||||
|
|
@ -186,6 +186,7 @@ describe('MrWidgetOptions', () => {
|
|||
|
||||
describe('computed', () => {
|
||||
describe('componentName', () => {
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/409365
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip.each`
|
||||
${'merged'} | ${'mr-widget-merged'}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// quarantine flaky spec:https://gitlab.com/gitlab-org/gitlab/-/issues/412618
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/412618
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('passes render_quick_actions param to renderMarkdownPath if quick actions are enabled', async () => {
|
||||
buildWrapper({ propsData: { supportsQuickActions: true } });
|
||||
|
|
@ -139,7 +139,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
|
|||
expect(mock.history.post[0].url).toContain(`render_quick_actions=true`);
|
||||
});
|
||||
|
||||
// quarantine flaky spec: https://gitlab.com/gitlab-org/gitlab/-/issues/411565
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/411565
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('does not pass render_quick_actions param to renderMarkdownPath if quick actions are disabled', async () => {
|
||||
buildWrapper({ propsData: { supportsQuickActions: false } });
|
||||
|
|
@ -213,7 +213,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
|
|||
expect(findMarkdownField().find('textarea').attributes('disabled')).toBe(undefined);
|
||||
});
|
||||
|
||||
// quarantine flaky spec: https://gitlab.com/gitlab-org/gitlab/-/issues/404734
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/404734
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('disables content editor when disabled prop is true', async () => {
|
||||
buildWrapper({ propsData: { disabled: true } });
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache, featur
|
|||
{ key: 'CI_PAGES_DOMAIN',
|
||||
value: Gitlab.config.pages.host },
|
||||
{ key: 'CI_PAGES_URL',
|
||||
value: project.pages_url },
|
||||
value: Gitlab::Pages::UrlBuilder.new(project).pages_url },
|
||||
{ key: 'CI_API_V4_URL',
|
||||
value: API::Helpers::Version.new('v4').root_url },
|
||||
{ key: 'CI_API_GRAPHQL_URL',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,227 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Pages::UrlBuilder, feature_category: :pages do
|
||||
let(:pages_enabled) { true }
|
||||
let(:artifacts_server) { true }
|
||||
let(:access_control) { true }
|
||||
|
||||
let(:port) { nil }
|
||||
let(:host) { 'example.com' }
|
||||
|
||||
let(:full_path) { 'group/project' }
|
||||
let(:project_public) { true }
|
||||
let(:unique_domain) { 'unique-domain' }
|
||||
let(:unique_domain_enabled) { false }
|
||||
|
||||
let(:project_setting) do
|
||||
instance_double(
|
||||
ProjectSetting,
|
||||
pages_unique_domain: unique_domain,
|
||||
pages_unique_domain_enabled?: unique_domain_enabled
|
||||
)
|
||||
end
|
||||
|
||||
let(:project) do
|
||||
instance_double(
|
||||
Project,
|
||||
flipper_id: 'project:1', # required for the feature flag check
|
||||
public?: project_public,
|
||||
project_setting: project_setting,
|
||||
full_path: full_path
|
||||
)
|
||||
end
|
||||
|
||||
subject(:builder) { described_class.new(project) }
|
||||
|
||||
before do
|
||||
stub_pages_setting(
|
||||
enabled: pages_enabled,
|
||||
host: host,
|
||||
url: 'http://example.com',
|
||||
protocol: 'http',
|
||||
artifacts_server: artifacts_server,
|
||||
access_control: access_control,
|
||||
port: port
|
||||
)
|
||||
end
|
||||
|
||||
describe '#pages_url' do
|
||||
subject(:pages_url) { builder.pages_url }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
|
||||
context 'when namespace is upper cased' do
|
||||
let(:full_path) { 'Group/project' }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when project is in a nested group page' do
|
||||
let(:full_path) { 'group/subgroup/project' }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/subgroup/project') }
|
||||
end
|
||||
|
||||
context 'when using domain pages' do
|
||||
let(:full_path) { 'group/group.example.com' }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com') }
|
||||
|
||||
context 'in development mode' do
|
||||
let(:port) { 3010 }
|
||||
|
||||
before do
|
||||
stub_rails_env('development')
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com:3010') }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not using pages_unique_domain' do
|
||||
subject(:pages_url) { builder.pages_url(with_unique_domain: false) }
|
||||
|
||||
context 'when pages_unique_domain feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: true)
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is false' do
|
||||
let(:unique_domain_enabled) { false }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is true' do
|
||||
let(:unique_domain_enabled) { true }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using pages_unique_domain' do
|
||||
subject(:pages_url) { builder.pages_url(with_unique_domain: true) }
|
||||
|
||||
context 'when pages_unique_domain feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: true)
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is false' do
|
||||
let(:unique_domain_enabled) { false }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is true' do
|
||||
let(:unique_domain_enabled) { true }
|
||||
|
||||
it { is_expected.to eq('http://unique-domain.example.com') }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#unique_host' do
|
||||
subject(:unique_host) { builder.unique_host }
|
||||
|
||||
context 'when pages_unique_domain feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: true)
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is false' do
|
||||
let(:unique_domain_enabled) { false }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is true' do
|
||||
let(:unique_domain_enabled) { true }
|
||||
|
||||
it { is_expected.to eq('unique-domain.example.com') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#artifact_url' do
|
||||
let(:job) { instance_double(Ci::Build, id: 1) }
|
||||
let(:artifact) do
|
||||
instance_double(
|
||||
Gitlab::Ci::Build::Artifacts::Metadata::Entry,
|
||||
name: artifact_name,
|
||||
path: "path/#{artifact_name}")
|
||||
end
|
||||
|
||||
subject(:artifact_url) { builder.artifact_url(artifact, job) }
|
||||
|
||||
context 'with not allowed extension' do
|
||||
let(:artifact_name) { 'file.gif' }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'with allowed extension' do
|
||||
let(:artifact_name) { 'file.txt' }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com/-/project/-/jobs/1/artifacts/path/file.txt") }
|
||||
|
||||
context 'when port is configured' do
|
||||
let(:port) { 1234 }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com:1234/-/project/-/jobs/1/artifacts/path/file.txt") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#artifact_url_available?' do
|
||||
let(:job) { instance_double(Ci::Build, id: 1) }
|
||||
let(:artifact) do
|
||||
instance_double(
|
||||
Gitlab::Ci::Build::Artifacts::Metadata::Entry,
|
||||
name: artifact_name,
|
||||
path: "path/#{artifact_name}")
|
||||
end
|
||||
|
||||
subject(:artifact_url_available) { builder.artifact_url_available?(artifact, job) }
|
||||
|
||||
context 'with not allowed extensions' do
|
||||
let(:artifact_name) { 'file.gif' }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'with allowed extensions' do
|
||||
let(:artifact_name) { 'file.txt' }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,9 +18,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
|
|||
# depending on which day of the week test is run.
|
||||
# Monday 6th of June
|
||||
described_class.clear_memoization(:known_events)
|
||||
described_class.clear_memoization(:known_events_names)
|
||||
reference_time = Time.utc(2020, 6, 1)
|
||||
travel_to(reference_time) { example.run }
|
||||
described_class.clear_memoization(:known_events)
|
||||
described_class.clear_memoization(:known_events_names)
|
||||
end
|
||||
|
||||
describe '.known_events' do
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Gitlab::UsageDataMetrics, :with_license, feature_category: :service_ping do
|
||||
describe '.uncached_data' do
|
||||
let(:aggregate) { instance_double('Gitlab::Usage::Metrics::Aggregates::Aggregate') }
|
||||
|
||||
subject { described_class.uncached_data }
|
||||
|
||||
around do |example|
|
||||
|
|
@ -15,11 +13,6 @@ RSpec.describe Gitlab::UsageDataMetrics, :with_license, feature_category: :servi
|
|||
end
|
||||
|
||||
before do
|
||||
# stub time-consuming and unnecessary computation
|
||||
allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).and_return(1)
|
||||
allow(Gitlab::Usage::Metrics::Aggregates::Aggregate).to receive(:new).and_return(aggregate)
|
||||
allow(aggregate).to receive(:calculate_count_for_aggregation).and_return(1)
|
||||
|
||||
allow_next_instance_of(Gitlab::Database::BatchCounter) do |batch_counter|
|
||||
allow(batch_counter).to receive(:transaction_open?).and_return(false)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,104 +3,92 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::ArtifactBlob, feature_category: :continuous_integration do
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
let_it_be(:project) { create(:project, :public, path: 'project1') }
|
||||
let_it_be(:build) { create(:ci_build, :artifacts, project: project) }
|
||||
|
||||
let(:pages_port) { nil }
|
||||
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/another-subdirectory/banana_sample.gif') }
|
||||
|
||||
subject { described_class.new(entry) }
|
||||
subject(:blob) { described_class.new(entry) }
|
||||
|
||||
before do
|
||||
stub_pages_setting(
|
||||
enabled: true,
|
||||
artifacts_server: true,
|
||||
access_control: true,
|
||||
port: pages_port
|
||||
)
|
||||
end
|
||||
|
||||
describe '#id' do
|
||||
it 'returns a hash of the path' do
|
||||
expect(subject.id).to eq(Digest::SHA1.hexdigest(entry.path))
|
||||
expect(blob.id).to eq(Digest::SHA1.hexdigest(entry.path))
|
||||
end
|
||||
end
|
||||
|
||||
describe '#name' do
|
||||
it 'returns the entry name' do
|
||||
expect(subject.name).to eq(entry.name)
|
||||
expect(blob.name).to eq(entry.name)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#path' do
|
||||
it 'returns the entry path' do
|
||||
expect(subject.path).to eq(entry.path)
|
||||
expect(blob.path).to eq(entry.path)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#size' do
|
||||
it 'returns the entry size' do
|
||||
expect(subject.size).to eq(entry.metadata[:size])
|
||||
expect(blob.size).to eq(entry.metadata[:size])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#mode' do
|
||||
it 'returns the entry mode' do
|
||||
expect(subject.mode).to eq(entry.metadata[:mode])
|
||||
expect(blob.mode).to eq(entry.metadata[:mode])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#external_storage' do
|
||||
it 'returns :build_artifact' do
|
||||
expect(subject.external_storage).to eq(:build_artifact)
|
||||
expect(blob.external_storage).to eq(:build_artifact)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#external_url' do
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
|
||||
allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true)
|
||||
subject(:url) { blob.external_url(build) }
|
||||
|
||||
context 'with not allowed extension' do
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
describe '.gif extension' do
|
||||
it 'returns nil' do
|
||||
expect(subject.external_url(build.project, build)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'txt extensions' do
|
||||
context 'with allowed extension' do
|
||||
let(:path) { 'other_artifacts_0.1.2/doc_sample.txt' }
|
||||
let(:entry) { build.artifacts_metadata_entry(path) }
|
||||
|
||||
it 'returns a URL' do
|
||||
url = subject.external_url(build.project, build)
|
||||
|
||||
expect(url).not_to be_nil
|
||||
expect(url).to eq("http://#{project.namespace.path}.#{Gitlab.config.pages.host}/-/#{project.path}/-/jobs/#{build.id}/artifacts/#{path}")
|
||||
end
|
||||
it { is_expected.to eq("http://#{project.namespace.path}.example.com/-/project1/-/jobs/#{build.id}/artifacts/other_artifacts_0.1.2/doc_sample.txt") }
|
||||
|
||||
context 'when port is configured' do
|
||||
let(:port) { 1234 }
|
||||
let(:pages_port) { 1234 }
|
||||
|
||||
it 'returns an URL with port number' do
|
||||
allow(Gitlab.config.pages).to receive(:url).and_return("#{Gitlab.config.pages.url}:#{port}")
|
||||
|
||||
url = subject.external_url(build.project, build)
|
||||
|
||||
expect(url).not_to be_nil
|
||||
expect(url).to eq("http://#{project.namespace.path}.#{Gitlab.config.pages.host}:#{port}/-/#{project.path}/-/jobs/#{build.id}/artifacts/#{path}")
|
||||
end
|
||||
it { is_expected.to eq("http://#{project.namespace.path}.example.com:1234/-/project1/-/jobs/#{build.id}/artifacts/other_artifacts_0.1.2/doc_sample.txt") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#external_link?' do
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
|
||||
allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true)
|
||||
end
|
||||
|
||||
context 'gif extensions' do
|
||||
context 'with not allowed extensions' do
|
||||
it 'returns false' do
|
||||
expect(subject.external_link?(build)).to be false
|
||||
expect(blob.external_link?(build)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'txt extensions' do
|
||||
context 'with allowed extensions' do
|
||||
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/doc_sample.txt') }
|
||||
|
||||
it 'returns true' do
|
||||
expect(subject.external_link?(build)).to be true
|
||||
expect(blob.external_link?(build)).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2899,7 +2899,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
|
|||
{ key: 'CI_DEFAULT_BRANCH', value: project.default_branch, public: true, masked: false },
|
||||
{ key: 'CI_CONFIG_PATH', value: project.ci_config_path_or_default, public: true, masked: false },
|
||||
{ key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true, masked: false },
|
||||
{ key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
|
||||
{ key: 'CI_PAGES_URL', value: Gitlab::Pages::UrlBuilder.new(project).pages_url, public: true, masked: false },
|
||||
{ key: 'CI_DEPENDENCY_PROXY_SERVER', value: Gitlab.host_with_port, public: true, masked: false },
|
||||
{ key: 'CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX',
|
||||
value: "#{Gitlab.host_with_port}/#{project.namespace.root_ancestor.path.downcase}#{DependencyProxy::URL_SUFFIX}",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@ RSpec.describe Pages::LookupPath, feature_category: :pages do
|
|||
subject(:lookup_path) { described_class.new(project) }
|
||||
|
||||
before do
|
||||
stub_pages_setting(access_control: true, external_https: ["1.1.1.1:443"])
|
||||
stub_pages_setting(
|
||||
access_control: true,
|
||||
external_https: ["1.1.1.1:443"],
|
||||
url: 'http://example.com',
|
||||
protocol: 'http'
|
||||
)
|
||||
stub_pages_object_storage(::Pages::DeploymentUploader)
|
||||
end
|
||||
|
||||
|
|
@ -120,18 +125,14 @@ RSpec.describe Pages::LookupPath, feature_category: :pages do
|
|||
|
||||
describe '#prefix' do
|
||||
it 'returns "/" for pages group root projects' do
|
||||
project = instance_double(Project, pages_namespace_url: "namespace.test", pages_url: "namespace.test")
|
||||
project = instance_double(Project, full_path: "namespace/namespace.example.com")
|
||||
lookup_path = described_class.new(project, trim_prefix: 'mygroup')
|
||||
|
||||
expect(lookup_path.prefix).to eq('/')
|
||||
end
|
||||
|
||||
it 'returns the project full path with the provided prefix removed' do
|
||||
project = instance_double(
|
||||
Project,
|
||||
pages_namespace_url: "namespace.test",
|
||||
pages_url: "namespace.other",
|
||||
full_path: 'mygroup/myproject')
|
||||
project = instance_double(Project, full_path: 'mygroup/myproject')
|
||||
lookup_path = described_class.new(project, trim_prefix: 'mygroup')
|
||||
|
||||
expect(lookup_path.prefix).to eq('/myproject/')
|
||||
|
|
|
|||
|
|
@ -2806,224 +2806,6 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
|||
end
|
||||
end
|
||||
|
||||
describe '#pages_url', feature_category: :pages do
|
||||
let(:group_name) { 'group' }
|
||||
let(:project_name) { 'project' }
|
||||
|
||||
let(:group) { create(:group, name: group_name) }
|
||||
let(:nested_group) { create(:group, parent: group) }
|
||||
|
||||
let(:project_path) { project_name.downcase }
|
||||
let(:project) do
|
||||
create(
|
||||
:project,
|
||||
namespace: group,
|
||||
name: project_name,
|
||||
path: project_path)
|
||||
end
|
||||
|
||||
let(:domain) { 'Example.com' }
|
||||
let(:port) { nil }
|
||||
|
||||
subject { project.pages_url }
|
||||
|
||||
before do
|
||||
allow(Settings.pages).to receive(:host).and_return(domain)
|
||||
allow(Gitlab.config.pages)
|
||||
.to receive(:url)
|
||||
.and_return(['http://example.com', port].compact.join(':'))
|
||||
end
|
||||
|
||||
context 'when not using pages_unique_domain' do
|
||||
subject { project.pages_url(with_unique_domain: false) }
|
||||
|
||||
context 'when pages_unique_domain feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: true)
|
||||
|
||||
project.project_setting.update!(
|
||||
pages_unique_domain_enabled: pages_unique_domain_enabled,
|
||||
pages_unique_domain: 'unique-domain'
|
||||
)
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is false' do
|
||||
let(:pages_unique_domain_enabled) { false }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is true' do
|
||||
let(:pages_unique_domain_enabled) { true }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using pages_unique_domain' do
|
||||
subject { project.pages_url(with_unique_domain: true) }
|
||||
|
||||
context 'when pages_unique_domain feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: false)
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(pages_unique_domain: true)
|
||||
|
||||
project.project_setting.update!(
|
||||
pages_unique_domain_enabled: pages_unique_domain_enabled,
|
||||
pages_unique_domain: 'unique-domain'
|
||||
)
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is false' do
|
||||
let(:pages_unique_domain_enabled) { false }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com/project') }
|
||||
end
|
||||
|
||||
context 'when pages_unique_domain_enabled is true' do
|
||||
let(:pages_unique_domain_enabled) { true }
|
||||
|
||||
it { is_expected.to eq('http://unique-domain.example.com') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with nested group' do
|
||||
let(:project) { create(:project, namespace: nested_group, name: project_name) }
|
||||
let(:expected_url) { "http://group.example.com/#{nested_group.path}/#{project.path}" }
|
||||
|
||||
context 'group page' do
|
||||
let(:project_name) { 'group.example.com' }
|
||||
|
||||
it { is_expected.to eq(expected_url) }
|
||||
end
|
||||
|
||||
context 'project page' do
|
||||
let(:project_name) { 'Project' }
|
||||
|
||||
it { is_expected.to eq(expected_url) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the project matches its namespace url' do
|
||||
let(:project_name) { 'group.example.com' }
|
||||
|
||||
it { is_expected.to eq('http://group.example.com') }
|
||||
|
||||
context 'with different group name capitalization' do
|
||||
let(:group_name) { 'Group' }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com") }
|
||||
end
|
||||
|
||||
context 'with different project path capitalization' do
|
||||
let(:project_path) { 'Group.example.com' }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com") }
|
||||
end
|
||||
|
||||
context 'with different project name capitalization' do
|
||||
let(:project_name) { 'Project' }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com/project") }
|
||||
end
|
||||
|
||||
context 'when there is an explicit port' do
|
||||
let(:port) { 3000 }
|
||||
|
||||
context 'when not in dev mode' do
|
||||
before do
|
||||
stub_rails_env('production')
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com:3000/group.example.com') }
|
||||
end
|
||||
|
||||
context 'when in dev mode' do
|
||||
before do
|
||||
stub_rails_env('development')
|
||||
end
|
||||
|
||||
it { is_expected.to eq('http://group.example.com:3000') }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pages_unique_url', feature_category: :pages do
|
||||
let(:project_settings) { create(:project_setting, pages_unique_domain: 'unique-domain') }
|
||||
let(:project) { build(:project, project_setting: project_settings) }
|
||||
let(:domain) { 'example.com' }
|
||||
|
||||
before do
|
||||
allow(Settings.pages).to receive(:host).and_return(domain)
|
||||
allow(Gitlab.config.pages).to receive(:url).and_return("http://#{domain}")
|
||||
end
|
||||
|
||||
it 'returns the pages unique url' do
|
||||
expect(project.pages_unique_url).to eq('http://unique-domain.example.com')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pages_unique_host', feature_category: :pages do
|
||||
let(:project_settings) { create(:project_setting, pages_unique_domain: 'unique-domain') }
|
||||
let(:project) { build(:project, project_setting: project_settings) }
|
||||
let(:domain) { 'example.com' }
|
||||
|
||||
before do
|
||||
allow(Settings.pages).to receive(:host).and_return(domain)
|
||||
allow(Gitlab.config.pages).to receive(:url).and_return("http://#{domain}")
|
||||
end
|
||||
|
||||
it 'returns the pages unique url' do
|
||||
expect(project.pages_unique_host).to eq('unique-domain.example.com')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#pages_namespace_url', feature_category: :pages do
|
||||
let(:group) { create(:group, name: group_name) }
|
||||
let(:project) { create(:project, namespace: group, name: project_name) }
|
||||
let(:domain) { 'Example.com' }
|
||||
let(:port) { 1234 }
|
||||
|
||||
subject { project.pages_namespace_url }
|
||||
|
||||
before do
|
||||
allow(Settings.pages).to receive(:host).and_return(domain)
|
||||
allow(Gitlab.config.pages).to receive(:url).and_return("http://example.com:#{port}")
|
||||
end
|
||||
|
||||
context 'group page' do
|
||||
let(:group_name) { 'Group' }
|
||||
let(:project_name) { 'group.example.com' }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com:#{port}") }
|
||||
end
|
||||
|
||||
context 'project page' do
|
||||
let(:group_name) { 'Group' }
|
||||
let(:project_name) { 'Project' }
|
||||
|
||||
it { is_expected.to eq("http://group.example.com:#{port}") }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.search' do
|
||||
let_it_be(:project) { create(:project, description: 'kitten mittens') }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue