Commit a9306b55 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-05-24

# Conflicts:
#	doc/api/issues.md
#	doc/api/merge_requests.md

[ci skip]
parents b367f55f 6d2a6139
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
return { return {
pipelineId: '', pipelineId: '',
endpoint: '', endpoint: '',
cancelingPipeline: null,
}; };
}, },
computed: { computed: {
...@@ -64,6 +65,7 @@ ...@@ -64,6 +65,7 @@
}, },
onSubmit() { onSubmit() {
eventHub.$emit('postAction', this.endpoint); eventHub.$emit('postAction', this.endpoint);
this.cancelingPipeline = this.pipelineId;
}, },
}, },
}; };
...@@ -106,6 +108,7 @@ ...@@ -106,6 +108,7 @@
:update-graph-dropdown="updateGraphDropdown" :update-graph-dropdown="updateGraphDropdown"
:auto-devops-help-path="autoDevopsHelpPath" :auto-devops-help-path="autoDevopsHelpPath"
:view-type="viewType" :view-type="viewType"
:canceling-pipeline="cancelingPipeline"
/> />
<modal <modal
......
...@@ -46,12 +46,16 @@ ...@@ -46,12 +46,16 @@
type: String, type: String,
required: true, required: true,
}, },
cancelingPipeline: {
type: String,
required: false,
default: null,
},
}, },
pipelinesTable: PIPELINES_TABLE, pipelinesTable: PIPELINES_TABLE,
data() { data() {
return { return {
isRetrying: false, isRetrying: false,
isCancelling: false,
}; };
}, },
computed: { computed: {
...@@ -227,12 +231,14 @@ ...@@ -227,12 +231,14 @@
isChildView() { isChildView() {
return this.viewType === 'child'; return this.viewType === 'child';
}, },
isCancelling() {
return this.cancelingPipeline === this.pipeline.id;
},
}, },
methods: { methods: {
handleCancelClick() { handleCancelClick() {
this.isCancelling = true;
eventHub.$emit('openConfirmationModal', { eventHub.$emit('openConfirmationModal', {
pipelineId: this.pipeline.id, pipelineId: this.pipeline.id,
endpoint: this.pipeline.cancel_path, endpoint: this.pipeline.cancel_path,
......
---
title: Fix backup creation and restore for specific Rake tasks
merge_request:
author:
type: fixed
...@@ -319,7 +319,10 @@ module.exports = { ...@@ -319,7 +319,10 @@ module.exports = {
host: DEV_SERVER_HOST, host: DEV_SERVER_HOST,
port: DEV_SERVER_PORT, port: DEV_SERVER_PORT,
disableHostCheck: true, disableHostCheck: true,
headers: { 'Access-Control-Allow-Origin': '*' }, headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
},
stats: 'errors-only', stats: 'errors-only',
hot: DEV_SERVER_LIVERELOAD, hot: DEV_SERVER_LIVERELOAD,
inline: DEV_SERVER_LIVERELOAD, inline: DEV_SERVER_LIVERELOAD,
......
...@@ -467,6 +467,7 @@ POST /projects/:id/issues ...@@ -467,6 +467,7 @@ POST /projects/:id/issues
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|-------------------------------------------|----------------|----------|--------------| |-------------------------------------------|----------------|----------|--------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
<<<<<<< HEAD
| `title` | string | yes | The title of an issue | | `title` | string | yes | The title of an issue |
| `description` | string | no | The description of an issue | | `description` | string | no | The description of an issue |
| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. | | `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
...@@ -478,6 +479,18 @@ POST /projects/:id/issues ...@@ -478,6 +479,18 @@ POST /projects/:id/issues
| `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This will fill the issue with a default description and mark all discussions as resolved. When passing a description or title, these values will take precedence over the default values.| | `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This will fill the issue with a default description and mark all discussions as resolved. When passing a description or title, these values will take precedence over the default values.|
| `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This will fill in the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. | | `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This will fill in the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. |
| `weight` | integer | no | The weight of the issue in range 0 to 9 | | `weight` | integer | no | The weight of the issue in range 0 to 9 |
=======
| `title` | string | yes | The title of an issue |
| `description` | string | no | The description of an issue |
| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
| `assignee_ids` | Array[integer] | no | The ID of the users to assign issue |
| `milestone_id` | integer | no | The global ID of a milestone to assign issue |
| `labels` | string | no | Comma-separated label names for an issue |
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) |
| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, e.g. `2016-03-11` |
| `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This will fill the issue with a default description and mark all discussions as resolved. When passing a description or title, these values will take precedence over the default values.|
| `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This will fill in the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. |
>>>>>>> upstream/master
```bash ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues?title=Issues%20with%20auth&labels=bug
......
...@@ -535,6 +535,7 @@ Creates a new merge request. ...@@ -535,6 +535,7 @@ Creates a new merge request.
POST /projects/:id/merge_requests POST /projects/:id/merge_requests
``` ```
<<<<<<< HEAD
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
...@@ -549,6 +550,20 @@ POST /projects/:id/merge_requests ...@@ -549,6 +550,20 @@ POST /projects/:id/merge_requests
| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging | | `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
| `approvals_before_merge` | integer| no | Number of approvals required before this can be merged (see below) | | `approvals_before_merge` | integer| no | Number of approvals required before this can be merged (see below) |
| `squash` | boolean| no | Squash commits into a single commit when merging | | `squash` | boolean| no | Squash commits into a single commit when merging |
=======
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `source_branch` | string | yes | The source branch |
| `target_branch` | string | yes | The target branch |
| `title` | string | yes | Title of MR |
| `assignee_id` | integer | no | Assignee user ID |
| `description` | string | no | Description of MR |
| `target_project_id` | integer | no | The target project (numeric id) |
| `labels` | string | no | Labels for MR as a comma-separated list |
| `milestone_id` | integer | no | The global ID of a milestone |
| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
>>>>>>> upstream/master
| `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch | | `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch |
If `approvals_before_merge` is not provided, it inherits the value from the If `approvals_before_merge` is not provided, it inherits the value from the
...@@ -634,6 +649,7 @@ Updates an existing merge request. You can change the target branch, title, or e ...@@ -634,6 +649,7 @@ Updates an existing merge request. You can change the target branch, title, or e
PUT /projects/:id/merge_requests/:merge_request_iid PUT /projects/:id/merge_requests/:merge_request_iid
``` ```
<<<<<<< HEAD
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
...@@ -649,6 +665,22 @@ PUT /projects/:id/merge_requests/:merge_request_iid ...@@ -649,6 +665,22 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `squash` | boolean| no | Squash commits into a single commit when merging | | `squash` | boolean| no | Squash commits into a single commit when merging |
| `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. | | `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. |
| `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch | | `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch |
=======
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `merge_request_iid` | integer | yes | The ID of a merge request |
| `target_branch` | string | no | The target branch |
| `title` | string | no | Title of MR |
| `assignee_id` | integer | no | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. |
| `milestone_id` | integer | no | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.|
| `labels` | string | no | Comma-separated label names for a merge request. Set to an empty string to unassign all labels. |
| `description` | string | no | Description of MR |
| `state_event` | string | no | New state (close/reopen) |
| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging |
| `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. |
| `allow_maintainer_to_push` | boolean | no | Whether or not a maintainer of the target project can push to the source branch |
>>>>>>> upstream/master
Must include at least one non-required attribute from above. Must include at least one non-required attribute from above.
......
...@@ -31,8 +31,8 @@ sudo apt-get install -y rsync ...@@ -31,8 +31,8 @@ sudo apt-get install -y rsync
>**Note:** >**Note:**
In GitLab 9.2 the timestamp format was changed from `EPOCH_YYYY_MM_DD` to In GitLab 9.2 the timestamp format was changed from `EPOCH_YYYY_MM_DD` to
`EPOCH_YYYY_MM_DD_GitLab version`, for example `1493107454_2017_04_25` `EPOCH_YYYY_MM_DD_GitLab_version`, for example `1493107454_2018_04_25`
would become `1493107454_2017_04_25_9.1.0`. would become `1493107454_2018_04_25_10.6.4-ce`.
The backup archive will be saved in `backup_path`, which is specified in the The backup archive will be saved in `backup_path`, which is specified in the
`config/gitlab.yml` file. `config/gitlab.yml` file.
...@@ -41,8 +41,8 @@ identifies the time at which each backup was created, plus the GitLab version. ...@@ -41,8 +41,8 @@ identifies the time at which each backup was created, plus the GitLab version.
The timestamp is needed if you need to restore GitLab and multiple backups are The timestamp is needed if you need to restore GitLab and multiple backups are
available. available.
For example, if the backup name is `1493107454_2017_04_25_9.1.0_gitlab_backup.tar`, For example, if the backup name is `1493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar`,
then the timestamp is `1493107454_2017_04_25_9.1.0`. then the timestamp is `1493107454_2018_04_25_10.6.4-ce`.
### Creating a backup of the GitLab system ### Creating a backup of the GitLab system
...@@ -574,7 +574,7 @@ First make sure your backup tar file is in the backup directory described in the ...@@ -574,7 +574,7 @@ First make sure your backup tar file is in the backup directory described in the
`/var/opt/gitlab/backups`. `/var/opt/gitlab/backups`.
```shell ```shell
sudo cp 1493107454_2017_04_25_9.1.0_gitlab_backup.tar /var/opt/gitlab/backups/ sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/
``` ```
Stop the processes that are connected to the database. Leave the rest of GitLab Stop the processes that are connected to the database. Leave the rest of GitLab
...@@ -592,7 +592,7 @@ restore: ...@@ -592,7 +592,7 @@ restore:
```shell ```shell
# This command will overwrite the contents of your GitLab database! # This command will overwrite the contents of your GitLab database!
sudo gitlab-rake gitlab:backup:restore BACKUP=1493107454_2017_04_25_9.1.0 sudo gitlab-rake gitlab:backup:restore BACKUP=1493107454_2018_04_25_10.6.4-ce
``` ```
Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary as mentioned above. Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary as mentioned above.
......
...@@ -2,7 +2,11 @@ require 'backup/files' ...@@ -2,7 +2,11 @@ require 'backup/files'
module Backup module Backup
class Artifacts < Files class Artifacts < Files
def initialize attr_reader :progress
def initialize(progress)
@progress = progress
super('artifacts', JobArtifactUploader.root) super('artifacts', JobArtifactUploader.root)
end end
end end
......
...@@ -2,7 +2,11 @@ require 'backup/files' ...@@ -2,7 +2,11 @@ require 'backup/files'
module Backup module Backup
class Builds < Files class Builds < Files
def initialize attr_reader :progress
def initialize(progress)
@progress = progress
super('builds', Settings.gitlab_ci.builds_path) super('builds', Settings.gitlab_ci.builds_path)
end end
end end
......
...@@ -2,9 +2,11 @@ require 'yaml' ...@@ -2,9 +2,11 @@ require 'yaml'
module Backup module Backup
class Database class Database
attr_reader :progress
attr_reader :config, :db_file_name attr_reader :config, :db_file_name
def initialize def initialize(progress)
@progress = progress
@config = YAML.load_file(File.join(Rails.root, 'config', 'database.yml'))[Rails.env] @config = YAML.load_file(File.join(Rails.root, 'config', 'database.yml'))[Rails.env]
@db_file_name = File.join(Gitlab.config.backup.path, 'db', 'database.sql.gz') @db_file_name = File.join(Gitlab.config.backup.path, 'db', 'database.sql.gz')
end end
...@@ -19,12 +21,12 @@ module Backup ...@@ -19,12 +21,12 @@ module Backup
dump_pid = dump_pid =
case config["adapter"] case config["adapter"]
when /^mysql/ then when /^mysql/ then
$progress.print "Dumping MySQL database #{config['database']} ... " progress.print "Dumping MySQL database #{config['database']} ... "
# Workaround warnings from MySQL 5.6 about passwords on cmd line # Workaround warnings from MySQL 5.6 about passwords on cmd line
ENV['MYSQL_PWD'] = config["password"].to_s if config["password"] ENV['MYSQL_PWD'] = config["password"].to_s if config["password"]
spawn('mysqldump', *mysql_args, config['database'], out: compress_wr) spawn('mysqldump', *mysql_args, config['database'], out: compress_wr)
when "postgresql" then when "postgresql" then
$progress.print "Dumping PostgreSQL database #{config['database']} ... " progress.print "Dumping PostgreSQL database #{config['database']} ... "
pg_env pg_env
pgsql_args = ["--clean"] # Pass '--clean' to include 'DROP TABLE' statements in the DB dump. pgsql_args = ["--clean"] # Pass '--clean' to include 'DROP TABLE' statements in the DB dump.
if Gitlab.config.backup.pg_schema if Gitlab.config.backup.pg_schema
...@@ -53,12 +55,12 @@ module Backup ...@@ -53,12 +55,12 @@ module Backup
restore_pid = restore_pid =
case config["adapter"] case config["adapter"]
when /^mysql/ then when /^mysql/ then
$progress.print "Restoring MySQL database #{config['database']} ... " progress.print "Restoring MySQL database #{config['database']} ... "
# Workaround warnings from MySQL 5.6 about passwords on cmd line # Workaround warnings from MySQL 5.6 about passwords on cmd line
ENV['MYSQL_PWD'] = config["password"].to_s if config["password"] ENV['MYSQL_PWD'] = config["password"].to_s if config["password"]
spawn('mysql', *mysql_args, config['database'], in: decompress_rd) spawn('mysql', *mysql_args, config['database'], in: decompress_rd)
when "postgresql" then when "postgresql" then
$progress.print "Restoring PostgreSQL database #{config['database']} ... " progress.print "Restoring PostgreSQL database #{config['database']} ... "
pg_env pg_env
spawn('psql', config['database'], in: decompress_rd) spawn('psql', config['database'], in: decompress_rd)
end end
...@@ -111,9 +113,9 @@ module Backup ...@@ -111,9 +113,9 @@ module Backup
def report_success(success) def report_success(success)
if success if success
$progress.puts '[DONE]'.color(:green) progress.puts '[DONE]'.color(:green)
else else
$progress.puts '[FAILED]'.color(:red) progress.puts '[FAILED]'.color(:red)
end end
end end
end end
......
...@@ -2,7 +2,11 @@ require 'backup/files' ...@@ -2,7 +2,11 @@ require 'backup/files'
module Backup module Backup
class Lfs < Files class Lfs < Files
def initialize attr_reader :progress
def initialize(progress)
@progress = progress
super('lfs', Settings.lfs.storage_path) super('lfs', Settings.lfs.storage_path)
end end
end end
......
...@@ -4,6 +4,12 @@ module Backup ...@@ -4,6 +4,12 @@ module Backup
FOLDERS_TO_BACKUP = %w[repositories db].freeze FOLDERS_TO_BACKUP = %w[repositories db].freeze
FILE_NAME_SUFFIX = '_gitlab_backup.tar'.freeze FILE_NAME_SUFFIX = '_gitlab_backup.tar'.freeze
attr_reader :progress
def initialize(progress)
@progress = progress
end
def pack def pack
# Make sure there is a connection # Make sure there is a connection
ActiveRecord::Base.connection.reconnect! ActiveRecord::Base.connection.reconnect!
...@@ -14,11 +20,11 @@ module Backup ...@@ -14,11 +20,11 @@ module Backup
end end
# create archive # create archive
$progress.print "Creating backup archive: #{tar_file} ... " progress.print "Creating backup archive: #{tar_file} ... "
# Set file permissions on open to prevent chmod races. # Set file permissions on open to prevent chmod races.
tar_system_options = { out: [tar_file, 'w', Gitlab.config.backup.archive_permissions] } tar_system_options = { out: [tar_file, 'w', Gitlab.config.backup.archive_permissions] }
if Kernel.system('tar', '-cf', '-', *backup_contents, tar_system_options) if Kernel.system('tar', '-cf', '-', *backup_contents, tar_system_options)
$progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
puts "creating archive #{tar_file} failed".color(:red) puts "creating archive #{tar_file} failed".color(:red)
abort 'Backup failed' abort 'Backup failed'
...@@ -29,11 +35,11 @@ module Backup ...@@ -29,11 +35,11 @@ module Backup
end end
def upload def upload
$progress.print "Uploading backup archive to remote storage #{remote_directory} ... " progress.print "Uploading backup archive to remote storage #{remote_directory} ... "
connection_settings = Gitlab.config.backup.upload.connection connection_settings = Gitlab.config.backup.upload.connection
if connection_settings.blank? if connection_settings.blank?
$progress.puts "skipped".color(:yellow) progress.puts "skipped".color(:yellow)
return return
end end
...@@ -43,7 +49,7 @@ module Backup ...@@ -43,7 +49,7 @@ module Backup
multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size, multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size,
encryption: Gitlab.config.backup.upload.encryption, encryption: Gitlab.config.backup.upload.encryption,
storage_class: Gitlab.config.backup.upload.storage_class) storage_class: Gitlab.config.backup.upload.storage_class)
$progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
puts "uploading backup to #{remote_directory} failed".color(:red) puts "uploading backup to #{remote_directory} failed".color(:red)
abort 'Backup failed' abort 'Backup failed'
...@@ -51,13 +57,13 @@ module Backup ...@@ -51,13 +57,13 @@ module Backup
end end
def cleanup def cleanup
$progress.print "Deleting tmp directories ... " progress.print "Deleting tmp directories ... "
backup_contents.each do |dir| backup_contents.each do |dir|
next unless File.exist?(File.join(backup_path, dir)) next unless File.exist?(File.join(backup_path, dir))
if FileUtils.rm_rf(File.join(backup_path, dir)) if FileUtils.rm_rf(File.join(backup_path, dir))
$progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
puts "deleting tmp directory '#{dir}' failed".color(:red) puts "deleting tmp directory '#{dir}' failed".color(:red)
abort 'Backup failed' abort 'Backup failed'
...@@ -67,7 +73,7 @@ module Backup ...@@ -67,7 +73,7 @@ module Backup
def remove_old def remove_old
# delete backups # delete backups
$progress.print "Deleting old backups ... " progress.print "Deleting old backups ... "
keep_time = Gitlab.config.backup.keep_time.to_i keep_time = Gitlab.config.backup.keep_time.to_i
if keep_time > 0 if keep_time > 0
...@@ -88,31 +94,32 @@ module Backup ...@@ -88,31 +94,32 @@ module Backup
FileUtils.rm(file) FileUtils.rm(file)
removed += 1 removed += 1
rescue => e rescue => e
$progress.puts "Deleting #{file} failed: #{e.message}".color(:red) progress.puts "Deleting #{file} failed: #{e.message}".color(:red)
end end
end end
end end
end end
$progress.puts "done. (#{removed} removed)".color(:green) progress.puts "done. (#{removed} removed)".color(:green)
else else
$progress.puts "skipping".color(:yellow) progress.puts "skipping".color(:yellow)
end end
end end
# rubocop: disable Metrics/AbcSize
def unpack def unpack
Dir.chdir(backup_path) do Dir.chdir(backup_path) do
# check for existing backups in the backup dir # check for existing backups in the backup dir
if backup_file_list.empty? if backup_file_list.empty?
$progress.puts "No backups found in #{backup_path}" progress.puts "No backups found in #{backup_path}"
$progress.puts "Please make sure that file name ends with #{FILE_NAME_SUFFIX}" progress.puts "Please make sure that file name ends with #{FILE_NAME_SUFFIX}"
exit 1 exit 1
elsif backup_file_list.many? && ENV["BACKUP"].nil? elsif backup_file_list.many? && ENV["BACKUP"].nil?
$progress.puts 'Found more than one backup:' progress.puts 'Found more than one backup:'
# print list of available backups # print list of available backups
$progress.puts " " + available_timestamps.join("\n ") progress.puts " " + available_timestamps.join("\n ")
$progress.puts 'Please specify which one you want to restore:' progress.puts 'Please specify which one you want to restore:'
$progress.puts 'rake gitlab:backup:restore BACKUP=timestamp_of_backup' progress.puts 'rake gitlab:backup:restore BACKUP=timestamp_of_backup'
exit 1 exit 1
end end
...@@ -123,31 +130,31 @@ module Backup ...@@ -123,31 +130,31 @@ module Backup
end end
unless File.exist?(tar_file) unless File.exist?(tar_file)
$progress.puts "The backup file #{tar_file} does not exist!" progress.puts "The backup file #{tar_file} does not exist!"
exit 1 exit 1
end end
$progress.print 'Unpacking backup ... ' progress.print 'Unpacking backup ... '
unless Kernel.system(*%W(tar -xf #{tar_file})) unless Kernel.system(*%W(tar -xf #{tar_file}))
$progress.puts 'unpacking backup failed'.color(:red) progress.puts 'unpacking backup failed'.color(:red)
exit 1 exit 1
else else
$progress.puts 'done'.color(:green) progress.puts 'done'.color(:green)
end end
ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0 ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0
# restoring mismatching backups can lead to unexpected problems # restoring mismatching backups can lead to unexpected problems
if settings[:gitlab_version] != Gitlab::VERSION if settings[:gitlab_version] != Gitlab::VERSION
$progress.puts(<<~HEREDOC.color(:red)) progress.puts(<<~HEREDOC.color(:red))
GitLab version mismatch: GitLab version mismatch:
Your current GitLab version (#{Gitlab::VERSION}) differs from the GitLab version in the backup! Your current GitLab version (#{Gitlab::VERSION}) differs from the GitLab version in the backup!
Please switch to the following version and try again: Please switch to the following version and try again:
version: #{settings[:gitlab_version]} version: #{settings[:gitlab_version]}
HEREDOC HEREDOC
$progress.puts progress.puts
$progress.puts "Hint: git checkout v#{settings[:gitlab_version]}" progress.puts "Hint: git checkout v#{settings[:gitlab_version]}"
exit 1 exit 1
end end
end end
......
...@@ -2,7 +2,11 @@ require 'backup/files' ...@@ -2,7 +2,11 @@ require 'backup/files'
module Backup module Backup
class Pages < Files class Pages < Files
def initialize attr_reader :progress
def initialize(progress)
@progress = progress
super('pages', Gitlab.config.pages.path) super('pages', Gitlab.config.pages.path)
end end
end end
......
...@@ -2,7 +2,11 @@ require 'backup/files' ...@@ -2,7 +2,11 @@ require 'backup/files'
module Backup module Backup
class Registry < Files class Registry < Files
def initialize attr_reader :progress
def initialize(progress)
@progress = progress
super('registry', Settings.registry.path) super('registry', Settings.registry.path)
end end
end end
......
...@@ -6,6 +6,12 @@ module Backup ...@@ -6,6 +6,12 @@ module Backup
include Backup::Helper include Backup::Helper
# rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/AbcSize
attr_reader :progress
def initialize(progress)
@progress = progress
end
def dump def dump
prepare prepare
...@@ -217,10 +223,6 @@ module Backup ...@@ -217,10 +223,6 @@ module Backup
Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path } Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path }
end end
def progress
$progress
end
def display_repo_path(project) def display_repo_path(project)
project.hashed_storage?(:repository) ? "#{project.full_path} (#{project.disk_path})" : project.full_path project.hashed_storage?(:repository) ? "#{project.full_path} (#{project.disk_path})" : project.full_path
end end
......
...@@ -2,7 +2,11 @@ require 'backup/files' ...@@ -2,7 +2,11 @@ require 'backup/files'
module Backup module Backup
class Uploads < Files class Uploads < Files
def initialize attr_reader :progress
def initialize(progress)
@progress = progress
super('uploads', Rails.root.join('public/uploads')) super('uploads', Rails.root.join('public/uploads'))
end end
end end
......
...@@ -6,7 +6,6 @@ namespace :gitlab do ...@@ -6,7 +6,6 @@ namespace :gitlab do
desc "GitLab | Create a backup of the GitLab system" desc "GitLab | Create a backup of the GitLab system"
task create: :gitlab_environment do task create: :gitlab_environment do
warn_user_is_not_gitlab warn_user_is_not_gitlab
configure_cron_mode
Rake::Task["gitlab:backup:db:create"].invoke Rake::Task["gitlab:backup:db:create"].invoke
Rake::Task["gitlab:backup:repo:create"].invoke Rake::Task["gitlab:backup:repo:create"].invoke
...@@ -17,7 +16,7 @@ namespace :gitlab do ...@@ -17,7 +16,7 @@ namespace :gitlab do
Rake::Task["gitlab:backup:lfs:create"].invoke Rake::Task["gitlab:backup:lfs:create"].invoke
Rake::Task["gitlab:backup:registry:create"].invoke Rake::Task["gitlab:backup:registry:create"].invoke
backup = Backup::Manager.new backup = Backup::Manager.new(progress)
backup.pack backup.pack
backup.cleanup backup.cleanup
backup.remove_old backup.remove_old
...@@ -27,9 +26,8 @@ namespace :gitlab do ...@@ -27,9 +26,8 @@ namespace :gitlab do
desc 'GitLab | Restore a previously created backup' desc 'GitLab | Restore a previously created backup'
task restore: :gitlab_environment do task restore: :gitlab_environment do
warn_user_is_not_gitlab warn_user_is_not_gitlab
configure_cron_mode
backup = Backup::Manager.new backup = Backup::Manager.new(progress)
backup.unpack backup.unpack
unless backup.skipped?('db') unless backup.skipped?('db')
...@@ -49,9 +47,9 @@ namespace :gitlab do ...@@ -49,9 +47,9 @@ namespace :gitlab do
# Drop all tables Load the schema to ensure we don't have any newer tables # Drop all tables Load the schema to ensure we don't have any newer tables
# hanging out from a failed upgrade # hanging out from a failed upgrade
$progress.puts 'Cleaning the database ... '.color(:blue) progress.puts 'Cleaning the database ... '.color(:blue)
Rake::Task['gitlab:db:drop_tables'].invoke Rake::Task['gitlab:db:drop_tables'].invoke
$progress.puts 'done'.color(:green) progress.puts 'done'.color(:green)
Rake::Task['gitlab:backup:db:restore'].invoke Rake::Task['gitlab:backup:db:restore'].invoke
rescue Gitlab::TaskAbortedByUserError rescue Gitlab::TaskAbortedByUserError
puts "Quitting...".color(:red) puts "Quitting...".color(:red)
...@@ -74,173 +72,173 @@ namespace :gitlab do ...@@ -74,173 +72,173 @@ namespace :gitlab do
namespace :repo do namespace :repo do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping repositories ...".color(:blue) progress.puts "Dumping repositories ...".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("repositories") if ENV["SKIP"] && ENV["SKIP"].include?("repositories")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Repository.new.dump Backup::Repository.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring repositories ...".color(:blue) progress.puts "Restoring repositories ...".color(:blue)
Backup::Repository.new.restore Backup::Repository.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :db do namespace :db do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping database ... ".color(:blue) progress.puts "Dumping database ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("db") if ENV["SKIP"] && ENV["SKIP"].include?("db")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Database.new.dump Backup::Database.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring database ... ".color(:blue) progress.puts "Restoring database ... ".color(:blue)
Backup::Database.new.restore Backup::Database.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :builds do namespace :builds do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping builds ... ".color(:blue) progress.puts "Dumping builds ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("builds") if ENV["SKIP"] && ENV["SKIP"].include?("builds")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Builds.new.dump Backup::Builds.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring builds ... ".color(:blue) progress.puts "Restoring builds ... ".color(:blue)
Backup::Builds.new.restore Backup::Builds.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :uploads do namespace :uploads do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping uploads ... ".color(:blue) progress.puts "Dumping uploads ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("uploads") if ENV["SKIP"] && ENV["SKIP"].include?("uploads")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Uploads.new.dump Backup::Uploads.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring uploads ... ".color(:blue) progress.puts "Restoring uploads ... ".color(:blue)
Backup::Uploads.new.restore Backup::Uploads.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :artifacts do namespace :artifacts do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping artifacts ... ".color(:blue) progress.puts "Dumping artifacts ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("artifacts") if ENV["SKIP"] && ENV["SKIP"].include?("artifacts")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Artifacts.new.dump Backup::Artifacts.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring artifacts ... ".color(:blue) progress.puts "Restoring artifacts ... ".color(:blue)
Backup::Artifacts.new.restore Backup::Artifacts.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :pages do namespace :pages do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping pages ... ".color(:blue) progress.puts "Dumping pages ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("pages") if ENV["SKIP"] && ENV["SKIP"].include?("pages")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Pages.new.dump Backup::Pages.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring pages ... ".color(:blue) progress.puts "Restoring pages ... ".color(:blue)
Backup::Pages.new.restore Backup::Pages.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :lfs do namespace :lfs do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping lfs objects ... ".color(:blue) progress.puts "Dumping lfs objects ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("lfs") if ENV["SKIP"] && ENV["SKIP"].include?("lfs")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Lfs.new.dump Backup::Lfs.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring lfs objects ... ".color(:blue) progress.puts "Restoring lfs objects ... ".color(:blue)
Backup::Lfs.new.restore Backup::Lfs.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
end end
namespace :registry do namespace :registry do
task create: :gitlab_environment do task create: :gitlab_environment do
$progress.puts "Dumping container registry images ... ".color(:blue) progress.puts "Dumping container registry images ... ".color(:blue)
if Gitlab.config.registry.enabled if Gitlab.config.registry.enabled
if ENV["SKIP"] && ENV["SKIP"].include?("registry") if ENV["SKIP"] && ENV["SKIP"].include?("registry")
$progress.puts "[SKIPPED]".color(:cyan) progress.puts "[SKIPPED]".color(:cyan)
else else
Backup::Registry.new.dump Backup::Registry.new(progress).dump
$progress.puts "done".color(:green) progress.puts "done".color(:green)
end end
else else
$progress.puts "[DISABLED]".color(:cyan) progress.puts "[DISABLED]".color(:cyan)
end end
end end
task restore: :gitlab_environment do task restore: :gitlab_environment do
$progress.puts "Restoring container registry images ... ".color(:blue) progress.puts "Restoring container registry images ... ".color(:blue)
if Gitlab.config.registry.enabled if Gitlab.config.registry.enabled
Backup::Registry.new.restore Backup::Registry.new(progress).restore
$progress.puts "done".color(:green) progress.puts "done".color(:green)
else else
$progress.puts "[DISABLED]".color(:cyan) progress.puts "[DISABLED]".color(:cyan)
end end
end end
end end
def configure_cron_mode def progress
if ENV['CRON'] if ENV['CRON']
# We need an object we can say 'puts' and 'print' to; let's use a # We need an object we can say 'puts' and 'print' to; let's use a
# StringIO. # StringIO.
require 'stringio' require 'stringio'
$progress = StringIO.new StringIO.new
else else
$progress = $stdout $stdout
end end
end end
end # namespace end: backup end # namespace end: backup
......
...@@ -182,7 +182,16 @@ describe('Pipelines Table Row', () => { ...@@ -182,7 +182,16 @@ describe('Pipelines Table Row', () => {
}); });
component.$el.querySelector('.js-pipelines-cancel-button').click(); component.$el.querySelector('.js-pipelines-cancel-button').click();
});
it('renders a loading icon when `cancelingPipeline` matches pipeline id', done => {
component.cancelingPipeline = pipeline.id;
component.$nextTick()
.then(() => {
expect(component.isCancelling).toEqual(true); expect(component.isCancelling).toEqual(true);
})
.then(done)
.catch(done.fail);
}); });
}); });
}); });
...@@ -5,6 +5,8 @@ describe Backup::Manager do ...@@ -5,6 +5,8 @@ describe Backup::Manager do
let(:progress) { StringIO.new } let(:progress) { StringIO.new }
subject { described_class.new(progress) }
before do before do
allow(progress).to receive(:puts) allow(progress).to receive(:puts)
allow(progress).to receive(:print) allow(progress).to receive(:print)
......
...@@ -3,6 +3,7 @@ require 'spec_helper' ...@@ -3,6 +3,7 @@ require 'spec_helper'
describe Backup::Repository do describe Backup::Repository do
let(:progress) { StringIO.new } let(:progress) { StringIO.new }
let!(:project) { create(:project, :wiki_repo) } let!(:project) { create(:project, :wiki_repo) }
subject { described_class.new(progress) }
before do before do
allow(progress).to receive(:puts) allow(progress).to receive(:puts)
...@@ -24,14 +25,12 @@ describe Backup::Repository do ...@@ -24,14 +25,12 @@ describe Backup::Repository do
end end
it 'does not raise error' do it 'does not raise error' do
expect { described_class.new.dump }.not_to raise_error expect { subject.dump }.not_to raise_error
end end
end end
end end
describe '#restore' do describe '#restore' do
subject { described_class.new }
let(:timestamp) { Time.utc(2017, 3, 22) } let(:timestamp) { Time.utc(2017, 3, 22) }
let(:temp_dirs) do let(:temp_dirs) do
Gitlab.config.repositories.storages.map do |name, storage| Gitlab.config.repositories.storages.map do |name, storage|
...@@ -102,20 +101,20 @@ describe Backup::Repository do ...@@ -102,20 +101,20 @@ describe Backup::Repository do
it 'invalidates the emptiness cache' do it 'invalidates the emptiness cache' do
expect(wiki.repository).to receive(:expire_emptiness_caches).once expect(wiki.repository).to receive(:expire_emptiness_caches).once
described_class.new.send(:empty_repo?, wiki) subject.send(:empty_repo?, wiki)
end end
context 'wiki repo has content' do context 'wiki repo has content' do
let!(:wiki_page) { create(:wiki_page, wiki: wiki) } let!(:wiki_page) { create(:wiki_page, wiki: wiki) }
it 'returns true, regardless of bad cache value' do it 'returns true, regardless of bad cache value' do
expect(described_class.new.send(:empty_repo?, wiki)).to be(false) expect(subject.send(:empty_repo?, wiki)).to be(false)
end end
end end
context 'wiki repo does not have content' do context 'wiki repo does not have content' do
it 'returns true, regardless of bad cache value' do it 'returns true, regardless of bad cache value' do
expect(described_class.new.send(:empty_repo?, wiki)).to be_truthy expect(subject.send(:empty_repo?, wiki)).to be_truthy
end end
end end
end end
......
...@@ -125,6 +125,16 @@ describe 'gitlab:app namespace rake task' do ...@@ -125,6 +125,16 @@ describe 'gitlab:app namespace rake task' do
expect(Dir.entries(File.join(project.repository.path, 'custom_hooks'))).to include("dummy.txt") expect(Dir.entries(File.join(project.repository.path, 'custom_hooks'))).to include("dummy.txt")
end end
end end
context 'specific backup tasks' do
let(:task_list) { %w(db repo uploads builds artifacts pages lfs registry) }
it 'prints a progress message to stdout' do
task_list.each do |task|
expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout
end
end
end
end end
context 'tar creation' do context 'tar creation' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment