diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index a19c00f20db17d0a150f12b5c2187674fca1b2b9..de1e1843260625d4dd8984002ca45cf0c35bcfc8 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -432,6 +432,11 @@ def pages_generator? self.name == 'pages' end + def pages_review_generator? + Gitlab.config.pages.enabled && + self.name == PagesReviewMergeRequest::PAGES_REVIEW_BUILD + end + def runnable? true end diff --git a/app/models/pages_review_merge_request.rb b/app/models/pages_review_merge_request.rb new file mode 100644 index 0000000000000000000000000000000000000000..7679e33f39f171444ca8e5d7b48abe5c0c79030a --- /dev/null +++ b/app/models/pages_review_merge_request.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class PagesReviewMergeRequest < ApplicationRecord + belongs_to :project, optional: false + belongs_to :merge_request, optional: false + belongs_to :ci_build, class_name: 'Ci::Build', optional: true + + SLUG_PREFIX = 'review-app-' + PAGES_REVIEW_BUILD = 'pages-review' + + before_validation :generate_slug, unless: :slug + + # Pages Review Merge Requests require the presence + # of Object Storage for Artifacts today + # + # This is limitation of Pages daemon that cannot read + # directly artifacts from disk + def self.supported?(project) + Feature.enabled?(:pages_review_merge_requests, project, default_enabled: :yaml) && + JobArtifactUploader.object_store_enabled? + end + + private + + def generate_slug + return unless project + + self.slug = SLUG_PREFIX \ + + project.full_path_slug[0..20] + '-' \ + + SecureRandom.hex(8) + end +end diff --git a/config/feature_flags/development/pages_review_merge_requests.yml b/config/feature_flags/development/pages_review_merge_requests.yml new file mode 100644 index 0000000000000000000000000000000000000000..4b6c248ebeade9e7b28be7aff54f62d4c8047e7a --- /dev/null +++ b/config/feature_flags/development/pages_review_merge_requests.yml @@ -0,0 +1,8 @@ +--- +name: pages_review_merge_requests +introduced_by_url: +rollout_issue_url: +milestone: '14.4' +type: development +group: group::sharding +default_enabled: false diff --git a/db/migrate/20211008093343_create_pages_merge_requests.rb b/db/migrate/20211008093343_create_pages_merge_requests.rb new file mode 100644 index 0000000000000000000000000000000000000000..f525f1a2427047bde204bb44256d3dc6e999f56d --- /dev/null +++ b/db/migrate/20211008093343_create_pages_merge_requests.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class CreatePagesMergeRequests < Gitlab::Database::Migration[1.0] + def change + create_table(:pages_review_merge_requests) do |t| + t.datetime_with_timezone :created_at, null: false + t.datetime_with_timezone :updated_at + t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade } + t.references :merge_request, index: true, null: false, foreign_key: { on_delete: :cascade } + t.references :ci_build, index: true, null: false, foreign_key: { on_delete: :nullify } + t.text :slug, null: false, limit: 255, unique: true + end + end +end diff --git a/db/schema_migrations/20211008093343 b/db/schema_migrations/20211008093343 new file mode 100644 index 0000000000000000000000000000000000000000..1fc20ee1d9424102873014e01b6602c5133a13c6 --- /dev/null +++ b/db/schema_migrations/20211008093343 @@ -0,0 +1 @@ +d922b73730997e806a1baaf342945dab34364a2b5e5555072bd0f3fab20b9287 \ No newline at end of file diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb index c648f4d1fd04e942f75f1f5ddf660ec28db1fcc5..f44a3357299a06712db382397a84ec6b38cf2953 100644 --- a/lib/gitlab/path_regex.rb +++ b/lib/gitlab/path_regex.rb @@ -56,6 +56,10 @@ module PathRegex v2 ].freeze + TOP_LEVEL_ROUTES_REGEX = [ + %r{review\-apps\-.*} + ].freeze + # NOTE: Do not add new items to this list unless necessary as this will # cause conflicts with existing namespaced routes for groups or projects. # See https://docs.gitlab.com/ee/development/routing.html#project-routes @@ -141,7 +145,8 @@ module PathRegex def root_namespace_route_regex @root_namespace_route_regex ||= begin - illegal_words = Regexp.new(Regexp.union(TOP_LEVEL_ROUTES).source, Regexp::IGNORECASE) + illegal_words = Regexp.union(TOP_LEVEL_ROUTES + TOP_LEVEL_ROUTES_REGEX).source + illegal_words = Regexp.new(illegal_words, Regexp::IGNORECASE) single_line_regexp %r{ (?!(#{illegal_words})/)