summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/ci/build.rb2
-rw-r--r--app/services/pages_service.rb (renamed from app/services/update_pages_service.rb)2
-rw-r--r--app/services/projects/update_pages_service.rb132
-rw-r--r--app/workers/pages_worker.rb133
-rw-r--r--spec/services/pages_service_spec.rb (renamed from spec/services/update_pages_service_spec.rb)4
-rw-r--r--spec/services/projects/update_pages_worker_spec.rb (renamed from spec/workers/pages_worker_spec.rb)23
6 files changed, 152 insertions, 144 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 095a346f337..da8e66e5f6e 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -457,7 +457,7 @@ module Ci
build_data = Gitlab::DataBuilder::Build.build(self)
project.execute_hooks(build_data.dup, :build_hooks)
project.execute_services(build_data.dup, :build_hooks)
- UpdatePagesService.new(build_data).execute
+ PagesService.new(build_data).execute
project.running_or_pending_build_count(force: true)
end
diff --git a/app/services/update_pages_service.rb b/app/services/pages_service.rb
index 39f08b2a03d..446eeb34d3b 100644
--- a/app/services/update_pages_service.rb
+++ b/app/services/pages_service.rb
@@ -1,4 +1,4 @@
-class UpdatePagesService
+class PagesService
attr_reader :data
def initialize(data)
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
new file mode 100644
index 00000000000..e1bb4c92e40
--- /dev/null
+++ b/app/services/projects/update_pages_service.rb
@@ -0,0 +1,132 @@
+module Projects
+ class UpdatePagesService < BaseService
+ BLOCK_SIZE = 32.kilobytes
+ MAX_SIZE = 1.terabyte
+
+ attr_reader :build
+
+ def initialize(project, build)
+ @project, @build = project, build
+ end
+
+ def execute
+ # Create status notifying the deployment of pages
+ @status = create_status
+ @status.run!
+
+ raise 'missing pages artifacts' unless build.artifacts_file?
+ raise 'pages are outdated' unless latest?
+
+ # Create temporary directory in which we will extract the artifacts
+ FileUtils.mkdir_p(tmp_path)
+ Dir.mktmpdir(nil, tmp_path) do |archive_path|
+ extract_archive!(archive_path)
+
+ # Check if we did extract public directory
+ archive_public_path = File.join(archive_path, 'public')
+ raise 'pages miss the public folder' unless Dir.exists?(archive_public_path)
+ raise 'pages are outdated' unless latest?
+
+ deploy_page!(archive_public_path)
+ success
+ end
+ rescue => e
+ error(e.message)
+ end
+
+ private
+
+ def success
+ @status.success
+ super
+ end
+
+ def error(message, http_status = nil)
+ @status.allow_failure = !latest?
+ @status.description = message
+ @status.drop
+ super
+ end
+
+ def create_status
+ GenericCommitStatus.new(
+ project: project,
+ commit: build.commit,
+ user: build.user,
+ ref: build.ref,
+ stage: 'deploy',
+ name: 'pages:deploy'
+ )
+ end
+
+ def extract_archive!(temp_path)
+ results = Open3.pipeline(%W(gunzip -c #{artifacts}),
+ %W(dd bs=#{BLOCK_SIZE} count=#{blocks}),
+ %W(tar -x -C #{temp_path} public/),
+ err: '/dev/null')
+ raise 'pages failed to extract' unless results.compact.all?(&:success?)
+ end
+
+ def deploy_page!(archive_public_path)
+ # Do atomic move of pages
+ # Move and removal may not be atomic, but they are significantly faster then extracting and removal
+ # 1. We move deployed public to previous public path (file removal is slow)
+ # 2. We move temporary public to be deployed public
+ # 3. We remove previous public path
+ FileUtils.mkdir_p(pages_path)
+ begin
+ FileUtils.move(public_path, previous_public_path)
+ rescue
+ end
+ FileUtils.move(archive_public_path, public_path)
+ ensure
+ FileUtils.rm_r(previous_public_path, force: true)
+ end
+
+ def latest?
+ # check if sha for the ref is still the most recent one
+ # this helps in case when multiple deployments happens
+ sha == latest_sha
+ end
+
+ def blocks
+ # Calculate dd parameters: we limit the size of pages
+ max_size = current_application_settings.max_pages_size.megabytes
+ max_size ||= MAX_SIZE
+ blocks = 1 + max_size / BLOCK_SIZE
+ blocks
+ end
+
+ def tmp_path
+ @tmp_path ||= File.join(Settings.pages.path, 'tmp')
+ end
+
+ def pages_path
+ @pages_path ||= project.pages_path
+ end
+
+ def public_path
+ @public_path ||= File.join(pages_path, 'public')
+ end
+
+ def previous_public_path
+ @previous_public_path ||= File.join(pages_path, "public.#{SecureRandom.hex}")
+ end
+
+ def ref
+ build.ref
+ end
+
+ def artifacts
+ build.artifacts_file.path
+ end
+
+ def latest_sha
+ project.commit(build.ref).try(:sha).to_s
+ end
+
+ def sha
+ build.sha
+ end
+ end
+end
diff --git a/app/workers/pages_worker.rb b/app/workers/pages_worker.rb
index ff765a6c13c..8c99e8dbe76 100644
--- a/app/workers/pages_worker.rb
+++ b/app/workers/pages_worker.rb
@@ -1,9 +1,5 @@
class PagesWorker
include Sidekiq::Worker
- include Gitlab::CurrentSettings
-
- BLOCK_SIZE = 32.kilobytes
- MAX_SIZE = 1.terabyte
sidekiq_options queue: :pages, retry: false
@@ -12,137 +8,12 @@ class PagesWorker
end
def deploy(build_id)
- @build_id = build_id
- return unless valid?
-
- # Create status notifying the deployment of pages
- @status = create_status
- @status.run!
-
- raise 'pages are outdated' unless latest?
-
- # Create temporary directory in which we will extract the artifacts
- FileUtils.mkdir_p(tmp_path)
- Dir.mktmpdir(nil, tmp_path) do |archive_path|
- extract_archive!(archive_path)
-
- # Check if we did extract public directory
- archive_public_path = File.join(archive_path, 'public')
- raise 'pages miss the public folder' unless Dir.exists?(archive_public_path)
- raise 'pages are outdated' unless latest?
-
- deploy_page!(archive_public_path)
-
- @status.success
- end
- rescue => e
- fail(e.message, !latest?)
- return false
+ build = Ci::Build.find_by(id: build_id)
+ Projects::UpdatePagesService.new(build.project, build).execute
end
def remove(namespace_path, project_path)
full_path = File.join(Settings.pages.path, namespace_path, project_path)
FileUtils.rm_r(full_path, force: true)
end
-
- private
-
- def create_status
- GenericCommitStatus.new(
- project: project,
- commit: build.commit,
- user: build.user,
- ref: build.ref,
- stage: 'deploy',
- name: 'pages:deploy'
- )
- end
-
- def extract_archive!(temp_path)
- results = Open3.pipeline(%W(gunzip -c #{artifacts}),
- %W(dd bs=#{BLOCK_SIZE} count=#{blocks}),
- %W(tar -x -C #{temp_path} public/),
- err: '/dev/null')
- raise 'pages failed to extract' unless results.compact.all?(&:success?)
- end
-
- def deploy_page!(archive_public_path)
- # Do atomic move of pages
- # Move and removal may not be atomic, but they are significantly faster then extracting and removal
- # 1. We move deployed public to previous public path (file removal is slow)
- # 2. We move temporary public to be deployed public
- # 3. We remove previous public path
- FileUtils.mkdir_p(pages_path)
- begin
- FileUtils.move(public_path, previous_public_path)
- rescue
- end
- FileUtils.move(archive_public_path, public_path)
- ensure
- FileUtils.rm_r(previous_public_path, force: true)
- end
-
- def fail(message, allow_failure = true)
- @status.allow_failure = allow_failure
- @status.description = message
- @status.drop
- end
-
- def valid?
- build && build.artifacts_file?
- end
-
- def latest?
- # check if sha for the ref is still the most recent one
- # this helps in case when multiple deployments happens
- sha == latest_sha
- end
-
- def blocks
- # Calculate dd parameters: we limit the size of pages
- max_size = current_application_settings.max_pages_size.megabytes
- max_size ||= MAX_SIZE
- blocks = 1 + max_size / BLOCK_SIZE
- blocks
- end
-
- def build
- @build ||= Ci::Build.find_by(id: @build_id)
- end
-
- def project
- @project ||= build.project
- end
-
- def tmp_path
- @tmp_path ||= File.join(Settings.pages.path, 'tmp')
- end
-
- def pages_path
- @pages_path ||= project.pages_path
- end
-
- def public_path
- @public_path ||= File.join(pages_path, 'public')
- end
-
- def previous_public_path
- @previous_public_path ||= File.join(pages_path, "public.#{SecureRandom.hex}")
- end
-
- def ref
- build.ref
- end
-
- def artifacts
- build.artifacts_file.path
- end
-
- def latest_sha
- project.commit(build.ref).try(:sha).to_s
- end
-
- def sha
- build.sha
- end
end
diff --git a/spec/services/update_pages_service_spec.rb b/spec/services/pages_service_spec.rb
index cf1ca15da44..e6ad93358a0 100644
--- a/spec/services/update_pages_service_spec.rb
+++ b/spec/services/pages_service_spec.rb
@@ -1,9 +1,9 @@
require 'spec_helper'
-describe UpdatePagesService, services: true do
+describe PagesService, services: true do
let(:build) { create(:ci_build) }
let(:data) { Gitlab::BuildDataBuilder.build(build) }
- let(:service) { UpdatePagesService.new(data) }
+ let(:service) { PagesService.new(data) }
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
diff --git a/spec/workers/pages_worker_spec.rb b/spec/services/projects/update_pages_worker_spec.rb
index 85592154598..0607c025b9e 100644
--- a/spec/workers/pages_worker_spec.rb
+++ b/spec/services/projects/update_pages_worker_spec.rb
@@ -1,13 +1,14 @@
require "spec_helper"
-describe PagesWorker do
+describe Projects::UpdatePagesService do
let(:project) { create :project }
let(:commit) { create :ci_commit, project: project, sha: project.commit('HEAD').sha }
let(:build) { create :ci_build, commit: commit, ref: 'HEAD' }
- let(:worker) { PagesWorker.new }
let(:file) { fixture_file_upload(Rails.root + 'spec/fixtures/pages.tar.gz', 'application/octet-stream') }
let(:empty_file) { fixture_file_upload(Rails.root + 'spec/fixtures/pages_empty.tar.gz', 'application/octet-stream') }
let(:invalid_file) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'application/octet-stream') }
+
+ subject { described_class.new(project, build) }
before do
project.remove_pages
@@ -18,19 +19,19 @@ describe PagesWorker do
it 'succeeds' do
expect(project.pages_url).to be_nil
- expect(worker.deploy(build.id)).to be_truthy
+ expect(execute).to eq(:success)
expect(project.pages_url).to_not be_nil
end
it 'limits pages size' do
stub_application_setting(max_pages_size: 1)
- expect(worker.deploy(build.id)).to_not be_truthy
+ expect(execute).to_not eq(:success)
end
it 'removes pages after destroy' do
expect(PagesWorker).to receive(:perform_in)
expect(project.pages_url).to be_nil
- expect(worker.deploy(build.id)).to be_truthy
+ expect(execute).to eq(:success)
expect(project.pages_url).to_not be_nil
project.destroy
expect(Dir.exist?(project.public_pages_path)).to be_falsey
@@ -44,22 +45,26 @@ describe PagesWorker do
end
it 'fails if no artifacts' do
- expect(worker.deploy(build.id)).to_not be_truthy
+ expect(execute).to_not eq(:success)
end
it 'fails for empty file fails' do
build.update_attributes(artifacts_file: empty_file)
- expect(worker.deploy(build.id)).to_not be_truthy
+ expect(execute).to_not eq(:success)
end
it 'fails for invalid archive' do
build.update_attributes(artifacts_file: invalid_file)
- expect(worker.deploy(build.id)).to_not be_truthy
+ expect(execute).to_not eq(:success)
end
it 'fails if sha on branch is not latest' do
commit.update_attributes(sha: 'old_sha')
build.update_attributes(artifacts_file: file)
- expect(worker.deploy(build.id)).to_not be_truthy
+ expect(execute).to_not eq(:success)
+ end
+
+ def execute
+ subject.execute[:status]
end
end