summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrasimir Angelov <kangelov@gitlab.com>2019-09-10 10:26:17 +1200
committerKrasimir Angelov <kangelov@gitlab.com>2019-09-19 12:09:36 +1200
commit7469a7726f367c5b426be18970463c6c25ed5643 (patch)
tree6854568878c9d6551c10debe308e8184b6e0f71e
parenta7706bcb567ee31c6454c4197354b3210839b564 (diff)
downloadgitlab-ce-61927-pages-namespaces-virtual-domain.tar.gz
Add support for namespaces to Pages internal API61927-pages-namespaces-virtual-domain
Introduce new `project_pages_metadata` table, insert new record on project creation. Update its `depoyed` flag when pages are deployed/removed. Return only these projects from namespace that have pages marked as deployed. On-demand and mass data migration will handled in subsequent commits. Related to https://gitlab.com/gitlab-org/gitlab-ee/issues/28781.
-rw-r--r--app/models/namespace.rb15
-rw-r--r--app/models/pages/lookup_path.rb11
-rw-r--r--app/models/pages/virtual_domain.rb7
-rw-r--r--app/models/pages_domain.rb6
-rw-r--r--app/models/project.rb26
-rw-r--r--app/models/project_pages_metadatum.rb25
-rw-r--r--app/services/projects/update_pages_service.rb1
-rw-r--r--changelogs/unreleased/61927-pages-namespaces-virtual-domain.yml5
-rw-r--r--db/migrate/20190909045845_create_project_pages_metadata.rb14
-rw-r--r--db/schema.rb8
-rw-r--r--lib/api/internal/pages.rb9
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/models/namespace_spec.rb24
-rw-r--r--spec/models/pages/lookup_path_spec.rb12
-rw-r--r--spec/models/pages/virtual_domain_spec.rb26
-rw-r--r--spec/models/pages_domain_spec.rb24
-rw-r--r--spec/models/project_pages_metadatum_spec.rb28
-rw-r--r--spec/models/project_spec.rb67
-rw-r--r--spec/requests/api/internal/pages_spec.rb75
-rw-r--r--spec/services/projects/update_pages_service_spec.rb15
20 files changed, 361 insertions, 38 deletions
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 9a7c3dc03c3..fb90ddc1048 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -120,6 +120,13 @@ class Namespace < ApplicationRecord
uniquify = Uniquify.new
uniquify.string(path) { |s| Namespace.find_by_path_or_name(s) }
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
def visibility_level_field
@@ -305,8 +312,16 @@ class Namespace < ApplicationRecord
aggregation_schedule.present?
end
+ def pages_virtual_domain
+ Pages::VirtualDomain.new(all_projects_with_pages, trim_prefix: full_path)
+ end
+
private
+ def all_projects_with_pages
+ all_projects.with_pages_deployed
+ end
+
def parent_changed?
parent_id_changed?
end
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 1b3183a2a43..51c496c77d3 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -2,9 +2,10 @@
module Pages
class LookupPath
- def initialize(project, domain: nil)
+ def initialize(project, trim_prefix: nil, domain: nil)
@project = project
@domain = domain
+ @trim_prefix = trim_prefix || project.full_path
end
def project_id
@@ -28,11 +29,15 @@ module Pages
end
def prefix
- '/'
+ if project.pages_group_root?
+ '/'
+ else
+ project.full_path.delete_prefix(trim_prefix) + '/'
+ end
end
private
- attr_reader :project, :domain
+ attr_reader :project, :trim_prefix, :domain
end
end
diff --git a/app/models/pages/virtual_domain.rb b/app/models/pages/virtual_domain.rb
index 3a876dc06a2..7e42b8e6ae2 100644
--- a/app/models/pages/virtual_domain.rb
+++ b/app/models/pages/virtual_domain.rb
@@ -2,8 +2,9 @@
module Pages
class VirtualDomain
- def initialize(projects, domain: nil)
+ def initialize(projects, trim_prefix: nil, domain: nil)
@projects = projects
+ @trim_prefix = trim_prefix
@domain = domain
end
@@ -17,12 +18,12 @@ module Pages
def lookup_paths
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
private
- attr_reader :projects, :domain
+ attr_reader :projects, :trim_prefix, :domain
end
end
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 22a6bae7cf7..85abdbc8e07 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -186,11 +186,17 @@ class PagesDomain < ApplicationRecord
end
def pages_virtual_domain
+ return unless pages_deployed?
+
Pages::VirtualDomain.new([project], domain: self)
end
private
+ def pages_deployed?
+ project.project_pages_metadatum&.deployed?
+ end
+
def set_verification_code
return if self.verification_code.present?
diff --git a/app/models/project.rb b/app/models/project.rb
index 18afccf7ddc..1115b370448 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -104,6 +104,9 @@ class Project < ApplicationRecord
unless: :ci_cd_settings,
if: proc { ProjectCiCdSetting.available? }
+ after_create :create_project_pages_metadatum,
+ unless: :project_pages_metadatum
+
after_create :set_timestamps_for_create
after_update :update_forks_visibility_level
@@ -295,6 +298,8 @@ class Project < ApplicationRecord
has_many :external_pull_requests, inverse_of: :project
+ has_one :project_pages_metadatum, inverse_of: :project
+
accepts_nested_attributes_for :variables, allow_destroy: true
accepts_nested_attributes_for :project_feature, update_only: true
accepts_nested_attributes_for :import_data
@@ -425,6 +430,10 @@ class Project < ApplicationRecord
.where(project_ci_cd_settings: { group_runners_enabled: true })
end
+ scope :with_pages_deployed, -> do
+ where('EXISTS (?)', ProjectPagesMetadatum.project_scoped.deployed.select(1))
+ end
+
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
@@ -1643,6 +1652,10 @@ class Project < ApplicationRecord
"#{url}/#{url_path}"
end
+ def pages_group_root?
+ pages_group_url == pages_url
+ end
+
def pages_subdomain
full_path.partition('/').first
end
@@ -1681,6 +1694,7 @@ class Project < ApplicationRecord
# Projects with a missing namespace cannot have their pages removed
return unless namespace
+ mark_pages_as_not_deployed unless destroyed?
::Projects::UpdatePagesConfigurationService.new(self).execute
# 1. We rename pages to temporary directory
@@ -1694,6 +1708,14 @@ class Project < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
+ def mark_pages_as_deployed
+ ProjectPagesMetadatum.update_pages_deployed(self, true)
+ end
+
+ def mark_pages_as_not_deployed
+ ProjectPagesMetadatum.update_pages_deployed(self, false)
+ end
+
# rubocop:disable Gitlab/RailsLogger
def write_repository_config(gl_full_path: full_path)
# We'd need to keep track of project full path otherwise directory tree
@@ -2213,8 +2235,8 @@ class Project < ApplicationRecord
members.maintainers.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
end
- def pages_lookup_path(domain: nil)
- Pages::LookupPath.new(self, domain: domain)
+ def pages_lookup_path(trim_prefix: nil, domain: nil)
+ Pages::LookupPath.new(self, trim_prefix: trim_prefix, domain: domain)
end
private
diff --git a/app/models/project_pages_metadatum.rb b/app/models/project_pages_metadatum.rb
new file mode 100644
index 00000000000..6774fb5c045
--- /dev/null
+++ b/app/models/project_pages_metadatum.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ProjectPagesMetadatum < ApplicationRecord
+ self.primary_key = :project_id
+
+ belongs_to :project, inverse_of: :project_pages_metadatum
+
+ scope :project_scoped, -> { where('projects.id=project_pages_metadata.project_id') }
+ scope :deployed, -> { where(deployed: true) }
+
+ def self.update_pages_deployed(project, flag)
+ flag = flag ? 'TRUE' : 'FALSE'
+
+ upsert = <<~SQL
+ INSERT INTO project_pages_metadata (project_id, deployed)
+ VALUES (#{project.id.to_i}, #{flag})
+ ON CONFLICT (project_id) DO UPDATE
+ SET deployed = EXCLUDED.deployed
+ SQL
+
+ connection_pool.with_connection do |connection|
+ connection.execute(upsert)
+ end
+ end
+end
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index fa7a4f0ed82..e8a87fc4320 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -53,6 +53,7 @@ module Projects
def success
@status.success
+ @project.mark_pages_as_deployed
super
end
diff --git a/changelogs/unreleased/61927-pages-namespaces-virtual-domain.yml b/changelogs/unreleased/61927-pages-namespaces-virtual-domain.yml
new file mode 100644
index 00000000000..d53755ef8c6
--- /dev/null
+++ b/changelogs/unreleased/61927-pages-namespaces-virtual-domain.yml
@@ -0,0 +1,5 @@
+---
+title: Add project_pages_metadata DB table
+merge_request: 32945
+author:
+type: added
diff --git a/db/migrate/20190909045845_create_project_pages_metadata.rb b/db/migrate/20190909045845_create_project_pages_metadata.rb
new file mode 100644
index 00000000000..5fc8fc6e6c1
--- /dev/null
+++ b/db/migrate/20190909045845_create_project_pages_metadata.rb
@@ -0,0 +1,14 @@
+# 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
diff --git a/db/schema.rb b/db/schema.rb
index b60593132f5..f96a679e4c5 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -2772,6 +2772,13 @@ ActiveRecord::Schema.define(version: 2019_09_18_104222) do
t.index ["status"], name: "index_project_mirror_data_on_status"
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|
t.integer "shard_id", null: false
t.string "disk_path", null: false
@@ -4082,6 +4089,7 @@ ActiveRecord::Schema.define(version: 2019_09_18_104222) do
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_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", "shards", on_delete: :restrict
add_foreign_key "project_repository_states", "projects", on_delete: :cascade
diff --git a/lib/api/internal/pages.rb b/lib/api/internal/pages.rb
index eaa434cff51..003af7f6dd4 100644
--- a/lib/api/internal/pages.rb
+++ b/lib/api/internal/pages.rb
@@ -17,11 +17,18 @@ module API
namespace 'internal' 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
- 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
virtual_domain = host.pages_virtual_domain
+ no_content! unless virtual_domain
present virtual_domain, with: Entities::Internal::Pages::VirtualDomain
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 3b43ff3a4e1..e9d5c91d58e 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -410,6 +410,7 @@ project:
- designs
- project_aliases
- external_pull_requests
+- project_pages_metadatum
award_emoji:
- awardable
- user
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 972f26ac745..e72e272f4d2 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -191,6 +191,16 @@ describe Namespace do
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
let(:parent) { create(:group) }
let(:child) { create(:group, parent: parent) }
@@ -913,4 +923,18 @@ describe Namespace do
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
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index 2146b0c9abd..c05d4c82634 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -57,8 +57,18 @@ describe Pages::LookupPath do
end
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('/')
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
diff --git a/spec/models/pages/virtual_domain_spec.rb b/spec/models/pages/virtual_domain_spec.rb
index eaa57b7acd6..a5310738482 100644
--- a/spec/models/pages/virtual_domain_spec.rb
+++ b/spec/models/pages/virtual_domain_spec.rb
@@ -25,19 +25,33 @@ describe Pages::VirtualDomain do
end
describe '#lookup_paths' do
- let(:domain) { instance_double(PagesDomain) }
let(:project_a) { instance_double(Project) }
let(:project_z) { instance_double(Project) }
let(:pages_lookup_path_a) { instance_double(Pages::LookupPath, prefix: 'aaa') }
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
- 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)
+ subject(:virtual_domain) { described_class.new([project_a, project_z], domain: domain) }
- 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
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index f745820a404..9ac80f8b795 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -557,15 +557,27 @@ describe PagesDomain do
end
end
- describe '.pages_virtual_domain' do
- let(:project) { build(:project) }
+ describe '#pages_virtual_domain' do
+ 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
- expect(Pages::VirtualDomain).to receive(:new).with([project], domain: pages_domain).and_call_original
+ context 'when there are pages deployed for the project' do
+ 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
diff --git a/spec/models/project_pages_metadatum_spec.rb b/spec/models/project_pages_metadatum_spec.rb
new file mode 100644
index 00000000000..86baf6a810e
--- /dev/null
+++ b/spec/models/project_pages_metadatum_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectPagesMetadatum do
+ describe '.update_pages_deployed' do
+ let(:project) { create(:project) }
+
+ [true, false].each do |flag|
+ it "creates new record and sets deployed to #{flag} if none exists yet" do
+ project.project_pages_metadatum.destroy!
+
+ described_class.update_pages_deployed(project, flag)
+
+ expect(project.reload.project_pages_metadatum.deployed).to eq(flag)
+ end
+
+ it "updates the existing record and sets deployed to #{flag}" do
+ project_pages_metadatum = project.project_pages_metadatum
+ project_pages_metadatum.update!(deployed: !flag)
+
+ expect { described_class.update_pages_deployed(project, flag) }.to change {
+ project_pages_metadatum.reload.deployed
+ }.from(!flag).to(flag)
+ end
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 67f64822184..0bac9155628 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -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_persisted
end
+
+ it 'automatically creates a Pages metadata row' do
+ project = create(:project)
+
+ expect(project.project_pages_metadatum).to be_an_instance_of(ProjectPagesMetadatum)
+ expect(project.project_pages_metadatum).to be_persisted
+ end
end
context 'updating cd_cd_settings' do
@@ -3526,7 +3533,8 @@ describe Project do
end
describe '#remove_pages' do
- let(:project) { create(:project) }
+ let(:project) { create(:project).tap { |project| project.mark_pages_as_deployed } }
+ let(:project_pages_metadatum) { project.project_pages_metadatum }
let(:namespace) { project.namespace }
let(:pages_path) { project.pages_path }
@@ -3539,12 +3547,12 @@ describe Project do
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(Gitlab::PagesTransfer).to receive(:rename_project).and_return(true)
expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, namespace.full_path, anything)
- project.remove_pages
+ expect { project.remove_pages }.to change { project_pages_metadatum.reload.deployed }.from(true).to(false)
end
it 'is a no-op when there is no namespace' do
@@ -3554,13 +3562,13 @@ describe Project do
expect_any_instance_of(Projects::UpdatePagesConfigurationService).not_to receive(:execute)
expect_any_instance_of(Gitlab::PagesTransfer).not_to receive(:rename_project)
- project.remove_pages
+ expect { project.remove_pages }.not_to change { project_pages_metadatum.reload.deployed }
end
it 'is run when the project is destroyed' do
expect(project).to receive(:remove_pages).and_call_original
- project.destroy
+ expect { project.destroy }.not_to raise_error
end
end
@@ -5014,6 +5022,26 @@ describe Project do
end
end
+ context 'pages deployed' do
+ let(:project) { build(:project) }
+
+ describe '#mark_pages_as_deployed' do
+ it 'delegates to ProjectPagesMetadatum.update_pages_deployed' do
+ expect(ProjectPagesMetadatum).to receive(:update_pages_deployed).with(project, true)
+
+ project.mark_pages_as_deployed
+ end
+ end
+
+ describe '#mark_pages_as_not_deployed' do
+ it 'delegates to ProjectPagesMetadatum.update_pages_deployed' do
+ expect(ProjectPagesMetadatum).to receive(:update_pages_deployed).with(project, false)
+
+ project.mark_pages_as_not_deployed
+ end
+ end
+ end
+
describe '#has_pool_repsitory?' do
it 'returns false when it does not have a pool repository' do
subject = create(:project, :repository)
@@ -5054,9 +5082,34 @@ describe Project do
let(:project) { build(:project) }
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
diff --git a/spec/requests/api/internal/pages_spec.rb b/spec/requests/api/internal/pages_spec.rb
index e1b563b92f4..04433b93d76 100644
--- a/spec/requests/api/internal/pages_spec.rb
+++ b/spec/requests/api/internal/pages_spec.rb
@@ -43,6 +43,10 @@ describe API::Internal::Pages do
super(host, headers)
end
+ def deploy_pages(project)
+ project.mark_pages_as_deployed
+ end
+
context 'not existing host' do
it 'responds with 404 Not Found' do
query_host('pages.gitlab.io')
@@ -56,18 +60,71 @@ describe API::Internal::Pages do
let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') }
let!(:pages_domain) { create(:pages_domain, domain: 'pages.gitlab.io', project: project) }
- it 'responds with the correct domain configuration' do
- query_host('pages.gitlab.io')
+ context 'when there are no pages deployed for the related project' do
+ it 'responds with 204 No Content' do
+ query_host('pages.gitlab.io')
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+ end
+
+ context 'when there are pages deployed for the related project' do
+ 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)
+
+ lookup_path = json_response['lookup_paths'][0]
+ expect(lookup_path['prefix']).to eq('/')
+ expect(lookup_path['source']['path']).to eq('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')
+
+ lookup_path = json_response['lookup_paths'][0]
+ expect(lookup_path['prefix']).to eq('/myproject/')
+ expect(lookup_path['source']['path']).to eq('mygroup/myproject/public/')
+ end
+ end
+
+ context 'group root project' do
+ it 'responds with the correct domain configuration' do
+ project = create(:project, group: group, name: 'mygroup.gitlab-pages.io')
+ deploy_pages(project)
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('internal/pages/virtual_domain')
+ query_host('mygroup.gitlab-pages.io')
- expect(json_response['certificate']).to eq(pages_domain.certificate)
- expect(json_response['key']).to eq(pages_domain.key)
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('internal/pages/virtual_domain')
- lookup_path = json_response['lookup_paths'][0]
- expect(lookup_path['prefix']).to eq('/')
- expect(lookup_path['source']['path']).to eq('gitlab-org/gitlab-ce/public/')
+ lookup_path = json_response['lookup_paths'][0]
+ expect(lookup_path['prefix']).to eq('/')
+ expect(lookup_path['source']['path']).to eq('mygroup/mygroup.gitlab-pages.io/public/')
+ end
end
end
end
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index b597717c347..25e77f232a4 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -40,6 +40,7 @@ describe Projects::UpdatePagesService do
it "doesn't delete artifacts after deploying" do
expect(execute).to eq(:success)
+ expect(project.project_pages_metadatum.deployed).to eq(true)
expect(build.artifacts?).to eq(true)
end
end
@@ -47,6 +48,7 @@ describe Projects::UpdatePagesService do
it 'succeeds' do
expect(project.pages_deployed?).to be_falsey
expect(execute).to eq(:success)
+ expect(project.project_pages_metadatum.deployed).to eq(true)
expect(project.pages_deployed?).to be_truthy
# Check that all expected files are extracted
@@ -63,16 +65,23 @@ describe Projects::UpdatePagesService do
it 'removes pages after destroy' do
expect(PagesWorker).to receive(:perform_in)
expect(project.pages_deployed?).to be_falsey
+
expect(execute).to eq(:success)
+
+ expect(project.project_pages_metadatum.deployed).to eq(true)
expect(project.pages_deployed?).to be_truthy
+
project.destroy
+
expect(project.pages_deployed?).to be_falsey
+ expect(ProjectPagesMetadatum.find_by_project_id(project)).to be_nil
end
it 'fails if sha on branch is not latest' do
build.update(ref: 'feature')
expect(execute).not_to eq(:success)
+ expect(project.project_pages_metadatum.deployed).to eq(false)
end
context 'when using empty file' do
@@ -94,6 +103,7 @@ describe Projects::UpdatePagesService do
it 'succeeds to extract' do
expect(execute).to eq(:success)
+ expect(project.project_pages_metadatum.deployed).to eq(true)
end
end
end
@@ -109,6 +119,7 @@ describe Projects::UpdatePagesService do
build.reload
expect(deploy_status).to be_failed
+ expect(project.project_pages_metadatum.deployed).to eq(false)
end
end
@@ -125,6 +136,7 @@ describe Projects::UpdatePagesService do
build.reload
expect(deploy_status).to be_failed
+ expect(project.project_pages_metadatum.deployed).to eq(false)
end
end
@@ -138,6 +150,7 @@ describe Projects::UpdatePagesService do
build.reload
expect(deploy_status).to be_failed
+ expect(project.project_pages_metadatum.deployed).to eq(false)
end
end
end
@@ -179,6 +192,7 @@ describe Projects::UpdatePagesService do
expect(deploy_status.description)
.to match(/artifacts for pages are too large/)
expect(deploy_status).to be_script_failure
+ expect(project.project_pages_metadatum.deployed).to eq(false)
end
end
@@ -196,6 +210,7 @@ describe Projects::UpdatePagesService do
subject.execute
expect(deploy_status.description).not_to be_present
+ expect(project.project_pages_metadatum.deployed).to eq(true)
end
end