Commit 41b08e4a authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce

parents fc4f5eef 8e05ee36
Please view this file on the master branch, on stable branches it's out of date.
v 8.1.0 (unreleased)
- Include full path of source and target branch names in New Merge Request page (Stan Hu)
- Add user preference to view activities as default dashboard (Stan Hu)
- Add option to admin area to sign in as a specific user (Pavel Forkert)
- Show CI status on all pages where commits list is rendered
......@@ -17,6 +18,9 @@ v 8.1.0 (unreleased)
- Move CI variables page to project settings area
- Move CI triggers page to project settings area
- Move CI project settings page to CE project settings area
- Fix bug when removed file was not appearing in merge request diff
- Note the original location of a moved project when notifying users of the move
- Improve error message when merging fails
v 8.0.3
- Fix URL shown in Slack notifications
......
......@@ -15,9 +15,10 @@ class @MergeRequestWidget
type: 'GET'
url: $('.merge-request').data('url')
success: (data) =>
switch data.state
when 'merged'
if data.state == "merged"
location.reload()
else if data.merge_error
$('.mr-widget-body').html("<h4>" + data.merge_error + "</h4>")
else
setTimeout(merge_request_widget.mergeInProgress, 2000)
dataType: 'json'
......
......@@ -12,7 +12,10 @@ module Ci
def show
@builds = @runner.builds.order('id DESC').first(30)
@projects = Ci::Project.all
@projects = @projects.search(params[:search]) if params[:search].present?
if params[:search].present?
@gl_projects = ::Project.search(params[:search])
@projects = @projects.where(gitlab_id: @gl_projects.select(:id))
end
@projects = @projects.where("ci_projects.id NOT IN (?)", @runner.projects.pluck(:id)) if @runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
end
......
......@@ -16,27 +16,6 @@ class PasswordsController < Devise::PasswordsController
end
end
# After a user resets their password, prompt for 2FA code if enabled instead
# of signing in automatically
#
# See http://git.io/vURrI
def update
super do |resource|
# TODO (rspeicher): In Devise master (> 3.4.1), we can set
# `Devise.sign_in_after_reset_password = false` and avoid this mess.
if resource.errors.empty? && resource.try(:two_factor_enabled?)
resource.unlock_access! if unlockable?(resource)
# Since we are not signing this user in, we use the :updated_not_active
# message which only contains "Your password was changed successfully."
set_flash_message(:notice, :updated_not_active) if is_flashing_format?
# Redirect to sign in so they can enter 2FA code
respond_with(resource, location: new_session_path(resource)) and return
end
end
end
def edit
super
reset_password_token = Devise.token_generator.digest(
......
......@@ -150,6 +150,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
return access_denied! unless @merge_request.can_be_merged_by?(current_user)
if @merge_request.mergeable?
@merge_request.update(merge_error: nil)
MergeWorker.perform_async(@merge_request.id, current_user.id, params)
@status = true
else
......
......@@ -167,4 +167,23 @@ module DiffHelper
content_tag(:span, commit_id, class: 'monospace'),
].join(' ').html_safe
end
def commit_for_diff(diff)
if diff.deleted_file
@merge_request ? @merge_request.commits.last : @commit.parent_id
else
@commit
end
end
def diff_file_html_data(project, diff_commit, diff_file)
{
blob_diff_path: namespace_project_blob_diff_path(project.namespace, project,
tree_join(diff_commit.id, diff_file.file_path))
}
end
def editable_diff?(diff)
!diff.deleted_file && @merge_request && @merge_request.source_project
end
end
......@@ -71,4 +71,17 @@ module MergeRequestsHelper
merge_request.source_branch
end
end
def format_mr_branch_names(merge_request)
source_path = merge_request.source_project_path
target_path = merge_request.target_project_path
source_branch = merge_request.source_branch
target_branch = merge_request.target_branch
if source_path == target_path
[source_branch, target_branch]
else
["#{source_path}:#{source_branch}", "#{target_path}:#{target_branch}"]
end
end
end
......@@ -50,10 +50,11 @@ module Emails
subject: subject("Invitation declined"))
end
def project_was_moved_email(project_id, user_id)
def project_was_moved_email(project_id, user_id, old_path_with_namespace)
@current_user = @user = User.find user_id
@project = Project.find project_id
@target_url = namespace_project_url(@project.namespace, @project)
@old_path_with_namespace = old_path_with_namespace
mail(to: @user.notification_email,
subject: subject("Project was moved"))
end
......
......@@ -48,11 +48,12 @@ module Ci
accepts_nested_attributes_for :variables, allow_destroy: true
delegate :name_with_namespace, :path_with_namespace, :web_url, :http_url_to_repo, :ssh_url_to_repo, to: :gl_project
#
# Validations
#
validates_presence_of :name, :timeout, :token, :default_ref,
:path, :ssh_url_to_repo, :gitlab_id
validates_presence_of :timeout, :token, :default_ref, :gitlab_id
validates_uniqueness_of :gitlab_id
......@@ -60,8 +61,6 @@ module Ci
presence: true,
if: ->(project) { project.always_build.present? }
scope :public_only, ->() { where(public: true) }
before_validation :set_default_values
class << self
......@@ -76,11 +75,8 @@ module Ci
def parse(project)
params = {
name: project.name_with_namespace,
gitlab_id: project.id,
path: project.path_with_namespace,
default_ref: project.default_branch || 'master',
ssh_url_to_repo: project.ssh_url_to_repo,
email_add_pusher: current_application_settings.add_pusher,
email_only_broken_builds: current_application_settings.all_broken_builds,
}
......@@ -105,11 +101,18 @@ module Ci
joins("LEFT JOIN #{last_commit_subquery} AS last_commit ON #{Ci::Project.table_name}.gitlab_id = last_commit.gl_project_id").
order("CASE WHEN last_commit.committed_at IS NULL THEN 1 ELSE 0 END, last_commit.committed_at DESC")
end
end
def name
name_with_namespace
end
def search(query)
where("LOWER(#{Ci::Project.table_name}.name) LIKE :query",
query: "%#{query.try(:downcase)}%")
def path
path_with_namespace
end
def gitlab_url
web_url
end
def any_runners?
......@@ -123,9 +126,6 @@ module Ci
def set_default_values
self.token = SecureRandom.hex(15) if self.token.blank?
self.default_ref ||= 'master'
self.name ||= gl_project.name_with_namespace
self.path ||= gl_project.path_with_namespace
self.ssh_url_to_repo ||= gl_project.ssh_url_to_repo
end
def tracked_refs
......@@ -169,7 +169,7 @@ module Ci
# using http and basic auth
def repo_url_with_auth
auth = "gitlab-ci-token:#{token}@"
url = gitlab_url + ".git"
url = http_url_to_repo + ".git"
url.sub(/^https?:\/\//) do |prefix|
prefix + auth
end
......@@ -201,10 +201,6 @@ module Ci
end
end
def gitlab_url
File.join(Gitlab.config.gitlab.url, path)
end
def setup_finished?
commits.any?
end
......
......@@ -137,7 +137,9 @@ class Namespace < ActiveRecord::Base
end
def send_update_instructions
projects.each(&:send_move_instructions)
projects.each do |project|
project.send_move_instructions("#{path_was}/#{project.path}")
end
end
def kind
......
......@@ -481,8 +481,8 @@ class Project < ActiveRecord::Base
end
end
def send_move_instructions
NotificationService.new.project_was_moved(self)
def send_move_instructions(old_path_with_namespace)
NotificationService.new.project_was_moved(self, old_path_with_namespace)
end
def owner
......@@ -624,7 +624,7 @@ class Project < ActiveRecord::Base
# So we basically we mute exceptions in next actions
begin
gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
send_move_instructions
send_move_instructions(old_path_with_namespace)
reset_events_cache
rescue
# Returning false does not rollback after_* transaction but gives
......
......@@ -70,11 +70,7 @@ class GitlabCiService < CiService
def fork_registration(new_project, current_user)
params = OpenStruct.new({
id: new_project.id,
name_with_namespace: new_project.name_with_namespace,
path_with_namespace: new_project.path_with_namespace,
web_url: new_project.web_url,
default_branch: new_project.default_branch,
ssh_url_to_repo: new_project.ssh_url_to_repo
default_branch: new_project.default_branch
})
ci_project = Ci::Project.find_by!(gitlab_id: project.id)
......
......@@ -38,6 +38,10 @@ module MergeRequests
}
repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
rescue Exception => e
merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message)
return false
end
def after_merge
......
......@@ -183,12 +183,12 @@ class NotificationService
mailer.group_access_granted_email(group_member.id)
end
def project_was_moved(project)
def project_was_moved(project, old_path_with_namespace)
recipients = project.team.members
recipients = reject_muted_users(recipients, project)
recipients.each do |recipient|
mailer.project_was_moved_email(project.id, recipient.id)
mailer.project_was_moved_email(project.id, recipient.id, old_path_with_namespace)
end
end
......
......@@ -38,7 +38,7 @@ module Projects
project.save!
# Notifications
project.send_move_instructions
project.send_move_instructions(old_path)
# Move main repository
unless gitlab_shell.mv_repository(old_path, new_path)
......
......@@ -2,7 +2,7 @@
%h3.page-title
System OAuth applications
%p.light
System OAuth application does not belong to certain user and can be managed only by admins
System OAuth applications don't belong to any user and can only be managed by admins
%hr
%p= link_to 'New Application', new_admin_application_path, class: 'btn btn-success'
%table.table.table-striped
......
%p
Project was moved to another location
Project #{@old_path_with_namespace} was moved to another location
%p
The project is now located under
= link_to namespace_project_url(@project.namespace, @project) do
......
Project was moved to another location
Project #{@old_path_with_namespace} was moved to another location
The project is now located under
<%= namespace_project_url(@project.namespace, @project) %>
......
......@@ -15,7 +15,12 @@
.files
- diff_files.each_with_index do |diff_file, index|
= render 'projects/diffs/file', diff_file: diff_file, i: index, project: project
- diff_commit = commit_for_diff(diff_file.diff)
- blob = project.repository.blob_for_diff(diff_commit, diff_file.diff)
- next unless blob
= render 'projects/diffs/file', i: index, project: project,
diff_file: diff_file, diff_commit: diff_commit, blob: blob
- if @diff_timeout
.alert.alert-danger
......
- blob = project.repository.blob_for_diff(@commit, diff_file.diff)
- return unless blob
- blob_diff_path = namespace_project_blob_diff_path(project.namespace, project, tree_join(@commit.id, diff_file.file_path))
.diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }}
.diff-file{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)}
.diff-header{id: "file-path-#{hexdigest(diff_file.new_path || diff_file.old_path)}"}
- if diff_file.deleted_file
%span="#{diff_file.old_path} deleted"
.diff-btn-group
- if @commit.parent_ids.present?
= view_file_btn(@commit.parent_id, diff_file, project)
- elsif diff_file.diff.submodule?
- if diff_file.diff.submodule?
%span
- submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path)
= submodule_link(submodule_item, @commit.id, project.repository)
- else
%span
- if diff_file.renamed_file
- if diff_file.deleted_file
= "#{diff_file.old_path} deleted"
- elsif diff_file.renamed_file
= "#{diff_file.old_path} renamed to #{diff_file.new_path}"
- else
= diff_file.new_path
- if diff_file.mode_changed?
%span.file-mode= "#{diff_file.diff.a_mode}#{diff_file.diff.b_mode}"
......@@ -28,12 +22,12 @@
%i.fa.fa-comments
&nbsp;
- if @merge_request && @merge_request.source_project
- if editable_diff?(diff_file)
= edit_blob_link(@merge_request.source_project,
@merge_request.source_branch, diff_file.new_path,
after: '&nbsp;', from_merge_request_id: @merge_request.id)
= view_file_btn(@commit.id, diff_file, project)
= view_file_btn(diff_commit.id, diff_file, project)
.diff-content.diff-wrap-lines
-# Skipp all non non-supported blobs
......
%h3.page-title
New merge request
%p.slead
- source_title, target_title = format_mr_branch_names(@merge_request)
From
%strong.label-branch #{@merge_request.source_project_namespace}:#{@merge_request.source_branch}
%strong.label-branch #{source_title}
%span into
%strong.label-branch #{@merge_request.target_project_namespace}:#{@merge_request.target_branch}
%strong.label-branch #{target_title}
%span.pull-right
= link_to 'Change branches', mr_change_branches_path(@merge_request)
......
......@@ -148,6 +148,10 @@ Devise.setup do |config|
# When someone else invites you to GitLab this time is also used so it should be pretty long.
config.reset_password_within = 2.days
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
config.sign_in_after_reset_password = false
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
......
class MergeRequestErrorField < ActiveRecord::Migration
def up
add_column :merge_requests, :merge_error, :string
end
end
class AddNullToNameForCiProjects < ActiveRecord::Migration
def up
change_column_null :ci_projects, :name, true
end
def down
change_column_null :ci_projects, :name, false
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150924125436) do
ActiveRecord::Schema.define(version: 20150930095736) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -158,7 +158,7 @@ ActiveRecord::Schema.define(version: 20150924125436) do
add_index "ci_jobs", ["project_id"], name: "index_ci_jobs_on_project_id", using: :btree
create_table "ci_projects", force: true do |t|
t.string "name", null: false
t.string "name"
t.integer "timeout", default: 3600, null: false
t.datetime "created_at"
t.datetime "updated_at"
......@@ -453,6 +453,7 @@ ActiveRecord::Schema.define(version: 20150924125436) do
t.integer "position", default: 0
t.datetime "locked_at"
t.integer "updated_by_id"
t.string "merge_error"
end
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
......
......@@ -100,8 +100,6 @@ Parameters:
* `name` (required) - The name of the project
* `gitlab_id` (required) - The ID of the project on the Gitlab instance
* `path` (required) - The gitlab project path
* `ssh_url_to_repo` (required) - The gitlab SSH url to the repo
* `default_ref` (optional) - The branch to run on (default to `master`)
### Update Project
......@@ -114,9 +112,6 @@ authenticated user has access to.
Parameters:
* `name` - The name of the project
* `gitlab_id` - The ID of the project on the Gitlab instance
* `path` - The gitlab project path
* `ssh_url_to_repo` - The gitlab SSH url to the repo
* `default_ref` - The branch to run on (default to `master`)
### Remove Project
......
......@@ -115,8 +115,9 @@ Remove the old Ruby 1.8 if present
Download Ruby and compile it:
mkdir /tmp/ruby && cd /tmp/ruby
curl -L --progress http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.6.tar.gz | tar xz
cd ruby-2.1.6
curl -O --progress https://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.7.tar.gz
echo 'e2e195a4a58133e3ad33b955c829bb536fa3c075 ruby-2.1.7.tar.gz' | shasum -c - && tar xzf ruby-2.1.7.tar.gz
cd ruby-2.1.7
./configure --disable-install-rdoc
make
sudo make install
......@@ -131,11 +132,11 @@ Since GitLab 8.0, Git HTTP requests are handled by gitlab-git-http-server.
This is a small daemon written in Go.
To install gitlab-git-http-server we need a Go compiler.
curl -O --progress https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz
echo '5817fa4b2252afdb02e11e8b9dc1d9173ef3bd5a go1.5.linux-amd64.tar.gz' | shasum -c - && \
sudo tar -C /usr/local -xzf go1.5.linux-amd64.tar.gz
curl -O --progress https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz
echo '46eecd290d8803887dec718c691cc243f2175fe0 go1.5.1.linux-amd64.tar.gz' | shasum -c - && \
sudo tar -C /usr/local -xzf go1.5.1.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
rm go1.5.linux-amd64.tar.gz
rm go1.5.1.linux-amd64.tar.gz
## 4. System Users
......
......@@ -36,6 +36,11 @@ mv /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds.$(date +%s)
and run `sudo gitlab-ctl reconfigure`.
#### 0. Updating Omnibus from versions prior to 7.13
If you are updating from older versions you should first update to 7.14 and then to 8.0.
Otherwise it's pretty likely that you will encounter problems described in the [Troubleshooting](#troubleshooting).
#### 1. Verify that backups work
Make sure that the backup script on both servers can connect to the database.
......@@ -43,6 +48,7 @@ Make sure that the backup script on both servers can connect to the database.
```
# On your CI server:
# Omnibus
sudo chown gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
sudo gitlab-ci-rake backup:create
# Source
......@@ -319,3 +325,102 @@ You should also make sure that you can:
If something went wrong and you need to restore a backup, consult the [Backup
restoration](../raketasks/backup_restore.md) guide.
### Troubleshooting
#### show:secrets problem (Omnibus-only)
If you see errors like this:
```
Missing `secret_key_base` or `db_key_base` for 'production' environment. The secrets will be generated and stored in `config/secrets.yml`
rake aborted!
Errno::EACCES: Permission denied @ rb_sysopen - config/secrets.yml
```
This can happen if you are updating from versions prior to 7.13 straight to 8.0.
The fix for this is to update to Omnibus 7.14 first and then update it to 8.0.
#### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds
To fix that issue you have to change builds/ folder permission before doing final backup:
```
chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
```
#### Problems when importing CI database to GitLab
If you were migrating CI database from MySQL to PostgreSQL manually you can see errros during import about missing sequences:
```
ALTER SEQUENCE
ERROR: relation "ci_builds_id_seq" does not exist
ERROR: relation "ci_commits_id_seq" does not exist
ERROR: relation "ci_events_id_seq" does not exist
ERROR: relation "ci_jobs_id_seq" does not exist
ERROR: relation "ci_projects_id_seq" does not exist
ERROR: relation "ci_runner_projects_id_seq" does not exist
ERROR: relation "ci_runners_id_seq" does not exist
ERROR: relation "ci_services_id_seq" does not exist
ERROR: relation "ci_taggings_id_seq" does not exist
ERROR: relation "ci_tags_id_seq" does not exist
CREATE TABLE
```
To fix that you need to apply this SQL statement before doing final backup:
```
# Omnibus
gitlab-ci-rails dbconsole <<EOF
-- ALTER TABLES - DROP DEFAULTS
ALTER TABLE ONLY ci_application_settings ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_builds ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_commits ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_events ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_jobs ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_projects ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_runners ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_services ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_taggings ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_tags ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_triggers ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_variables ALTER COLUMN id DROP DEFAULT;
ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id DROP DEFAULT;
-- ALTER SEQUENCES
ALTER SEQUENCE ci_application_settings_id_seq OWNED BY ci_application_settings.id;
ALTER SEQUENCE ci_builds_id_seq OWNED BY ci_builds.id;
ALTER SEQUENCE ci_commits_id_seq OWNED BY ci_commits.id;
ALTER SEQUENCE ci_events_id_seq OWNED BY ci_events.id;
ALTER SEQUENCE ci_jobs_id_seq OWNED BY ci_jobs.id;
ALTER SEQUENCE ci_projects_id_seq OWNED BY ci_projects.id;
ALTER SEQUENCE ci_runner_projects_id_seq OWNED BY ci_runner_projects.id;
ALTER SEQUENCE ci_runners_id_seq OWNED BY ci_runners.id;
ALTER SEQUENCE ci_services_id_seq OWNED BY ci_services.id;
ALTER SEQUENCE ci_taggings_id_seq OWNED BY ci_taggings.id;
ALTER SEQUENCE ci_tags_id_seq OWNED BY ci_tags.id;
ALTER SEQUENCE ci_trigger_requests_id_seq OWNED BY ci_trigger_requests.id;
ALTER SEQUENCE ci_triggers_id_seq OWNED BY ci_triggers.id;
ALTER SEQUENCE ci_variables_id_seq OWNED BY ci_variables.id;
ALTER SEQUENCE ci_web_hooks_id_seq OWNED BY ci_web_hooks.id;
-- ALTER TABLES - RE-APPLY DEFAULTS
ALTER TABLE ONLY ci_application_settings ALTER COLUMN id SET DEFAULT nextval('ci_application_settings_id_seq'::regclass);
ALTER TABLE ONLY ci_builds ALTER COLUMN id SET DEFAULT nextval('ci_builds_id_seq'::regclass);
ALTER TABLE ONLY ci_commits ALTER COLUMN id SET DEFAULT nextval('ci_commits_id_seq'::regclass);
ALTER TABLE ONLY ci_events ALTER COLUMN id SET DEFAULT nextval('ci_events_id_seq'::regclass);
ALTER TABLE ONLY ci_jobs ALTER COLUMN id SET DEFAULT nextval('ci_jobs_id_seq'::regclass);
ALTER TABLE ONLY ci_projects ALTER COLUMN id SET DEFAULT nextval('ci_projects_id_seq'::regclass);
ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id SET DEFAULT nextval('ci_runner_projects_id_seq'::regclass);
ALTER TABLE ONLY ci_runners ALTER COLUMN id SET DEFAULT nextval('ci_runners_id_seq'::regclass);
ALTER TABLE ONLY ci_services ALTER COLUMN id SET DEFAULT nextval('ci_services_id_seq'::regclass);
ALTER TABLE ONLY ci_taggings ALTER COLUMN id SET DEFAULT nextval('ci_taggings_id_seq'::regclass);
ALTER TABLE ONLY ci_tags ALTER COLUMN id SET DEFAULT nextval('ci_tags_id_seq'::regclass);
ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_trigger_requests_id_seq'::regclass);
ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
ALTER TABLE ONLY ci_web_hooks ALTER COLUMN id SET DEFAULT nextval('ci_web_hooks_id_seq'::regclass);
EOF
# Source
cd /home/gitlab_ci/gitlab-ci
sudo -u gitlab_ci -H bundle exec rails dbconsole production <<EOF
... COPY SQL STATEMENTS FROM ABOVE ...
EOF
```
......@@ -168,6 +168,7 @@ git diff origin/7-14-stable:lib/support/nginx/gitlab origin/8-0-stable:lib/suppo
```
If you are using Apache instead of NGINX please see the updated [Apache templates](https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache).
Also note that because Apache does not support upstreams behind Unix sockets you will need to let gitlab-git-http-server listen on a TCP port. You can do this via [/etc/default/gitlab](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-0-stable/lib/support/init.d/gitlab.default.example#L34).
### 9. Migrate GitLab CI to GitLab CE/EE
......
app:
image: gitlab/gitlab-ce:latest
FROM ubuntu:14.04
MAINTAINER Sytse Sijbrandij
# Install required packages
RUN apt-get update -q \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
ca-certificates \
openssh-server \
wget \
apt-transport-https \
vim \
nano
# Download & Install GitLab
# If you run GitLab Enterprise Edition point it to a location where you have downloaded it.
RUN echo "deb https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/gitlab_gitlab-ce.list
RUN wget -q -O - https://packages.gitlab.com/gpg.key | apt-key add -
RUN apt-get update && apt-get install -yq --no-install-recommends gitlab-ce
# Manage SSHD through runit
RUN mkdir -p /opt/gitlab/sv/sshd/supervise \
&& mkfifo /opt/gitlab/sv/sshd/supervise/ok \
&& printf "#!/bin/sh\nexec 2>&1\numask 077\nexec /usr/sbin/sshd -D" > /opt/gitlab/sv/sshd/run \
&& chmod a+x /opt/gitlab/sv/sshd/run \
&& ln -s /opt/gitlab/sv/sshd /opt/gitlab/service \
&& mkdir -p /var/run/sshd
# Disabling use DNS in ssh since it tends to slow connecting
RUN echo "UseDNS no" >> /etc/ssh/sshd_config
# Prepare default configuration
RUN ( \
echo "" && \
echo "# Docker options" && \
echo "# Prevent Postgres from trying to allocate 25% of total memory" && \
echo "postgresql['shared_buffers'] = '1MB'" ) >> /etc/gitlab/gitlab.rb && \
mkdir -p /assets/ && \
cp /etc/gitlab/gitlab.rb /assets/gitlab.rb
# Expose web & ssh
EXPOSE 443 80 22
# Define data volumes
VOLUME ["/etc/gitlab", "/var/opt/gitlab", "/var/log/gitlab"]
# Copy assets
COPY assets/wrapper /usr/local/bin/
# Wrapper to handle signal, trigger runit and reconfigure GitLab
CMD ["/usr/local/bin/wrapper"]
# GitLab Docker images
The GitLab docker image is [available on Docker Hub](https://registry.hub.docker.com/u/gitlab/gitlab-ce/).
## After starting a container
After starting a container you can go to [http://localhost:8080/](http://localhost:8080/) or [http://192.168.59.103:8080/](http://192.168.59.103:8080/) if you use boot2docker.
It might take a while before the docker container is responding to queries.
You can check the status with something like `sudo docker logs -f gitlab`.
You can login to the web interface with username `root` and password `5iveL!fe`.
Next time, you can just use docker start and stop to run the container.
## Run the image
Run the image:
```bash
sudo docker run --detach \
--publish 8443:443 --publish 8080:80 --publish 2222:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
```
This will download and start GitLab CE container and publish ports needed to access SSH, HTTP and HTTPS.
All GitLab data will be stored as subdirectories of `/srv/gitlab/`.
The container will automatically `restart` after system reboot.
After this you can login to the web interface as explained above in 'After starting a container'.
## Where is the data stored?
The GitLab container uses host mounted volumes to store persistent data:
- `/srv/gitlab/data` mounted as `/var/opt/gitlab` in the container is used for storing *application data*
- `/srv/gitlab/logs` mounted as `/var/log/gitlab` in the container is used for storing *logs*
- `/srv/gitlab/config` mounted as `/etc/gitlab` in the container is used for storing *configuration*
You can fine tune these directories to meet your requirements.
### Configure GitLab
This container uses the official Omnibus GitLab distribution, so all configuration is done in the unique configuration file `/etc/gitlab/gitlab.rb`.
To access GitLab configuration, you can start an bash in a new the context of running container, you will be able to browse all directories and use your favorite text editor:
```bash
sudo docker exec -it gitlab /bin/bash
```
You can also edit just `/etc/gitlab/gitlab.rb`:
```bash
sudo docker exec -it gitlab vi /etc/gitlab/gitlab.rb
```
**You should set the `external_url` to point to a valid URL.**
**You may also be interesting in [Enabling HTTPS](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md#enable-https).**
**To receive e-mails from GitLab you have to configure the [SMTP settings](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/smtp.md),
because Docker image doesn't have a SMTP server.**
**Note** that GitLab will reconfigure itself **at each container start.** You will need to restart the container to reconfigure your GitLab:
```bash
sudo docker restart gitlab
```
For more options for configuring the container please check [Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#configuration).
## Diagnose potential problems
Read container logs:
```bash
sudo docker logs gitlab
```
Enter running container:
```bash
sudo docker exec -it gitlab /bin/bash
```
From within container you can administrer GitLab container as you would normally administer Omnibus installation: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md.
### Upgrade GitLab to newer version
To upgrade GitLab to new version you have to do:
1. pull new image,
```bash
sudo docker stop gitlab
```
1. stop running container,
```bash
sudo docker rm gitlab
```
1. remove existing container,
```bash
sudo docker pull gitlab/gitlab-ce:latest
```
1. create the container once again with previously specified options.
```bash
sudo docker run --detach \
--publish 8443:443 --publish 8080:80 --publish 2222:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
```
On the first run GitLab will reconfigure and update itself.
### Run GitLab CE on public IP address
You can make Docker to use your IP address and forward all traffic to the GitLab CE container.
You can do that by modifying the `--publish` ([Binding container ports to the host](https://docs.docker.com/articles/networking/#binding-ports)):
> --publish=[] : Publish a container᾿s port or a range of ports to the host format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
To expose GitLab CE on IP 1.1.1.1:
```bash
sudo docker run --detach \
--publish 1.1.1.1:443:443 --publish 1.1.1.1:80:80 --publish 1.1.1.1:22:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
```
You can then access GitLab instance at http://1.1.1.1/ and https://1.1.1.1/.
### Build the image
This guide will also let you know how to build docker image yourself.
Please run the command from the GitLab repo root directory.
People using boot2docker should run all the commands without sudo.
```bash
sudo docker build --tag gitlab/gitlab-ce:latest docker/
```
### Publish the image to Dockerhub
- Ensure the containers are running
- Login to Dockerhub with `sudo docker login`
```bash
sudo docker login
sudo docker push gitlab/gitlab-ce:latest
```
## Troubleshooting
Please see the [troubleshooting](troubleshooting.md) file in this directory.
Note: We use `fig.yml` to have compatibility with fig and because docker-compose also supports it.
Our docker image runs chef at every start to generate GitLab configuration.
* The official GitLab Community Edition Docker image is [available on Docker Hub](https://registry.hub.docker.com/u/gitlab/gitlab-ce/).
* The official GitLab Enterprise Edition Docker image is [available on Docker Hub](https://registry.hub.docker.com/u/gitlab/gitlab-ee/).
* The complete usage guide can be found in [Using GitLab Docker images](http://doc.gitlab.com/omnibus/docker/)
* The Dockerfile used for building public images is in [Omnibus Repository](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker)
* Check the guide for [creating Omnibus-based Docker Image](http://doc.gitlab.com/omnibus/build/README.html#Build-Docker-image)
#!/bin/bash
function sigterm_handler() {
echo "SIGTERM signal received, try to gracefully shutdown all services..."
gitlab-ctl stop
}
trap "sigterm_handler; exit" TERM
function entrypoint() {
/opt/gitlab/embedded/bin/runsvdir-start &
gitlab-ctl reconfigure # will also start everything
gitlab-ctl tail # tail all logs
}
if [[ ! -e /etc/gitlab/gitlab.rb ]]; then
cp /assets/gitlab.rb /etc/gitlab/gitlab.rb
chmod 0600 /etc/gitlab/gitlab.rb
fi
entrypoint
{
"id": "/gitlab",
"ports": [0,0],
"cpus": 2,
"mem": 2048.0,
"disk": 10240.0,
"container": {
"type": "DOCKER",
"docker": {
"network": "HOST",
"image": "gitlab/gitlab-ce:latest"
},
"volumes": [
{
"containerPath": "/etc/gitlab",
"hostPath": "/var/data/etc/gitlab",
"mode": "RW"
},
{
"containerPath": "/var/opt/gitlab",
"hostPath": "/var/data/opt/gitlab",
"mode": "RW"
},
{
"containerPath": "/var/log/gitlab",
"hostPath": "/var/data/log/gitlab",
"mode": "RW"
}
]
}
}
\ No newline at end of file
# Troubleshooting
This is to troubleshoot https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/245
But it might contain useful commands for other cases as well.
The configuration to add the postgres log in vim is:
postgresql['log_directory'] = '/var/log/gitlab/postgresql'
# Commands
```bash
sudo docker build --tag gitlab/gitlab-ce:latest docker/
sudo docker rm -f gitlab
sudo docker exec -it gitlab vim /etc/gitlab/gitlab.rb
sudo docker exec gitlab tail -f /var/log/gitlab/reconfigure.log
sudo docker exec gitlab tail -f /var/log/gitlab/postgresql/current
sudo docker exec gitlab cat /var/opt/gitlab/postgresql/data/postgresql.conf | grep shared_buffers
sudo docker exec gitlab cat /etc/gitlab/gitlab.rb
```
# Interactively
```bash
# First start a GitLab container without starting GitLab
# This is almost the same as starting the GitLab container except:
# - we run interactively (-t -i)
# - we define TERM=linux because it allows to use arrow keys in vi (!!!)
# - we choose another startup command (bash)
sudo docker run --ti \
-e TERM=linux
--publish 80443:443 --publish 8080:80 --publish 2222:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest \
bash
# Configure GitLab to redirect PostgreSQL logs
echo "postgresql['log_directory'] = '/var/log/gitlab/postgresql'" >> /etc/gitlab/gitlab.rb
# Prevent Postgres from allocating 25% of total memory
echo "postgresql['shared_buffers'] = '1MB'" >> /etc/gitlab/gitlab.rb
# You can now start GitLab manually from Bash (in the background)
# Maybe the command below is still missing something to run in the background
gitlab-ctl reconfigure > /var/log/gitlab/reconfigure.log & /opt/gitlab/embedded/bin/runsvdir-start &
# Inspect PostgreSQL config
cat /var/opt/gitlab/postgresql/data/postgresql.conf | grep shared_buffers
# And tail the logs (PostgreSQL log may not exist immediately)
tail -f /var/log/gitlab/reconfigure.log /var/log/gitlab/postgresql/current
# And get the memory
cat /proc/meminfo
head /proc/sys/kernel/shmmax /proc/sys/kernel/shmall
free -m
```
# Cleanup
Remove ALL docker containers and images (also non GitLab ones).
**Be careful, because the `-v` also removes volumes attached to the images.**
```bash
# Remove all containers with attached volumes
docker rm -v $(docker ps -a -q)
# Remove all images
docker rmi $(docker images -q)
# Remove GitLab persistent data
rm -rf /srv/gitlab
```
......@@ -115,40 +115,40 @@ Feature: Project Merge Requests
Given project "Shop" have "Bug NS-05" open merge request with diffs inside
And I visit merge request page "Bug NS-05"
And I click on the Changes tab
And I leave a comment like "Line is wrong" on line 39 of the second file
And I click link "Hide inline discussion" of the second file
Then I should not see a comment like "Line is wrong here" in the second file
And I leave a comment like "Line is wrong" on line 39 of the third file
And I click link "Hide inline discussion" of the third file
Then I should not see a comment like "Line is wrong here" in the third file
@javascript
Scenario: I show comments on a merge request diff with comments in a single file
Given project "Shop" have "Bug NS-05" open merge request with diffs inside
And I visit merge request page "Bug NS-05"
And I click on the Changes tab
And I leave a comment like "Line is wrong" on line 39 of the second file
Then I should see a comment like "Line is wrong" in the second file
And I leave a comment like "Line is wrong" on line 39 of the third file
Then I should see a comment like "Line is wrong" in the third file
@javascript
Scenario: I hide comments on a merge request diff with comments in multiple files
Given project "Shop" have "Bug NS-05" open merge request with diffs inside
And I visit merge request page "Bug NS-05"
And I click on the Changes tab
And I leave a comment like "Line is correct" on line 12 of the first file
And I leave a comment like "Line is wrong" on line 39 of the second file
And I click link "Hide inline discussion" of the second file
Then I should not see a comment like "Line is wrong here" in the second file
And I should still see a comment like "Line is correct" in the first file
And I leave a comment like "Line is correct" on line 12 of the second file
And I leave a comment like "Line is wrong" on line 39 of the third file
And I click link "Hide inline discussion" of the third file
Then I should not see a comment like "Line is wrong here" in the third file
And I should still see a comment like "Line is correct" in the second file
@javascript
Scenario: I show comments on a merge request diff with comments in multiple files
Given project "Shop" have "Bug NS-05" open merge request with diffs inside
And I visit merge request page "Bug NS-05"
And I click on the Changes tab
And I leave a comment like "Line is correct" on line 12 of the first file
And I leave a comment like "Line is wrong" on line 39 of the second file
And I click link "Hide inline discussion" of the second file
And I click link "Show inline discussion" of the second file
Then I should see a comment like "Line is wrong" in the second file
And I should still see a comment like "Line is correct" in the first file
And I leave a comment like "Line is correct" on line 12 of the second file
And I leave a comment like "Line is wrong" on line 39 of the third file
And I click link "Hide inline discussion" of the third file
And I click link "Show inline discussion" of the third file
Then I should see a comment like "Line is wrong" in the third file
And I should still see a comment like "Line is correct" in the second file
@javascript
Scenario: I unfold diff
......@@ -163,8 +163,8 @@ Feature: Project Merge Requests
Given project "Shop" have "Bug NS-05" open merge request with diffs inside
And I visit merge request page "Bug NS-05"
And I click on the Changes tab
And I leave a comment like "Line is correct" on line 12 of the first file
And I leave a comment like "Line is wrong" on line 39 of the second file
And I leave a comment like "Line is correct" on line 12 of the second file
And I leave a comment like "Line is wrong" on line 39 of the third file
And I click Side-by-side Diff tab
Then I should see comments on the side-by-side diff page
......
......@@ -224,43 +224,43 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end
end
step 'I click link "Hide inline discussion" of the second file' do
page.within '.files [id^=diff]:nth-child(2)' do
step 'I click link "Hide inline discussion" of the third file' do
page.within '.files [id^=diff]:nth-child(3)' do
find('.js-toggle-diff-comments').trigger('click')
end
end
step 'I click link "Show inline discussion" of the second file' do
page.within '.files [id^=diff]:nth-child(2)' do
step 'I click link "Show inline discussion" of the third file' do
page.within '.files [id^=diff]:nth-child(3)' do
find('.js-toggle-diff-comments').trigger('click')
end
end
step 'I should not see a comment like "Line is wrong" in the second file' do
page.within '.files [id^=diff]:nth-child(2)' do
step 'I should not see a comment like "Line is wrong" in the third file' do
page.within '.files [id^=diff]:nth-child(3)' do
expect(page).not_to have_visible_content "Line is wrong"
end
end
step 'I should see a comment like "Line is wrong" in the second file' do
page.within '.files [id^=diff]:nth-child(2) .note-body > .note-text' do
step 'I should see a comment like "Line is wrong" in the third file' do
page.within '.files [id^=diff]:nth-child(3) .note-body > .note-text' do
expect(page).to have_visible_content "Line is wrong"
end
end
step 'I should not see a comment like "Line is wrong here" in the second file' do
page.within '.files [id^=diff]:nth-child(2)' do
step 'I should not see a comment like "Line is wrong here" in the third file' do
page.within '.files [id^=diff]:nth-child(3)' do
expect(page).not_to have_visible_content "Line is wrong here"
end
end
step 'I should see a comment like "Line is wrong here" in the second file' do
page.within '.files [id^=diff]:nth-child(2) .note-body > .note-text' do
step 'I should see a comment like "Line is wrong here" in the third file' do
page.within '.files [id^=diff]:nth-child(3) .note-body > .note-text' do
expect(page).to have_visible_content "Line is wrong here"
end
end
step 'I leave a comment like "Line is correct" on line 12 of the first file' do
step 'I leave a comment like "Line is correct" on line 12 of the second file' do
init_diff_note_first_file
page.within(".js-discussion-note-form") do
......@@ -268,12 +268,12 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
click_button "Add Comment"
end
page.within ".files [id^=diff]:nth-child(1) .note-body > .note-text" do
page.within ".files [id^=diff]:nth-child(2) .note-body > .note-text" do
expect(page).to have_content "Line is correct"
end
end
step 'I leave a comment like "Line is wrong" on line 39 of the second file' do
step 'I leave a comment like "Line is wrong" on line 39 of the third file' do
init_diff_note_second_file
page.within(".js-discussion-note-form") do
......@@ -282,8 +282,8 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end
end
step 'I should still see a comment like "Line is correct" in the first file' do
page.within '.files [id^=diff]:nth-child(1) .note-body > .note-text' do
step 'I should still see a comment like "Line is correct" in the second file' do
page.within '.files [id^=diff]:nth-child(2) .note-body > .note-text' do
expect(page).to have_visible_content "Line is correct"
end
end
......@@ -303,7 +303,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
end
step 'I should see comments on the side-by-side diff page' do
page.within '.files [id^=diff]:nth-child(1) .parallel .note-body > .note-text' do
page.within '.files [id^=diff]:nth-child(2) .parallel .note-body > .note-text' do
expect(page).to have_visible_content "Line is correct"
end
end
......
......@@ -75,23 +75,17 @@ module Ci
# Create Gitlab CI project using Gitlab project info
#
# Parameters:
# name (required) - The name of the project
# gitlab_id (required) - The gitlab id of the project
# path (required) - The gitlab project path, ex. randx/six
# ssh_url_to_repo (required) - The gitlab ssh url to the repo
# default_ref - The branch to run against (defaults to `master`)
# Example Request:
# POST /projects
post do
required_attributes! [:name, :gitlab_id, :ssh_url_to_repo]
required_attributes! [:gitlab_id]
filtered_params = {
name: params[:name],
gitlab_id: params[:gitlab_id],
# we accept gitlab_url for backward compatibility for a while (added to 7.11)
path: params[:path] || params[:gitlab_url].sub(/.*\/(.*\/.*)$/, '\1'),
default_ref: params[:default_ref] || 'master',
ssh_url_to_repo: params[:ssh_url_to_repo]
default_ref: params[:default_ref] || 'master'
}
project = Ci::Project.new(filtered_params)
......@@ -109,10 +103,6 @@ module Ci
#
# Parameters:
# id (required) - The ID of a project
# name - The name of the project
# gitlab_id - The gitlab id of the project
# path - The gitlab project path, ex. randx/six
# ssh_url_to_repo - The gitlab ssh url to the repo
# default_ref - The branch to run against (defaults to `master`)
# Example Request:
# PUT /projects/:id
......@@ -121,12 +111,7 @@ module Ci
unauthorized! unless can?(current_user, :admin_project, project.gl_project)
attrs = attributes_for_keys [:name, :gitlab_id, :path, :gitlab_url, :default_ref, :ssh_url_to_repo]
# we accept gitlab_url for backward compatibility for a while (added to 7.11)
if attrs[:gitlab_url] && !attrs[:path]
attrs[:path] = attrs[:gitlab_url].sub(/.*\/(.*\/.*)$/, '\1')
end
attrs = attributes_for_keys [:default_ref]
if project.update_attributes(attrs)
present project, with: Entities::Project
......
......@@ -29,20 +29,8 @@
FactoryGirl.define do
factory :ci_project_without_token, class: Ci::Project do
sequence :name do |n|
"GitLab / gitlab-shell#{n}"
end
default_ref 'master'
sequence :path do |n|
"gitlab/gitlab-shell#{n}"
end
sequence :ssh_url_to_repo do |n|
"git@demo.gitlab.com:gitlab/gitlab-shell#{n}.git"
end
gl_project factory: :empty_project
factory :ci_project do
......
......@@ -2,8 +2,7 @@ require 'spec_helper'
describe "Admin Runners" do
before do
skip_ci_admin_auth
login_as :user
login_as :admin
end
describe "Runners page" do
......@@ -20,16 +19,16 @@ describe "Admin Runners" do
describe 'search' do
before do
FactoryGirl.create :ci_runner, description: 'foo'
FactoryGirl.create :ci_runner, description: 'bar'
FactoryGirl.create :ci_runner, description: 'runner-foo'
FactoryGirl.create :ci_runner, description: 'runner-bar'
search_form = find('#runners-search')
search_form.fill_in 'search', with: 'foo'
search_form.fill_in 'search', with: 'runner-foo'
search_form.click_button 'Search'
end
it { expect(page).to have_content("foo") }
it { expect(page).not_to have_content("bar") }
it { expect(page).to have_content("runner-foo") }
it { expect(page).not_to have_content("runner-bar") }
end
end
......@@ -37,8 +36,8 @@ describe "Admin Runners" do
let(:runner) { FactoryGirl.create :ci_runner }
before do
FactoryGirl.create(:ci_project, name: "foo")
FactoryGirl.create(:ci_project, name: "bar")
@project1 = FactoryGirl.create(:ci_project)
@project2 = FactoryGirl.create(:ci_project)
visit ci_admin_runner_path(runner)
end
......@@ -47,19 +46,19 @@ describe "Admin Runners" do
end
describe 'projects' do
it { expect(page).to have_content("foo") }
it { expect(page).to have_content("bar") }
it { expect(page).to have_content(@project1.name_with_namespace) }
it { expect(page).to have_content(@project2.name_with_namespace) }
end
describe 'search' do
before do
search_form = find('#runner-projects-search')
search_form.fill_in 'search', with: 'foo'
search_form.fill_in 'search', with: @project1.gl_project.name
search_form.click_button 'Search'
end
it { expect(page).to have_content("foo") }
it { expect(page).not_to have_content("bar") }
it { expect(page).to have_content(@project1.name_with_namespace) }
it { expect(page).not_to have_content(@project2.name_with_namespace) }
end
end
end
require 'spec_helper'
feature 'Password reset', feature: true do
def forgot_password
click_on 'Forgot your password?'
fill_in 'Email', with: user.email
click_button 'Reset password'
user.reload
end
def get_reset_token
mail = ActionMailer::Base.deliveries.last
body = mail.body.encoded
body.scan(/reset_password_token=(.+)\"/).flatten.first
end
def reset_password(password = 'password')
visit edit_user_password_path(reset_password_token: get_reset_token)
fill_in 'New password', with: password
fill_in 'Confirm new password', with: password
click_button 'Change your password'
end
describe 'with two-factor authentication' do
let(:user) { create(:user, :two_factor) }
......@@ -40,14 +19,35 @@ feature 'Password reset', feature: true do
describe 'without two-factor authentication' do
let(:user) { create(:user) }
it 'automatically logs in after password reset' do
it 'requires login after password reset' do
visit root_path
forgot_password
reset_password
expect(current_path).to eq root_path
expect(page).to have_content("Your password was changed successfully. You are now signed in.")
expect(page).to have_content("Your password was changed successfully.")
expect(current_path).to eq new_user_session_path
end
end
def forgot_password
click_on 'Forgot your password?'
fill_in 'Email', with: user.email
click_button 'Reset password'
user.reload
end
def get_reset_token
mail = ActionMailer::Base.deliveries.last
body = mail.body.encoded
body.scan(/reset_password_token=(.+)\"/).flatten.first
end
def reset_password(password = 'password')
visit edit_user_password_path(reset_password_token: get_reset_token)
fill_in 'New password', with: password
fill_in 'Confirm new password', with: password
click_button 'Change your password'
end
end
require 'spec_helper'
describe MergeRequestsHelper do
describe :issues_sentence do
subject { issues_sentence(issues) }
let(:issues) do
[build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
end
it { is_expected.to eq('#1, #2, and #3') }
end
end
require 'spec_helper'
describe MergeRequestsHelper do
describe "#issues_sentence" do
subject { issues_sentence(issues) }
let(:issues) do
[build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
end
it { is_expected.to eq('#1, #2, and #3') }
end
describe "#format_mr_branch_names" do
describe "within the same project" do
let(:merge_request) { create(:merge_request) }
subject { format_mr_branch_names(merge_request) }
it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) }
end
describe "within different projects" do
let(:project) { create(:project) }
let(:fork_project) { create(:project, forked_from_project: project) }
let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) }
subject { format_mr_branch_names(merge_request) }
let(:source_title) { "#{fork_project.path_with_namespace}:#{merge_request.source_branch}" }
let(:target_title) { "#{project.path_with_namespace}:#{merge_request.target_branch}" }
it { is_expected.to eq([source_title, target_title]) }
end
end
end
......@@ -399,7 +399,7 @@ describe Notify do
describe 'project was moved' do
let(:project) { create(:project) }
let(:user) { create(:user) }
subject { Notify.project_was_moved_email(project.id, user.id) }
subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
it_behaves_like 'an email sent from GitLab'
......
......@@ -29,7 +29,8 @@ require 'spec_helper'
describe Ci::Project do
let(:gl_project) { FactoryGirl.create :empty_project }
subject { FactoryGirl.create :ci_project, gl_project: gl_project }
let(:project) { FactoryGirl.create :ci_project, gl_project: gl_project }
subject { project }
it { is_expected.to have_many(:runner_projects) }
it { is_expected.to have_many(:runners) }
......@@ -40,6 +41,7 @@ describe Ci::Project do
it { is_expected.to have_many(:services) }
it { is_expected.to validate_presence_of :timeout }
it { is_expected.to validate_presence_of :gitlab_id }
describe 'before_validation' do
it 'should set an random token if none provided' do
......@@ -53,6 +55,66 @@ describe Ci::Project do
end
end
describe :name_with_namespace do
subject { project.name_with_namespace }
it { is_expected.to eq(project.name) }
it { is_expected.to eq(gl_project.name_with_namespace) }
end
describe :path_with_namespace do
subject { project.path_with_namespace }
it { is_expected.to eq(project.path) }
it { is_expected.to eq(gl_project.path_with_namespace) }
end
describe :path_with_namespace do
subject { project.web_url }
it { is_expected.to eq(gl_project.web_url) }
end
describe :web_url do
subject { project.web_url }
it { is_expected.to eq(project.gitlab_url) }
it { is_expected.to eq(gl_project.web_url) }
end
describe :http_url_to_repo do
subject { project.http_url_to_repo }
it { is_expected.to eq(gl_project.http_url_to_repo) }
end
describe :ssh_url_to_repo do
subject { project.ssh_url_to_repo }
it { is_expected.to eq(gl_project.ssh_url_to_repo) }
end
describe :commits do
subject { project.commits }
before do
FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: gl_project
end
it { is_expected.to eq(gl_project.ci_commits) }
end
describe :builds do
subject { project.builds }
before do
commit = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: gl_project
FactoryGirl.create :ci_build, commit: commit
end
it { is_expected.to eq(gl_project.ci_builds) }
end
describe "ordered_by_last_commit_date" do
it "returns ordered projects" do
newest_project = FactoryGirl.create :empty_project
......@@ -174,13 +236,6 @@ describe Ci::Project do
it { is_expected.to include(project.gitlab_url[7..-1]) }
end
describe :search do
let!(:project) { FactoryGirl.create(:ci_project, name: "foo") }
it { expect(Ci::Project.search('fo')).to include(project) }
it { expect(Ci::Project.search('bar')).to be_empty }
end
describe :any_runners do
it "there are no runners available" do
project = FactoryGirl.create(:ci_project)
......
......@@ -134,7 +134,7 @@ describe Ci::API::API do
describe "PUT /projects/:id" do
let!(:project) { FactoryGirl.create(:ci_project) }
let!(:project_info) { { name: "An updated name!" } }
let!(:project_info) { { default_ref: "develop" } }
before do
options.merge!(project_info)
......@@ -144,7 +144,7 @@ describe Ci::API::API do
project.gl_project.team << [user, :master]
put ci_api("/projects/#{project.id}"), options
expect(response.status).to eq(200)
expect(json_response["name"]).to eq(project_info[:name])
expect(json_response["default_ref"]).to eq(project_info[:default_ref])
end
it "fails to update a non-existing project" do
......@@ -181,12 +181,10 @@ describe Ci::API::API do
end
describe "POST /projects" do
let(:gl_project) { FactoryGirl.create :empty_project }
let(:project_info) do
{
name: "My project",
gitlab_id: 1,
path: "testing/testing",
ssh_url_to_repo: "ssh://example.com/testing/testing.git"
gitlab_id: gl_project.id
}
end
......@@ -200,7 +198,7 @@ describe Ci::API::API do
it "should create a project with valid data" do
post ci_api("/projects"), options
expect(response.status).to eq(201)
expect(json_response['name']).to eq(project_info[:name])
expect(json_response['name']).to eq(gl_project.name_with_namespace)
end
end
......
require 'spec_helper'
describe Ci::EventService do
let(:project) { FactoryGirl.create :ci_project, name: "GitLab / gitlab-shell" }
let(:project) { FactoryGirl.create :ci_project }
let(:user) { double(username: "root", id: 1) }
before do
......@@ -12,7 +12,7 @@ describe Ci::EventService do
it "creates event" do
Ci::EventService.new.remove_project(user, project)
expect(Ci::Event.admin.last.description).to eq("Project \"GitLab / gitlab-shell\" has been removed by root")
expect(Ci::Event.admin.last.description).to eq("Project \"#{project.name_with_namespace}\" has been removed by root")
end
end
......@@ -20,7 +20,7 @@ describe Ci::EventService do
it "creates event" do
Ci::EventService.new.create_project(user, project)
expect(Ci::Event.admin.last.description).to eq("Project \"GitLab / gitlab-shell\" has been created by root")
expect(Ci::Event.admin.last.description).to eq("Project \"#{project.name_with_namespace}\" has been created by root")
end
end
......
......@@ -35,5 +35,19 @@ describe MergeRequests::MergeService do
expect(note.note).to include 'Status changed to merged'
end
end
context "error handling" do
let(:service) { MergeRequests::MergeService.new(project, user, {}) }
it 'saves error if there is an exception' do
allow(service).to receive(:repository).and_raise("error")
allow(service).to receive(:execute_hooks)
service.execute(merge_request, 'Awesome message')
expect(merge_request.merge_error).to eq("Something went wrong during merge")
end
end
end
end
......@@ -427,15 +427,15 @@ describe NotificationService do
should_email(@u_watcher.id)
should_email(@u_participating.id)
should_not_email(@u_disabled.id)
notification.project_was_moved(project)
notification.project_was_moved(project, "gitlab/gitlab")
end
def should_email(user_id)
expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id)
expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab")
end
def should_not_email(user_id)
expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id)
expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id, "gitlab/gitlab")
end
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