Commit b193e849 authored by Rémy Coutable's avatar Rémy Coutable

Move task helpers to a module

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent a9c250ea
......@@ -397,24 +397,24 @@ GitLab Shell is an SSH access and repository management software developed speci
### Install gitlab-workhorse
GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). The
following command-line will install GitLab-Workhorse in `home/git/gitlab-workhorse`
following command-line will install GitLab-Workhorse in `/home/git/gitlab-workhorse`
which is the recommended location.
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:workhorse:install[/home/git/gitlab-workhorse] RAILS_ENV=production
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
You can specify a different Git repository by providing `GITLAB_WORKHORSE_REPO`:
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:workhorse:install[/home/git/gitlab-workhorse] GITLAB_WORKHORSE_REPO=https://example.com/gitlab-workhorse.git RAILS_ENV=production
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" GITLAB_WORKHORSE_REPO=https://example.com/gitlab-workhorse.git RAILS_ENV=production
You can specify a different version to use by providing `GITLAB_WORKHORSE_VERSION`:
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:workhorse:install[/home/git/gitlab-workhorse] GITLAB_WORKHORSE_VERSION=0.8.1 RAILS_ENV=production
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" GITLAB_WORKHORSE_VERSION=0.8.1 RAILS_ENV=production
### Initialize Database and Activate Advanced Features
......
......@@ -82,7 +82,7 @@ Install and compile gitlab-workhorse. This requires
GitLab 8.1.
```bash
sudo -u git -H bundle exec rake gitlab:workhorse:install[/home/git/gitlab-workhorse] RAILS_ENV=production
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
```
### 7. Install libs, migrations, etc.
......
require 'tasks/gitlab/task_helpers'
# Prevent StateMachine warnings from outputting during a cron task
StateMachines::Machine.ignore_method_conflicts = true if ENV['CRON']
namespace :gitlab do
include Gitlab::TaskHelpers
end
module Gitlab
class TaskFailedError < StandardError; end
class TaskAbortedByUserError < StandardError; end
end
require 'rainbow/ext/string'
# Prevent StateMachine warnings from outputting during a cron task
StateMachines::Machine.ignore_method_conflicts = true if ENV['CRON']
namespace :gitlab do
# Ask if the user wants to continue
#
# Returns "yes" the user chose to continue
# Raises Gitlab::TaskAbortedByUserError if the user chose *not* to continue
def ask_to_continue
answer = prompt("Do you want to continue (yes/no)? ".color(:blue), %w{yes no})
raise Gitlab::TaskAbortedByUserError unless answer == "yes"
end
# Check which OS is running
#
# It will primarily use lsb_relase to determine the OS.
# It has fallbacks to Debian, SuSE, OS X and systems running systemd.
def os_name
os_name = run_command(%W(lsb_release -irs))
os_name ||= if File.readable?('/etc/system-release')
File.read('/etc/system-release')
end
os_name ||= if File.readable?('/etc/debian_version')
debian_version = File.read('/etc/debian_version')
"Debian #{debian_version}"
end
os_name ||= if File.readable?('/etc/SuSE-release')
File.read('/etc/SuSE-release')
end
os_name ||= if os_x_version = run_command(%W(sw_vers -productVersion))
"Mac OS X #{os_x_version}"
end
os_name ||= if File.readable?('/etc/os-release')
File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
end
os_name.try(:squish!)
end
# Prompt the user to input something
#
# message - the message to display before input
# choices - array of strings of acceptable answers or nil for any answer
#
# Returns the user's answer
def prompt(message, choices = nil)
begin
print(message)
answer = STDIN.gets.chomp
end while choices.present? && !choices.include?(answer)
answer
end
# Runs the given command and matches the output against the given pattern
#
# Returns nil if nothing matched
# Returns the MatchData if the pattern matched
#
# see also #run_command
# see also String#match
def run_and_match(command, regexp)
run_command(command).try(:match, regexp)
end
# Runs the given command
#
# Returns '' if the command was not found
# Returns the output of the command otherwise
#
# see also #run_and_match
def run_command(command)
output, _ = Gitlab::Popen.popen(command)
output
rescue Errno::ENOENT
'' # if the command does not exist, return an empty string
end
# Runs the given command and raise a Gitlab::TaskFailedError exception if
# the command does not exit with 0
#
# Returns the output of the command otherwise
def run_command!(command)
output, status = Gitlab::Popen.popen(command)
raise Gitlab::TaskFailedError unless status.zero?
output
end
def uid_for(user_name)
run_command(%W(id -u #{user_name})).chomp.to_i
end
def gid_for(group_name)
begin
Etc.getgrnam(group_name).gid
rescue ArgumentError # no group
"group #{group_name} doesn't exist"
end
end
def warn_user_is_not_gitlab
unless @warned_user_not_gitlab
gitlab_user = Gitlab.config.gitlab.user
current_user = run_command(%W(whoami)).chomp
unless current_user == gitlab_user
puts " Warning ".color(:black).background(:yellow)
puts " You are running as user #{current_user.color(:magenta)}, we hope you know what you are doing."
puts " Things may work\/fail for the wrong reasons."
puts " For correct results you should run this as user #{gitlab_user.color(:magenta)}."
puts ""
end
@warned_user_not_gitlab = true
end
end
# Tries to configure git itself
#
# Returns true if all subcommands were successfull (according to their exit code)
# Returns false if any or all subcommands failed.
def auto_fix_git_config(options)
if !@warned_user_not_gitlab
command_success = options.map do |name, value|
system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value}))
end
command_success.all?
else
false
end
end
def all_repos
Gitlab.config.repositories.storages.each do |name, path|
IO.popen(%W(find #{path} -mindepth 2 -maxdepth 2 -type d -name *.git)) do |find|
find.each_line do |path|
yield path.chomp
end
end
end
end
def repository_storage_paths_args
Gitlab.config.repositories.storages.values
end
def user_home
Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
end
def checkout_or_clone_tag(tag:, repo:, target_dir:)
if Dir.exist?(target_dir)
Dir.chdir(target_dir) do
run_command!(%W[#{Gitlab.config.git.bin_path} fetch --tags --quiet])
run_command!(%W[#{Gitlab.config.git.bin_path} checkout --quiet #{tag}])
end
else
run_command!(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{target_dir}])
end
# Make sure we're on the right tag
Dir.chdir(target_dir) do
# First try to checkout without fetching
# to avoid stalling tests if the Internet is down.
reset_to_tag(tag)
end
end
def reset_to_tag(tag_wanted)
tag =
begin
run_command!(%W[#{Gitlab.config.git.bin_path} describe -- #{tag_wanted}])
rescue Gitlab::TaskFailedError
run_command!(%W[#{Gitlab.config.git.bin_path} fetch origin])
run_command!(%W[#{Gitlab.config.git.bin_path} describe -- origin/#{tag_wanted}])
end
if tag
run_command!(%W[#{Gitlab.config.git.bin_path} reset --hard #{tag.strip}])
else
raise Gitlab::TaskFailedError
end
end
end
require 'rainbow/ext/string'
module Gitlab
TaskFailedError = Class.new(StandardError)
TaskAbortedByUserError = Class.new(StandardError)
module TaskHelpers
# Ask if the user wants to continue
#
# Returns "yes" the user chose to continue
# Raises Gitlab::TaskAbortedByUserError if the user chose *not* to continue
def ask_to_continue
answer = prompt("Do you want to continue (yes/no)? ".color(:blue), %w{yes no})
raise Gitlab::TaskAbortedByUserError unless answer == "yes"
end
# Check which OS is running
#
# It will primarily use lsb_relase to determine the OS.
# It has fallbacks to Debian, SuSE, OS X and systems running systemd.
def os_name
os_name = run_command(%W(lsb_release -irs))
os_name ||= if File.readable?('/etc/system-release')
File.read('/etc/system-release')
end
os_name ||= if File.readable?('/etc/debian_version')
debian_version = File.read('/etc/debian_version')
"Debian #{debian_version}"
end
os_name ||= if File.readable?('/etc/SuSE-release')
File.read('/etc/SuSE-release')
end
os_name ||= if os_x_version = run_command(%W(sw_vers -productVersion))
"Mac OS X #{os_x_version}"
end
os_name ||= if File.readable?('/etc/os-release')
File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
end
os_name.try(:squish!)
end
# Prompt the user to input something
#
# message - the message to display before input
# choices - array of strings of acceptable answers or nil for any answer
#
# Returns the user's answer
def prompt(message, choices = nil)
begin
print(message)
answer = STDIN.gets.chomp
end while choices.present? && !choices.include?(answer)
answer
end
# Runs the given command and matches the output against the given pattern
#
# Returns nil if nothing matched
# Returns the MatchData if the pattern matched
#
# see also #run_command
# see also String#match
def run_and_match(command, regexp)
run_command(command).try(:match, regexp)
end
# Runs the given command
#
# Returns '' if the command was not found
# Returns the output of the command otherwise
#
# see also #run_and_match
def run_command(command)
output, _ = Gitlab::Popen.popen(command)
output
rescue Errno::ENOENT
'' # if the command does not exist, return an empty string
end
# Runs the given command and raises a Gitlab::TaskFailedError exception if
# the command does not exit with 0
#
# Returns the output of the command otherwise
def run_command!(command)
output, status = Gitlab::Popen.popen(command)
raise Gitlab::TaskFailedError unless status.zero?
output
end
def uid_for(user_name)
run_command(%W(id -u #{user_name})).chomp.to_i
end
def gid_for(group_name)
begin
Etc.getgrnam(group_name).gid
rescue ArgumentError # no group
"group #{group_name} doesn't exist"
end
end
def warn_user_is_not_gitlab
unless @warned_user_not_gitlab
gitlab_user = Gitlab.config.gitlab.user
current_user = run_command(%W(whoami)).chomp
unless current_user == gitlab_user
puts " Warning ".color(:black).background(:yellow)
puts " You are running as user #{current_user.color(:magenta)}, we hope you know what you are doing."
puts " Things may work\/fail for the wrong reasons."
puts " For correct results you should run this as user #{gitlab_user.color(:magenta)}."
puts ""
end
@warned_user_not_gitlab = true
end
end
# Tries to configure git itself
#
# Returns true if all subcommands were successfull (according to their exit code)
# Returns false if any or all subcommands failed.
def auto_fix_git_config(options)
if !@warned_user_not_gitlab
command_success = options.map do |name, value|
system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value}))
end
command_success.all?
else
false
end
end
def all_repos
Gitlab.config.repositories.storages.each do |name, path|
IO.popen(%W(find #{path} -mindepth 2 -maxdepth 2 -type d -name *.git)) do |find|
find.each_line do |path|
yield path.chomp
end
end
end
end
def repository_storage_paths_args
Gitlab.config.repositories.storages.values
end
def user_home
Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
end
def checkout_or_clone_tag(tag:, repo:, target_dir:)
if Dir.exist?(target_dir)
checkout_tag(tag, target_dir)
else
clone_repo(repo, target_dir)
end
reset_to_tag(tag, target_dir)
end
def clone_repo(repo, target_dir)
run_command!(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{target_dir}])
end
def checkout_tag(tag, target_dir)
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --tags --quiet])
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout --quiet #{tag}])
end
def reset_to_tag(tag_wanted, target_dir)
tag =
begin
# First try to checkout without fetching
# to avoid stalling tests if the Internet is down.
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} describe -- #{tag_wanted}])
rescue Gitlab::TaskFailedError
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch origin])
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} describe -- origin/#{tag_wanted}])
end
if tag
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} reset --hard #{tag.strip}])
else
raise Gitlab::TaskFailedError
end
end
end
end
......@@ -4,7 +4,7 @@ namespace :gitlab do
task :install, [:dir] => :environment do |t, args|
warn_user_is_not_gitlab
unless args.dir.present?
abort "Please specify the directory where you want to install gitlab-workhorse:\n rake gitlab:workhorse:install[/home/git/gitlab-workhorse]"
abort %(Please specify the directory where you want to install gitlab-workhorse:\n rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]")
end
tag = "v#{ENV['GITLAB_WORKHORSE_VERSION'] || Gitlab::Workhorse.version}"
......
......@@ -8,7 +8,7 @@ RSpec.configure do |config|
config.before(:all) do
$stdout = StringIO.new
Rake.application.rake_require 'tasks/gitlab/task_helpers'
Rake.application.rake_require 'tasks/gitlab/helpers'
Rake::Task.define_task :environment
end
......
module RakeHelpers
def run_rake_task(task_name)
def run_rake_task(task_name, *args)
Rake::Task[task_name].reenable
Rake.application.invoke_task task_name
Rake.application.invoke_task("#{task_name}[#{args.join(',')}]")
end
def stub_warn_user_is_not_gitlab
......
......@@ -17,10 +17,6 @@ module StubConfiguration
allow(Gitlab.config.gravatar).to receive_messages(messages)
end
def stub_gitlab_workhorse_setting(messages)
allow(Gitlab.config.gitlab_workhorse).to receive_messages(messages)
end
def stub_incoming_email_setting(messages)
allow(Gitlab.config.incoming_email).to receive_messages(messages)
end
......
......@@ -5,7 +5,7 @@ describe 'gitlab:app namespace rake task' do
let(:enable_registry) { true }
before :all do
Rake.application.rake_require 'tasks/gitlab/task_helpers'
Rake.application.rake_require 'tasks/gitlab/helpers'
Rake.application.rake_require 'tasks/gitlab/backup'
Rake.application.rake_require 'tasks/gitlab/shell'
Rake.application.rake_require 'tasks/gitlab/db'
......
......@@ -3,7 +3,7 @@ require 'rake'
describe 'gitlab:mail_google_schema_whitelisting rake task' do
before :all do
Rake.application.rake_require "tasks/gitlab/task_helpers"
Rake.application.rake_require "tasks/gitlab/helpers"
Rake.application.rake_require "tasks/gitlab/mail_google_schema_whitelisting"
# empty task as env is already loaded
Rake::Task.define_task :environment
......
require 'spec_helper'
require 'rake'
require 'tasks/gitlab/task_helpers'
describe 'gitlab:workhorse namespace rake task' do
before :all do
Rake.application.rake_require 'tasks/gitlab/task_helpers'
class TestHelpersTest
include Gitlab::TaskHelpers
end
# empty task as env is already loaded
Rake::Task.define_task :environment
end
describe Gitlab::TaskHelpers do
subject { TestHelpersTest.new }
describe '#checkout_or_clone_tag' do
let(:repo) { 'https://gitlab.com/gitlab-org/gitlab-test.git' }
let(:clone_path) { Rails.root.join('tmp/tests/task_helpers_tests').to_s }
let(:tag) { 'v1.1.0' }
before do
FileUtils.rm_rf(clone_path)
allow_any_instance_of(Object).to receive(:run_command!)
expect_any_instance_of(Object).to receive(:reset_to_tag).with(tag)
end
after do
FileUtils.rm_rf(clone_path)
describe '#checkout_or_clone_tag' do
before do
allow(subject).to receive(:run_command!)
expect(subject).to receive(:reset_to_tag).with(tag, clone_path)
end
context 'target_dir does not exist' do
it 'clones the repo, retrieve the tag from origin, and checkout the tag' do
expect(Dir).to receive(:chdir).and_call_original
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{clone_path}]) { FileUtils.mkdir_p(clone_path) } # Fake the cloning
expect(subject).to receive(:clone_repo).with(repo, clone_path)
checkout_or_clone_tag(tag: tag, repo: repo, target_dir: clone_path)
subject.checkout_or_clone_tag(tag: tag, repo: repo, target_dir: clone_path)
end
end
context 'target_dir exists' do
before do
FileUtils.mkdir_p(clone_path)
expect(Dir).to receive(:exist?).and_return(true)
end
it 'fetch and checkout the tag' do
expect(Dir).to receive(:chdir).twice.and_call_original
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} fetch --tags --quiet])
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} checkout --quiet #{tag}])
expect(subject).to receive(:checkout_tag).with(tag, clone_path)
checkout_or_clone_tag(tag: tag, repo: repo, target_dir: clone_path)
subject.checkout_or_clone_tag(tag: tag, repo: repo, target_dir: clone_path)
end
end
end
describe '#clone_repo' do
it 'clones the repo in the target dir' do
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{clone_path}])
subject.clone_repo(repo, clone_path)
end
end
describe '#checkout_tag' do
it 'clones the repo in the target dir' do
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} fetch --tags --quiet])
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} checkout --quiet #{tag}])
subject.checkout_tag(tag, clone_path)
end
end
describe '#reset_to_tag' do
let(:tag) { 'v1.1.0' }
before do
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} reset --hard #{tag}])
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} reset --hard #{tag}])
end
context 'when the tag is not checked out locally' do
before do
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} describe -- #{tag}]).and_raise(Gitlab::TaskFailedError)
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} describe -- #{tag}]).and_raise(Gitlab::TaskFailedError)
end
it 'fetch origin, ensure the tag exists, and resets --hard to the given tag' do
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} fetch origin])
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} describe -- origin/#{tag}]).and_return(tag)
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} fetch origin])
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} describe -- origin/#{tag}]).and_return(tag)
reset_to_tag(tag)
subject.reset_to_tag(tag, clone_path)
end
end
context 'when the tag is checked out locally' do
before do
expect_any_instance_of(Object).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} describe -- #{tag}]).and_return(tag)
expect(subject).
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} describe -- #{tag}]).and_return(tag)
end
it 'resets --hard to the given tag' do
reset_to_tag(tag)
subject.reset_to_tag(tag, clone_path)
end
end
end
......
......@@ -5,7 +5,7 @@ describe 'gitlab:users namespace rake task' do
let(:enable_registry) { true }
before :all do
Rake.application.rake_require 'tasks/gitlab/task_helpers'
Rake.application.rake_require 'tasks/gitlab/helpers'
Rake.application.rake_require 'tasks/gitlab/users'
# empty task as env is already loaded
......
require 'spec_helper'
require 'rake'
require 'rake_helper'
describe 'gitlab:workhorse namespace rake task' do
before :all do
Rake.application.rake_require 'tasks/gitlab/task_helpers'
Rake.application.rake_require 'tasks/gitlab/workhorse'
# empty task as env is already loaded
Rake::Task.define_task :environment
end
def run_rake_task(task_name, *args)
Rake::Task[task_name].reenable
Rake.application.invoke_task("#{task_name}[#{args.join(',')}]")
end
describe 'install' do
......@@ -20,13 +10,13 @@ describe 'gitlab:workhorse namespace rake task' do
let(:clone_path) { Rails.root.join('tmp/tests/gitlab-workhorse').to_s }
let(:tag) { "v#{File.read(Rails.root.join(Gitlab::Workhorse::VERSION_FILE)).chomp}" }
before do
# avoid writing task output to spec progress
allow($stdout).to receive :write
allow(ENV).to receive(:[])
end
context 'no dir given' do
it 'aborts and display a help message' do
# avoid writing task output to spec progress
allow($stderr).to receive :write
expect { run_rake_task('gitlab:workhorse:install') }.to raise_error /Please specify the directory where you want to install gitlab-workhorse/
end
end
......
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