From 3d0bdacf007f109eab5f58cb5f311bdcd98c0686 Mon Sep 17 00:00:00 2001
From: Vladimir Shushlin <vshushlin@gitlab.com>
Date: Fri, 4 Sep 2020 15:35:35 +0000
Subject: [PATCH] Use latest pages build artifact as source for pages

---
 app/models/pages/lookup_path.rb               | 32 ++++++++--
 .../development/pages_artifacts_archive.yml   |  7 +++
 spec/models/pages/lookup_path_spec.rb         | 61 +++++++++++++++----
 3 files changed, 84 insertions(+), 16 deletions(-)
 create mode 100644 config/feature_flags/development/pages_artifacts_archive.yml

diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 51c496c77d3d8..84d820e539ca0 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -22,10 +22,11 @@ def https_only
     end
 
     def source
-      {
-        type: 'file',
-        path: File.join(project.full_path, 'public/')
-      }
+      if artifacts_archive && !artifacts_archive.file_storage?
+        zip_source
+      else
+        file_source
+      end
     end
 
     def prefix
@@ -39,5 +40,28 @@ def prefix
     private
 
     attr_reader :project, :trim_prefix, :domain
+
+    def artifacts_archive
+      return unless Feature.enabled?(:pages_artifacts_archive, project)
+
+      # Using build artifacts is temporary solution for quick test
+      # in production environment, we'll replace this with proper
+      # `pages_deployments` later
+      project.pages_metadatum.artifacts_archive&.file
+    end
+
+    def zip_source
+      {
+        type: 'zip',
+        path: artifacts_archive.url(expire_at: 1.day.from_now)
+      }
+    end
+
+    def file_source
+      {
+        type: 'file',
+        path: File.join(project.full_path, 'public/')
+      }
+    end
   end
 end
diff --git a/config/feature_flags/development/pages_artifacts_archive.yml b/config/feature_flags/development/pages_artifacts_archive.yml
new file mode 100644
index 0000000000000..5cd4f4bd62be9
--- /dev/null
+++ b/config/feature_flags/development/pages_artifacts_archive.yml
@@ -0,0 +1,7 @@
+---
+name: pages_artifacts_archive
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40361
+rollout_issue_url: 
+group: group::release management
+type: development
+default_enabled: false
\ No newline at end of file
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index 38bd9b39a56f0..cb1938a0113b6 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -3,20 +3,20 @@
 require 'spec_helper'
 
 RSpec.describe Pages::LookupPath do
-  let(:project) do
-    instance_double(Project,
-      id: 12345,
-      private_pages?: true,
-      pages_https_only?: true,
-      full_path: 'the/full/path'
-    )
+  let_it_be(:project) do
+    create(:project, :pages_private, pages_https_only: true)
   end
 
   subject(:lookup_path) { described_class.new(project) }
 
+  before do
+    stub_pages_setting(access_control: true, external_https: ["1.1.1.1:443"])
+    stub_artifacts_object_storage
+  end
+
   describe '#project_id' do
     it 'delegates to Project#id' do
-      expect(lookup_path.project_id).to eq(12345)
+      expect(lookup_path.project_id).to eq(project.id)
     end
   end
 
@@ -47,12 +47,49 @@
   end
 
   describe '#source' do
-    it 'sets the source type to "file"' do
-      expect(lookup_path.source[:type]).to eq('file')
+    shared_examples 'uses disk storage' do
+      it 'sets the source type to "file"' do
+        expect(lookup_path.source[:type]).to eq('file')
+      end
+
+      it 'sets the source path to the project full path suffixed with "public/' do
+        expect(lookup_path.source[:path]).to eq(project.full_path + "/public/")
+      end
     end
 
-    it 'sets the source path to the project full path suffixed with "public/' do
-      expect(lookup_path.source[:path]).to eq('the/full/path/public/')
+    include_examples 'uses disk storage'
+
+    context 'when artifact_id from build job is present in pages metadata' do
+      let(:artifacts_archive) { create(:ci_job_artifact, :zip, :remote_store, project: project) }
+
+      before do
+        project.mark_pages_as_deployed(artifacts_archive: artifacts_archive)
+      end
+
+      it 'sets the source type to "zip"' do
+        expect(lookup_path.source[:type]).to eq('zip')
+      end
+
+      it 'sets the source path to the artifacts archive URL' do
+        Timecop.freeze do
+          expect(lookup_path.source[:path]).to eq(artifacts_archive.file.url(expire_at: 1.day.from_now))
+          expect(lookup_path.source[:path]).to include("Expires=86400")
+        end
+      end
+
+      context 'when artifact is not uploaded to object storage' do
+        let(:artifacts_archive) { create(:ci_job_artifact, :zip) }
+
+        include_examples 'uses disk storage'
+      end
+
+      context 'when feature flag is disabled' do
+        before do
+          stub_feature_flags(pages_artifacts_archive: false)
+        end
+
+        include_examples 'uses disk storage'
+      end
     end
   end
 
-- 
GitLab