Commit 1cfd8874 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent fbcb3688
...@@ -547,3 +547,13 @@ export const calculateRemainingMilliseconds = endDate => { ...@@ -547,3 +547,13 @@ export const calculateRemainingMilliseconds = endDate => {
const remainingMilliseconds = new Date(endDate).getTime() - Date.now(); const remainingMilliseconds = new Date(endDate).getTime() - Date.now();
return Math.max(remainingMilliseconds, 0); return Math.max(remainingMilliseconds, 0);
}; };
/**
* Subtracts a given number of days from a given date and returns the new date.
*
* @param {Date} date the date that we will substract days from
* @param {number} daysInPast number of days that are subtracted from a given date
* @returns {String} Date string in ISO format
*/
export const getDateInPast = (date, daysInPast) =>
new Date(date.setTime(date.getTime() - daysInPast * 24 * 60 * 60 * 1000)).toISOString();
...@@ -106,3 +106,14 @@ export const sum = (a = 0, b = 0) => a + b; ...@@ -106,3 +106,14 @@ export const sum = (a = 0, b = 0) => a + b;
* @param {Int} number * @param {Int} number
*/ */
export const isOdd = (number = 0) => number % 2; export const isOdd = (number = 0) => number % 2;
/**
* Computes the median for a given array.
* @param {Array} arr An array of numbers
* @returns {Number} The median of the given array
*/
export const median = arr => {
const middle = Math.floor(arr.length / 2);
const sorted = arr.sort((a, b) => a - b);
return arr.length % 2 !== 0 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
};
...@@ -120,6 +120,13 @@ class Namespace < ApplicationRecord ...@@ -120,6 +120,13 @@ class Namespace < ApplicationRecord
uniquify = Uniquify.new uniquify = Uniquify.new
uniquify.string(path) { |s| Namespace.find_by_path_or_name(s) } uniquify.string(path) { |s| Namespace.find_by_path_or_name(s) }
end end
def find_by_pages_host(host)
gitlab_host = "." + Settings.pages.host.downcase
name = host.downcase.delete_suffix(gitlab_host)
Namespace.find_by_full_path(name)
end
end end
def visibility_level_field def visibility_level_field
...@@ -305,8 +312,16 @@ class Namespace < ApplicationRecord ...@@ -305,8 +312,16 @@ class Namespace < ApplicationRecord
aggregation_schedule.present? aggregation_schedule.present?
end end
def pages_virtual_domain
Pages::VirtualDomain.new(all_projects_with_pages, trim_prefix: full_path)
end
private private
def all_projects_with_pages
all_projects.with_pages_deployed
end
def parent_changed? def parent_changed?
parent_id_changed? parent_id_changed?
end end
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
module Pages module Pages
class LookupPath class LookupPath
def initialize(project, domain: nil) def initialize(project, trim_prefix: nil, domain: nil)
@project = project @project = project
@domain = domain @domain = domain
@trim_prefix = trim_prefix || project.full_path
end end
def project_id def project_id
...@@ -28,11 +29,15 @@ module Pages ...@@ -28,11 +29,15 @@ module Pages
end end
def prefix def prefix
'/' if project.pages_group_root?
'/'
else
project.full_path.delete_prefix(trim_prefix) + '/'
end
end end
private private
attr_reader :project, :domain attr_reader :project, :trim_prefix, :domain
end end
end end
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
module Pages module Pages
class VirtualDomain class VirtualDomain
def initialize(projects, domain: nil) def initialize(projects, trim_prefix: nil, domain: nil)
@projects = projects @projects = projects
@trim_prefix = trim_prefix
@domain = domain @domain = domain
end end
...@@ -17,12 +18,12 @@ module Pages ...@@ -17,12 +18,12 @@ module Pages
def lookup_paths def lookup_paths
projects.map do |project| projects.map do |project|
project.pages_lookup_path(domain: domain) project.pages_lookup_path(trim_prefix: trim_prefix, domain: domain)
end.sort_by(&:prefix).reverse end.sort_by(&:prefix).reverse
end end
private private
attr_reader :projects, :domain attr_reader :projects, :trim_prefix, :domain
end end
end end
...@@ -186,11 +186,17 @@ class PagesDomain < ApplicationRecord ...@@ -186,11 +186,17 @@ class PagesDomain < ApplicationRecord
end end
def pages_virtual_domain def pages_virtual_domain
return unless pages_deployed?
Pages::VirtualDomain.new([project], domain: self) Pages::VirtualDomain.new([project], domain: self)
end end
private private
def pages_deployed?
project.pages_metadatum&.deployed?
end
def set_verification_code def set_verification_code
return if self.verification_code.present? return if self.verification_code.present?
......
...@@ -104,6 +104,9 @@ class Project < ApplicationRecord ...@@ -104,6 +104,9 @@ class Project < ApplicationRecord
unless: :ci_cd_settings, unless: :ci_cd_settings,
if: proc { ProjectCiCdSetting.available? } if: proc { ProjectCiCdSetting.available? }
after_create :create_pages_metadatum,
unless: :pages_metadatum
after_create :set_timestamps_for_create after_create :set_timestamps_for_create
after_update :update_forks_visibility_level after_update :update_forks_visibility_level
...@@ -295,6 +298,8 @@ class Project < ApplicationRecord ...@@ -295,6 +298,8 @@ class Project < ApplicationRecord
has_many :external_pull_requests, inverse_of: :project has_many :external_pull_requests, inverse_of: :project
has_one :pages_metadatum, class_name: 'ProjectPagesMetadatum', inverse_of: :project
accepts_nested_attributes_for :variables, allow_destroy: true accepts_nested_attributes_for :variables, allow_destroy: true
accepts_nested_attributes_for :project_feature, update_only: true accepts_nested_attributes_for :project_feature, update_only: true
accepts_nested_attributes_for :import_data accepts_nested_attributes_for :import_data
...@@ -425,6 +430,10 @@ class Project < ApplicationRecord ...@@ -425,6 +430,10 @@ class Project < ApplicationRecord
.where(project_ci_cd_settings: { group_runners_enabled: true }) .where(project_ci_cd_settings: { group_runners_enabled: true })
end end
scope :with_pages_deployed, -> do
joins(:pages_metadatum).merge(ProjectPagesMetadatum.deployed)
end
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 } enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout, chronic_duration_attr :build_timeout_human_readable, :build_timeout,
...@@ -1643,6 +1652,10 @@ class Project < ApplicationRecord ...@@ -1643,6 +1652,10 @@ class Project < ApplicationRecord
"#{url}/#{url_path}" "#{url}/#{url_path}"
end end
def pages_group_root?
pages_group_url == pages_url
end
def pages_subdomain def pages_subdomain
full_path.partition('/').first full_path.partition('/').first
end end
...@@ -1681,6 +1694,7 @@ class Project < ApplicationRecord ...@@ -1681,6 +1694,7 @@ class Project < ApplicationRecord
# Projects with a missing namespace cannot have their pages removed # Projects with a missing namespace cannot have their pages removed
return unless namespace return unless namespace
mark_pages_as_not_deployed unless destroyed?
::Projects::UpdatePagesConfigurationService.new(self).execute ::Projects::UpdatePagesConfigurationService.new(self).execute
# 1. We rename pages to temporary directory # 1. We rename pages to temporary directory
...@@ -1694,6 +1708,14 @@ class Project < ApplicationRecord ...@@ -1694,6 +1708,14 @@ class Project < ApplicationRecord
end end
# rubocop: enable CodeReuse/ServiceClass # rubocop: enable CodeReuse/ServiceClass
def mark_pages_as_deployed
ensure_pages_metadatum.update!(deployed: true)
end
def mark_pages_as_not_deployed
ensure_pages_metadatum.update!(deployed: false)
end
# rubocop:disable Gitlab/RailsLogger # rubocop:disable Gitlab/RailsLogger
def write_repository_config(gl_full_path: full_path) def write_repository_config(gl_full_path: full_path)
# We'd need to keep track of project full path otherwise directory tree # We'd need to keep track of project full path otherwise directory tree
...@@ -2213,8 +2235,8 @@ class Project < ApplicationRecord ...@@ -2213,8 +2235,8 @@ class Project < ApplicationRecord
members.maintainers.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT) members.maintainers.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
end end
def pages_lookup_path(domain: nil) def pages_lookup_path(trim_prefix: nil, domain: nil)
Pages::LookupPath.new(self, domain: domain) Pages::LookupPath.new(self, trim_prefix: trim_prefix, domain: domain)
end end
private private
...@@ -2342,6 +2364,13 @@ class Project < ApplicationRecord ...@@ -2342,6 +2364,13 @@ class Project < ApplicationRecord
def services_templates def services_templates
@services_templates ||= Service.where(template: true) @services_templates ||= Service.where(template: true)
end end
def ensure_pages_metadatum
pages_metadatum || create_pages_metadatum!
rescue ActiveRecord::RecordNotUnique
reset
retry
end
end end
Project.prepend_if_ee('EE::Project') Project.prepend_if_ee('EE::Project')
# frozen_string_literal: true
class ProjectPagesMetadatum < ApplicationRecord
self.primary_key = :project_id
belongs_to :project, inverse_of: :pages_metadatum
scope :deployed, -> { where(deployed: true) }
end
...@@ -53,6 +53,7 @@ module Projects ...@@ -53,6 +53,7 @@ module Projects
def success def success
@status.success @status.success
@project.mark_pages_as_deployed
super super
end end
......
---
title: Add project_pages_metadata DB table
merge_request: 17197
author:
type: added
# frozen_string_literal: true
class CreateProjectPagesMetadata < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :project_pages_metadata, id: false do |t|
t.references :project, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
t.boolean :deployed, null: false, default: false
t.index :project_id, name: 'index_project_pages_metadata_on_project_id_and_deployed_is_true', where: "deployed = TRUE"
end
end
end
...@@ -2774,6 +2774,13 @@ ActiveRecord::Schema.define(version: 2019_09_19_162036) do ...@@ -2774,6 +2774,13 @@ ActiveRecord::Schema.define(version: 2019_09_19_162036) do
t.index ["status"], name: "index_project_mirror_data_on_status" t.index ["status"], name: "index_project_mirror_data_on_status"
end end
create_table "project_pages_metadata", id: false, force: :cascade do |t|
t.bigint "project_id", null: false
t.boolean "deployed", default: false, null: false
t.index ["project_id"], name: "index_project_pages_metadata_on_project_id", unique: true
t.index ["project_id"], name: "index_project_pages_metadata_on_project_id_and_deployed_is_true", where: "(deployed = true)"
end
create_table "project_repositories", force: :cascade do |t| create_table "project_repositories", force: :cascade do |t|
t.integer "shard_id", null: false t.integer "shard_id", null: false
t.string "disk_path", null: false t.string "disk_path", null: false
...@@ -4084,6 +4091,7 @@ ActiveRecord::Schema.define(version: 2019_09_19_162036) do ...@@ -4084,6 +4091,7 @@ ActiveRecord::Schema.define(version: 2019_09_19_162036) do
add_foreign_key "project_incident_management_settings", "projects", on_delete: :cascade add_foreign_key "project_incident_management_settings", "projects", on_delete: :cascade
add_foreign_key "project_metrics_settings", "projects", on_delete: :cascade add_foreign_key "project_metrics_settings", "projects", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", name: "fk_d1aad367d7", on_delete: :cascade add_foreign_key "project_mirror_data", "projects", name: "fk_d1aad367d7", on_delete: :cascade
add_foreign_key "project_pages_metadata", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "projects", on_delete: :cascade add_foreign_key "project_repositories", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "shards", on_delete: :restrict add_foreign_key "project_repositories", "shards", on_delete: :restrict
add_foreign_key "project_repository_states", "projects", on_delete: :cascade add_foreign_key "project_repository_states", "projects", on_delete: :cascade
......
...@@ -32,9 +32,9 @@ For example, [Active Directory](https://technet.microsoft.com/en-us/library/hh83 ...@@ -32,9 +32,9 @@ For example, [Active Directory](https://technet.microsoft.com/en-us/library/hh83
We won't cover the installation and configuration of Windows Server or Active Directory Domain Services in this tutorial. There are a number of resources online to guide you through this process: We won't cover the installation and configuration of Windows Server or Active Directory Domain Services in this tutorial. There are a number of resources online to guide you through this process:
- Install Windows Server 2012 - (_technet.microsoft.com_) - [Installing Windows Server 2012](https://technet.microsoft.com/en-us/library/jj134246(v=ws.11).aspx) - Install Windows Server 2012 - (`technet.microsoft.com`) - [Installing Windows Server 2012](https://technet.microsoft.com/en-us/library/jj134246(v=ws.11).aspx)
- Install Active Directory Domain Services (AD DS) (_technet.microsoft.com_)- [Install Active Directory Domain Services](https://technet.microsoft.com/windows-server-docs/identity/ad-ds/deploy/install-active-directory-domain-services--level-100-#BKMK_PS) - Install Active Directory Domain Services (AD DS) (`technet.microsoft.com`)- [Install Active Directory Domain Services](https://technet.microsoft.com/windows-server-docs/identity/ad-ds/deploy/install-active-directory-domain-services--level-100-#BKMK_PS)
> **Shortcut:** You can quickly install AD DS via PowerShell using > **Shortcut:** You can quickly install AD DS via PowerShell using
`Install-WindowsFeature AD-Domain-Services -IncludeManagementTools` `Install-WindowsFeature AD-Domain-Services -IncludeManagementTools`
......
...@@ -413,7 +413,7 @@ nested members in the user filter should not be confused with ...@@ -413,7 +413,7 @@ nested members in the user filter should not be confused with
[group sync nested groups support](ldap-ee.md#supported-ldap-group-typesattributes). **(STARTER ONLY)** [group sync nested groups support](ldap-ee.md#supported-ldap-group-typesattributes). **(STARTER ONLY)**
Please note that GitLab does not support the custom filter syntax used by Please note that GitLab does not support the custom filter syntax used by
omniauth-ldap. OmniAuth LDAP.
### Escaping special characters ### Escaping special characters
...@@ -536,7 +536,7 @@ ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$ba ...@@ -536,7 +536,7 @@ ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$ba
- Variables beginning with a `$` refer to a variable from the LDAP section of - Variables beginning with a `$` refer to a variable from the LDAP section of
your configuration file. your configuration file.
- Replace ldaps:// with ldap:// if you are using the plain authentication method. - Replace `ldaps://` with `ldap://` if you are using the plain authentication method.
Port `389` is the default `ldap://` port and `636` is the default `ldaps://` Port `389` is the default `ldap://` port and `636` is the default `ldaps://`
port. port.
- We are assuming the password for the bind_dn user is in bind_dn_password.txt. - We are assuming the password for the bind_dn user is in bind_dn_password.txt.
......
...@@ -206,7 +206,7 @@ attribute. As a prerequisite, you must use an LDAP server that: ...@@ -206,7 +206,7 @@ attribute. As a prerequisite, you must use an LDAP server that:
**For installations from source** **For installations from source**
1. Add the `san_extensions` line to config/gitlab.yml` within the smartcard section: 1. Add the `san_extensions` line to `config/gitlab.yml` within the smartcard section:
```yaml ```yaml
smartcard: smartcard:
......
...@@ -96,7 +96,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a ...@@ -96,7 +96,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
| `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true | | `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true |
| `region` | AWS region | us-east-1 | | `region` | AWS region | us-east-1 |
| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com | | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com |
| `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) | | `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
| `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false | | `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false |
| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false | `use_iam_profile` | Set to true to use IAM profile instead of access keys | false
......
...@@ -81,7 +81,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a ...@@ -81,7 +81,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
| `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true | | `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true |
| `region` | AWS region | us-east-1 | | `region` | AWS region | us-east-1 |
| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com | | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com |
| `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) | | `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
| `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false | | `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false |
| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false | `use_iam_profile` | Set to true to use IAM profile instead of access keys | false
...@@ -165,7 +165,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a ...@@ -165,7 +165,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
|---------|-------------|---------| |---------|-------------|---------|
| `provider` | Always `OpenStack` for compatible hosts | OpenStack | | `provider` | Always `OpenStack` for compatible hosts | OpenStack |
| `openstack_username` | OpenStack username | | | `openstack_username` | OpenStack username | |
| `openstack_api_key` | OpenStack api key | | | `openstack_api_key` | OpenStack API key | |
| `openstack_temp_url_key` | OpenStack key for generating temporary urls | | | `openstack_temp_url_key` | OpenStack key for generating temporary urls | |
| `openstack_auth_url` | OpenStack authentication endpont | | | `openstack_auth_url` | OpenStack authentication endpont | |
| `openstack_region` | OpenStack region | | | `openstack_region` | OpenStack region | |
......
...@@ -14,7 +14,7 @@ Note that color settings will only be applied within the app interface and not t ...@@ -14,7 +14,7 @@ Note that color settings will only be applied within the app interface and not t
![appearance](system_header_and_footer_messages/appearance.png) ![appearance](system_header_and_footer_messages/appearance.png)
After saving, all GitLab pages will contain the custom system header and/or footer messages: After saving, all pages within GitLab will contain the custom system header and/or footer messages:
![custom_header_footer](system_header_and_footer_messages/custom_header_footer.png) ![custom_header_footer](system_header_and_footer_messages/custom_header_footer.png)
......
...@@ -27,7 +27,7 @@ The Admin Area is made up of the following sections: ...@@ -27,7 +27,7 @@ The Admin Area is made up of the following sections:
| Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. | | Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. |
| Abuse Reports | Manage [abuse reports](abuse_reports.md) submitted by your users. | | Abuse Reports | Manage [abuse reports](abuse_reports.md) submitted by your users. |
| License **(STARTER ONLY)** | Upload, display, and remove [licenses](license.md). | | License **(STARTER ONLY)** | Upload, display, and remove [licenses](license.md). |
| Push Rules **(STARTER)** | Configure pre-defined git [push rules](../../push_rules/push_rules.md) for projects. | | Push Rules **(STARTER)** | Configure pre-defined Git [push rules](../../push_rules/push_rules.md) for projects. |
| Geo **(PREMIUM ONLY)** | Configure and maintain [Geo nodes](geo_nodes.md). | | Geo **(PREMIUM ONLY)** | Configure and maintain [Geo nodes](geo_nodes.md). |
| Deploy Keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). | | Deploy Keys | Create instance-wide [SSH deploy keys](../../ssh/README.md#deploy-keys). |
| Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. | | Service Templates | Create [service templates](../project/integrations/services_templates.md) for projects. |
......
...@@ -59,7 +59,7 @@ GitLab OK ...@@ -59,7 +59,7 @@ GitLab OK
## Readiness ## Readiness
The readiness probe checks whether the Gitlab instance is ready to use. It checks the dependent services (Database, Redis, Gitaly etc.) and gives a status for each. The readiness probe checks whether the GitLab instance is ready to use. It checks the dependent services (Database, Redis, Gitaly etc.) and gives a status for each.
```text ```text
GET /-/readiness GET /-/readiness
......
...@@ -58,7 +58,7 @@ not selected. ...@@ -58,7 +58,7 @@ not selected.
CAUTION: **Important:** CAUTION: **Important:**
Starting with [GitLab 10.7][ce-18021], HTTP(s) protocol will be allowed for Starting with [GitLab 10.7][ce-18021], HTTP(s) protocol will be allowed for
git clone/fetch requests done by GitLab Runner from CI/CD Jobs, even if Git clone/fetch requests done by GitLab Runner from CI/CD Jobs, even if
_Only SSH_ was selected. _Only SSH_ was selected.
> **Note:** Please keep in mind that disabling an access protocol does not actually > **Note:** Please keep in mind that disabling an access protocol does not actually
......
...@@ -7,7 +7,7 @@ type: reference ...@@ -7,7 +7,7 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.6. > [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.6.
When you create a new [project](../project/index.md), creating it based on custom project templates is When you create a new [project](../project/index.md), creating it based on custom project templates is
a convenient bootstrap option. a convenient option.
Users can configure a GitLab group that serves as template Users can configure a GitLab group that serves as template
source under a group's **Settings > General > Custom project templates**. source under a group's **Settings > General > Custom project templates**.
......
[Rouge]: https://rubygems.org/gems/rouge
# Syntax Highlighting # Syntax Highlighting
GitLab provides syntax highlighting on all files and snippets through the [Rouge][] rubygem. It will try to guess what language to use based on the file extension, which most of the time is sufficient. GitLab provides syntax highlighting on all files and snippets through the [Rouge](https://rubygems.org/gems/rouge) rubygem. It will try to guess what language to use based on the file extension, which most of the time is sufficient.
If GitLab is guessing wrong, you can override its choice of language using the `gitlab-language` attribute in `.gitattributes`. For example, if you are working in a Prolog project and using the `.pl` file extension (which would normally be highlighted as Perl), you can add the following to your `.gitattributes` file: If GitLab is guessing wrong, you can override its choice of language using the `gitlab-language` attribute in `.gitattributes`. For example, if you are working in a Prolog project and using the `.pl` file extension (which would normally be highlighted as Perl), you can add the following to your `.gitattributes` file:
...@@ -12,7 +10,7 @@ If GitLab is guessing wrong, you can override its choice of language using the ` ...@@ -12,7 +10,7 @@ If GitLab is guessing wrong, you can override its choice of language using the `
When you check in and push that change, all `*.pl` files in your project will be highlighted as Prolog. When you check in and push that change, all `*.pl` files in your project will be highlighted as Prolog.
The paths here are simply git's builtin [`.gitattributes` interface](https://git-scm.com/docs/gitattributes). So, if you were to invent a file format called a `Nicefile` at the root of your project that used ruby syntax, all you need is: The paths here are simply Git's built-in [`.gitattributes` interface](https://git-scm.com/docs/gitattributes). So, if you were to invent a file format called a `Nicefile` at the root of your project that used ruby syntax, all you need is:
``` conf ``` conf
/Nicefile gitlab-language=ruby /Nicefile gitlab-language=ruby
......
...@@ -129,7 +129,7 @@ Read through the documentation on [project settings](settings/index.md). ...@@ -129,7 +129,7 @@ Read through the documentation on [project settings](settings/index.md).
- [Import a project](import/index.md) from: - [Import a project](import/index.md) from:
- [GitHub to GitLab](import/github.md) - [GitHub to GitLab](import/github.md)
- [BitBucket to GitLab](import/bitbucket.md) - [Bitbucket to GitLab](import/bitbucket.md)
- [Gitea to GitLab](import/gitea.md) - [Gitea to GitLab](import/gitea.md)
- [FogBugz to GitLab](import/fogbugz.md) - [FogBugz to GitLab](import/fogbugz.md)
- [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data) - [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data)
......
...@@ -311,7 +311,7 @@ as pushing changes: ...@@ -311,7 +311,7 @@ as pushing changes:
- Set the description of the merge request to a particular description. - Set the description of the merge request to a particular description.
- Add or remove labels from the merge request. - Add or remove labels from the merge request.
### Create a new merge request using git push options ### Create a new merge request using Git push options
To create a new merge request for a branch, use the To create a new merge request for a branch, use the
`merge_request.create` push option: `merge_request.create` push option:
...@@ -320,7 +320,7 @@ To create a new merge request for a branch, use the ...@@ -320,7 +320,7 @@ To create a new merge request for a branch, use the
git push -o merge_request.create git push -o merge_request.create
``` ```
### Set the target branch of a merge request using git push options ### Set the target branch of a merge request using Git push options
To update an existing merge request's target branch, use the To update an existing merge request's target branch, use the
`merge_request.target=<branch_name>` push option: `merge_request.target=<branch_name>` push option:
...@@ -336,7 +336,7 @@ same time using a `-o` flag per push option: ...@@ -336,7 +336,7 @@ same time using a `-o` flag per push option:
git push -o merge_request.create -o merge_request.target=branch_name git push -o merge_request.create -o merge_request.target=branch_name
``` ```
### Set merge when pipeline succeeds using git push options ### Set merge when pipeline succeeds using Git push options
To set an existing merge request to To set an existing merge request to
[merge when its pipeline succeeds](merge_when_pipeline_succeeds.md), use [merge when its pipeline succeeds](merge_when_pipeline_succeeds.md), use
...@@ -353,7 +353,7 @@ pipeline succeeds at the same time using a `-o` flag per push option: ...@@ -353,7 +353,7 @@ pipeline succeeds at the same time using a `-o` flag per push option:
git push -o merge_request.create -o merge_request.merge_when_pipeline_succeeds git push -o merge_request.create -o merge_request.merge_when_pipeline_succeeds
``` ```
### Set removing the source branch using git push options ### Set removing the source branch using Git push options
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/64320) in GitLab 12.2. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/64320) in GitLab 12.2.
...@@ -368,7 +368,7 @@ git push -o merge_request.remove_source_branch ...@@ -368,7 +368,7 @@ git push -o merge_request.remove_source_branch
You can also use this push option in addition to the You can also use this push option in addition to the
`merge_request.create` push option. `merge_request.create` push option.
### Set merge request title using git push options ### Set merge request title using Git push options
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/64320) in GitLab 12.2. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/64320) in GitLab 12.2.
...@@ -382,7 +382,7 @@ git push -o merge_request.title="The title I want" ...@@ -382,7 +382,7 @@ git push -o merge_request.title="The title I want"
You can also use this push option in addition to the You can also use this push option in addition to the
`merge_request.create` push option. `merge_request.create` push option.
### Set merge request description using git push options ### Set merge request description using Git push options
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/64320) in GitLab 12.2. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/64320) in GitLab 12.2.
...@@ -396,7 +396,7 @@ git push -o merge_request.description="The description I want" ...@@ -396,7 +396,7 @@ git push -o merge_request.description="The description I want"
You can also use this push option in addition to the You can also use this push option in addition to the
`merge_request.create` push option. `merge_request.create` push option.
### Add or remove labels using git push options ### Add or remove labels using Git push options
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31831) in GitLab 12.3. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31831) in GitLab 12.3.
...@@ -666,7 +666,7 @@ tricks to checkout a merge request locally. ...@@ -666,7 +666,7 @@ tricks to checkout a merge request locally.
Please note that you can checkout a merge request locally even if the source Please note that you can checkout a merge request locally even if the source
project is a fork (even a private fork) of the target project. project is a fork (even a private fork) of the target project.
#### Checkout locally by adding a git alias #### Checkout locally by adding a Git alias
Add the following alias to your `~/.gitconfig`: Add the following alias to your `~/.gitconfig`:
...@@ -736,9 +736,8 @@ And to check out a particular merge request: ...@@ -736,9 +736,8 @@ And to check out a particular merge request:
git checkout origin/merge-requests/1 git checkout origin/merge-requests/1
``` ```
all the above can be done with [git-mr] script. All the above can be done with the [`git-mr`](https://gitlab.com/glensc/git-mr) script.
[git-mr]: https://gitlab.com/glensc/git-mr
[products]: https://about.gitlab.com/products/ "GitLab products page" [products]: https://about.gitlab.com/products/ "GitLab products page"
[protected branches]: ../protected_branches.md [protected branches]: ../protected_branches.md
[ci]: ../../../ci/README.md [ci]: ../../../ci/README.md
......
...@@ -97,9 +97,9 @@ merge. ...@@ -97,9 +97,9 @@ merge.
## Limitations ## Limitations
- API support: [gitlab#12551](https://gitlab.com/gitlab-org/gitlab/issues/12551) - API support: [issue #12551](https://gitlab.com/gitlab-org/gitlab/issues/12551)
- Dependencies are not preserved across project export/import: [gitlab#12549](https://gitlab.com/gitlab-org/gitlab/issues/12549) - Dependencies are not preserved across project export/import: [issue #12549](https://gitlab.com/gitlab-org/gitlab/issues/12549)
- Complex merge order dependencies are not supported: [gitlab#11393](https://gitlab.com/gitlab-org/gitlab/issues/11393) - Complex merge order dependencies are not supported: [issue #11393](https://gitlab.com/gitlab-org/gitlab/issues/11393)
The last item merits a little more explanation. Dependencies between merge The last item merits a little more explanation. Dependencies between merge
requests can be described as a graph of relationships. The simplest possible requests can be described as a graph of relationships. The simplest possible
......
...@@ -41,7 +41,7 @@ that the `master` branch is protected by default. ...@@ -41,7 +41,7 @@ that the `master` branch is protected by default.
## Using the Allowed to merge and Allowed to push settings ## Using the Allowed to merge and Allowed to push settings
> [Introduced][ce-5081] in GitLab 8.11. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/5081) in GitLab 8.11.
Since GitLab 8.11, we added another layer of branch protection which provides Since GitLab 8.11, we added another layer of branch protection which provides
more granular management of protected branches. The "Developers can push" more granular management of protected branches. The "Developers can push"
...@@ -71,7 +71,7 @@ they are set to "Maintainers" by default. ...@@ -71,7 +71,7 @@ they are set to "Maintainers" by default.
## Restricting push and merge access to certain users **(STARTER)** ## Restricting push and merge access to certain users **(STARTER)**
> [Introduced][ce-5081] in [GitLab Starter][ee] 8.11. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/5081) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.11.
With GitLab Enterprise Edition you can restrict access to protected branches With GitLab Enterprise Edition you can restrict access to protected branches
by choosing a role (Maintainers, Developers) as well as certain users. From the by choosing a role (Maintainers, Developers) as well as certain users. From the
...@@ -86,7 +86,7 @@ Click **Protect** and the branch will appear in the "Protected branch" list. ...@@ -86,7 +86,7 @@ Click **Protect** and the branch will appear in the "Protected branch" list.
## Wildcard protected branches ## Wildcard protected branches
> [Introduced][ce-4665] in GitLab 8.10. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/4665) in GitLab 8.10.
You can specify a wildcard protected branch, which will protect all branches You can specify a wildcard protected branch, which will protect all branches
matching the wildcard. For example: matching the wildcard. For example:
...@@ -131,12 +131,12 @@ To create a new branch through the user interface: ...@@ -131,12 +131,12 @@ To create a new branch through the user interface:
## Deleting a protected branch ## Deleting a protected branch
> [Introduced][ce-21393] in GitLab 9.3. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/21393) in GitLab 9.3.
From time to time, it may be required to delete or clean up branches that are From time to time, it may be required to delete or clean up branches that are
protected. protected.
User with [Maintainer permissions][perm] and up can manually delete protected User with [Maintainer permissions](../permissions.md) and up can manually delete protected
branches via GitLab's web interface: branches via GitLab's web interface:
1. Visit **Repository > Branches** 1. Visit **Repository > Branches**
...@@ -166,23 +166,16 @@ for details about the pipelines security model. ...@@ -166,23 +166,16 @@ for details about the pipelines security model.
**9.2** **9.2**
- Allow deletion of protected branches via the web interface [gitlab-org/gitlab-foss#21393][ce-21393] - Allow deletion of protected branches via the web interface ([issue #21393](https://gitlab.com/gitlab-org/gitlab-foss/issues/21393)).
**8.11** **8.11**
- Allow creating protected branches that can't be pushed to [gitlab-org/gitlab-foss!5081][ce-5081] - Allow creating protected branches that can't be pushed to ([merge request !5081](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/5081)).
**8.10** **8.10**
- Allow developers to merge into a protected branch without having push access [gitlab-org/gitlab-foss!4892][ce-4892] - Allow developers without push access to merge into a protected branch ([merge request !4892](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/4892)).
- Allow specifying protected branches using wildcards [gitlab-org/gitlab-foss!4665][ce-4665] - Allow specifying protected branches using wildcards ([merge request !4665](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/4665)).
[ce-4665]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/4665 "Allow specifying protected branches using wildcards"
[ce-4892]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/4892 "Allow developers to merge into a protected branch without having push access"
[ce-5081]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/5081 "Allow creating protected branches that can't be pushed to"
[ce-21393]: https://gitlab.com/gitlab-org/gitlab-foss/issues/21393
[perm]: ../permissions.md
[ee]: https://about.gitlab.com/pricing/
<!-- ## Troubleshooting <!-- ## Troubleshooting
......
...@@ -99,7 +99,7 @@ removed from the repository. ...@@ -99,7 +99,7 @@ removed from the repository.
![Repository settings cleanup form](img/repository_cleanup.png) ![Repository settings cleanup form](img/repository_cleanup.png)
Upload the `object-id-map.old-new.txt` file and press **Start cleanup**. Upload the `object-id-map.old-new.txt` file and press **Start cleanup**.
This will remove any internal git references to the old commits, and run This will remove any internal Git references to the old commits, and run
`git gc` against the repository. You will receive an email once it has `git gc` against the repository. You will receive an email once it has
completed. completed.
......
...@@ -4,7 +4,8 @@ Not all project & group names are allowed because they would conflict with ...@@ -4,7 +4,8 @@ Not all project & group names are allowed because they would conflict with
existing routes used by GitLab. existing routes used by GitLab.
For a list of words that are not allowed to be used as group or project names, see the For a list of words that are not allowed to be used as group or project names, see the
[`path_regex.rb` file][reserved] under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists: [`path_regex.rb` file](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/path_regex.rb)
under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists:
- `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups - `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups
- `PROJECT_WILDCARD_ROUTES`: are names that are reserved for child groups or projects. - `PROJECT_WILDCARD_ROUTES`: are names that are reserved for child groups or projects.
...@@ -40,52 +41,50 @@ It is currently not possible to create a project with the following names: ...@@ -40,52 +41,50 @@ It is currently not possible to create a project with the following names:
Currently the following names are reserved as top level groups: Currently the following names are reserved as top level groups:
- \- - `\-`
- .well-known - `.well-known`
- 404.html - `404.html`
- 422.html - `422.html`
- 500.html - `500.html`
- 502.html - `502.html`
- 503.html - `503.html`
- abuse_reports - `abuse_reports`
- admin - `admin`
- api - `api`
- apple-touch-icon-precomposed.png - `apple-touch-icon-precomposed.png`
- apple-touch-icon.png - `apple-touch-icon.png`
- assets - `assets`
- autocomplete - `autocomplete`
- ci - `ci`
- dashboard - `dashboard`
- deploy.html - `deploy.html`
- explore - `explore`
- favicon.ico - `favicon.ico`
- favicon.png - `favicon.png`
- files - `files`
- groups - `groups`
- health_check - `health_check`
- help - `help`
- import - `import`
- invites - `invites`
- jwt - `jwt`
- login - `login`
- notification_settings - `notification_settings`
- oauth - `oauth`
- profile - `profile`
- projects - `projects`
- public - `public`
- robots.txt - `robots.txt`
- s - `s`
- search - `search`
- sent_notifications - `sent_notifications`
- slash-command-logo.png - `slash-command-logo.png`
- snippets - `snippets`
- unsubscribes - `unsubscribes`
- uploads - `uploads`
- users - `users`
- v2 - `v2`
These group names are unavailable as subgroup names: These group names are unavailable as subgroup names:
- \- - `\-`
[reserved]: https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/path_regex.rb
...@@ -965,13 +965,7 @@ module API ...@@ -965,13 +965,7 @@ module API
end end
expose :target_url do |todo, options| expose :target_url do |todo, options|
target_type = todo.target_type.underscore todo_target_url(todo)
target_url = "#{todo.parent.class.to_s.underscore}_#{target_type}_url"
target_anchor = "note_#{todo.note_id}" if todo.note_id?
Gitlab::Routing
.url_helpers
.public_send(target_url, todo.parent, todo.target, anchor: target_anchor) # rubocop:disable GitlabSecurity/PublicSend
end end
expose :body expose :body
...@@ -983,6 +977,19 @@ module API ...@@ -983,6 +977,19 @@ module API
# see also https://gitlab.com/gitlab-org/gitlab-foss/issues/59719 # see also https://gitlab.com/gitlab-org/gitlab-foss/issues/59719
::API::Entities.const_get(target_type, false) ::API::Entities.const_get(target_type, false)
end end
def todo_target_url(todo)
target_type = todo.target_type.underscore
target_url = "#{todo.parent.class.to_s.underscore}_#{target_type}_url"
Gitlab::Routing
.url_helpers
.public_send(target_url, todo.parent, todo.target, anchor: todo_target_anchor(todo)) # rubocop:disable GitlabSecurity/PublicSend
end
def todo_target_anchor(todo)
"note_#{todo.note_id}" if todo.note_id?
end
end end
class NamespaceBasic < Grape::Entity class NamespaceBasic < Grape::Entity
......
...@@ -17,11 +17,18 @@ module API ...@@ -17,11 +17,18 @@ module API
namespace 'internal' do namespace 'internal' do
namespace 'pages' do namespace 'pages' do
desc 'Get GitLab Pages domain configuration by hostname' do
detail 'This feature was introduced in GitLab 12.3.'
end
params do
requires :host, type: String, desc: 'The host to query for'
end
get "/" do get "/" do
host = PagesDomain.find_by_domain(params[:host]) host = Namespace.find_by_pages_host(params[:host]) || PagesDomain.find_by_domain(params[:host])
not_found! unless host not_found! unless host
virtual_domain = host.pages_virtual_domain virtual_domain = host.pages_virtual_domain
no_content! unless virtual_domain
present virtual_domain, with: Entities::Internal::Pages::VirtualDomain present virtual_domain, with: Entities::Internal::Pages::VirtualDomain
end end
......
...@@ -81,3 +81,5 @@ module Gitlab ...@@ -81,3 +81,5 @@ module Gitlab
end end
end end
end end
::Gitlab::UrlBuilder.prepend_if_ee('EE::Gitlab::UrlBuilder')
...@@ -4752,6 +4752,9 @@ msgstr "" ...@@ -4752,6 +4752,9 @@ msgstr ""
msgid "Days" msgid "Days"
msgstr "" msgstr ""
msgid "Days to merge"
msgstr ""
msgid "Debug" msgid "Debug"
msgstr "" msgstr ""
...@@ -8096,9 +8099,6 @@ msgstr "" ...@@ -8096,9 +8099,6 @@ msgstr ""
msgid "Hook was successfully updated." msgid "Hook was successfully updated."
msgstr "" msgstr ""
msgid "Hours"
msgstr ""
msgid "Housekeeping" msgid "Housekeeping"
msgstr "" msgstr ""
...@@ -11599,15 +11599,42 @@ msgstr "" ...@@ -11599,15 +11599,42 @@ msgstr ""
msgid "Productivity analytics can help identify the problems that are delaying your team" msgid "Productivity analytics can help identify the problems that are delaying your team"
msgstr "" msgstr ""
msgid "ProductivityAanalytics|Merge requests"
msgstr ""
msgid "ProductivityAnalytics|Ascending" msgid "ProductivityAnalytics|Ascending"
msgstr "" msgstr ""
msgid "ProductivityAnalytics|Days"
msgstr ""
msgid "ProductivityAnalytics|Days to merge" msgid "ProductivityAnalytics|Days to merge"
msgstr "" msgstr ""
msgid "ProductivityAnalytics|Descending" msgid "ProductivityAnalytics|Descending"
msgstr "" msgstr ""
msgid "ProductivityAnalytics|Hours"
msgstr ""
msgid "ProductivityAnalytics|List"
msgstr ""
msgid "ProductivityAnalytics|Merge Requests"
msgstr ""
msgid "ProductivityAnalytics|Merge date"
msgstr ""
msgid "ProductivityAnalytics|Merge requests"
msgstr ""
msgid "ProductivityAnalytics|Time to merge"
msgstr ""
msgid "ProductivityAnalytics|Trendline"
msgstr ""
msgid "Profile" msgid "Profile"
msgstr "" msgstr ""
......
...@@ -114,6 +114,7 @@ module QA ...@@ -114,6 +114,7 @@ module QA
module Integration module Integration
autoload :Github, 'qa/scenario/test/integration/github' autoload :Github, 'qa/scenario/test/integration/github'
autoload :LDAPNoTLS, 'qa/scenario/test/integration/ldap_no_tls' autoload :LDAPNoTLS, 'qa/scenario/test/integration/ldap_no_tls'
autoload :LDAPNoServer, 'qa/scenario/test/integration/ldap_no_server'
autoload :LDAPTLS, 'qa/scenario/test/integration/ldap_tls' autoload :LDAPTLS, 'qa/scenario/test/integration/ldap_tls'
autoload :InstanceSAML, 'qa/scenario/test/integration/instance_saml' autoload :InstanceSAML, 'qa/scenario/test/integration/instance_saml'
autoload :OAuth, 'qa/scenario/test/integration/oauth' autoload :OAuth, 'qa/scenario/test/integration/oauth'
...@@ -394,6 +395,7 @@ module QA ...@@ -394,6 +395,7 @@ module QA
autoload :KubernetesCluster, 'qa/service/kubernetes_cluster' autoload :KubernetesCluster, 'qa/service/kubernetes_cluster'
autoload :Omnibus, 'qa/service/omnibus' autoload :Omnibus, 'qa/service/omnibus'
autoload :Runner, 'qa/service/runner' autoload :Runner, 'qa/service/runner'
autoload :LDAP, 'qa/service/ldap'
module ClusterProvider module ClusterProvider
autoload :Base, 'qa/service/cluster_provider/base' autoload :Base, 'qa/service/cluster_provider/base'
......
dn: ou=Global Groups,dc=example,dc=org
objectClass: organizationalUnit
ou: Global Groups
dn: ou=People,ou=Global Groups,dc=example,dc=org
objectClass: organizationalUnit
ou: People
# 1. hruser1
dn: uid=hruser1,ou=People,ou=Global Groups,dc=example,dc=org
cn: HR User 1
givenName: HR
sn: User1
uid: hruser1
uidNumber: 5000
gidNumber: 10000
homeDirectory: /home/hruser1
mail: hruser1@example.org
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
# hashed value for 'password'
userPassword: {SSHA}ICMhr6Jxt5bk2awD7HL7GxRTM3BZ1pFI
# 2. adminuser1
dn: uid=adminuser1,ou=People,ou=Global Groups,dc=example,dc=org
cn: Admin User 1
givenName: Admin
sn: User1
uid: adminuser1
uidNumber: 5009
gidNumber: 10009
homeDirectory: /home/adminuser1
mail: adminuser1@example.org
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
# hashed value for 'password'
userPassword: {SSHA}ICMhr6Jxt5bk2awD7HL7GxRTM3BZ1pFI
# 2. adminuser2
dn: uid=adminuser2,ou=People,ou=Global Groups,dc=example,dc=org
cn: Admin User 2
givenName: Admin
sn: User1
uid: adminuser2
uidNumber: 5010
gidNumber: 10010
homeDirectory: /home/adminuser2
mail: adminuser2@example.org
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
# hashed value for 'password'
userPassword: {SSHA}ICMhr6Jxt5bk2awD7HL7GxRTM3BZ1pFI
# 1. Human Resources
dn: cn=Human Resources,ou=Global Groups,dc=example,dc=org
objectClass: groupofnames
cn: Human Resources
description: Human Resources
member: uid=hruser1,ou=People,ou=Global Groups,dc=example,dc=org
# 2. Admin
dn: cn=AdminGroup,ou=Global Groups,dc=example,dc=org
objectClass: groupofnames
cn: AdminGroup
description: Human Resources
member: uid=adminuser1,ou=People,ou=Global Groups,dc=example,dc=org
member: uid=adminuser2,ou=People,ou=Global Groups,dc=example,dc=org
dn: ou=Global Groups,dc=example,dc=org
objectClass: organizationalUnit
ou: Global Groups
dn: ou=People,ou=Global Groups,dc=example,dc=org
objectClass: organizationalUnit
ou: People
# 1. Human Resources
dn: uid=hruser1,ou=People,ou=Global Groups,dc=example,dc=org
cn: HR User 1
givenName: HR
sn: User1
uid: hruser1
uidNumber: 5000
gidNumber: 10000
homeDirectory: /home/hruser1
mail: hruser1@example.org
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
# hashed value for 'password'
userPassword: {SSHA}ICMhr6Jxt5bk2awD7HL7GxRTM3BZ1pFI
# 2. Admin
dn: uid=adminuser1,ou=People,ou=Global Groups,dc=example,dc=org
cn: Admin User 1
givenName: Admin
sn: User1
uid: adminuser1
uidNumber: 5009
gidNumber: 10009
homeDirectory: /home/adminuser1
mail: adminuser1@example.org
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
# hashed value for 'password'
userPassword: {SSHA}ICMhr6Jxt5bk2awD7HL7GxRTM3BZ1pFI
dn: uid=adminuser2,ou=People,ou=Global Groups,dc=example,dc=org
cn: Admin User 2
givenName: Admin
sn: User1
uid: adminuser2
uidNumber: 5010
gidNumber: 10010
homeDirectory: /home/adminuser2
mail: adminuser2@example.org
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
# hashed value for 'password'
userPassword: {SSHA}ICMhr6Jxt5bk2awD7HL7GxRTM3BZ1pFI
# 1. Human Resources
dn: cn=Human Resources,ou=Global Groups,dc=example,dc=org
objectClass: groupofnames
cn: Human Resources
description: Human Resources
member: uid=hruser1,ou=People,ou=Global Groups,dc=example,dc=org
member: uid=adminuser1,ou=People,ou=Global Groups,dc=example,dc=org
# 2. Admin
dn: cn=AdminGroup,ou=Global Groups,dc=example,dc=org
objectClass: groupofnames
cn: AdminGroup
description: Human Resources
member: uid=adminuser2,ou=People,ou=Global Groups,dc=example,dc=org
...@@ -87,7 +87,7 @@ module QA ...@@ -87,7 +87,7 @@ module QA
click_element :sign_in_button click_element :sign_in_button
end end
Page::Main::Menu.perform(&:has_personal_area?) Page::Main::Menu.perform(&:signed_in?)
end end
def self.path def self.path
......
...@@ -96,6 +96,10 @@ module QA ...@@ -96,6 +96,10 @@ module QA
has_element?(:admin_area_link, wait: wait) has_element?(:admin_area_link, wait: wait)
end end
def has_no_admin_area_link?(wait: Capybara.default_max_wait_time)
has_no_element?(:admin_area_link, wait: wait)
end
def click_stop_impersonation_link def click_stop_impersonation_link
click_element(:stop_impersonation_link) click_element(:stop_impersonation_link)
end end
......
# frozen_string_literal: true
module QA
module Scenario
module Test
module Integration
class LDAPNoServer < Test::Instance::All
tags :ldap_no_server
end
end
end
end
end
# frozen_string_literal: true
module QA
module Service
class LDAP
include Service::Shellout
def initialize(volume)
@image = 'osixia/openldap:latest'
@name = 'ldap-server'
@network = Runtime::Scenario.attributes[:network] || 'test'
@volume = volume
end
def network
shell "docker network inspect #{@network}"
rescue CommandError
'bridge'
else
@network
end
def pull
shell "docker pull #{@image}"
end
def host_name
"#{@name}.#{network}"
end
def register!
shell <<~CMD.tr("\n", ' ')
docker run -d --rm
--network #{network}
--hostname #{host_name}
--name #{@name}
-p 389:389
--volume #{volume_or_fixture(@volume)}:/container/service/slapd/assets/config/bootstrap/ldif/custom
#{@image} --copy-service
CMD
end
def remove!
shell "docker rm -f #{@name}" if running?
end
def running?
`docker ps -f name=#{@name}`.include?(@name)
end
def volume_or_fixture(volume_name)
if volume_exists?(volume_name)
volume_name
else
File.expand_path("../fixtures/ldap/#{volume_name}", __dir__)
end
end
def volume_exists?(volume_name)
`docker volume ls -q -f name=#{volume_name}`.include?(volume_name)
end
end
end
end
...@@ -8,6 +8,14 @@ describe QA::Scenario::Test::Integration::LDAPNoTLS do ...@@ -8,6 +8,14 @@ describe QA::Scenario::Test::Integration::LDAPNoTLS do
end end
end end
describe QA::Scenario::Test::Integration::LDAPNoServer do
context '#perform' do
it_behaves_like 'a QA scenario class' do
let(:tags) { [:ldap_no_server] }
end
end
end
describe QA::Scenario::Test::Integration::LDAPTLS do describe QA::Scenario::Test::Integration::LDAPTLS do
context '#perform' do context '#perform' do
it_behaves_like 'a QA scenario class' do it_behaves_like 'a QA scenario class' do
......
...@@ -98,8 +98,11 @@ describe ApplicationController do ...@@ -98,8 +98,11 @@ describe ApplicationController do
# remove line below once `privacy_policy_update_callout` # remove line below once `privacy_policy_update_callout`
# feature flag is removed and `gon` reverts back to # feature flag is removed and `gon` reverts back to
# to not setting any variables. # to not setting any variables.
it_behaves_like 'setting gon variables' if Gitlab.ee?
# it_behaves_like 'not setting gon variables' it_behaves_like 'setting gon variables'
else
it_behaves_like 'not setting gon variables'
end
end end
end end
...@@ -110,8 +113,11 @@ describe ApplicationController do ...@@ -110,8 +113,11 @@ describe ApplicationController do
# remove line below once `privacy_policy_update_callout` # remove line below once `privacy_policy_update_callout`
# feature flag is removed and `gon` reverts back to # feature flag is removed and `gon` reverts back to
# to not setting any variables. # to not setting any variables.
it_behaves_like 'setting gon variables' if Gitlab.ee?
# it_behaves_like 'not setting gon variables' it_behaves_like 'setting gon variables'
else
it_behaves_like 'not setting gon variables'
end
end end
end end
......
...@@ -426,3 +426,13 @@ describe('newDate', () => { ...@@ -426,3 +426,13 @@ describe('newDate', () => {
expect(initialDate instanceof Date).toBe(true); expect(initialDate instanceof Date).toBe(true);
}); });
}); });
describe('getDateInPast', () => {
it('returns the correct date in the past', () => {
const date = new Date(1563235200000); // 2019-07-16T00:00:00.00Z
const daysInPast = 90;
const dateInPast = datetimeUtility.getDateInPast(date, daysInPast);
expect(dateInPast).toBe('2019-04-17T00:00:00.000Z');
});
});
...@@ -6,6 +6,7 @@ import { ...@@ -6,6 +6,7 @@ import {
numberToHumanSize, numberToHumanSize,
sum, sum,
isOdd, isOdd,
median,
} from '~/lib/utils/number_utils'; } from '~/lib/utils/number_utils';
describe('Number Utils', () => { describe('Number Utils', () => {
...@@ -109,4 +110,16 @@ describe('Number Utils', () => { ...@@ -109,4 +110,16 @@ describe('Number Utils', () => {
expect(isOdd(1)).toEqual(1); expect(isOdd(1)).toEqual(1);
}); });
}); });
describe('median', () => {
it('computes the median for a given array with odd length', () => {
const items = [10, 27, 20, 5, 19];
expect(median(items)).toBe(19);
});
it('computes the median for a given array with even length', () => {
const items = [10, 27, 20, 5, 19, 4];
expect(median(items)).toBe(14.5);
});
});
}); });
...@@ -410,6 +410,7 @@ project: ...@@ -410,6 +410,7 @@ project:
- designs - designs
- project_aliases - project_aliases
- external_pull_requests - external_pull_requests
- pages_metadatum
award_emoji: award_emoji:
- awardable - awardable
- user - user
......
...@@ -191,6 +191,16 @@ describe Namespace do ...@@ -191,6 +191,16 @@ describe Namespace do
end end
end end
describe '.find_by_pages_host' do
it 'finds namespace by GitLab Pages host and is case-insensitive' do
namespace = create(:namespace, name: 'topnamespace')
create(:namespace, name: 'annother_namespace')
host = "TopNamespace.#{Settings.pages.host.upcase}"
expect(described_class.find_by_pages_host(host)).to eq(namespace)
end
end
describe '#ancestors_upto' do describe '#ancestors_upto' do
let(:parent) { create(:group) } let(:parent) { create(:group) }
let(:child) { create(:group, parent: parent) } let(:child) { create(:group, parent: parent) }
...@@ -913,4 +923,18 @@ describe Namespace do ...@@ -913,4 +923,18 @@ describe Namespace do
end end
end end
end end
describe '#pages_virtual_domain' do
let(:project) { create(:project, namespace: namespace) }
context 'when there are pages deployed for the project' do
before do
project.mark_pages_as_deployed
end
it 'returns the virual domain' do
expect(namespace.pages_virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
end
end
end
end end
...@@ -57,8 +57,18 @@ describe Pages::LookupPath do ...@@ -57,8 +57,18 @@ describe Pages::LookupPath do
end end
describe '#prefix' do describe '#prefix' do
it 'returns "/"' do it 'returns "/" for pages group root projects' do
project = instance_double(Project, pages_group_root?: true)
lookup_path = described_class.new(project, trim_prefix: 'mygroup')
expect(lookup_path.prefix).to eq('/') expect(lookup_path.prefix).to eq('/')
end end
it 'returns the project full path with the provided prefix removed' do
project = instance_double(Project, pages_group_root?: false, full_path: 'mygroup/myproject')
lookup_path = described_class.new(project, trim_prefix: 'mygroup')
expect(lookup_path.prefix).to eq('/myproject/')
end
end end
end end
...@@ -25,19 +25,33 @@ describe Pages::VirtualDomain do ...@@ -25,19 +25,33 @@ describe Pages::VirtualDomain do
end end
describe '#lookup_paths' do describe '#lookup_paths' do
let(:domain) { instance_double(PagesDomain) }
let(:project_a) { instance_double(Project) } let(:project_a) { instance_double(Project) }
let(:project_z) { instance_double(Project) } let(:project_z) { instance_double(Project) }
let(:pages_lookup_path_a) { instance_double(Pages::LookupPath, prefix: 'aaa') } let(:pages_lookup_path_a) { instance_double(Pages::LookupPath, prefix: 'aaa') }
let(:pages_lookup_path_z) { instance_double(Pages::LookupPath, prefix: 'zzz') } let(:pages_lookup_path_z) { instance_double(Pages::LookupPath, prefix: 'zzz') }
subject(:virtual_domain) { described_class.new([project_a, project_z], domain: domain) } context 'when there is pages domain provided' do
let(:domain) { instance_double(PagesDomain) }
it 'returns collection of projects pages lookup paths sorted by prefix in reverse' do subject(:virtual_domain) { described_class.new([project_a, project_z], domain: domain) }
expect(project_a).to receive(:pages_lookup_path).with(domain: domain).and_return(pages_lookup_path_a)
expect(project_z).to receive(:pages_lookup_path).with(domain: domain).and_return(pages_lookup_path_z)
expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_z, pages_lookup_path_a]) it 'returns collection of projects pages lookup paths sorted by prefix in reverse' do
expect(project_a).to receive(:pages_lookup_path).with(domain: domain, trim_prefix: nil).and_return(pages_lookup_path_a)
expect(project_z).to receive(:pages_lookup_path).with(domain: domain, trim_prefix: nil).and_return(pages_lookup_path_z)
expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_z, pages_lookup_path_a])
end
end
context 'when there is trim_prefix provided' do
subject(:virtual_domain) { described_class.new([project_a, project_z], trim_prefix: 'group/') }
it 'returns collection of projects pages lookup paths sorted by prefix in reverse' do
expect(project_a).to receive(:pages_lookup_path).with(trim_prefix: 'group/', domain: nil).and_return(pages_lookup_path_a)
expect(project_z).to receive(:pages_lookup_path).with(trim_prefix: 'group/', domain: nil).and_return(pages_lookup_path_z)
expect(virtual_domain.lookup_paths).to eq([pages_lookup_path_z, pages_lookup_path_a])
end
end end
end end
end end
...@@ -557,15 +557,27 @@ describe PagesDomain do ...@@ -557,15 +557,27 @@ describe PagesDomain do
end end
end end
describe '.pages_virtual_domain' do describe '#pages_virtual_domain' do
let(:project) { build(:project) } let(:project) { create(:project) }
let(:pages_domain) { create(:pages_domain, project: project) }
subject(:pages_domain) { build(:pages_domain, project: project) } context 'when there are no pages deployed for the project' do
it 'returns nil' do
expect(pages_domain.pages_virtual_domain).to be_nil
end
end
it 'returns instance of Pages::VirtualDomain' do context 'when there are pages deployed for the project' do
expect(Pages::VirtualDomain).to receive(:new).with([project], domain: pages_domain).and_call_original before do
project.mark_pages_as_deployed
project.reload
end
it 'returns the virual domain' do
expect(Pages::VirtualDomain).to receive(:new).with([project], domain: pages_domain).and_call_original
expect(pages_domain.pages_virtual_domain).to be_a(Pages::VirtualDomain) expect(pages_domain.pages_virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
end
end end
end end
end end
...@@ -132,6 +132,13 @@ describe Project do ...@@ -132,6 +132,13 @@ describe Project do
expect(project.ci_cd_settings).to be_an_instance_of(ProjectCiCdSetting) expect(project.ci_cd_settings).to be_an_instance_of(ProjectCiCdSetting)
expect(project.ci_cd_settings).to be_persisted expect(project.ci_cd_settings).to be_persisted
end end
it 'automatically creates a Pages metadata row' do
project = create(:project)
expect(project.pages_metadatum).to be_an_instance_of(ProjectPagesMetadatum)
expect(project.pages_metadatum).to be_persisted
end
end end
context 'updating cd_cd_settings' do context 'updating cd_cd_settings' do
...@@ -3526,7 +3533,8 @@ describe Project do ...@@ -3526,7 +3533,8 @@ describe Project do
end end
describe '#remove_pages' do describe '#remove_pages' do
let(:project) { create(:project) } let(:project) { create(:project).tap { |project| project.mark_pages_as_deployed } }
let(:pages_metadatum) { project.pages_metadatum }
let(:namespace) { project.namespace } let(:namespace) { project.namespace }
let(:pages_path) { project.pages_path } let(:pages_path) { project.pages_path }
...@@ -3539,12 +3547,12 @@ describe Project do ...@@ -3539,12 +3547,12 @@ describe Project do
end end
end end
it 'removes the pages directory' do it 'removes the pages directory and marks the project as not having pages deployed' do
expect_any_instance_of(Projects::UpdatePagesConfigurationService).to receive(:execute) expect_any_instance_of(Projects::UpdatePagesConfigurationService).to receive(:execute)
expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return(true) expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return(true)
expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, namespace.full_path, anything) expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, namespace.full_path, anything)
project.remove_pages expect { project.remove_pages }.to change { pages_metadatum.reload.deployed }.from(true).to(false)
end end
it 'is a no-op when there is no namespace' do it 'is a no-op when there is no namespace' do
...@@ -3554,13 +3562,13 @@ describe Project do ...@@ -3554,13 +3562,13 @@ describe Project do
expect_any_instance_of(Projects::UpdatePagesConfigurationService).not_to receive(:execute) expect_any_instance_of(Projects::UpdatePagesConfigurationService).not_to receive(:execute)
expect_any_instance_of(Gitlab::PagesTransfer).not_to receive(:rename_project) expect_any_instance_of(Gitlab::PagesTransfer).not_to receive(:rename_project)
project.remove_pages expect { project.remove_pages }.not_to change { pages_metadatum.reload.deployed }
end end
it 'is run when the project is destroyed' do it 'is run when the project is destroyed' do
expect(project).to receive(:remove_pages).and_call_original expect(project).to receive(:remove_pages).and_call_original
project.destroy expect { project.destroy }.not_to raise_error
end end
end end
...@@ -5014,6 +5022,35 @@ describe Project do ...@@ -5014,6 +5022,35 @@ describe Project do
end end
end end
context 'pages deployed' do
let(:project) { create(:project) }
{
mark_pages_as_deployed: true,
mark_pages_as_not_deployed: false
}.each do |method_name, flag|
describe method_name do
it "creates new record and sets deployed to #{flag} if none exists yet" do
project.pages_metadatum.destroy!
project.reload
project.send(method_name)
expect(project.pages_metadatum.reload.deployed).to eq(flag)
end
it "updates the existing record and sets deployed to #{flag}" do
pages_metadatum = project.pages_metadatum
pages_metadatum.update!(deployed: !flag)
expect { project.send(method_name) }.to change {
pages_metadatum.reload.deployed
}.from(!flag).to(flag)
end
end
end
end
describe '#has_pool_repsitory?' do describe '#has_pool_repsitory?' do
it 'returns false when it does not have a pool repository' do it 'returns false when it does not have a pool repository' do
subject = create(:project, :repository) subject = create(:project, :repository)
...@@ -5054,9 +5091,34 @@ describe Project do ...@@ -5054,9 +5091,34 @@ describe Project do
let(:project) { build(:project) } let(:project) { build(:project) }
it 'returns instance of Pages::LookupPath' do it 'returns instance of Pages::LookupPath' do
expect(Pages::LookupPath).to receive(:new).with(project, domain: pages_domain).and_call_original expect(Pages::LookupPath).to receive(:new).with(project, domain: pages_domain, trim_prefix: 'mygroup').and_call_original
expect(project.pages_lookup_path(domain: pages_domain, trim_prefix: 'mygroup')).to be_a(Pages::LookupPath)
end
end
describe '.with_pages_deployed' do
it 'returns only projects that have pages deployed' do
_project_without_pages = create(:project)
project_with_pages = create(:project)
project_with_pages.mark_pages_as_deployed
expect(described_class.with_pages_deployed).to contain_exactly(project_with_pages)
end
end
describe '#pages_group_root?' do
it 'returns returns true if pages_url is same as pages_group_url' do
project = build(:project)
expect(project).to receive(:pages_url).and_return(project.pages_group_url)
expect(project.pages_group_root?).to eq(true)
end
it 'returns returns false if pages_url is different than pages_group_url' do
project = build(:project)
expect(project.pages_lookup_path(domain: pages_domain)).to be_a(Pages::LookupPath) expect(project.pages_group_root?).to eq(false)
end end
end end
......
...@@ -43,6 +43,10 @@ describe API::Internal::Pages do ...@@ -43,6 +43,10 @@ describe API::Internal::Pages do
super(host, headers) super(host, headers)
end end
def deploy_pages(project)
project.mark_pages_as_deployed
end
context 'not existing host' do context 'not existing host' do
it 'responds with 404 Not Found' do it 'responds with 404 Not Found' do
query_host('pages.gitlab.io') query_host('pages.gitlab.io')
...@@ -56,18 +60,104 @@ describe API::Internal::Pages do ...@@ -56,18 +60,104 @@ describe API::Internal::Pages do
let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') } let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') }
let!(:pages_domain) { create(:pages_domain, domain: 'pages.gitlab.io', project: project) } let!(:pages_domain) { create(:pages_domain, domain: 'pages.gitlab.io', project: project) }
it 'responds with the correct domain configuration' do context 'when there are no pages deployed for the related project' do
query_host('pages.gitlab.io') it 'responds with 204 No Content' do
query_host('pages.gitlab.io')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(204)
expect(response).to match_response_schema('internal/pages/virtual_domain') end
end
expect(json_response['certificate']).to eq(pages_domain.certificate) context 'when there are pages deployed for the related project' do
expect(json_response['key']).to eq(pages_domain.key) it 'responds with the correct domain configuration' do
deploy_pages(project)
query_host('pages.gitlab.io')
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('internal/pages/virtual_domain')
expect(json_response['certificate']).to eq(pages_domain.certificate)
expect(json_response['key']).to eq(pages_domain.key)
expect(json_response['lookup_paths']).to eq(
[
{
'project_id' => project.id,
'access_control' => false,
'https_only' => false,
'prefix' => '/',
'source' => {
'type' => 'file',
'path' => 'gitlab-org/gitlab-ce/public/'
}
}
]
)
end
end
end
context 'namespaced domain' do
let(:group) { create(:group, name: 'mygroup') }
before do
allow(Settings.pages).to receive(:host).and_return('gitlab-pages.io')
allow(Gitlab.config.pages).to receive(:url).and_return("http://gitlab-pages.io")
end
context 'regular project' do
it 'responds with the correct domain configuration' do
project = create(:project, group: group, name: 'myproject')
deploy_pages(project)
query_host('mygroup.gitlab-pages.io')
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('internal/pages/virtual_domain')
expect(json_response['lookup_paths']).to eq(
[
{
'project_id' => project.id,
'access_control' => false,
'https_only' => false,
'prefix' => '/myproject/',
'source' => {
'type' => 'file',
'path' => 'mygroup/myproject/public/'
}
}
]
)
end
end
lookup_path = json_response['lookup_paths'][0] context 'group root project' do
expect(lookup_path['prefix']).to eq('/') it 'responds with the correct domain configuration' do
expect(lookup_path['source']['path']).to eq('gitlab-org/gitlab-ce/public/') project = create(:project, group: group, name: 'mygroup.gitlab-pages.io')
deploy_pages(project)
query_host('mygroup.gitlab-pages.io')
expect(response).to have_gitlab_http_status(200)
expect(response).to match_response_schema('internal/pages/virtual_domain')
expect(json_response['lookup_paths']).to eq(
[
{
'project_id' => project.id,
'access_control' => false,
'https_only' => false,
'prefix' => '/',
'source' => {
'type' => 'file',
'path' => 'mygroup/mygroup.gitlab-pages.io/public/'
}
}
]
)
end
end end
end end
end end
......
...@@ -40,6 +40,7 @@ describe Projects::UpdatePagesService do ...@@ -40,6 +40,7 @@ describe Projects::UpdatePagesService do
it "doesn't delete artifacts after deploying" do it "doesn't delete artifacts after deploying" do
expect(execute).to eq(:success) expect(execute).to eq(:success)
expect(project.pages_metadatum).to be_deployed
expect(build.artifacts?).to eq(true) expect(build.artifacts?).to eq(true)
end end
end end
...@@ -47,6 +48,7 @@ describe Projects::UpdatePagesService do ...@@ -47,6 +48,7 @@ describe Projects::UpdatePagesService do
it 'succeeds' do it 'succeeds' do
expect(project.pages_deployed?).to be_falsey expect(project.pages_deployed?).to be_falsey
expect(execute).to eq(:success) expect(execute).to eq(:success)
expect(project.pages_metadatum).to be_deployed
expect(project.pages_deployed?).to be_truthy expect(project.pages_deployed?).to be_truthy
# Check that all expected files are extracted # Check that all expected files are extracted
...@@ -63,16 +65,23 @@ describe Projects::UpdatePagesService do ...@@ -63,16 +65,23 @@ describe Projects::UpdatePagesService do
it 'removes pages after destroy' do it 'removes pages after destroy' do
expect(PagesWorker).to receive(:perform_in) expect(PagesWorker).to receive(:perform_in)
expect(project.pages_deployed?).to be_falsey expect(project.pages_deployed?).to be_falsey
expect(execute).to eq(:success) expect(execute).to eq(:success)
expect(project.pages_metadatum).to be_deployed
expect(project.pages_deployed?).to be_truthy expect(project.pages_deployed?).to be_truthy
project.destroy project.destroy
expect(project.pages_deployed?).to be_falsey expect(project.pages_deployed?).to be_falsey
expect(ProjectPagesMetadatum.find_by_project_id(project)).to be_nil
end end
it 'fails if sha on branch is not latest' do it 'fails if sha on branch is not latest' do
build.update(ref: 'feature') build.update(ref: 'feature')
expect(execute).not_to eq(:success) expect(execute).not_to eq(:success)
expect(project.pages_metadatum).not_to be_deployed
end end
context 'when using empty file' do context 'when using empty file' do
...@@ -94,6 +103,7 @@ describe Projects::UpdatePagesService do ...@@ -94,6 +103,7 @@ describe Projects::UpdatePagesService do
it 'succeeds to extract' do it 'succeeds to extract' do
expect(execute).to eq(:success) expect(execute).to eq(:success)
expect(project.pages_metadatum).to be_deployed
end end
end end
end end
...@@ -109,6 +119,7 @@ describe Projects::UpdatePagesService do ...@@ -109,6 +119,7 @@ describe Projects::UpdatePagesService do
build.reload build.reload
expect(deploy_status).to be_failed expect(deploy_status).to be_failed
expect(project.pages_metadatum).not_to be_deployed
end end
end end
...@@ -125,6 +136,7 @@ describe Projects::UpdatePagesService do ...@@ -125,6 +136,7 @@ describe Projects::UpdatePagesService do
build.reload build.reload
expect(deploy_status).to be_failed expect(deploy_status).to be_failed
expect(project.pages_metadatum).not_to be_deployed
end end
end end
...@@ -138,6 +150,7 @@ describe Projects::UpdatePagesService do ...@@ -138,6 +150,7 @@ describe Projects::UpdatePagesService do
build.reload build.reload
expect(deploy_status).to be_failed expect(deploy_status).to be_failed
expect(project.pages_metadatum).not_to be_deployed
end end
end end
end end
...@@ -179,6 +192,7 @@ describe Projects::UpdatePagesService do ...@@ -179,6 +192,7 @@ describe Projects::UpdatePagesService do
expect(deploy_status.description) expect(deploy_status.description)
.to match(/artifacts for pages are too large/) .to match(/artifacts for pages are too large/)
expect(deploy_status).to be_script_failure expect(deploy_status).to be_script_failure
expect(project.pages_metadatum).not_to be_deployed
end end
end end
...@@ -196,6 +210,7 @@ describe Projects::UpdatePagesService do ...@@ -196,6 +210,7 @@ describe Projects::UpdatePagesService do
subject.execute subject.execute
expect(deploy_status.description).not_to be_present expect(deploy_status.description).not_to be_present
expect(project.pages_metadatum).to be_deployed
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment