Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6d31b8f052
commit
6e3880e2bb
|
@ -0,0 +1,117 @@
|
|||
@import 'framework/variables';
|
||||
|
||||
// Do not use 3-letter hex codes, bgcolor vs css background-color is problematic in emails
|
||||
// See https://stackoverflow.com/questions/28551981/why-are-3-digit-hex-color-code-values-interpreted-differently-in-internet-explor
|
||||
//
|
||||
// stylelint-disable color-hex-length
|
||||
|
||||
$mailer-font: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
$mailer-text-color: #333333;
|
||||
$mailer-bg-color: #fafafa;
|
||||
$mailer-link-color: #3777b0;
|
||||
$mailer-link-muted-color: #333333;
|
||||
$mailer-line-cell-bg-color: #6b4fbb;
|
||||
$mailer-wrapper-cell-bg-color: #ffffff;
|
||||
$mailer-wrapper-cell-border-color: #ededed;
|
||||
$mailer-header-footer-text-color: #5c5c5c;
|
||||
|
||||
body {
|
||||
margin: 0 !important;
|
||||
background-color: $mailer-bg-color;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
min-width: 640px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: $mailer-font;
|
||||
}
|
||||
|
||||
table#body {
|
||||
background-color: $mailer-bg-color;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
min-width: 640px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $mailer-link-color;
|
||||
text-decoration: none;
|
||||
|
||||
&.muted {
|
||||
color: $mailer-link-muted-color;
|
||||
}
|
||||
}
|
||||
|
||||
.highlight {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
tr td {
|
||||
font-family: $mailer-font;
|
||||
}
|
||||
|
||||
tr.line td {
|
||||
font-family: $mailer-font;
|
||||
background-color: $mailer-line-cell-bg-color;
|
||||
height: 4px;
|
||||
font-size: 4px;
|
||||
line-height: 4px;
|
||||
}
|
||||
|
||||
tr.header td,
|
||||
tr.footer td,
|
||||
td.footer-message {
|
||||
font-family: $mailer-font;
|
||||
padding: 25px 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: $mailer-header-footer-text-color;
|
||||
}
|
||||
|
||||
table.wrapper {
|
||||
width: 640px;
|
||||
margin: 0 auto;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
|
||||
td.wrapper-cell {
|
||||
font-family: $mailer-font;
|
||||
background-color: $mailer-wrapper-cell-bg-color;
|
||||
text-align: left;
|
||||
padding: 18px 25px;
|
||||
border: 1px solid $mailer-wrapper-cell-border-color;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
table.content {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
|
||||
td.text-content {
|
||||
font-family: $mailer-font;
|
||||
color: $mailer-text-color;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
padding: 15px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
tr.footer td {
|
||||
img {
|
||||
display: block;
|
||||
margin: 0 auto 1em;
|
||||
}
|
||||
|
||||
.mng-notif-link,
|
||||
.help-link {
|
||||
color: $mailer-link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/* CLIENT-SPECIFIC STYLES */
|
||||
|
||||
// These are client-specific rules, ignore some linting rules
|
||||
//
|
||||
// stylelint-disable property-no-vendor-prefix, property-no-unknown, length-zero-no-unit
|
||||
// scss-lint:disable PropertySpelling, ZeroUnit
|
||||
|
||||
body,
|
||||
table,
|
||||
td,
|
||||
a {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
table,
|
||||
td {
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
}
|
||||
|
||||
img {
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
/* iOS BLUE LINKS */
|
||||
a[x-apple-data-detectors] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
font-size: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
|
||||
/* ANDROID MARGIN HACK */
|
||||
div[style*='margin: 16px 0'] {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 639px) {
|
||||
body,
|
||||
#body {
|
||||
min-width: 320px !important;
|
||||
}
|
||||
|
||||
table.wrapper {
|
||||
width: 100% !important;
|
||||
min-width: 320px !important;
|
||||
}
|
||||
|
||||
table.wrapper td.wrapper-cell {
|
||||
border-left: 0 !important;
|
||||
border-right: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding-left: 10px !important;
|
||||
padding-right: 10px !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -270,7 +270,7 @@
|
|||
}
|
||||
|
||||
.count-badge,
|
||||
.btn {
|
||||
.btn-xs {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
|
|
|
@ -324,6 +324,15 @@ module ApplicationHelper
|
|||
}
|
||||
end
|
||||
|
||||
def asset_to_string(name)
|
||||
app = Rails.application
|
||||
if Rails.configuration.assets.compile
|
||||
app.assets.find_asset(name).to_s
|
||||
else
|
||||
controller.view_context.render(file: File.join('public/assets', app.assets_manifest.assets[name]))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def appearance
|
||||
|
|
|
@ -15,16 +15,18 @@ module Emails
|
|||
|
||||
user = User.find(recipient_id)
|
||||
|
||||
mail(to: user.notification_email_for(notification_group),
|
||||
subject: subject("Request to join the #{member_source.human_name} #{member_source.model_name.singular}"))
|
||||
member_email_with_layout(
|
||||
to: user.notification_email_for(notification_group),
|
||||
subject: subject("Request to join the #{member_source.human_name} #{member_source.model_name.singular}"))
|
||||
end
|
||||
|
||||
def member_access_granted_email(member_source_type, member_id)
|
||||
@member_source_type = member_source_type
|
||||
@member_id = member_id
|
||||
|
||||
mail(to: member.user.notification_email_for(notification_group),
|
||||
subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was granted"))
|
||||
member_email_with_layout(
|
||||
to: member.user.notification_email_for(notification_group),
|
||||
subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was granted"))
|
||||
end
|
||||
|
||||
def member_access_denied_email(member_source_type, source_id, user_id)
|
||||
|
@ -33,8 +35,9 @@ module Emails
|
|||
|
||||
user = User.find(user_id)
|
||||
|
||||
mail(to: user.notification_email_for(notification_group),
|
||||
subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was denied"))
|
||||
member_email_with_layout(
|
||||
to: user.notification_email_for(notification_group),
|
||||
subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was denied"))
|
||||
end
|
||||
|
||||
def member_invited_email(member_source_type, member_id, token)
|
||||
|
@ -42,8 +45,9 @@ module Emails
|
|||
@member_id = member_id
|
||||
@token = token
|
||||
|
||||
mail(to: member.invite_email,
|
||||
subject: subject("Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}"))
|
||||
member_email_with_layout(
|
||||
to: member.invite_email,
|
||||
subject: subject("Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}"))
|
||||
end
|
||||
|
||||
def member_invite_accepted_email(member_source_type, member_id)
|
||||
|
@ -51,8 +55,9 @@ module Emails
|
|||
@member_id = member_id
|
||||
return unless member.created_by
|
||||
|
||||
mail(to: member.created_by.notification_email_for(notification_group),
|
||||
subject: subject('Invitation accepted'))
|
||||
member_email_with_layout(
|
||||
to: member.created_by.notification_email_for(notification_group),
|
||||
subject: subject('Invitation accepted'))
|
||||
end
|
||||
|
||||
def member_invite_declined_email(member_source_type, source_id, invite_email, created_by_id)
|
||||
|
@ -64,8 +69,9 @@ module Emails
|
|||
|
||||
user = User.find(created_by_id)
|
||||
|
||||
mail(to: user.notification_email_for(notification_group),
|
||||
subject: subject('Invitation declined'))
|
||||
member_email_with_layout(
|
||||
to: user.notification_email_for(notification_group),
|
||||
subject: subject('Invitation declined'))
|
||||
end
|
||||
|
||||
def member
|
||||
|
@ -85,5 +91,12 @@ module Emails
|
|||
def member_source_class
|
||||
@member_source_type.classify.constantize
|
||||
end
|
||||
|
||||
def member_email_with_layout(to:, subject:)
|
||||
mail(to: to, subject: subject) do |format|
|
||||
format.html { render layout: 'mailer' }
|
||||
format.text { render layout: 'mailer' }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,12 +18,11 @@ module Emails
|
|||
@merge_request = pipeline.all_merge_requests.first
|
||||
add_headers
|
||||
|
||||
# We use bcc here because we don't want to generate this emails for a
|
||||
# We use bcc here because we don't want to generate these emails for a
|
||||
# thousand times. This could be potentially expensive in a loop, and
|
||||
# recipients would contain all project watchers so it could be a lot.
|
||||
mail(bcc: recipients,
|
||||
subject: pipeline_subject(status),
|
||||
skip_premailer: true) do |format|
|
||||
subject: pipeline_subject(status)) do |format|
|
||||
format.html { render layout: 'mailer' }
|
||||
format.text { render layout: 'mailer' }
|
||||
end
|
||||
|
|
|
@ -21,7 +21,13 @@ module Emails
|
|||
private
|
||||
|
||||
def release_email_subject
|
||||
release_info = [@release.name, @release.tag].select(&:presence).join(' - ')
|
||||
release_info =
|
||||
if @release.name == @release.tag
|
||||
@release.tag
|
||||
else
|
||||
[@release.name, @release.tag].select(&:presence).join(' - ')
|
||||
end
|
||||
|
||||
"New release: #{release_info}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -77,7 +77,7 @@ class NotifyPreview < ActionMailer::Preview
|
|||
end
|
||||
|
||||
def import_issues_csv_email
|
||||
Notify.import_issues_csv_email(user, project, { success: 3, errors: [5, 6, 7], valid_file: true })
|
||||
Notify.import_issues_csv_email(user.id, project.id, { success: 3, errors: [5, 6, 7], valid_file: true })
|
||||
end
|
||||
|
||||
def closed_merge_request_email
|
||||
|
@ -109,11 +109,11 @@ class NotifyPreview < ActionMailer::Preview
|
|||
end
|
||||
|
||||
def member_access_requested_email
|
||||
Notify.member_access_requested_email('group', user.id, user.id).message
|
||||
Notify.member_access_requested_email(member.source_type, member.id, user.id).message
|
||||
end
|
||||
|
||||
def member_invite_accepted_email
|
||||
Notify.member_invite_accepted_email('project', user.id).message
|
||||
Notify.member_invite_accepted_email(member.source_type, member.id).message
|
||||
end
|
||||
|
||||
def member_invite_declined_email
|
||||
|
|
|
@ -69,6 +69,10 @@ class Release < ApplicationRecord
|
|||
released_at.present? && released_at > Time.zone.now
|
||||
end
|
||||
|
||||
def name
|
||||
self.read_attribute(:name) || tag
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def actual_sha
|
||||
|
|
|
@ -1,80 +1,48 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
%html{ lang: "en" }
|
||||
%head
|
||||
%meta{ content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type" }/
|
||||
%meta{ content: "width=device-width, initial-scale=1", name: "viewport" }/
|
||||
%meta{ content: "IE=edge", "http-equiv" => "X-UA-Compatible" }/
|
||||
%title= message.subject
|
||||
:css
|
||||
/* CLIENT-SPECIFIC STYLES */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; }
|
||||
.hidden {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
/* iOS BLUE LINKS */
|
||||
a[x-apple-data-detectors] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
font-size: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
-# Avoid premailer processing of client-specific styles (@media tag not supported)
|
||||
-# We need to inline the contents here because mail clients (e.g. iOS Mail, Outlook)
|
||||
-# do not support linked stylesheets.
|
||||
%style{ type: 'text/css', 'data-premailer': 'ignore' }
|
||||
= asset_to_string('mailer_client_specific.css').html_safe
|
||||
|
||||
/* ANDROID MARGIN HACK */
|
||||
body { margin:0 !important; }
|
||||
div[style*="margin: 16px 0"] { margin:0 !important; }
|
||||
|
||||
@media only screen and (max-width: 639px) {
|
||||
body, #body {
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper {
|
||||
width: 100% !important;
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper > tbody > tr > td {
|
||||
border-left: 0 !important;
|
||||
border-right: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding-left: 10px !important;
|
||||
padding-right: 10px !important;
|
||||
}
|
||||
}
|
||||
%body{ style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;height:100%;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table#body{ border: "0", cellpadding: "0", cellspacing: "0", style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;" }
|
||||
= stylesheet_link_tag 'mailer.css'
|
||||
%body
|
||||
%table#body{ border: "0", cellpadding: "0", cellspacing: "0" }
|
||||
%tbody
|
||||
%tr.line
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#6b4fbb;height:4px;font-size:4px;line-height:4px;" }
|
||||
%td
|
||||
%tr.header
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%td
|
||||
= html_header_message
|
||||
= header_logo
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:640px;margin:0 auto;border-collapse:separate;border-spacing:0;" }
|
||||
%td
|
||||
%table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#ffffff;text-align:left;padding:18px 25px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.content{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;border-collapse:separate;border-spacing:0;" }
|
||||
%td.wrapper-cell
|
||||
%table.content{ border: "0", cellpadding: "0", cellspacing: "0" }
|
||||
%tbody
|
||||
= yield
|
||||
|
||||
= render_if_exists 'layouts/mailer/additional_text'
|
||||
|
||||
%tr.footer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%img{ alt: "GitLab", height: "33", src: image_url('mailers/gitlab_footer_logo.gif'), style: "display:block;margin:0 auto 1em;", width: "90" }/
|
||||
%td
|
||||
%img{ alt: "GitLab", height: "33", width: "90", src: image_url('mailers/gitlab_footer_logo.gif') }
|
||||
%div
|
||||
- manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, style: "color:#3777b0;text-decoration:none;")
|
||||
- help_link = link_to(_("Help"), help_url, style: "color:#3777b0;text-decoration:none;")
|
||||
- manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, class: 'mng-notif-link')
|
||||
- help_link = link_to(_("Help"), help_url, class: 'help-link')
|
||||
= _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} · %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
|
||||
|
||||
= yield :additional_footer
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%td.footer-message
|
||||
= html_footer_message
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
%p
|
||||
Your request to join the
|
||||
#{link_to member_source.human_name, member_source.web_url} #{member_source.model_name.singular}
|
||||
has been denied.
|
||||
%tr
|
||||
%td.text-content
|
||||
%p
|
||||
Your request to join the
|
||||
#{link_to member_source.human_name, member_source.web_url, class: :highlight} #{member_source.model_name.singular}
|
||||
has been #{content_tag :span, 'denied', class: :highlight}.
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
- link_end = '</a>'.html_safe
|
||||
- source_type = member_source.model_name.singular
|
||||
- leave_link = polymorphic_url([member_source], leave: 1)
|
||||
- source_link = link_to(member_source.human_name, member_source.web_url, target: '_blank', rel: 'noopener noreferrer')
|
||||
- source_link = link_to(member_source.human_name, member_source.web_url, target: '_blank', rel: 'noopener noreferrer', class: :highlight)
|
||||
- access_level = content_tag(:span, member.human_access, class: :highlight)
|
||||
|
||||
%tr
|
||||
%td.text-content
|
||||
%p
|
||||
= _('You have been granted %{access_level} access to the %{source_link} %{source_type}.').html_safe % { access_level: access_level, source_link: source_link, source_type: source_type }
|
||||
%p
|
||||
- leave_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: leave_link }
|
||||
= _('If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}.').html_safe % { source_type: source_type, leave_link_start: leave_link_start, link_end: link_end }
|
||||
|
||||
%p
|
||||
= _('You have been granted %{access_level} access to the %{source_link} %{source_type}.').html_safe % { access_level: member.human_access, source_link: source_link, source_type: source_type }
|
||||
%p
|
||||
- leave_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: leave_link }
|
||||
= _('If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}.').html_safe % { source_type: source_type, leave_link_start: leave_link_start, link_end: link_end }
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
%p
|
||||
#{link_to member.user.name, member.user} requested #{member.human_access}
|
||||
access to the #{link_to member_source.human_name, polymorphic_url([member_source, :members])} #{member_source.model_name.singular}.
|
||||
%tr
|
||||
%td.text-content
|
||||
%p
|
||||
#{link_to member.user.name, member.user, class: :highlight} requested #{content_tag :span, member.human_access, class: :highlight}
|
||||
access to the #{link_to member_source.human_name, polymorphic_url([member_source, :members]), class: :highlight} #{member_source.model_name.singular}.
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
%p
|
||||
#{member.invite_email}, now known as
|
||||
#{link_to member.user.name, user_url(member.user)},
|
||||
has accepted your invitation to join the
|
||||
#{link_to member_source.human_name, member_source.web_url} #{member_source.model_name.singular}.
|
||||
%tr
|
||||
%td.text-content
|
||||
%p
|
||||
#{content_tag :span, member.invite_email, class: :highlight}, now known as
|
||||
#{link_to member.user.name, user_url(member.user)},
|
||||
has accepted your invitation to join the
|
||||
#{link_to member_source.human_name, member_source.web_url, class: :highlight} #{member_source.model_name.singular}.
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
%p
|
||||
#{@invite_email}
|
||||
has declined your invitation to join the
|
||||
#{link_to member_source.human_name, member_source.web_url} #{member_source.model_name.singular}.
|
||||
%tr
|
||||
%td.text-content
|
||||
%p
|
||||
#{content_tag :span, @invite_email, class: :highlight}
|
||||
has #{content_tag :span, 'declined', class: :highlight} your invitation to join the
|
||||
#{link_to member_source.human_name, member_source.web_url, class: :highlight} #{member_source.model_name.singular}.
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
%p
|
||||
You have been invited
|
||||
- if member.created_by
|
||||
by
|
||||
= link_to member.created_by.name, user_url(member.created_by)
|
||||
to join the
|
||||
= link_to member_source.human_name, member_source.public? ? member_source.web_url : invite_url(@token)
|
||||
#{member_source.model_name.singular} as #{member.human_access}.
|
||||
%tr
|
||||
%td.text-content
|
||||
%p
|
||||
You have been invited
|
||||
- if member.created_by
|
||||
by
|
||||
= link_to member.created_by.name, user_url(member.created_by)
|
||||
to join the
|
||||
= link_to member_source.human_name, member_source.public? ? member_source.web_url : invite_url(@token), class: :highlight
|
||||
#{member_source.model_name.singular} as #{content_tag :span, member.human_access, class: :highlight}.
|
||||
|
||||
%p
|
||||
= link_to 'Accept invitation', invite_url(@token)
|
||||
or
|
||||
= link_to 'decline', decline_invite_url(@token)
|
||||
|
||||
%p
|
||||
= link_to 'Accept invitation', invite_url(@token)
|
||||
or
|
||||
= link_to 'decline', decline_invite_url(@token)
|
||||
|
|
|
@ -5,18 +5,19 @@
|
|||
.file-actions
|
||||
= render 'projects/blob/viewer_switcher', blob: blob unless blame
|
||||
|
||||
.btn-group{ role: "group" }<
|
||||
= edit_blob_button
|
||||
= ide_edit_button
|
||||
.btn-group{ role: "group" }<
|
||||
= render_if_exists 'projects/blob/header_file_locks_link'
|
||||
- if current_user
|
||||
= replace_blob_link
|
||||
= delete_blob_link
|
||||
.btn-group{ role: "group" }<
|
||||
= copy_blob_source_button(blob) unless blame
|
||||
= open_raw_blob_button(blob)
|
||||
= download_blob_button(blob)
|
||||
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
|
||||
.btn-group{ role: "group" }<
|
||||
= render_if_exists 'projects/blob/header_file_locks_link'
|
||||
= edit_blob_button
|
||||
= ide_edit_button
|
||||
- if current_user
|
||||
= replace_blob_link
|
||||
= delete_blob_link
|
||||
|
||||
= render 'projects/fork_suggestion'
|
||||
= render_if_exists 'projects/blob/header_file_locks', project: @project, path: @path
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Made `name` optional parameter of Release entity
|
||||
merge_request: 19705
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Revert btn-xs styling in projects scss
|
||||
merge_request: 19640
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Visual design for edit buttons in blob view
|
||||
merge_request: 19932
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Unify html email layout for member html emails
|
||||
merge_request: 17699
|
||||
author: Diego Louzán
|
||||
type: added
|
|
@ -157,6 +157,8 @@ module Gitlab
|
|||
config.assets.paths << "#{config.root}/vendor/assets/fonts"
|
||||
|
||||
config.assets.precompile << "print.css"
|
||||
config.assets.precompile << "mailer.css"
|
||||
config.assets.precompile << "mailer_client_specific.css"
|
||||
config.assets.precompile << "notify.css"
|
||||
config.assets.precompile << "mailers/*.css"
|
||||
config.assets.precompile << "page_bundles/ide.css"
|
||||
|
|
|
@ -303,7 +303,7 @@ POST /projects/:id/releases
|
|||
| Attribute | Type | Required | Description |
|
||||
| -------------------| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
|
||||
| `name` | string | yes | The release name. |
|
||||
| `name` | string | no | The release name. |
|
||||
| `tag_name` | string | yes | The tag where the release will be created from. |
|
||||
| `description` | string | yes | The description of the release. You can use [markdown](../../user/markdown.md). |
|
||||
| `ref` | string | yes, if `tag_name` doesn't exist | If `tag_name` doesn't exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. |
|
||||
|
|
|
@ -38,7 +38,7 @@ that's tested and deployed on every push to the `master` branch of the [codebase
|
|||
This will also provide
|
||||
boilerplate code for starting a browser-based game with the following components:
|
||||
|
||||
- Written in [Typescript](https://www.typescriptlang.org/) and [PhaserJs](https://phaser.io)
|
||||
- Written in [TypeScript](https://www.typescriptlang.org/) and [PhaserJs](https://phaser.io)
|
||||
- Building, running, and testing with [Gulp](https://gulpjs.com)
|
||||
- Unit tests with [Chai](https://www.chaijs.com) and [Mocha](https://mochajs.org/)
|
||||
- CI/CD with GitLab
|
||||
|
@ -508,7 +508,7 @@ deploy:
|
|||
## Conclusion
|
||||
|
||||
Within the [demo repository](https://gitlab.com/blitzgren/gitlab-game-demo) you can also find a handful of boilerplate code to get
|
||||
[Typescript](https://www.typescriptlang.org/), [Mocha](https://mochajs.org/), [Gulp](https://gulpjs.com/) and [Phaser](https://phaser.io) all playing
|
||||
[TypeScript](https://www.typescriptlang.org/), [Mocha](https://mochajs.org/), [Gulp](https://gulpjs.com/) and [Phaser](https://phaser.io) all playing
|
||||
together nicely with GitLab CI/CD, which is the result of lessons learned while making [Dark Nova](https://www.darknova.io).
|
||||
Using a combination of free and open source software, we have a full CI/CD pipeline, a game foundation,
|
||||
and unit tests, all running and deployed at every push to master - with shockingly little code.
|
||||
|
|
|
@ -268,7 +268,7 @@ Each issue scheduled for the current milestone should be labeled ~Deliverable
|
|||
or ~"Stretch". Any open issue for a previous milestone should be labeled
|
||||
~"Next Patch Release", or otherwise rescheduled to a different milestone.
|
||||
|
||||
#### Priority labels
|
||||
### Priority labels
|
||||
|
||||
Priority labels help us define the time a ~bug fix should be completed. Priority determines how quickly the defect turnaround time must be.
|
||||
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
|
||||
|
|
|
@ -25,7 +25,7 @@ SAST supports the following official analyzers:
|
|||
- [`security-code-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) (Security Code Scan (.NET))
|
||||
- [`sobelow`](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow) (Sobelow (Elixir Phoenix))
|
||||
- [`spotbugs`](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) (SpotBugs with the Find Sec Bugs plugin (Ant, Gradle and wrapper, Grails, Maven and wrapper, SBT))
|
||||
- [`tslint`](https://gitlab.com/gitlab-org/security-products/analyzers/tslint) (TSLint (Typescript))
|
||||
- [`tslint`](https://gitlab.com/gitlab-org/security-products/analyzers/tslint) (TSLint (TypeScript))
|
||||
|
||||
The analyzers are published as Docker images that SAST will use to launch
|
||||
dedicated containers for each analysis.
|
||||
|
|
|
@ -78,7 +78,7 @@ The following table shows which languages, package managers and frameworks are s
|
|||
| Python ([pip](https://pip.pypa.io/en/stable/)) | [bandit](https://github.com/PyCQA/bandit) | 10.3 |
|
||||
| Ruby on Rails | [brakeman](https://brakemanscanner.org) | 10.3 |
|
||||
| Scala ([Ant](https://ant.apache.org/), [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) and [SBT](https://www.scala-sbt.org/)) | [SpotBugs](https://spotbugs.github.io/) with the [find-sec-bugs](https://find-sec-bugs.github.io/) plugin | 11.0 (SBT) & 11.9 (Ant, Gradle, Maven) |
|
||||
| Typescript | [TSLint config security](https://github.com/webschik/tslint-config-security/) | 11.9 |
|
||||
| TypeScript | [TSLint config security](https://github.com/webschik/tslint-config-security/) | 11.9 |
|
||||
|
||||
NOTE: **Note:**
|
||||
The Java analyzers can also be used for variants like the
|
||||
|
|
|
@ -1299,7 +1299,9 @@ module API
|
|||
class Release < Grape::Entity
|
||||
include ::API::Helpers::Presentable
|
||||
|
||||
expose :name
|
||||
expose :name do |release, _|
|
||||
can_download_code? ? release.name : "Release-#{release.id}"
|
||||
end
|
||||
expose :tag, as: :tag_name, if: ->(_, _) { can_download_code? }
|
||||
expose :description
|
||||
expose :description_html do |entity|
|
||||
|
|
|
@ -45,7 +45,7 @@ module API
|
|||
end
|
||||
params do
|
||||
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
|
||||
requires :name, type: String, desc: 'The name of the release'
|
||||
optional :name, type: String, desc: 'The name of the release'
|
||||
requires :description, type: String, desc: 'The release notes'
|
||||
optional :ref, type: String, desc: 'The commit sha or branch name'
|
||||
optional :assets, type: Hash do
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"type": "object",
|
||||
"required": ["name", "tag_name"],
|
||||
"required": ["tag_name", "description"],
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"tag_name": { "type": "string" },
|
||||
"ref": { "type": "string "},
|
||||
"description": { "type": "string" },
|
||||
"description_html": { "type": "string" },
|
||||
"created_at": { "type": "date" },
|
||||
|
|
|
@ -18,6 +18,7 @@ describe Emails::Releases do
|
|||
|
||||
context 'when the release has a name' do
|
||||
it 'shows the correct subject' do
|
||||
release.name = 'beta-1'
|
||||
expected_subject = "#{release.project.name} | New release: #{release.name} - #{release.tag}"
|
||||
is_expected.to have_subject(expected_subject)
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ describe Evidence do
|
|||
let(:release) { create(:release, project: project, name: nil) }
|
||||
|
||||
it 'creates a valid JSON object' do
|
||||
expect(release.name).to be_nil
|
||||
expect(release.name).to eq(release.tag)
|
||||
expect(summary_json).to match_schema(schema_file)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,7 +34,7 @@ RSpec.describe Release do
|
|||
|
||||
expect(existing_release_without_name).to be_valid
|
||||
expect(existing_release_without_name.description).to eq("change")
|
||||
expect(existing_release_without_name.name).to be_nil
|
||||
expect(existing_release_without_name.name).not_to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -129,4 +129,16 @@ RSpec.describe Release do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#name' do
|
||||
context 'name is nil' do
|
||||
before do
|
||||
release.update(name: nil)
|
||||
end
|
||||
|
||||
it 'returns tag' do
|
||||
expect(release.name).to eq(release.tag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue