Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1cfb48ddd0
39 changed files with 243 additions and 244 deletions
|
@ -1,6 +1,7 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.1.0 (unreleased)
|
||||
- Fix bug where transferring a project would result in stale commit links (Stan Hu)
|
||||
- Include full path of source and target branch names in New Merge Request page (Stan Hu)
|
||||
- Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
|
||||
- Add user preference to view activities as default dashboard (Stan Hu)
|
||||
|
@ -26,6 +27,8 @@ v 8.1.0 (unreleased)
|
|||
- Show additions/deletions stats on merge request diff
|
||||
- Remove footer text in emails (Zeger-Jan van de Weg)
|
||||
- Ensure code blocks are properly highlighted after a note is updated
|
||||
- Fix wrong access level badge on MR comments
|
||||
- Hide password in the service settings form
|
||||
|
||||
v 8.0.3
|
||||
- Fix URL shown in Slack notifications
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -270,6 +270,8 @@ group :development, :test do
|
|||
gem 'rubocop', '~> 0.28.0', require: false
|
||||
gem 'coveralls', '~> 0.8.2', require: false
|
||||
gem 'simplecov', '~> 0.10.0', require: false
|
||||
|
||||
gem 'benchmark-ips', require: false
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
|
|
@ -66,6 +66,7 @@ GEM
|
|||
ice_nine (~> 0.11.0)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
bcrypt (3.1.10)
|
||||
benchmark-ips (2.3.0)
|
||||
better_errors (1.0.1)
|
||||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.6.6)
|
||||
|
@ -795,6 +796,7 @@ DEPENDENCIES
|
|||
asciidoctor (~> 1.5.2)
|
||||
attr_encrypted (~> 1.3.4)
|
||||
awesome_print (~> 1.2.0)
|
||||
benchmark-ips
|
||||
better_errors (~> 1.0.1)
|
||||
binding_of_caller (~> 0.7.2)
|
||||
bootstrap-sass (~> 3.0)
|
||||
|
|
|
@ -1,18 +1,34 @@
|
|||
html {
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
&.touch .tooltip { display: none !important; }
|
||||
|
||||
body {
|
||||
padding-top: $header-height;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content section {
|
||||
height: 100%;
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.container .content {
|
||||
margin: 0 0;
|
||||
}
|
||||
|
@ -24,3 +40,9 @@ html {
|
|||
.container-limited {
|
||||
max-width: $fixed-layout-width;
|
||||
}
|
||||
|
||||
.max-height {
|
||||
height: 100%;
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
|
@ -94,6 +94,7 @@ body {
|
|||
|
||||
@mixin btn-info {
|
||||
@include border-radius(2px);
|
||||
@include transition (all 0.2s ease 0s);
|
||||
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
|
@ -116,6 +117,7 @@ body {
|
|||
|
||||
&:active {
|
||||
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
|
||||
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
@ -123,6 +125,7 @@ body {
|
|||
|
||||
@mixin btn-middle {
|
||||
@include border-radius(2px);
|
||||
@include transition (all 0.2s ease 0s);
|
||||
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
|
@ -145,6 +148,7 @@ body {
|
|||
|
||||
&:active {
|
||||
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
|
||||
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
.page-with-sidebar {
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
|
||||
.sidebar-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -18,15 +21,19 @@
|
|||
}
|
||||
|
||||
.content-wrapper {
|
||||
min-height: 100vh;
|
||||
min-height: 900px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
background: #EAEBEC;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.container-fluid {
|
||||
background: #FFF;
|
||||
padding: $gl-padding;
|
||||
min-height: 90vh;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
|
||||
&.container-blank {
|
||||
background: none;
|
||||
|
|
|
@ -510,4 +510,3 @@ pre.light-well {
|
|||
.inline-form {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
@projects = current_user.starred_projects
|
||||
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@last_push = current_user.recent_push
|
||||
@groups = []
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
@ -1,20 +1,7 @@
|
|||
class PasswordsController < Devise::PasswordsController
|
||||
|
||||
def create
|
||||
email = resource_params[:email]
|
||||
resource_found = resource_class.find_by_email(email)
|
||||
if resource_found && resource_found.ldap_user?
|
||||
flash[:alert] = "Cannot reset password for LDAP user."
|
||||
respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name)) and return
|
||||
end
|
||||
|
||||
self.resource = resource_class.send_reset_password_instructions(resource_params)
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
|
||||
else
|
||||
respond_with(resource)
|
||||
end
|
||||
end
|
||||
before_action :resource_from_email, only: [:create]
|
||||
before_action :prevent_ldap_reset, only: [:create]
|
||||
before_action :throttle_reset, only: [:create]
|
||||
|
||||
def edit
|
||||
super
|
||||
|
@ -35,4 +22,25 @@ class PasswordsController < Devise::PasswordsController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def resource_from_email
|
||||
email = resource_params[:email]
|
||||
self.resource = resource_class.find_by_email(email)
|
||||
end
|
||||
|
||||
def prevent_ldap_reset
|
||||
return unless resource && resource.ldap_user?
|
||||
|
||||
redirect_to after_sending_reset_password_instructions_path_for(resource_name),
|
||||
alert: "Cannot reset password for LDAP user."
|
||||
end
|
||||
|
||||
def throttle_reset
|
||||
return unless resource && resource.recently_sent_password_reset?
|
||||
|
||||
redirect_to new_password_path(resource_name),
|
||||
alert: I18n.t('devise.passwords.recently_reset')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,6 +58,8 @@ class Projects::ServicesController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def service_params
|
||||
params.require(:service).permit(ALLOWED_PARAMS)
|
||||
service_params = params.require(:service).permit(ALLOWED_PARAMS)
|
||||
service_params.delete("password") if service_params["password"].blank?
|
||||
service_params
|
||||
end
|
||||
end
|
||||
|
|
|
@ -296,7 +296,7 @@ module ProjectsHelper
|
|||
|
||||
def readme_cache_key
|
||||
sha = @project.commit.try(:sha) || 'nil'
|
||||
[@project.id, sha, "readme"].join('-')
|
||||
[@project.path_with_namespace, sha, "readme"].join('-')
|
||||
end
|
||||
|
||||
def round_commit_count(project)
|
||||
|
|
|
@ -751,13 +751,9 @@ class Project < ActiveRecord::Base
|
|||
gitlab_ci_project || create_gitlab_ci_project
|
||||
end
|
||||
|
||||
def enable_ci(user)
|
||||
# Enable service
|
||||
def enable_ci
|
||||
service = gitlab_ci_service || create_gitlab_ci_service
|
||||
service.active = true
|
||||
service.save
|
||||
|
||||
# Create Ci::Project
|
||||
Ci::CreateProjectService.new.execute(user, self)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,12 +22,17 @@ class GitlabCiService < CiService
|
|||
include Gitlab::Application.routes.url_helpers
|
||||
|
||||
after_save :compose_service_hook, if: :activated?
|
||||
after_save :ensure_gitlab_ci_project, if: :activated?
|
||||
|
||||
def compose_service_hook
|
||||
hook = service_hook || build_service_hook
|
||||
hook.save
|
||||
end
|
||||
|
||||
def ensure_gitlab_ci_project
|
||||
project.ensure_gitlab_ci_project
|
||||
end
|
||||
|
||||
def supported_events
|
||||
%w(push tag_push)
|
||||
end
|
||||
|
@ -67,21 +72,6 @@ class GitlabCiService < CiService
|
|||
:error
|
||||
end
|
||||
|
||||
def fork_registration(new_project, current_user)
|
||||
params = OpenStruct.new({
|
||||
id: new_project.id,
|
||||
default_branch: new_project.default_branch
|
||||
})
|
||||
|
||||
ci_project = Ci::Project.find_by!(gitlab_id: project.id)
|
||||
|
||||
Ci::CreateProjectService.new.execute(
|
||||
current_user,
|
||||
params,
|
||||
ci_project
|
||||
)
|
||||
end
|
||||
|
||||
def commit_coverage(sha, ref)
|
||||
get_ci_commit(sha, ref).coverage
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
|
|
|
@ -135,6 +135,10 @@ class ProjectTeam
|
|||
!!find_member(user_id)
|
||||
end
|
||||
|
||||
def human_max_access(user_id)
|
||||
Gitlab::Access.options.key max_member_access(user_id)
|
||||
end
|
||||
|
||||
def max_member_access(user_id)
|
||||
access = []
|
||||
access << project.project_members.find_by(user_id: user_id).try(:access_field)
|
||||
|
|
|
@ -328,6 +328,10 @@ class User < ActiveRecord::Base
|
|||
@reset_token
|
||||
end
|
||||
|
||||
def recently_sent_password_reset?
|
||||
reset_password_sent_at.present? && reset_password_sent_at >= 1.minute.ago
|
||||
end
|
||||
|
||||
def disable_two_factor!
|
||||
update_attributes(
|
||||
two_factor_enabled: false,
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
module Ci
|
||||
class CreateProjectService
|
||||
include Gitlab::Application.routes.url_helpers
|
||||
|
||||
def execute(current_user, params, forked_project = nil)
|
||||
@project = Ci::Project.parse(params)
|
||||
|
||||
Ci::Project.transaction do
|
||||
@project.save!
|
||||
|
||||
gl_project = ::Project.find(@project.gitlab_id)
|
||||
gl_project.build_missing_services
|
||||
gl_project.gitlab_ci_service.update_attributes(active: true)
|
||||
end
|
||||
|
||||
if forked_project
|
||||
# Copy settings
|
||||
settings = forked_project.attributes.select do |attr_name, value|
|
||||
["public", "shared_runners_enabled", "allow_git_fetch"].include? attr_name
|
||||
end
|
||||
|
||||
@project.update(settings)
|
||||
end
|
||||
|
||||
Ci::EventService.new.create_project(current_user, @project)
|
||||
|
||||
@project
|
||||
end
|
||||
end
|
||||
end
|
|
@ -58,7 +58,7 @@ class GitPushService
|
|||
# If CI was disabled but .gitlab-ci.yml file was pushed
|
||||
# we enable CI automatically
|
||||
if !project.gitlab_ci? && gitlab_ci_yaml?(newrev)
|
||||
project.enable_ci(user)
|
||||
project.enable_ci
|
||||
end
|
||||
|
||||
EventCreateService.new.push(project, user, @push_data)
|
||||
|
|
|
@ -18,7 +18,13 @@ module Projects
|
|||
|
||||
if new_project.persisted?
|
||||
if @project.gitlab_ci?
|
||||
@project.gitlab_ci_service.fork_registration(new_project, @current_user)
|
||||
new_project.enable_ci
|
||||
|
||||
settings = @project.gitlab_ci_project.attributes.select do |attr_name, value|
|
||||
["public", "shared_runners_enabled", "allow_git_fetch"].include? attr_name
|
||||
end
|
||||
|
||||
new_project.gitlab_ci_project.update(settings)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
= render 'dashboard/projects_head'
|
||||
|
||||
- if @last_push
|
||||
= render "events/event_last_push", event: @last_push
|
||||
|
||||
- if @projects.any?
|
||||
= render 'projects'
|
||||
- else
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.devise-errors
|
||||
= devise_error_messages!
|
||||
.clearfix.append-bottom-20
|
||||
= f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email]
|
||||
= f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email], autofocus: true
|
||||
.clearfix
|
||||
= f.submit "Reset password", class: "btn-primary btn"
|
||||
|
||||
|
|
|
@ -25,5 +25,5 @@
|
|||
= render "layouts/flash"
|
||||
%div{ class: container_class }
|
||||
.content
|
||||
.clearfix
|
||||
.clearfix.max-height
|
||||
= yield
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
- note_count = notes.user.count
|
||||
|
||||
- ci_commit = project.ci_commit(commit.sha)
|
||||
- cache_key = [project.id, commit.id, note_count]
|
||||
- cache_key = [project.path_with_namespace, commit.id, note_count]
|
||||
- cache_key.push(ci_commit.status) if ci_commit
|
||||
|
||||
= cache(cache_key) do
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
= icon('trash-o')
|
||||
|
||||
- unless note.system
|
||||
- member = note.project.team.find_member(note.author.id)
|
||||
- if member
|
||||
- access = note.project.team.human_max_access(note.author.id)
|
||||
- if access
|
||||
%span.note-role.label
|
||||
= member.human_access
|
||||
= access
|
||||
|
||||
= link_to_member(note.project, note.author, avatar: false)
|
||||
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
- help = field[:help]
|
||||
|
||||
.form-group
|
||||
= form.label name, title, class: "control-label"
|
||||
- if type == "password" && value.present?
|
||||
= form.label name, "Change #{title}", class: "control-label"
|
||||
- else
|
||||
= form.label name, title, class: "control-label"
|
||||
.col-sm-10
|
||||
- if type == 'text'
|
||||
= form.text_field name, class: "form-control", placeholder: placeholder
|
||||
|
@ -19,6 +22,6 @@
|
|||
- elsif type == 'select'
|
||||
= form.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
|
||||
- elsif type == 'password'
|
||||
= form.password_field name, value: value, class: 'form-control'
|
||||
= form.password_field name, autocomplete: "new-password", class: 'form-control'
|
||||
- if help
|
||||
%span.help-block= help
|
||||
|
|
|
@ -1,61 +1,63 @@
|
|||
# Additional translations at http://github.com/plataformatec/devise/wiki/I18n
|
||||
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
|
||||
|
||||
en:
|
||||
devise:
|
||||
confirmations:
|
||||
confirmed: "Your email address has been successfully confirmed."
|
||||
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
|
||||
failure:
|
||||
already_authenticated: "You are already signed in."
|
||||
inactive: "Your account is not activated yet."
|
||||
invalid: "Invalid %{authentication_keys} or password."
|
||||
locked: "Your account is locked."
|
||||
last_attempt: "You have one more attempt before your account is locked."
|
||||
not_found_in_database: "Invalid %{authentication_keys} or password."
|
||||
timeout: "Your session expired. Please sign in again to continue."
|
||||
unauthenticated: "You need to sign in or sign up before continuing."
|
||||
unconfirmed: "You have to confirm your email address before continuing."
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: "Confirmation instructions"
|
||||
reset_password_instructions:
|
||||
subject: "Reset password instructions"
|
||||
unlock_instructions:
|
||||
subject: "Unlock instructions"
|
||||
password_change:
|
||||
subject: "Password Changed"
|
||||
omniauth_callbacks:
|
||||
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
|
||||
success: "Successfully authenticated from %{kind} account."
|
||||
passwords:
|
||||
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||
recently_reset: "Instructions about how to reset your password have already been sent recently. Please wait a few minutes to try again."
|
||||
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
updated: "Your password has been changed successfully. You are now signed in."
|
||||
updated_not_active: "Your password has been changed successfully."
|
||||
registrations:
|
||||
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
|
||||
signed_up: "Welcome! You have signed up successfully."
|
||||
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
|
||||
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
|
||||
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
|
||||
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
|
||||
updated: "Your account has been updated successfully."
|
||||
sessions:
|
||||
signed_in: "Signed in successfully."
|
||||
signed_out: "Signed out successfully."
|
||||
already_signed_out: "Signed out successfully."
|
||||
unlocks:
|
||||
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
|
||||
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
|
||||
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
|
||||
errors:
|
||||
messages:
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
|
||||
expired: "has expired, please request a new one"
|
||||
not_found: "not found"
|
||||
already_confirmed: "was already confirmed, please try signing in"
|
||||
not_locked: "was not locked"
|
||||
not_saved:
|
||||
one: "1 error prohibited this %{resource} from being saved:"
|
||||
other: "%{count} errors prohibited this %{resource} from being saved:"
|
||||
|
||||
devise:
|
||||
failure:
|
||||
already_authenticated: 'You are already signed in.'
|
||||
unauthenticated: 'You need to sign in before continuing.'
|
||||
unconfirmed: 'You have to confirm your account before continuing.'
|
||||
locked: 'Your account is locked.'
|
||||
not_found_in_database: 'Invalid email or password.'
|
||||
invalid: 'Invalid email or password.'
|
||||
invalid_token: 'Invalid authentication token.'
|
||||
timeout: 'Your session expired, please sign in again to continue.'
|
||||
inactive: 'Your account was not activated yet.'
|
||||
sessions:
|
||||
signed_in: ''
|
||||
signed_out: ''
|
||||
users_sessions:
|
||||
user:
|
||||
signed_in: 'Signed in successfully.'
|
||||
passwords:
|
||||
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
||||
updated: 'Your password was changed successfully. You are now signed in.'
|
||||
updated_not_active: 'Your password was changed successfully.'
|
||||
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
||||
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
||||
confirmations:
|
||||
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
send_paranoid_instructions: 'If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
|
||||
confirmed: 'Your account was successfully confirmed. You are now signed in.'
|
||||
registrations:
|
||||
signed_up: 'Welcome! You have signed up successfully.'
|
||||
updated: 'You updated your account successfully.'
|
||||
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
|
||||
signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
|
||||
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
|
||||
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
|
||||
unlocks:
|
||||
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
|
||||
unlocked: 'Your account was successfully unlocked. You are now signed in.'
|
||||
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
|
||||
omniauth_callbacks:
|
||||
success: 'Successfully authorized from %{kind} account.'
|
||||
failure: 'Could not authorize you from %{kind} because "%{reason}".'
|
||||
mailer:
|
||||
confirmation_instructions:
|
||||
subject: 'Confirmation instructions'
|
||||
reset_password_instructions:
|
||||
subject: 'Reset password instructions'
|
||||
unlock_instructions:
|
||||
subject: 'Unlock Instructions'
|
||||
|
|
|
@ -182,6 +182,7 @@ will need this file later.
|
|||
```
|
||||
# On your CI server:
|
||||
# Omnibus
|
||||
sudo chown gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
|
||||
sudo gitlab-ci-rake backup:create
|
||||
|
||||
# Source
|
||||
|
@ -228,6 +229,7 @@ be no CI data yet because you turned CI on the GitLab server off earlier.
|
|||
```
|
||||
# On your GitLab server:
|
||||
# Omnibus
|
||||
sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
|
||||
sudo gitlab-rake ci:migrate
|
||||
|
||||
# Source
|
||||
|
@ -342,7 +344,12 @@ 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
|
||||
sudo chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
|
||||
```
|
||||
|
||||
Then before executing `ci:migrate` you need to fix builds folder permission:
|
||||
```
|
||||
sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
|
||||
```
|
||||
|
||||
#### Problems when importing CI database to GitLab
|
||||
|
|
|
@ -72,6 +72,7 @@ Feature: Project Services
|
|||
And I click Atlassian Bamboo CI service link
|
||||
And I fill Atlassian Bamboo CI settings
|
||||
Then I should see Atlassian Bamboo CI service settings saved
|
||||
And I should see empty field Change Password
|
||||
|
||||
Scenario: Activate jetBrains TeamCity CI service
|
||||
When I visit project "Shop" services page
|
||||
|
|
|
@ -103,7 +103,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
|
|||
end
|
||||
|
||||
step 'commit has ci status' do
|
||||
@project.enable_ci(@user)
|
||||
@project.enable_ci
|
||||
create :ci_commit, gl_project: @project, sha: sample_commit.id
|
||||
end
|
||||
|
||||
|
|
|
@ -202,6 +202,10 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
|
|||
expect(find_field('Username').value).to eq 'user'
|
||||
end
|
||||
|
||||
step 'I should see empty field Change Password' do
|
||||
expect(find_field('Change Password').value).to be_nil
|
||||
end
|
||||
|
||||
step 'I click JetBrains TeamCity CI service link' do
|
||||
click_link 'JetBrains TeamCity CI'
|
||||
end
|
||||
|
|
|
@ -199,7 +199,7 @@ module SharedProject
|
|||
|
||||
step 'project "Shop" has CI enabled' do
|
||||
project = Project.find_by(name: "Shop")
|
||||
project.enable_ci(@user)
|
||||
project.enable_ci
|
||||
end
|
||||
|
||||
step 'project "Shop" has CI build' do
|
||||
|
|
|
@ -95,7 +95,7 @@ feature 'Login', feature: true do
|
|||
user = create(:user, password: 'not-the-default')
|
||||
|
||||
login_with(user)
|
||||
expect(page).to have_content('Invalid email or password.')
|
||||
expect(page).to have_content('Invalid login or password.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,53 +1,43 @@
|
|||
require 'spec_helper'
|
||||
|
||||
feature 'Password reset', feature: true do
|
||||
describe 'with two-factor authentication' do
|
||||
let(:user) { create(:user, :two_factor) }
|
||||
|
||||
it 'requires login after password reset' do
|
||||
describe 'throttling' do
|
||||
it 'sends reset instructions when not previously sent' do
|
||||
visit root_path
|
||||
forgot_password(create(:user))
|
||||
|
||||
forgot_password
|
||||
reset_password
|
||||
|
||||
expect(page).to have_content("Your password was changed successfully.")
|
||||
expect(page).not_to have_content("You are now signed in.")
|
||||
expect(page).to have_content(I18n.t('devise.passwords.send_instructions'))
|
||||
expect(current_path).to eq new_user_session_path
|
||||
end
|
||||
|
||||
it 'sends reset instructions when previously sent more than a minute ago' do
|
||||
user = create(:user)
|
||||
user.send_reset_password_instructions
|
||||
user.update_attribute(:reset_password_sent_at, 5.minutes.ago)
|
||||
|
||||
visit root_path
|
||||
forgot_password(user)
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.passwords.send_instructions'))
|
||||
expect(current_path).to eq new_user_session_path
|
||||
end
|
||||
|
||||
it "throttles multiple resets in a short timespan" do
|
||||
user = create(:user)
|
||||
user.send_reset_password_instructions
|
||||
|
||||
visit root_path
|
||||
forgot_password(user)
|
||||
|
||||
expect(page).to have_content(I18n.t('devise.passwords.recently_reset'))
|
||||
expect(current_path).to eq new_user_password_path
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without two-factor authentication' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'requires login after password reset' do
|
||||
visit root_path
|
||||
|
||||
forgot_password
|
||||
reset_password
|
||||
|
||||
expect(page).to have_content("Your password was changed successfully.")
|
||||
expect(current_path).to eq new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
def forgot_password
|
||||
def forgot_password(user)
|
||||
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
|
||||
|
|
|
@ -61,13 +61,13 @@ describe ProjectsHelper do
|
|||
end
|
||||
|
||||
it "returns a valid cach key" do
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.id}-#{project.commit.id}-readme")
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.path_with_namespace}-#{project.commit.id}-readme")
|
||||
end
|
||||
|
||||
it "returns a valid cache key if HEAD does not exist" do
|
||||
allow(project).to receive(:commit) { nil }
|
||||
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.id}-nil-readme")
|
||||
expect(helper.send(:readme_cache_key)).to eq("#{project.path_with_namespace}-nil-readme")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,25 +55,4 @@ describe GitlabCiService do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Fork registration" do
|
||||
before do
|
||||
@old_project = create(:ci_project).gl_project
|
||||
@project = create(:empty_project)
|
||||
@user = create(:user)
|
||||
|
||||
@service = GitlabCiService.new
|
||||
allow(@service).to receive_messages(
|
||||
service_hook: true,
|
||||
project_url: 'http://ci.gitlab.org/projects/2',
|
||||
token: 'verySecret',
|
||||
project: @old_project
|
||||
)
|
||||
end
|
||||
|
||||
it "creates fork on CI" do
|
||||
expect_any_instance_of(Ci::CreateProjectService).to receive(:execute)
|
||||
@service.fork_registration(@project, @user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -417,9 +417,8 @@ describe Project do
|
|||
|
||||
describe :enable_ci do
|
||||
let(:project) { create :project }
|
||||
let(:user) { create :user }
|
||||
|
||||
before { project.enable_ci(user) }
|
||||
before { project.enable_ci }
|
||||
|
||||
it { expect(project.gitlab_ci?).to be_truthy }
|
||||
it { expect(project.gitlab_ci_project).to be_a(Ci::Project) }
|
||||
|
|
|
@ -66,4 +66,16 @@ describe ProjectTeam do
|
|||
it { expect(project.team.member?(guest)).to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#human_max_access" do
|
||||
it "return master role" do
|
||||
user = create :user
|
||||
group = create :group
|
||||
group.add_users([user.id], GroupMember::MASTER)
|
||||
project = create(:project, namespace: group)
|
||||
project.team << [user, :guest]
|
||||
|
||||
expect(project.team.human_max_access(user.id)).to eq("Master")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -228,6 +228,26 @@ describe User do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#recently_sent_password_reset?' do
|
||||
it 'is false when reset_password_sent_at is nil' do
|
||||
user = build_stubbed(:user, reset_password_sent_at: nil)
|
||||
|
||||
expect(user.recently_sent_password_reset?).to eq false
|
||||
end
|
||||
|
||||
it 'is false when sent more than one minute ago' do
|
||||
user = build_stubbed(:user, reset_password_sent_at: 5.minutes.ago)
|
||||
|
||||
expect(user.recently_sent_password_reset?).to eq false
|
||||
end
|
||||
|
||||
it 'is true when sent less than one minute ago' do
|
||||
user = build_stubbed(:user, reset_password_sent_at: Time.now)
|
||||
|
||||
expect(user.recently_sent_password_reset?).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#disable_two_factor!' do
|
||||
it 'clears all 2FA-related fields' do
|
||||
user = create(:user, :two_factor)
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Ci::CreateProjectService do
|
||||
let(:service) { Ci::CreateProjectService.new }
|
||||
let(:current_user) { double.as_null_object }
|
||||
let(:project) { FactoryGirl.create :project }
|
||||
|
||||
describe :execute do
|
||||
context 'valid params' do
|
||||
subject { service.execute(current_user, project) }
|
||||
|
||||
it { is_expected.to be_kind_of(Ci::Project) }
|
||||
it { is_expected.to be_persisted }
|
||||
end
|
||||
|
||||
context 'without project dump' do
|
||||
it 'should raise exception' do
|
||||
expect { service.execute(current_user, '', '') }.
|
||||
to raise_error(NoMethodError)
|
||||
end
|
||||
end
|
||||
|
||||
context "forking" do
|
||||
let(:ci_origin_project) do
|
||||
FactoryGirl.create(:ci_project, shared_runners_enabled: true, public: true, allow_git_fetch: true)
|
||||
end
|
||||
|
||||
subject { service.execute(current_user, project, ci_origin_project) }
|
||||
|
||||
it "uses project as a template for settings and jobs" do
|
||||
expect(subject.shared_runners_enabled).to be_truthy
|
||||
expect(subject.public).to be_truthy
|
||||
expect(subject.allow_git_fetch).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -43,14 +43,10 @@ describe Projects::ForkService do
|
|||
end
|
||||
|
||||
context 'GitLab CI is enabled' do
|
||||
it "calls fork registrator for CI" do
|
||||
create(:ci_project, gl_project: @from_project)
|
||||
@from_project.build_missing_services
|
||||
@from_project.gitlab_ci_service.update_attributes(active: true)
|
||||
|
||||
expect_any_instance_of(Ci::CreateProjectService).to receive(:execute)
|
||||
|
||||
fork_project(@from_project, @to_user)
|
||||
it "fork and enable CI for fork" do
|
||||
@from_project.enable_ci
|
||||
@to_project = fork_project(@from_project, @to_user)
|
||||
expect(@to_project.gitlab_ci?).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue