Commit 16da0223 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-02-14

parents 1f32cbbf 3ea923a8
...@@ -71,11 +71,15 @@ star, smile, etc.). Some good tips about code reviews can be found in our ...@@ -71,11 +71,15 @@ star, smile, etc.). Some good tips about code reviews can be found in our
## Feature freeze on the 7th for the release on the 22nd ## Feature freeze on the 7th for the release on the 22nd
After the 7th (Pacific Standard Time Zone) of each month, RC1 of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com and the stable branch for this release is frozen, which means master is no longer merged into it. After 7th at 23:59 (Pacific Standard Time Zone) of each month, RC1 of the upcoming release (to be shipped on the 22nd) is created and deployed to GitLab.com and the stable branch for this release is frozen, which means master is no longer merged into it.
Merge requests may still be merged into master during this period, Merge requests may still be merged into master during this period,
but they will go into the _next_ release, unless they are manually cherry-picked into the stable branch. but they will go into the _next_ release, unless they are manually cherry-picked into the stable branch.
By freezing the stable branches 2 weeks prior to a release, we reduce the risk of a last minute merge request potentially breaking things. By freezing the stable branches 2 weeks prior to a release, we reduce the risk of a last minute merge request potentially breaking things.
Any release candidate that gets created after this date can become a final release,
hence the name release candidate.
### Between the 1st and the 7th ### Between the 1st and the 7th
These types of merge requests for the upcoming release need special consideration: These types of merge requests for the upcoming release need special consideration:
...@@ -193,11 +197,10 @@ to be backported down to the `9.5` release, you will need to assign it the ...@@ -193,11 +197,10 @@ to be backported down to the `9.5` release, you will need to assign it the
### Asking for an exception ### Asking for an exception
If you think a merge request should go into an RC or patch even though it does not meet these requirements, If you think a merge request should go into an RC or patch even though it does not meet these requirements,
you can ask for an exception to be made. Exceptions require sign-off from 3 people besides the developer: you can ask for an exception to be made.
1. a Release Manager Go to [Release tasks issue tracker](https://gitlab.com/gitlab-org/release/tasks/issues/new) and create an issue
2. an Engineering Lead using the `Exception-request` issue template.
3. an Engineering Director, the VP of Engineering, or the CTO
You can find who is who on the [team page](https://about.gitlab.com/team/). You can find who is who on the [team page](https://about.gitlab.com/team/).
......
...@@ -21,7 +21,7 @@ class IssuesFinder < IssuableFinder ...@@ -21,7 +21,7 @@ class IssuesFinder < IssuableFinder
CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER
def klass def klass
Issue Issue.includes(:author)
end end
def with_confidentiality_access_check def with_confidentiality_access_check
......
...@@ -57,7 +57,7 @@ class NotesFinder ...@@ -57,7 +57,7 @@ class NotesFinder
types = %w(commit issue merge_request snippet) types = %w(commit issue merge_request snippet)
note_relations = types.map { |t| notes_for_type(t) } note_relations = types.map { |t| notes_for_type(t) }
note_relations.map! { |notes| search(notes) } note_relations.map! { |notes| search(notes) }
UnionFinder.new.find_union(note_relations, Note) UnionFinder.new.find_union(note_relations, Note.includes(:author))
end end
def noteables_for_type(noteable_type) def noteables_for_type(noteable_type)
......
...@@ -68,18 +68,32 @@ module ApplicationHelper ...@@ -68,18 +68,32 @@ module ApplicationHelper
end end
end end
def avatar_icon(user_or_email = nil, size = nil, scale = 2, only_path: true) # Takes both user and email and returns the avatar_icon by
user = # user (preferred) or email.
if user_or_email.is_a?(User) def avatar_icon_for(user = nil, email = nil, size = nil, scale = 2, only_path: true)
user_or_email if user
else avatar_icon_for_user(user, size, scale, only_path: only_path)
User.find_by_any_email(user_or_email.try(:downcase)) elsif email
end avatar_icon_for_email(email, size, scale, only_path: only_path)
else
default_avatar
end
end
def avatar_icon_for_email(email = nil, size = nil, scale = 2, only_path: true)
user = User.find_by_any_email(email.try(:downcase))
if user
avatar_icon_for_user(user, size, scale, only_path: only_path)
else
gravatar_icon(email, size, scale)
end
end
def avatar_icon_for_user(user = nil, size = nil, scale = 2, only_path: true)
if user if user
user.avatar_url(size: size, only_path: only_path) || default_avatar user.avatar_url(size: size, only_path: only_path) || default_avatar
else else
gravatar_icon(user_or_email, size, scale) gravatar_icon(nil, size, scale)
end end
end end
......
...@@ -8,10 +8,22 @@ module AvatarsHelper ...@@ -8,10 +8,22 @@ module AvatarsHelper
})) }))
end end
def user_avatar_url_for(options = {})
if options[:url]
options[:url]
elsif options[:user]
avatar_icon_for_user(options[:user], options[:size])
else
avatar_icon_for_email(options[:user_email], options[:size])
end
end
def user_avatar_without_link(options = {}) def user_avatar_without_link(options = {})
avatar_size = options[:size] || 16 avatar_size = options[:size] || 16
user_name = options[:user].try(:name) || options[:user_name] user_name = options[:user].try(:name) || options[:user_name]
avatar_url = options[:url] || avatar_icon(options[:user] || options[:user_email], avatar_size)
avatar_url = user_avatar_url_for(options.merge(size: avatar_size))
has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip] has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip]
data_attributes = options[:data] || {} data_attributes = options[:data] || {}
css_class = %W[avatar s#{avatar_size}].push(*options[:css_class]) css_class = %W[avatar s#{avatar_size}].push(*options[:css_class])
......
...@@ -35,7 +35,7 @@ module NamespacesHelper ...@@ -35,7 +35,7 @@ module NamespacesHelper
if namespace.is_a?(Group) if namespace.is_a?(Group)
group_icon(namespace) group_icon(namespace)
else else
avatar_icon(namespace.owner.email, size) avatar_icon_for_user(namespace.owner, size)
end end
end end
......
...@@ -21,7 +21,7 @@ module ProjectsHelper ...@@ -21,7 +21,7 @@ module ProjectsHelper
classes = %W[avatar avatar-inline s#{opts[:size]}] classes = %W[avatar avatar-inline s#{opts[:size]}]
classes << opts[:avatar_class] if opts[:avatar_class] classes << opts[:avatar_class] if opts[:avatar_class]
avatar = avatar_icon(author, opts[:size]) avatar = avatar_icon_for_user(author, opts[:size])
src = opts[:lazy_load] ? nil : avatar src = opts[:lazy_load] ? nil : avatar
image_tag(src, width: opts[:size], class: classes, alt: '', "data-src" => avatar) image_tag(src, width: opts[:size], class: classes, alt: '', "data-src" => avatar)
......
...@@ -44,12 +44,41 @@ module Ci ...@@ -44,12 +44,41 @@ module Ci
scope :unstarted, ->() { where(runner_id: nil) } scope :unstarted, ->() { where(runner_id: nil) }
scope :ignore_failures, ->() { where(allow_failure: false) } scope :ignore_failures, ->() { where(allow_failure: false) }
# This convoluted mess is because we need to handle two cases of
# artifact files during the migration. And a simple OR clause
# makes it impossible to optimize.
# Instead we want to use UNION ALL and do two carefully
# constructed disjoint queries. But Rails cannot handle UNION or
# UNION ALL queries so we do the query in a subquery and wrap it
# in an otherwise redundant WHERE IN query (IN is fine for
# non-null columns).
# This should all be ripped out when the migration is finished and
# replaced with just the new storage to avoid the extra work.
scope :with_artifacts, ->() do scope :with_artifacts, ->() do
where('(artifacts_file IS NOT NULL AND artifacts_file <> ?) OR EXISTS (?)', old = Ci::Build.select(:id).where(%q[artifacts_file <> ''])
'', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id')) new = Ci::Build.select(:id).where(%q[(artifacts_file IS NULL OR artifacts_file = '') AND EXISTS (?)],
Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id'))
where('ci_builds.id IN (? UNION ALL ?)', old, new)
end end
scope :with_artifacts_not_expired, ->() { with_artifacts.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) }
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :with_artifacts_not_expired, ->() do
old = Ci::Build.select(:id).where(%q[artifacts_file <> '' AND (artifacts_expire_at IS NULL OR artifacts_expire_at > ?)], Time.now)
new = Ci::Build.select(:id).where(%q[(artifacts_file IS NULL OR artifacts_file = '') AND EXISTS (?)],
Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id AND (expire_at IS NULL OR expire_at > ?)', Time.now))
where('ci_builds.id IN (? UNION ALL ?)', old, new)
end
scope :with_expired_artifacts, ->() do
old = Ci::Build.select(:id).where(%q[artifacts_file <> '' AND artifacts_expire_at < ?], Time.now)
new = Ci::Build.select(:id).where(%q[(artifacts_file IS NULL OR artifacts_file = '') AND EXISTS (?)],
Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id AND expire_at < ?', Time.now))
where('ci_builds.id IN (? UNION ALL ?)', old, new)
end
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + [:manual]) } scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + [:manual]) }
scope :ref_protected, -> { where(protected: true) } scope :ref_protected, -> { where(protected: true) }
......
...@@ -102,10 +102,6 @@ class Event < ActiveRecord::Base ...@@ -102,10 +102,6 @@ class Event < ActiveRecord::Base
self.inheritance_column = 'action' self.inheritance_column = 'action'
# "data" will be removed in 10.0 but it may be possible that JOINs happen that
# include this column, hence we're ignoring it as well.
ignore_column :data
class << self class << self
def model_name def model_name
ActiveModel::Name.new(self, nil, 'event') ActiveModel::Name.new(self, nil, 'event')
......
...@@ -5,11 +5,15 @@ module Projects ...@@ -5,11 +5,15 @@ module Projects
end end
def execute def execute
params[:file] = Gitlab::ProjectTemplate.find(params[:template_name]).file template_name = params.delete(:template_name)
file = Gitlab::ProjectTemplate.find(template_name).file
params[:file] = file
GitlabProjectsImportService.new(current_user, params).execute
GitlabProjectsImportService.new(@current_user, @params).execute
ensure ensure
params[:file]&.close file&.close
end end
end end
end end
...@@ -11,12 +11,14 @@ module Projects ...@@ -11,12 +11,14 @@ module Projects
def execute def execute
FileUtils.mkdir_p(File.dirname(import_upload_path)) FileUtils.mkdir_p(File.dirname(import_upload_path))
file = params.delete(:file)
FileUtils.copy_entry(file.path, import_upload_path) FileUtils.copy_entry(file.path, import_upload_path)
Gitlab::ImportExport::ProjectCreator.new(params[:namespace_id], params[:import_type] = 'gitlab_project'
current_user, params[:import_source] = import_upload_path
import_upload_path,
params[:path]).execute ::Projects::CreateService.new(current_user, params).execute
end end
private private
...@@ -28,9 +30,5 @@ module Projects ...@@ -28,9 +30,5 @@ module Projects
def tmp_filename def tmp_filename
SecureRandom.hex SecureRandom.hex
end end
def file
params[:file]
end
end end
end end
%li.flex-row %li.flex-row
.user-avatar .user-avatar
= image_tag avatar_icon(user), class: "avatar", alt: '' = image_tag avatar_icon_for_user(user), class: "avatar", alt: ''
.row-main-content .row-main-content
.user-name.row-title.str-truncated-100 .user-name.row-title.str-truncated-100
= link_to user.name, [:admin, user] = link_to user.name, [:admin, user]
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= @user.name = @user.name
%ul.well-list %ul.well-list
%li %li
= image_tag avatar_icon(@user, 60), class: "avatar s60" = image_tag avatar_icon_for_user(@user, 60), class: "avatar s60"
%li %li
%span.light Profile page: %span.light Profile page:
%strong %strong
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
.timeline-entry-inner .timeline-entry-inner
.timeline-icon .timeline-icon
= link_to user_path(discussion.author) do = link_to user_path(discussion.author) do
= image_tag avatar_icon(discussion.author), class: "avatar s40" = image_tag avatar_icon_for_user(discussion.author), class: "avatar s40"
.timeline-content .timeline-content
.discussion.js-toggle-container{ data: { discussion_id: discussion.id } } .discussion.js-toggle-container{ data: { discussion_id: discussion.id } }
.discussion-header .discussion-header
......
...@@ -10,7 +10,7 @@ xml.entry do ...@@ -10,7 +10,7 @@ xml.entry do
# eager-loaded. This allows us to re-use the user object's Email address, # eager-loaded. This allows us to re-use the user object's Email address,
# instead of having to run additional queries to figure out what Email to use # instead of having to run additional queries to figure out what Email to use
# for the avatar. # for the avatar.
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author)) xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon_for_user(event.author))
xml.author do xml.author do
xml.username event.author_username xml.username event.author_username
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
.example .example
.cover-block .cover-block
.avatar-holder .avatar-holder
= image_tag avatar_icon('admin@example.com', 90), class: "avatar s90", alt: '' = image_tag avatar_icon_for_email('admin@example.com', 90), class: "avatar s90", alt: ''
.cover-title .cover-title
John Smith John Smith
......
...@@ -3,7 +3,7 @@ xml.entry do ...@@ -3,7 +3,7 @@ xml.entry do
xml.link href: project_issue_url(issue.project, issue) xml.link href: project_issue_url(issue.project, issue)
xml.title truncate(issue.title, length: 80) xml.title truncate(issue.title, length: 80)
xml.updated issue.updated_at.xmlschema xml.updated issue.updated_at.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email)) xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon_for_user(issue.author))
xml.author do xml.author do
xml.name issue.author_name xml.name issue.author_name
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
= todos_count_format(todos_pending_count) = todos_count_format(todos_pending_count)
%li.header-user.dropdown %li.header-user.dropdown
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
= image_tag avatar_icon(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar" = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar"
= sprite_icon('angle-down', css_class: 'caret-down') = sprite_icon('angle-down', css_class: 'caret-down')
.dropdown-menu-nav.dropdown-menu-align-right .dropdown-menu-nav.dropdown-menu-align-right
%ul %ul
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
%tbody %tbody
%tr %tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.author || commit.author_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/ %img.avatar{ height: "24", src: avatar_icon_for(commit.author, commit.author_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.author - if commit.author
%a.muted{ href: user_url(commit.author), style: "color:#333333;text-decoration:none;" } %a.muted{ href: user_url(commit.author), style: "color:#333333;text-decoration:none;" }
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
%tbody %tbody
%tr %tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.committer || commit.committer_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/ %img.avatar{ height: "24", src: avatar_icon_for(commit.committer, commit.committer_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.committer - if commit.committer
%a.muted{ href: user_url(commit.committer), style: "color:#333333;text-decoration:none;" } %a.muted{ href: user_url(commit.committer), style: "color:#333333;text-decoration:none;" }
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
triggered by triggered by
- if @pipeline.user - if @pipeline.user
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;padding-left:5px", width: "24" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;padding-left:5px", width: "24" }
%img.avatar{ height: "24", src: avatar_icon(@pipeline.user, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/ %img.avatar{ height: "24", src: avatar_icon_for_user(@pipeline.user, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;font-weight:500;line-height:1.4;vertical-align:baseline;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;font-weight:500;line-height:1.4;vertical-align:baseline;" }
%a.muted{ href: user_url(@pipeline.user), style: "color:#333333;text-decoration:none;" } %a.muted{ href: user_url(@pipeline.user), style: "color:#333333;text-decoration:none;" }
= @pipeline.user.name = @pipeline.user.name
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
%tbody %tbody
%tr %tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.author || commit.author_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/ %img.avatar{ height: "24", src: avatar_icon_for(commit.author, commit.author_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.author - if commit.author
%a.muted{ href: user_url(commit.author), style: "color:#333333;text-decoration:none;" } %a.muted{ href: user_url(commit.author), style: "color:#333333;text-decoration:none;" }
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
%tbody %tbody
%tr %tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.committer || commit.committer_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/ %img.avatar{ height: "24", src: avatar_icon_for(commit.committer, commit.committer_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.committer - if commit.committer
%a.muted{ href: user_url(commit.committer), style: "color:#333333;text-decoration:none;" } %a.muted{ href: user_url(commit.committer), style: "color:#333333;text-decoration:none;" }
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
triggered by triggered by
- if @pipeline.user - if @pipeline.user
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;padding-left:5px", width: "24" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;padding-left:5px", width: "24" }
%img.avatar{ height: "24", src: avatar_icon(@pipeline.user, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/ %img.avatar{ height: "24", src: avatar_icon_for_user(@pipeline.user, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;font-weight:500;line-height:1.4;vertical-align:baseline;" } %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;font-weight:500;line-height:1.4;vertical-align:baseline;" }
%a.muted{ href: user_url(@pipeline.user), style: "color:#333333;text-decoration:none;" } %a.muted{ href: user_url(@pipeline.user), style: "color:#333333;text-decoration:none;" }
= @pipeline.user.name = @pipeline.user.name
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
or change it at #{link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host} or change it at #{link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host}
.col-lg-8 .col-lg-8
.clearfix.avatar-image.append-bottom-default .clearfix.avatar-image.append-bottom-default
= link_to avatar_icon(@user, 400), target: '_blank', rel: 'noopener noreferrer' do = link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
= image_tag avatar_icon(@user, 160), alt: '', class: 'avatar s160' = image_tag avatar_icon_for_user(@user, 160), alt: '', class: 'avatar s160'
%h5.prepend-top-0= _("Upload new avatar") %h5.prepend-top-0= _("Upload new avatar")
.prepend-top-5.append-bottom-10 .prepend-top-5.append-bottom-10
%button.btn.js-choose-user-avatar-button{ type: 'button' }= _("Choose file...") %button.btn.js-choose-user-avatar-button{ type: 'button' }= _("Choose file...")
......
...@@ -3,7 +3,7 @@ xml.entry do ...@@ -3,7 +3,7 @@ xml.entry do
xml.link href: project_commit_url(@project, id: commit.id) xml.link href: project_commit_url(@project, id: commit.id)
xml.title truncate(commit.title, length: 80, escape: false) xml.title truncate(commit.title, length: 80, escape: false)
xml.updated commit.committed_date.xmlschema xml.updated commit.committed_date.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email)) xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon_for_email(commit.author_email))
xml.author do |author| xml.author do |author|
xml.name commit.author_name xml.name commit.author_name
......
by by
%a{ href: user_path(@build.user) } %a{ href: user_path(@build.user) }
%span.hidden-xs %span.hidden-xs
= image_tag avatar_icon(@build.user, 24), class: "avatar s24" = image_tag avatar_icon_for_user(@build.user, 24), class: "avatar s24"
%strong{ data: { toggle: 'tooltip', placement: 'top', title: @build.user.to_reference } } %strong{ data: { toggle: 'tooltip', placement: 'top', title: @build.user.to_reference } }
= @build.user.name = @build.user.name
%strong.visible-xs-inline= @build.user.to_reference %strong.visible-xs-inline= @build.user.to_reference
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
author: { author: {
name: c.author_name, name: c.author_name,
email: c.author_email, email: c.author_email,
icon: image_path(avatar_icon(c.author_email, 20)) icon: image_path(avatar_icon_for_email(c.author_email, 20))
}, },
time: c.time, time: c.time,
space: c.spaces.first, space: c.spaces.first,
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
= s_("PipelineSchedules|Inactive") = s_("PipelineSchedules|Inactive")
%td %td
- if pipeline_schedule.owner - if pipeline_schedule.owner
= image_tag avatar_icon(pipeline_schedule.owner, 20), class: "avatar s20" = image_tag avatar_icon_for_user(pipeline_schedule.owner, 20), class: "avatar s20"
= link_to user_path(pipeline_schedule.owner) do = link_to user_path(pipeline_schedule.owner) do
= pipeline_schedule.owner&.name = pipeline_schedule.owner&.name
%td %td
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
%div %div
= link_to project_commits_path(@project, commit.id) do = link_to project_commits_path(@project, commit.id) do
%code= commit.short_id %code= commit.short_id
= image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: '' = image_tag avatar_icon_for_email(commit.author_email), class: "", width: 16, alt: ''
= markdown(truncate(commit.title, length: 40), pipeline: :single_line, author: commit.author) = markdown(truncate(commit.title, length: 40), pipeline: :single_line, author: commit.author)
%td %td
%span.pull-right.cgray %span.pull-right.cgray
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
= snippet.title = snippet.title
by by
= link_to user_snippets_path(snippet.author) do = link_to user_snippets_path(snippet.author) do
= image_tag avatar_icon(snippet.author), class: "avatar avatar-inline s16", alt: '' = image_tag avatar_icon_for_user(snippet.author), class: "avatar avatar-inline s16", alt: ''
= snippet.author_name = snippet.author_name
%span.light= time_ago_with_tooltip(snippet.created_at) %span.light= time_ago_with_tooltip(snippet.created_at)
%h4.snippet-title %h4.snippet-title
......
...@@ -18,6 +18,6 @@ ...@@ -18,6 +18,6 @@
%span %span
by by
= link_to user_snippets_path(snippet_title.author) do = link_to user_snippets_path(snippet_title.author) do
= image_tag avatar_icon(snippet_title.author), class: "avatar avatar-inline s16", alt: '' = image_tag avatar_icon_for_user(snippet_title.author), class: "avatar avatar-inline s16", alt: ''
= snippet_title.author_name = snippet_title.author_name
%span.light= time_ago_with_tooltip(snippet_title.created_at) %span.light= time_ago_with_tooltip(snippet_title.created_at)
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
%li.member{ class: [dom_class(member), ("is-overriden" if member.override)], id: dom_id(member) } %li.member{ class: [dom_class(member), ("is-overriden" if member.override)], id: dom_id(member) }
%span.list-item-name %span.list-item-name
- if user - if user
= image_tag avatar_icon(user, 40), class: "avatar s40", alt: '' = image_tag avatar_icon_for_user(user, 40), class: "avatar s40", alt: ''
.user-info .user-info
= link_to user.name, user_path(user), class: 'member' = link_to user.name, user_path(user), class: 'member'
%span.cgray= user.to_reference %span.cgray= user.to_reference
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
Expires in #{distance_of_time_in_words_to_now(member.expires_at)} Expires in #{distance_of_time_in_words_to_now(member.expires_at)}
- else - else
= image_tag avatar_icon(member.invite_email, 40), class: "avatar s40", alt: '' = image_tag avatar_icon_for_email(member.invite_email, 40), class: "avatar s40", alt: ''
.user-info .user-info
.member= member.invite_email .member= member.invite_email
.cgray .cgray
......
...@@ -28,4 +28,4 @@ ...@@ -28,4 +28,4 @@
- assignees.each do |assignee| - assignees.each do |assignee|
= link_to polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, assignee_id: assignee.id, state: 'all' }), = link_to polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, assignee_id: assignee.id, state: 'all' }),
class: 'has-tooltip', title: "Assigned to #{assignee.name}", data: { container: 'body' } do class: 'has-tooltip', title: "Assigned to #{assignee.name}", data: { container: 'body' } do
- image_tag(avatar_icon(assignee, 16), class: "avatar s16", alt: '') - image_tag(avatar_icon_for_user(assignee, 16), class: "avatar s16", alt: '')
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- users.each do |user| - users.each do |user|
%li %li
= link_to user, title: user.name, class: "darken" do = link_to user, title: user.name, class: "darken" do
= image_tag avatar_icon(user, 32), class: "avatar s32" = image_tag avatar_icon_for_user(user, 32), class: "avatar s32"
%strong= truncate(user.name, length: 40) %strong= truncate(user.name, length: 40)
%div %div
%small.cgray= user.username %small.cgray= user.username
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
= icon_for_system_note(note) = icon_for_system_note(note)
- else - else
%a.image-diff-avatar-link{ href: user_path(note.author) } %a.image-diff-avatar-link{ href: user_path(note.author) }
= image_tag avatar_icon(note.author), alt: '', class: 'avatar s40' = image_tag avatar_icon_for_user(note.author), alt: '', class: 'avatar s40'
- if note.is_a?(DiffNote) && note.on_image? - if note.is_a?(DiffNote) && note.on_image?
- if show_image_comment_badge && note_counter == 0 - if show_image_comment_badge && note_counter == 0
-# Only show this for the first comment in the discussion -# Only show this for the first comment in the discussion
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
.timeline-icon.hidden-xs.hidden-sm .timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) } %a.author_link{ href: user_path(current_user) }
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40' = image_tag avatar_icon_for_user(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form .timeline-content.timeline-content-form
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete = render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
- elsif !current_user - elsif !current_user
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
.avatar-container.s40 .avatar-container.s40
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
- if project.creator && use_creator_avatar - if project.creator && use_creator_avatar
= image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' = image_tag avatar_icon_for_user(project.creator, 40), class: "avatar s40", alt:''
- else - else
= project_icon(project, alt: '', class: 'avatar project-avatar s40') = project_icon(project, alt: '', class: 'avatar project-avatar s40')
.project-details .project-details
......
- link_project = local_assigns.fetch(:link_project, false) - link_project = local_assigns.fetch(:link_project, false)
%li.snippet-row %li.snippet-row
= image_tag avatar_icon(snippet.author), class: "avatar s40 hidden-xs", alt: '' = image_tag avatar_icon_for_user(snippet.author), class: "avatar s40 hidden-xs", alt: ''
.title .title
= link_to reliable_snippet_path(snippet) do = link_to reliable_snippet_path(snippet) do
......
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
.profile-header .profile-header
.avatar-holder .avatar-holder
= link_to avatar_icon(@user, 400), target: '_blank', rel: 'noopener noreferrer' do = link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
= image_tag avatar_icon(@user, 90), class: "avatar s90", alt: '' = image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: ''
.user-info .user-info
.cover-title .cover-title
......
---
title: Use a user object in ApplicationHelper#avatar_icon where possible to avoid
N+1 queries.
merge_request: 42800
author:
type: performance
---
title: Change SQL for expired artifacts to use new ci_job_artifacts.expire_at
merge_request: 16578
author:
type: performance
---
title: Respect description and visibility when creating project from template
merge_request: 16820
author: George Tsiolis
type: fixed
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class OptimizeCiJobArtifacts < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
# job_id is just here to be a covering index for index only scans
# since we'll almost always be joining against ci_builds on job_id
add_concurrent_index(:ci_job_artifacts, [:expire_at, :job_id])
add_concurrent_index(:ci_builds, [:artifacts_expire_at], where: "artifacts_file <> ''")
end
def down
remove_concurrent_index(:ci_job_artifacts, [:expire_at, :job_id])
remove_concurrent_index(:ci_builds, [:artifacts_expire_at], where: "artifacts_file <> ''")
end
end
...@@ -370,6 +370,7 @@ ActiveRecord::Schema.define(version: 20180208183958) do ...@@ -370,6 +370,7 @@ ActiveRecord::Schema.define(version: 20180208183958) do
t.integer "failure_reason" t.integer "failure_reason"
end end
add_index "ci_builds", ["artifacts_expire_at"], name: "index_ci_builds_on_artifacts_expire_at", where: "(artifacts_file <> ''::text)", using: :btree
add_index "ci_builds", ["auto_canceled_by_id"], name: "index_ci_builds_on_auto_canceled_by_id", using: :btree add_index "ci_builds", ["auto_canceled_by_id"], name: "index_ci_builds_on_auto_canceled_by_id", using: :btree
add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
add_index "ci_builds", ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree add_index "ci_builds", ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree
...@@ -411,6 +412,7 @@ ActiveRecord::Schema.define(version: 20180208183958) do ...@@ -411,6 +412,7 @@ ActiveRecord::Schema.define(version: 20180208183958) do
t.integer "file_store" t.integer "file_store"
end end
add_index "ci_job_artifacts", ["expire_at", "job_id"], name: "index_ci_job_artifacts_on_expire_at_and_job_id", using: :btree
add_index "ci_job_artifacts", ["job_id", "file_type"], name: "index_ci_job_artifacts_on_job_id_and_file_type", unique: true, using: :btree add_index "ci_job_artifacts", ["job_id", "file_type"], name: "index_ci_job_artifacts_on_job_id_and_file_type", unique: true, using: :btree
add_index "ci_job_artifacts", ["project_id"], name: "index_ci_job_artifacts_on_project_id", using: :btree add_index "ci_job_artifacts", ["project_id"], name: "index_ci_job_artifacts_on_project_id", using: :btree
......
# Manage feature flags # Manage feature flags
Starting from GitLab 9.3 we support feature flags via Starting from GitLab 9.3 we support feature flags for features in GitLab via
[Flipper](https://github.com/jnunemaker/flipper/). You should use the `Feature` [Flipper](https://github.com/jnunemaker/flipper/). You should use the `Feature`
class (defined in `lib/feature.rb`) in your code to get, set and list feature class (defined in `lib/feature.rb`) in your code to get, set and list feature
flags. flags.
...@@ -19,3 +19,8 @@ dynamic (querying the DB etc.). ...@@ -19,3 +19,8 @@ dynamic (querying the DB etc.).
Once defined in `lib/feature.rb`, you will be able to activate a Once defined in `lib/feature.rb`, you will be able to activate a
feature for a given feature group via the [`feature_group` param of the features API](../api/features.md#set-or-create-a-feature) feature for a given feature group via the [`feature_group` param of the features API](../api/features.md#set-or-create-a-feature)
## Feature flags for user applications
GitLab does not yet support the use of feature flags in deployed user applications.
You can follow the progress on that [in the issue on our issue tracker](https://gitlab.com/gitlab-org/gitlab-ee/issues/779).
\ No newline at end of file
...@@ -40,37 +40,12 @@ See [Translation guidelines](translation.md). ...@@ -40,37 +40,12 @@ See [Translation guidelines](translation.md).
### Proof reading ### Proof reading
Proof reading helps ensure the accuracy and consistency of translations. Proof reading helps ensure the accuracy and consistency of translations. All
All translations are proof read before being accepted. translations are proof read before being accepted. If a translations requires
If a translations requires changes, you will be notified with a comment explaining why. changes, you will be notified with a comment explaining why.
Community assistance proof reading translations is encouraged and appreciated. See [Proofreading Translations](proofreader.md) for more information on who's
Requests to become a proof reader will be considered on the merits of previous translations. able to proofread and instructions on becoming a proofreader yourself.
- Bulgarian
- Chinese Simplified
- [Huang Tao](https://crowdin.com/profile/htve)
- Chinese Traditional
- [Huang Tao](https://crowdin.com/profile/htve)
- Chinese Traditional, Hong Kong
- [Huang Tao](https://crowdin.com/profile/htve)
- Dutch
- Esperanto
- French
- German
- Italian
- [Paolo Falomo](https://crowdin.com/profile/paolo.falomo)
- Japanese
- Korean
- [Huang Tao](https://crowdin.com/profile/htve)
- Portuguese, Brazilian
- Russian
- [Alexy Lustin](https://crowdin.com/profile/lustin)
- [Nikita Grylov](https://crowdin.com/profile/nixel2007)
- Spanish
- Ukrainian
If you would like to be added as a proof reader, please [open an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues).
## Release ## Release
......
# Proofread Translations
Most translations are contributed, reviewed, and accepted by the community. We
are very appreciative of the work done by translators and proofreaders!
## Proofreaders
- Bulgarian
- Chinese Simplified
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Chinese Traditional
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Chinese Traditional, Hong Kong
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Dutch
- Esperanto
- French
- German
- Italian
- Paolo Falomo - [GitLab](https://gitlab.com/paolofalomo), [Crowdin](https://crowdin.com/profile/paolo.falomo)
- Japanese
- Korean
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Portuguese, Brazilian
- Paulo George Gomes Bezerra - [GitLab](https://gitlab.com/paulobezerra), [Crowdin](https://crowdin.com/profile/paulogomes.rep)
- Russian
- Nikita Grylov - [GitLab](https://gitlab.com/nixel2007), [Crowdin](https://crowdin.com/profile/nixel2007)
- Alexy Lustin - [GitLab](https://gitlab.com/allustin), [Crowdin](https://crowdin.com/profile/lustin)
- Spanish
- Ukrainian
- Volodymyr Sobotovych - [GitLab](https://gitlab.com/wheleph), [Crowdin](https://crowdin.com/profile/wheleph)
- Andrew Vityuk - [GitLab](https://gitlab.com/3_1_3_u), [Crowdin](https://crowdin.com/profile/andruwa13)
## Become a proofreader
> **Note:** Before requesting Proofreader permissions in Crowdin please make
> sure that you have a history of contributing translations to the GitLab
> project.
1. Once your translations have been accepted,
[open a merge request](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/new)
to request Proofreader permissions and add yourself to the list above.
In the merge request description, please include links to any projects you
have previously translated.
1. Your request to become a proofreader will be considered on the merits of
your previous translations.
module Gitlab
module ImportExport
class ProjectCreator
def initialize(namespace_id, current_user, file, project_path)
@namespace_id = namespace_id
@current_user = current_user
@file = file
@project_path = project_path
end
def execute
::Projects::CreateService.new(
@current_user,
name: @project_path,
path: @project_path,
namespace_id: @namespace_id,
import_type: "gitlab_project",
import_source: @file
).execute
end
end
end
end
...@@ -180,8 +180,8 @@ FactoryBot.define do ...@@ -180,8 +180,8 @@ FactoryBot.define do
trait :artifacts do trait :artifacts do
after(:create) do |build| after(:create) do |build|
create(:ci_job_artifact, :archive, job: build) create(:ci_job_artifact, :archive, job: build, expire_at: build.artifacts_expire_at)
create(:ci_job_artifact, :metadata, job: build) create(:ci_job_artifact, :metadata, job: build, expire_at: build.artifacts_expire_at)
build.reload build.reload
end end
end end
......
...@@ -63,13 +63,29 @@ describe ApplicationHelper do ...@@ -63,13 +63,29 @@ describe ApplicationHelper do
end end
end end
describe 'avatar_icon' do describe 'avatar_icon_for' do
let!(:user) { create(:user, avatar: File.open(uploaded_image_temp_path), email: 'bar@example.com') }
let(:email) { 'foo@example.com' }
let!(:another_user) { create(:user, avatar: File.open(uploaded_image_temp_path), email: email) }
it 'prefers the user to retrieve the avatar_url' do
expect(helper.avatar_icon_for(user, email).to_s)
.to eq(user.avatar.url)
end
it 'falls back to email lookup if no user given' do
expect(helper.avatar_icon_for(nil, email).to_s)
.to eq(another_user.avatar.url)
end
end
describe 'avatar_icon_for_email' do
let(:user) { create(:user, avatar: File.open(uploaded_image_temp_path)) } let(:user) { create(:user, avatar: File.open(uploaded_image_temp_path)) }
context 'using an email' do context 'using an email' do
context 'when there is a matching user' do context 'when there is a matching user' do
it 'returns a relative URL for the avatar' do it 'returns a relative URL for the avatar' do
expect(helper.avatar_icon(user.email).to_s) expect(helper.avatar_icon_for_email(user.email).to_s)
.to eq(user.avatar.url) .to eq(user.avatar.url)
end end
end end
...@@ -78,17 +94,37 @@ describe ApplicationHelper do ...@@ -78,17 +94,37 @@ describe ApplicationHelper do
it 'calls gravatar_icon' do it 'calls gravatar_icon' do
expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20, 2) expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20, 2)
helper.avatar_icon('foo@example.com', 20, 2) helper.avatar_icon_for_email('foo@example.com', 20, 2)
end
end
context 'without an email passed' do
it 'calls gravatar_icon' do
expect(helper).to receive(:gravatar_icon).with(nil, 20, 2)
helper.avatar_icon_for_email(nil, 20, 2)
end end
end end
end end
end
describe 'avatar_icon_for_user' do
let(:user) { create(:user, avatar: File.open(uploaded_image_temp_path)) }
describe 'using a user' do context 'with a user object passed' do
it 'returns a relative URL for the avatar' do it 'returns a relative URL for the avatar' do
expect(helper.avatar_icon(user).to_s) expect(helper.avatar_icon_for_user(user).to_s)
.to eq(user.avatar.url) .to eq(user.avatar.url)
end end
end end
context 'without a user object passed' do
it 'calls gravatar_icon' do
expect(helper).to receive(:gravatar_icon).with(nil, 20, 2)
helper.avatar_icon_for_user(nil, 20, 2)
end
end
end end
describe 'gravatar_icon' do describe 'gravatar_icon' do
......
...@@ -29,7 +29,7 @@ describe AvatarsHelper do ...@@ -29,7 +29,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: avatar_icon(user, 16), src: avatar_icon_for_user(user, 16),
data: { container: 'body' }, data: { container: 'body' },
class: 'avatar s16 has-tooltip', class: 'avatar s16 has-tooltip',
title: user.name title: user.name
...@@ -43,7 +43,7 @@ describe AvatarsHelper do ...@@ -43,7 +43,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: avatar_icon(user, 16), src: avatar_icon_for_user(user, 16),
data: { container: 'body' }, data: { container: 'body' },
class: "avatar s16 #{options[:css_class]} has-tooltip", class: "avatar s16 #{options[:css_class]} has-tooltip",
title: user.name title: user.name
...@@ -58,7 +58,7 @@ describe AvatarsHelper do ...@@ -58,7 +58,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: avatar_icon(user, options[:size]), src: avatar_icon_for_user(user, options[:size]),
data: { container: 'body' }, data: { container: 'body' },
class: "avatar s#{options[:size]} has-tooltip", class: "avatar s#{options[:size]} has-tooltip",
title: user.name title: user.name
...@@ -89,7 +89,7 @@ describe AvatarsHelper do ...@@ -89,7 +89,7 @@ describe AvatarsHelper do
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: LazyImageTagHelper.placeholder_image, src: LazyImageTagHelper.placeholder_image,
data: { container: 'body', src: avatar_icon(user, 16) }, data: { container: 'body', src: avatar_icon_for_user(user, 16) },
class: "avatar s16 has-tooltip lazy", class: "avatar s16 has-tooltip lazy",
title: user.name title: user.name
) )
...@@ -104,7 +104,7 @@ describe AvatarsHelper do ...@@ -104,7 +104,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: avatar_icon(user, 16), src: avatar_icon_for_user(user, 16),
data: { container: 'body' }, data: { container: 'body' },
class: "avatar s16 has-tooltip", class: "avatar s16 has-tooltip",
title: user.name title: user.name
...@@ -119,7 +119,7 @@ describe AvatarsHelper do ...@@ -119,7 +119,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: avatar_icon(user, 16), src: avatar_icon_for_user(user, 16),
class: "avatar s16", class: "avatar s16",
title: user.name title: user.name
) )
...@@ -137,7 +137,7 @@ describe AvatarsHelper do ...@@ -137,7 +137,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{user.name}'s avatar", alt: "#{user.name}'s avatar",
src: avatar_icon(user, 16), src: avatar_icon_for_user(user, 16),
data: { container: 'body' }, data: { container: 'body' },
class: "avatar s16 has-tooltip", class: "avatar s16 has-tooltip",
title: user.name title: user.name
...@@ -149,7 +149,7 @@ describe AvatarsHelper do ...@@ -149,7 +149,7 @@ describe AvatarsHelper do
is_expected.to eq tag( is_expected.to eq tag(
:img, :img,
alt: "#{options[:user_name]}'s avatar", alt: "#{options[:user_name]}'s avatar",
src: avatar_icon(options[:user_email], 16), src: avatar_icon_for_email(options[:user_email], 16),
data: { container: 'body' }, data: { container: 'body' },
class: "avatar s16 has-tooltip", class: "avatar s16 has-tooltip",
title: options[:user_name] title: options[:user_name]
......
...@@ -215,7 +215,7 @@ describe ProjectsHelper do ...@@ -215,7 +215,7 @@ describe ProjectsHelper do
let(:expected) { double } let(:expected) { double }
before do before do
expect(helper).to receive(:avatar_icon).with(user, 16).and_return(expected) expect(helper).to receive(:avatar_icon_for_user).with(user, 16).and_return(expected)
end end
it 'returns image tag for member avatar' do it 'returns image tag for member avatar' do
......
...@@ -4,8 +4,10 @@ describe Projects::CreateFromTemplateService do ...@@ -4,8 +4,10 @@ describe Projects::CreateFromTemplateService do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project_params) do let(:project_params) do
{ {
path: user.to_param, path: user.to_param,
template_name: 'rails' template_name: 'rails',
description: 'project description',
visibility_level: Gitlab::VisibilityLevel::PRIVATE
} }
end end
...@@ -22,5 +24,7 @@ describe Projects::CreateFromTemplateService do ...@@ -22,5 +24,7 @@ describe Projects::CreateFromTemplateService do
expect(project).to be_saved expect(project).to be_saved
expect(project.scheduled?).to be(true) expect(project.scheduled?).to be(true)
expect(project.description).to match('project description')
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end 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