summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2015-11-03 21:28:07 +0100
committerJames Edwards-Jones <jedwardsjones@gitlab.com>2017-01-31 22:50:39 +0000
commit120f9abaa15ce0feec1dc457ad3dc3787e4fbfc6 (patch)
tree4bb8bf5f7e47613ea967555e01fc2c7e27e994c6
parent659cceb0e8694b58a8b665de3f338245244ef114 (diff)
downloadgitlab-ce-120f9abaa15ce0feec1dc457ad3dc3787e4fbfc6.tar.gz
Add GitLab Pages
- The pages are created when build artifacts for `pages` job are uploaded - Pages serve the content under: http://group.pages.domain.com/project - Pages can be used to serve the group page, special project named as host: group.pages.domain.com - User can provide own 403 and 404 error pages by creating 403.html and 404.html in group page project - Pages can be explicitly removed from the project by clicking Remove Pages in Project Settings - The size of pages is limited by Application Setting: max pages size, which limits the maximum size of unpacked archive (default: 100MB) - The public/ is extracted from artifacts and content is served as static pages - Pages asynchronous worker use `dd` to limit the unpacked tar size - Pages needs to be explicitly enabled and domain needs to be specified in gitlab.yml - Pages are part of backups - Pages notify the deployment status using Commit Status API - Pages use a new sidekiq queue: pages - Pages use a separate nginx config which needs to be explicitly added
-rw-r--r--app/controllers/admin/application_settings_controller.rb1
-rw-r--r--app/controllers/projects_controller.rb10
-rw-r--r--app/models/ci/build.rb3
-rw-r--r--app/models/project.rb25
-rw-r--r--app/policies/project_policy.rb1
-rw-r--r--app/services/update_pages_service.rb15
-rw-r--r--app/views/admin/application_settings/_form.html.haml8
-rw-r--r--app/views/projects/edit.html.haml35
-rw-r--r--app/workers/pages_worker.rb123
-rw-r--r--config/gitlab.yml.example11
-rw-r--r--config/initializers/1_settings.rb6
-rw-r--r--config/routes/project.rb1
-rw-r--r--db/migrate/20151215132013_add_pages_size_to_application_settings.rb5
-rw-r--r--db/schema.rb1
-rw-r--r--doc/README.md1
-rw-r--r--doc/install/installation.md13
-rw-r--r--doc/pages/README.md12
-rw-r--r--lib/backup/pages.rb13
-rw-r--r--lib/support/nginx/gitlab-pages27
-rw-r--r--lib/tasks/gitlab/backup.rake21
-rw-r--r--shared/pages/.gitkeep0
-rw-r--r--spec/fixtures/pages.tar.gzbin0 -> 1795 bytes
-rw-r--r--spec/fixtures/pages_empty.tar.gzbin0 -> 128 bytes
-rw-r--r--spec/services/update_pages_service_spec.rb43
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb14
-rw-r--r--spec/workers/pages_worker_spec.rb58
26 files changed, 441 insertions, 6 deletions
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 543d5eac504..df8682e246e 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -109,6 +109,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:plantuml_url,
:max_artifacts_size,
:max_attachment_size,
+ :max_pages_size,
:metrics_enabled,
:metrics_host,
:metrics_method_call_threshold,
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 444ff837bb3..123dc179e73 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -151,6 +151,16 @@ class ProjectsController < Projects::ApplicationController
end
end
+ def remove_pages
+ return access_denied! unless can?(current_user, :remove_pages, @project)
+
+ @project.remove_pages
+
+ respond_to do |format|
+ format.html { redirect_to project_path(@project) }
+ end
+ end
+
def housekeeping
::Projects::HousekeepingService.new(@project).execute
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 5fe8ddf69d7..095a346f337 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -256,7 +256,7 @@ module Ci
end
def project_id
- pipeline.project_id
+ gl_project_id
end
def project_name
@@ -457,6 +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
project.running_or_pending_build_count(force: true)
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 37f4705adbd..48ff5ec7fc7 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -53,6 +53,8 @@ class Project < ActiveRecord::Base
update_column(:last_activity_at, self.created_at)
end
+ after_destroy :remove_pages
+
# update visibility_level of forks
after_update :update_forks_visibility_level
def update_forks_visibility_level
@@ -1160,6 +1162,29 @@ class Project < ActiveRecord::Base
ensure_runners_token!
end
+ def pages_url
+ if Dir.exist?(public_pages_path)
+ host = "#{namespace.path}.#{Settings.pages.domain}"
+
+ # If the project path is the same as host, leave the short version
+ return "http://#{host}" if host == path
+
+ "http://#{host}/#{path}"
+ end
+ end
+
+ def pages_path
+ File.join(Settings.pages.path, path_with_namespace)
+ end
+
+ def public_pages_path
+ File.join(pages_path, 'public')
+ end
+
+ def remove_pages
+ FileUtils.rm_r(pages_path, force: true)
+ end
+
def wiki
@wiki ||= ProjectWiki.new(self, self.owner)
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 71ef8901932..63bc639688d 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -136,6 +136,7 @@ class ProjectPolicy < BasePolicy
can! :remove_fork_project
can! :destroy_merge_request
can! :destroy_issue
+ can! :remove_pages
end
def team_member_owner_access!
diff --git a/app/services/update_pages_service.rb b/app/services/update_pages_service.rb
new file mode 100644
index 00000000000..818bb94a293
--- /dev/null
+++ b/app/services/update_pages_service.rb
@@ -0,0 +1,15 @@
+class UpdatePagesService
+ attr_reader :data
+
+ def initialize(data)
+ @data = data
+ end
+
+ def execute
+ return unless Settings.pages.enabled
+ return unless data[:build_name] == 'pages'
+ return unless data[:build_status] == 'success'
+
+ PagesWorker.perform_async(data[:build_id])
+ end
+end
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 558bbe07b16..125a805a897 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -187,6 +187,14 @@
.help-block Markdown enabled
%fieldset
+ %legend Pages
+ .form-group
+ = f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.number_field :max_pages_size, class: 'form-control'
+ .help-block Zero for unlimited
+
+ %fieldset
%legend Continuous Integration
.form-group
.col-sm-offset-2.col-sm-10
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index ec944d4ffb7..89e2d4046b8 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -133,6 +133,41 @@
%hr
= link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
= f.submit 'Save changes', class: "btn btn-save"
+
+ - if Settings.pages.enabled
+ .pages-settings
+ .panel.panel-default
+ .panel-heading Pages
+ .errors-holder
+ .panel-body
+ - if @project.pages_url
+ %strong
+ Congratulations. Your pages are served at:
+ %p= link_to @project.pages_url, @project.pages_url
+ - else
+ %p
+ To publish pages create .gitlab-ci.yml with
+ %strong pages job
+ and send public/ folder to GitLab.
+ %p
+ Use existing tools:
+ %ul
+ %li
+ %pre
+ :plain
+ pages:
+ image: jekyll
+ script: jekyll build
+ artifacts:
+ paths:
+ - public
+
+ - if @project.pages_url && can?(current_user, :remove_pages, @project)
+ .form-actions
+ = link_to 'Remove pages', remove_pages_namespace_project_path(@project.namespace, @project),
+ data: { confirm: "Are you sure that you want to remove pages for this project?" },
+ method: :post, class: "btn btn-warning"
+
.row.prepend-top-default
%hr
.row.prepend-top-default
diff --git a/app/workers/pages_worker.rb b/app/workers/pages_worker.rb
new file mode 100644
index 00000000000..9aa3030264b
--- /dev/null
+++ b/app/workers/pages_worker.rb
@@ -0,0 +1,123 @@
+class PagesWorker
+ include Sidekiq::Worker
+ include Gitlab::CurrentSettings
+
+ BLOCK_SIZE = 32.kilobytes
+ MAX_SIZE = 1.terabyte
+
+ sidekiq_options queue: :pages
+
+ def perform(build_id)
+ @build_id = build_id
+ return unless valid?
+
+ # Create status notifying the deployment of pages
+ @status = GenericCommitStatus.new(
+ project: project,
+ commit: build.commit,
+ user: build.user,
+ ref: build.ref,
+ stage: 'deploy',
+ name: 'pages:deploy'
+ )
+ @status.run!
+
+ FileUtils.mkdir_p(tmp_path)
+
+ # 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
+
+ # Create temporary directory in which we will extract the artifacts
+ Dir.mktmpdir(nil, tmp_path) do |temp_path|
+ # We manually extract the archive and limit the archive size with dd
+ results = Open3.pipeline(%W(gunzip -c #{artifacts}),
+ %W(dd bs=#{BLOCK_SIZE} count=#{blocks}),
+ %W(tar -x -C #{temp_path} public/))
+ return unless results.compact.all?(&:success?)
+
+ # Check if we did extract public directory
+ temp_public_path = File.join(temp_path, 'public')
+ return unless Dir.exists?(temp_public_path)
+
+ FileUtils.mkdir_p(pages_path)
+
+ # Lock file for time of deployment to prevent the two processes from doing the concurrent deployment
+ File.open(lock_path, File::RDWR|File::CREAT, 0644) do |f|
+ f.flock(File::LOCK_EX)
+ return unless valid?
+
+ # 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
+ if File.exists?(public_path)
+ FileUtils.move(public_path, previous_public_path)
+ end
+ FileUtils.move(temp_public_path, public_path)
+ end
+
+ if File.exists?(previous_public_path)
+ FileUtils.rm_r(previous_public_path, force: true)
+ end
+
+ @status.success
+ end
+ ensure
+ @status.drop if @status && @status.active?
+ end
+
+ private
+
+ def valid?
+ # check if sha for the ref is still the most recent one
+ # this helps in case when multiple deployments happens
+ build && build.artifacts_file? && sha == latest_sha
+ 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 lock_path
+ @lock_path ||= File.join(pages_path, 'deploy.lock')
+ 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/config/gitlab.yml.example b/config/gitlab.yml.example
index 42e5f105d46..d41280624ae 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -153,6 +153,17 @@ production: &base
# The location where LFS objects are stored (default: shared/lfs-objects).
# storage_path: shared/lfs-objects
+ ## GitLab Pages
+ pages:
+ enabled: false
+ # The location where pages are stored (default: shared/pages).
+ # path: shared/pages
+
+ # The domain under which the pages are served:
+ # http://group.example.com/project
+ # or project path can be a group page: group.example.com
+ domain: example.com
+
## Mattermost
## For enabling Add to Mattermost button
mattermost:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 4f33aad8693..0c06b73ba36 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -254,6 +254,12 @@ Settings.registry['issuer'] ||= nil
Settings.registry['host_port'] ||= [Settings.registry['host'], Settings.registry['port']].compact.join(':')
Settings.registry['path'] = File.expand_path(Settings.registry['path'] || File.join(Settings.shared['path'], 'registry'), Rails.root)
+# Pages
+Settings['pages'] ||= Settingslogic.new({})
+Settings.pages['enabled'] = false if Settings.pages['enabled'].nil?
+Settings.pages['path'] = File.expand_path('shared/pages/', Rails.root)
+Settings.pages['domain'] ||= "example.com"
+
#
# Git LFS
#
diff --git a/config/routes/project.rb b/config/routes/project.rb
index f36febc6e04..cd56f6281f5 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -329,6 +329,7 @@ constraints(ProjectUrlConstrainer.new) do
post :archive
post :unarchive
post :housekeeping
+ post :remove_pages
post :toggle_star
post :preview_markdown
post :export
diff --git a/db/migrate/20151215132013_add_pages_size_to_application_settings.rb b/db/migrate/20151215132013_add_pages_size_to_application_settings.rb
new file mode 100644
index 00000000000..e7fb73190e8
--- /dev/null
+++ b/db/migrate/20151215132013_add_pages_size_to_application_settings.rb
@@ -0,0 +1,5 @@
+class AddPagesSizeToApplicationSettings < ActiveRecord::Migration
+ def up
+ add_column :application_settings, :max_pages_size, :integer, default: 100, null: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5efb4f6595c..15f378b28ff 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -61,6 +61,7 @@ ActiveRecord::Schema.define(version: 20170130204620) do
t.boolean "shared_runners_enabled", default: true, null: false
t.integer "max_artifacts_size", default: 100, null: false
t.string "runners_registration_token"
+ t.integer "max_pages_size", default: 100, null: false
t.boolean "require_two_factor_authentication", default: false
t.integer "two_factor_grace_period", default: 48
t.boolean "metrics_enabled", default: false
diff --git a/doc/README.md b/doc/README.md
index 909740211a6..f036febb7b9 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -12,6 +12,7 @@
- [GitLab as OAuth2 authentication service provider](integration/oauth_provider.md). It allows you to login to other applications from GitLab.
- [Container Registry](user/project/container_registry.md) Learn how to use GitLab Container Registry.
- [GitLab basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab.
+- [GitLab Pages](pages/README.md) Using GitLab Pages.
- [Importing to GitLab](workflow/importing/README.md) Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab.
- [Importing and exporting projects between instances](user/project/settings/import_export.md).
- [Markdown](user/markdown.md) GitLab's advanced formatting system.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 425c5d93efb..c78e469055d 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -313,6 +313,9 @@ sudo usermod -aG redis git
# Change the permissions of the directory where CI artifacts are stored
sudo chmod -R u+rwX shared/artifacts/
+ # Change the permissions of the directory where CI artifacts are stored
+ sudo chmod -R ug+rwX shared/pages/
+
# Copy the example Unicorn config
sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
@@ -484,6 +487,16 @@ Make sure to edit the config file to match your setup. Also, ensure that you mat
# or else sudo rm -f /etc/nginx/sites-enabled/default
sudo editor /etc/nginx/sites-available/gitlab
+Copy the GitLab pages site config:
+
+ sudo cp lib/support/nginx/gitlab-pages /etc/nginx/sites-available/gitlab-pages
+ sudo ln -s /etc/nginx/sites-available/gitlab-pages /etc/nginx/sites-enabled/gitlab-pages
+
+ # Change YOUR_GITLAB_PAGES\.DOMAIN to the fully-qualified
+ # domain name under which the pages will be served.
+ # The . (dot) replace with \. (backslash+dot)
+ sudo editor /etc/nginx/sites-available/gitlab-pages
+
**Note:** If you want to use HTTPS, replace the `gitlab` Nginx config with `gitlab-ssl`. See [Using HTTPS](#using-https) for HTTPS configuration details.
### Test Configuration
diff --git a/doc/pages/README.md b/doc/pages/README.md
new file mode 100644
index 00000000000..d08c34c3ebc
--- /dev/null
+++ b/doc/pages/README.md
@@ -0,0 +1,12 @@
+# GitLab Pages
+
+To start using GitLab Pages add to your project .gitlab-ci.yml with special pages job.
+
+ pages:
+ image: jekyll
+ script: jekyll build
+ artifacts:
+ paths:
+ - public
+
+TODO
diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb
new file mode 100644
index 00000000000..215ded93bfe
--- /dev/null
+++ b/lib/backup/pages.rb
@@ -0,0 +1,13 @@
+require 'backup/files'
+
+module Backup
+ class Pages < Files
+ def initialize
+ super('pages', Gitlab.config.pages.path)
+ end
+
+ def create_files_dir
+ Dir.mkdir(app_files_dir, 0700)
+ end
+ end
+end
diff --git a/lib/support/nginx/gitlab-pages b/lib/support/nginx/gitlab-pages
new file mode 100644
index 00000000000..0eeb0cd1917
--- /dev/null
+++ b/lib/support/nginx/gitlab-pages
@@ -0,0 +1,27 @@
+## Pages serving host
+server {
+ listen 0.0.0.0:80;
+ listen [::]:80 ipv6only=on;
+
+ ## Replace this with something like pages.gitlab.com
+ server_name ~^(?<group>.*)\.YOUR_GITLAB_PAGES\.DOMAIN$;
+ root /home/git/gitlab/shared/pages/${group};
+
+ ## Individual nginx logs for GitLab pages
+ access_log /var/log/nginx/gitlab_pages_access.log;
+ error_log /var/log/nginx/gitlab_pages_error.log;
+
+ # 1. Try to get /project/ to => shared/pages/${group}/public/ or index.html
+ # 2. Try to get / to => shared/pages/${group}/${host}/public/ or index.html
+ location ~ ^/([^/]*)(/.*)?$ {
+ try_files "/$1/public$2"
+ "/$1/public$2/index.html"
+ "/${host}/public/${uri}"
+ "/${host}/public/${uri}/index.html"
+ =404;
+ }
+
+ # Define custom error pages
+ error_page 403 /403.html;
+ error_page 404 /404.html;
+}
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index a9f1255e8cf..ffab6f492fb 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -13,6 +13,7 @@ namespace :gitlab do
Rake::Task["gitlab:backup:uploads:create"].invoke
Rake::Task["gitlab:backup:builds:create"].invoke
Rake::Task["gitlab:backup:artifacts:create"].invoke
+ Rake::Task["gitlab:backup:pages:create"].invoke
Rake::Task["gitlab:backup:lfs:create"].invoke
Rake::Task["gitlab:backup:registry:create"].invoke
@@ -56,6 +57,7 @@ namespace :gitlab do
Rake::Task['gitlab:backup:uploads:restore'].invoke unless backup.skipped?('uploads')
Rake::Task['gitlab:backup:builds:restore'].invoke unless backup.skipped?('builds')
Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts')
+ Rake::Task["gitlab:backup:pages:restore"].invoke unless backup.skipped?("pages")
Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs')
Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry')
Rake::Task['gitlab:shell:setup'].invoke
@@ -159,6 +161,25 @@ namespace :gitlab do
end
end
+ namespace :pages do
+ task create: :environment do
+ $progress.puts "Dumping pages ... ".blue
+
+ if ENV["SKIP"] && ENV["SKIP"].include?("pages")
+ $progress.puts "[SKIPPED]".cyan
+ else
+ Backup::Pages.new.dump
+ $progress.puts "done".green
+ end
+ end
+
+ task restore: :environment do
+ $progress.puts "Restoring pages ... ".blue
+ Backup::Pages.new.restore
+ $progress.puts "done".green
+ end
+ end
+
namespace :lfs do
task create: :environment do
$progress.puts "Dumping lfs objects ... ".color(:blue)
diff --git a/shared/pages/.gitkeep b/shared/pages/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/shared/pages/.gitkeep
diff --git a/spec/fixtures/pages.tar.gz b/spec/fixtures/pages.tar.gz
new file mode 100644
index 00000000000..d0e89378b3e
--- /dev/null
+++ b/spec/fixtures/pages.tar.gz
Binary files differ
diff --git a/spec/fixtures/pages_empty.tar.gz b/spec/fixtures/pages_empty.tar.gz
new file mode 100644
index 00000000000..5c2afa1a8f6
--- /dev/null
+++ b/spec/fixtures/pages_empty.tar.gz
Binary files differ
diff --git a/spec/services/update_pages_service_spec.rb b/spec/services/update_pages_service_spec.rb
new file mode 100644
index 00000000000..ed392cd94ee
--- /dev/null
+++ b/spec/services/update_pages_service_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe UpdatePagesService, services: true do
+ let(:build) { create(:ci_build) }
+ let(:data) { Gitlab::BuildDataBuilder.build(build) }
+ let(:service) { UpdatePagesService.new(data) }
+
+ context 'execute asynchronously for pages job' do
+ before { build.name = 'pages' }
+
+ context 'on success' do
+ before { build.success }
+
+ it 'should execute worker' do
+ expect(PagesWorker).to receive(:perform_async)
+ service.execute
+ end
+ end
+
+ %w(pending running failed canceled).each do |status|
+ context "on #{status}" do
+ before { build.status = status }
+
+ it 'should not execute worker' do
+ expect(PagesWorker).to_not receive(:perform_async)
+ service.execute
+ end
+ end
+ end
+ end
+
+ context 'for other jobs' do
+ before do
+ build.name = 'other job'
+ build.success
+ end
+
+ it 'should not execute worker' do
+ expect(PagesWorker).to_not receive(:perform_async)
+ service.execute
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index bc751d20ce1..df8a47893f9 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -28,7 +28,7 @@ describe 'gitlab:app namespace rake task' do
end
def reenable_backup_sub_tasks
- %w{db repo uploads builds artifacts lfs registry}.each do |subtask|
+ %w{db repo uploads builds artifacts pages lfs registry}.each do |subtask|
Rake::Task["gitlab:backup:#{subtask}:create"].reenable
end
end
@@ -71,6 +71,7 @@ describe 'gitlab:app namespace rake task' do
expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
+ expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
@@ -202,7 +203,7 @@ describe 'gitlab:app namespace rake task' do
it 'sets correct permissions on the tar contents' do
tar_contents, exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz registry.tar.gz}
+ %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz registry.tar.gz}
)
expect(exit_status).to eq(0)
expect(tar_contents).to match('db/')
@@ -210,14 +211,15 @@ describe 'gitlab:app namespace rake task' do
expect(tar_contents).to match('repositories/')
expect(tar_contents).to match('builds.tar.gz')
expect(tar_contents).to match('artifacts.tar.gz')
+ expect(tar_contents).to match('pages.tar.gz')
expect(tar_contents).to match('lfs.tar.gz')
expect(tar_contents).to match('registry.tar.gz')
- expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|artifacts.tar.gz|registry.tar.gz)\/$/)
+ expect(tar_contents).not_to match(/^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|pages.tar.gz|artifacts.tar.gz|registry.tar.gz)\/$/)
end
it 'deletes temp directories' do
temp_dirs = Dir.glob(
- File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,lfs,registry}')
+ File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,pages,lfs,registry}')
)
expect(temp_dirs).to be_empty
@@ -304,7 +306,7 @@ describe 'gitlab:app namespace rake task' do
it "does not contain skipped item" do
tar_contents, _exit_status = Gitlab::Popen.popen(
- %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz lfs.tar.gz registry.tar.gz}
+ %W{tar -tvf #{@backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz registry.tar.gz}
)
expect(tar_contents).to match('db/')
@@ -312,6 +314,7 @@ describe 'gitlab:app namespace rake task' do
expect(tar_contents).to match('builds.tar.gz')
expect(tar_contents).to match('artifacts.tar.gz')
expect(tar_contents).to match('lfs.tar.gz')
+ expect(tar_contents).to match('pages.tar.gz')
expect(tar_contents).to match('registry.tar.gz')
expect(tar_contents).not_to match('repositories/')
end
@@ -327,6 +330,7 @@ describe 'gitlab:app namespace rake task' do
expect(Rake::Task['gitlab:backup:uploads:restore']).not_to receive :invoke
expect(Rake::Task['gitlab:backup:builds:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke
+ expect(Rake::Task['gitlab:backup:pages:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
diff --git a/spec/workers/pages_worker_spec.rb b/spec/workers/pages_worker_spec.rb
new file mode 100644
index 00000000000..158a4b3ba8d
--- /dev/null
+++ b/spec/workers/pages_worker_spec.rb
@@ -0,0 +1,58 @@
+require "spec_helper"
+
+describe PagesWorker 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') }
+
+ before do
+ project.remove_pages
+ end
+
+ context 'for valid file' do
+ before { build.update_attributes(artifacts_file: file) }
+
+ it 'succeeds' do
+ expect(project.pages_url).to be_nil
+ expect(worker.perform(build.id)).to be_truthy
+ expect(project.pages_url).to_not be_nil
+ end
+
+ it 'limits pages size' do
+ stub_application_setting(max_pages_size: 1)
+ expect(worker.perform(build.id)).to_not be_truthy
+ end
+
+ it 'removes pages after destroy' do
+ expect(project.pages_url).to be_nil
+ expect(worker.perform(build.id)).to be_truthy
+ expect(project.pages_url).to_not be_nil
+ project.destroy
+ expect(Dir.exist?(project.public_pages_path)).to be_falsey
+ end
+ end
+
+ it 'fails if no artifacts' do
+ expect(worker.perform(build.id)).to_not be_truthy
+ end
+
+ it 'fails for empty file fails' do
+ build.update_attributes(artifacts_file: empty_file)
+ expect(worker.perform(build.id)).to_not be_truthy
+ end
+
+ it 'fails for invalid archive' do
+ build.update_attributes(artifacts_file: invalid_file)
+ expect(worker.perform(build.id)).to_not be_truthy
+ 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.perform(build.id)).to_not be_truthy
+ end
+end