Commit 3434b923 authored by Rémy Coutable's avatar Rémy Coutable

Merge remote-tracking branch 'origin/master' into 8-6-stable

parents 51807dca ab9970e2
...@@ -25,6 +25,7 @@ v 8.6.0 (unreleased) ...@@ -25,6 +25,7 @@ v 8.6.0 (unreleased)
- Rewrite logo to simplify SVG code (Sean Lang) - Rewrite logo to simplify SVG code (Sean Lang)
- Allow to use YAML anchors when parsing the `.gitlab-ci.yml` (Pascal Bach) - Allow to use YAML anchors when parsing the `.gitlab-ci.yml` (Pascal Bach)
- Ignore jobs that start with `.` (hidden jobs) - Ignore jobs that start with `.` (hidden jobs)
- Hide builds from project's settings when the feature is disabled
- Allow to pass name of created artifacts archive in `.gitlab-ci.yml` - Allow to pass name of created artifacts archive in `.gitlab-ci.yml`
- Refactor and greatly improve search performance - Refactor and greatly improve search performance
- Add support for cross-project label references - Add support for cross-project label references
...@@ -59,6 +60,7 @@ v 8.5.5 ...@@ -59,6 +60,7 @@ v 8.5.5
- Fix pagination for filtered dashboard and explore pages - Fix pagination for filtered dashboard and explore pages
- Fix "Show all" link behavior - Fix "Show all" link behavior
- Add #upcoming filter to Milestone filter (Tiago Botelho) - Add #upcoming filter to Milestone filter (Tiago Botelho)
- HTTP error pages work independently from location and config (Artem Sidorenko)
v 8.5.4 v 8.5.4
- Do not cache requests for badges (including builds badge) - Do not cache requests for badges (including builds badge)
......
...@@ -3,3 +3,16 @@ class @ProjectNew ...@@ -3,3 +3,16 @@ class @ProjectNew
$('.project-edit-container').on 'ajax:before', => $('.project-edit-container').on 'ajax:before', =>
$('.project-edit-container').hide() $('.project-edit-container').hide()
$('.save-project-loader').show() $('.save-project-loader').show()
@toggleSettings()
@toggleSettingsOnclick()
toggleSettings: ->
checked = $("#project_builds_enabled").prop("checked")
if checked
$('.builds-feature').show()
else
$('.builds-feature').hide()
toggleSettingsOnclick: ->
$("#project_builds_enabled").on 'click', @toggleSettings
...@@ -28,10 +28,6 @@ ...@@ -28,10 +28,6 @@
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
color: $gl-gray; color: $gl-gray;
a {
color: $md-link-color;
}
&.oneline-block { &.oneline-block {
line-height: 42px; line-height: 42px;
} }
......
...@@ -20,6 +20,23 @@ module IssuablesHelper ...@@ -20,6 +20,23 @@ module IssuablesHelper
base_issuable_scope(issuable).where('iid < ?', issuable.iid).first base_issuable_scope(issuable).where('iid < ?', issuable.iid).first
end end
def user_dropdown_label(user_id, default_label)
return "Unassigned" if user_id == "0"
if @project
member = @project.team.find_member(user_id)
user = member.user if member
else
user = User.find_by(id: user_id)
end
if user
user.name
else
default_label
end
end
private private
def sidebar_gutter_collapsed? def sidebar_gutter_collapsed?
......
...@@ -571,10 +571,7 @@ class Project < ActiveRecord::Base ...@@ -571,10 +571,7 @@ class Project < ActiveRecord::Base
end end
def avatar_in_git def avatar_in_git
@avatar_file ||= 'logo.png' if repository.blob_at_branch('master', 'logo.png') repository.avatar
@avatar_file ||= 'logo.jpg' if repository.blob_at_branch('master', 'logo.jpg')
@avatar_file ||= 'logo.gif' if repository.blob_at_branch('master', 'logo.gif')
@avatar_file
end end
def avatar_url def avatar_url
......
...@@ -3,6 +3,10 @@ require 'securerandom' ...@@ -3,6 +3,10 @@ require 'securerandom'
class Repository class Repository
class CommitError < StandardError; end class CommitError < StandardError; end
# Files to use as a project avatar in case no avatar was uploaded via the web
# UI.
AVATAR_FILES = %w{logo.png logo.jpg logo.gif}
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
attr_accessor :path_with_namespace, :project attr_accessor :path_with_namespace, :project
...@@ -241,12 +245,13 @@ class Repository ...@@ -241,12 +245,13 @@ class Repository
@branches = nil @branches = nil
end end
def expire_cache(branch_name = nil) def expire_cache(branch_name = nil, revision = nil)
cache_keys.each do |key| cache_keys.each do |key|
cache.expire(key) cache.expire(key)
end end
expire_branch_cache(branch_name) expire_branch_cache(branch_name)
expire_avatar_cache(branch_name, revision)
# This ensures this particular cache is flushed after the first commit to a # This ensures this particular cache is flushed after the first commit to a
# new repository. # new repository.
...@@ -316,6 +321,23 @@ class Repository ...@@ -316,6 +321,23 @@ class Repository
cache.expire(:branch_names) cache.expire(:branch_names)
end end
def expire_avatar_cache(branch_name = nil, revision = nil)
# Avatars are pulled from the default branch, thus if somebody pushes to a
# different branch there's no need to expire anything.
return if branch_name && branch_name != root_ref
# We don't want to flush the cache if the commit didn't actually make any
# changes to any of the possible avatar files.
if revision && commit = self.commit(revision)
return unless commit.diffs.
any? { |diff| AVATAR_FILES.include?(diff.new_path) }
end
cache.expire(:avatar)
@avatar = nil
end
# Runs code just before a repository is deleted. # Runs code just before a repository is deleted.
def before_delete def before_delete
expire_cache if exists? expire_cache if exists?
...@@ -350,8 +372,8 @@ class Repository ...@@ -350,8 +372,8 @@ class Repository
end end
# Runs code after a new commit has been pushed. # Runs code after a new commit has been pushed.
def after_push_commit(branch_name) def after_push_commit(branch_name, revision)
expire_cache(branch_name) expire_cache(branch_name, revision)
end end
# Runs code after a new branch has been created. # Runs code after a new branch has been created.
...@@ -857,6 +879,14 @@ class Repository ...@@ -857,6 +879,14 @@ class Repository
end end
end end
def avatar
@avatar ||= cache.fetch(:avatar) do
AVATAR_FILES.find do |file|
blob_at_branch('master', file)
end
end
end
private private
def cache def cache
......
...@@ -17,7 +17,7 @@ class GitPushService < BaseService ...@@ -17,7 +17,7 @@ class GitPushService < BaseService
# 6. Checks if the project's main language has changed # 6. Checks if the project's main language has changed
# #
def execute def execute
@project.repository.after_push_commit(branch_name) @project.repository.after_push_commit(branch_name, params[:newrev])
if push_remove_branch? if push_remove_branch?
@project.repository.after_remove_branch @project.repository.after_remove_branch
......
%fieldset.builds-feature
%legend
Builds:
.form-group
.col-sm-offset-2.col-sm-10
%p Get recent application code using the following command:
.radio
= f.label :build_allow_git_fetch_false do
= f.radio_button :build_allow_git_fetch, 'false'
%strong git clone
%br
%span.descr Slower but makes sure you have a clean dir before every build
.radio
= f.label :build_allow_git_fetch_true do
= f.radio_button :build_allow_git_fetch, 'true'
%strong git fetch
%br
%span.descr Faster
.form-group
= f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label'
.col-sm-10
= f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
%p.help-block per build in minutes
.form-group
= f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label'
.col-sm-10
.input-group
%span.input-group-addon /
= f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
%span.input-group-addon /
%p.help-block
We will use this regular expression to find test coverage output in build trace.
Leave blank if you want to disable this feature
.bs-callout.bs-callout-info
%p Below are examples of regex for existing tools:
%ul
%li
Simplecov (Ruby) -
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
%code \d+\%\s*$
%li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :public_builds do
= f.check_box :public_builds
%strong Public builds
.help-block Allow everyone to access builds for Public and Internal projects
.form-group
= f.label :runners_token, "Runners token", class: 'control-label'
.col-sm-10
= f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
%p.help-block The secure token used to checkout project.
...@@ -84,6 +84,8 @@ ...@@ -84,6 +84,8 @@
%br %br
%span.descr Share code pastes with others out of git repository %span.descr Share code pastes with others out of git repository
= render 'builds_settings', f: f
%fieldset.features %fieldset.features
%legend %legend
Project avatar: Project avatar:
...@@ -110,69 +112,6 @@ ...@@ -110,69 +112,6 @@
%hr %hr
= link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" = link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
%fieldset.features
%legend
Continuous Integration
.form-group
.col-sm-offset-2.col-sm-10
%p Get recent application code using the following command:
.radio
= f.label :build_allow_git_fetch_false do
= f.radio_button :build_allow_git_fetch, 'false'
%strong git clone
%br
%span.descr Slower but makes sure you have a clean dir before every build
.radio
= f.label :build_allow_git_fetch_true do
= f.radio_button :build_allow_git_fetch, 'true'
%strong git fetch
%br
%span.descr Faster
.form-group
= f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label'
.col-sm-10
= f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
%p.help-block per build in minutes
.form-group
= f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label'
.col-sm-10
.input-group
%span.input-group-addon /
= f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
%span.input-group-addon /
%p.help-block
We will use this regular expression to find test coverage output in build trace.
Leave blank if you want to disable this feature
.bs-callout.bs-callout-info
%p Below are examples of regex for existing tools:
%ul
%li
Simplecov (Ruby) -
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
%code \d+\%\s*$
%li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :public_builds do
= f.check_box :public_builds
%strong Public builds
.help-block Allow everyone to access builds for Public and Internal projects
%fieldset.features
%legend
Advanced settings
.form-group
= f.label :runners_token, "CI token", class: 'control-label'
.col-sm-10
= f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
%p.help-block The secure token used to checkout project.
.form-actions .form-actions
= f.submit 'Save changes', class: "btn btn-save" = f.submit 'Save changes', class: "btn btn-save"
......
...@@ -9,19 +9,19 @@ ...@@ -9,19 +9,19 @@
.filter-item.inline .filter-item.inline
- if params[:author_id] - if params[:author_id]
= hidden_field_tag(:author_id, params[:author_id]) = hidden_field_tag(:author_id, params[:author_id])
= dropdown_tag("Author", options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author", = dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author",
placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id" } }) placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id" } })
.filter-item.inline .filter-item.inline
- if params[:assignee_id] - if params[:assignee_id]
= hidden_field_tag(:assignee_id, params[:assignee_id]) = hidden_field_tag(:assignee_id, params[:assignee_id])
= dropdown_tag("Assignee", options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee", = dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee",
placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id" } }) placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id" } })
.filter-item.inline.milestone-filter .filter-item.inline.milestone-filter
- if params[:milestone_title] - if params[:milestone_title]
= hidden_field_tag(:milestone_title, params[:milestone_title]) = hidden_field_tag(:milestone_title, params[:milestone_title])
= dropdown_tag("Milestone", options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable", = dropdown_tag(h(params[:milestone_name] || "Milestone"), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
placeholder: "Search milestones", footer_content: true, data: { show_no: true, show_any: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: (@project.id if @project), milestones: (namespace_project_milestones_path(@project.namespace, @project, :js) if @project) } }) do placeholder: "Search milestones", footer_content: true, data: { show_no: true, show_any: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: (@project.id if @project), milestones: (namespace_project_milestones_path(@project.namespace, @project, :js) if @project) } }) do
- if @project - if @project
%ul.dropdown-footer-list %ul.dropdown-footer-list
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
.dropdown .dropdown
%button.dropdown-menu-toggle.js-label-select.js-filter-submit{type: "button", data: {toggle: "dropdown", field_name: "label_name", show_no: "true", show_any: "true", selected: params[:label_name], project_id: (@project.id if @project), labels: (namespace_project_labels_path(@project.namespace, @project, :js) if @project)}} %button.dropdown-menu-toggle.js-label-select.js-filter-submit{type: "button", data: {toggle: "dropdown", field_name: "label_name", show_no: "true", show_any: "true", selected: params[:label_name], project_id: (@project.id if @project), labels: (namespace_project_labels_path(@project.namespace, @project, :js) if @project)}}
%span.dropdown-toggle-text %span.dropdown-toggle-text
Label = h(params[:label_name] || "Label")
= icon('chevron-down') = icon('chevron-down')
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
.dropdown-page-one .dropdown-page-one
......
...@@ -30,7 +30,6 @@ server { ...@@ -30,7 +30,6 @@ server {
listen [::]:80 default_server; listen [::]:80 default_server;
server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice server_tokens off; ## Don't show the nginx version number, a security best practice
root /home/git/gitlab/public;
## See app/controllers/application_controller.rb for headers set ## See app/controllers/application_controller.rb for headers set
...@@ -57,4 +56,14 @@ server { ...@@ -57,4 +56,14 @@ server {
proxy_pass http://gitlab-workhorse; proxy_pass http://gitlab-workhorse;
} }
error_page 404 /404.html;
error_page 422 /422.html;
error_page 500 /500.html;
error_page 502 /502.html;
location ~ ^/(404|422|500|502)\.html$ {
root /home/git/gitlab/public;
internal;
}
} }
...@@ -45,7 +45,6 @@ server { ...@@ -45,7 +45,6 @@ server {
listen [::]:443 ipv6only=on ssl default_server; listen [::]:443 ipv6only=on ssl default_server;
server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice server_tokens off; ## Don't show the nginx version number, a security best practice
root /home/git/gitlab/public;
## Strong SSL Security ## Strong SSL Security
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/ ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
...@@ -101,4 +100,13 @@ server { ...@@ -101,4 +100,13 @@ server {
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://gitlab-workhorse; proxy_pass http://gitlab-workhorse;
} }
error_page 404 /404.html;
error_page 422 /422.html;
error_page 500 /500.html;
error_page 502 /502.html;
location ~ ^/(404|422|500|502)\.html$ {
root /home/git/gitlab/public;
internal;
}
} }
...@@ -2,11 +2,51 @@ ...@@ -2,11 +2,51 @@
<html> <html>
<head> <head>
<title>The page you're looking for could not be found (404)</title> <title>The page you're looking for could not be found (404)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <style>
body {
color: #666;
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
width: 800px;
margin: auto;
font-size: 14px;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 {
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
hr {
margin: 18px 0;
border: 0;
border-top: 1px solid #EEE;
border-bottom: 1px solid white;
}
</style>
</head> </head>
<body> <body>
<h1>404</h1> <h1>
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIxMCIgdmlld0JveD0iMCAwIDIxMCAyMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTVsMzguNjQtMTE4LjkyMWgtNzcuMjhsMzguNjQgMTE4LjkyMXoiIGZpbGw9IiNlMjQzMjkiLz4KICA8cGF0aCBkPSJNMTA1LjA2MTQgMjAzLjY1NDhsLTM4LjY0LTExOC45MjFoLTU0LjE1M2w5Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTIuMjY4NSA4NC43MzQxbC0xMS43NDIgMzYuMTM5Yy0xLjA3MSAzLjI5Ni4xMDIgNi45MDcgMi45MDYgOC45NDRsMTAxLjYyOSA3My44MzgtOTIuNzkzLTExOC45MjF6IiBmaWxsPSIjZmNhMzI2Ii8+CiAgPHBhdGggZD0iTTEyLjI2ODUgODQuNzM0Mmg1NC4xNTNsLTIzLjI3My03MS42MjVjLTEuMTk3LTMuNjg2LTYuNDExLTMuNjg1LTcuNjA4IDBsLTIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTQ4bDM4LjY0LTExOC45MjFoNTQuMTUzbC05Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTk3Ljg1NDQgODQuNzM0MWwxMS43NDIgMzYuMTM5YzEuMDcxIDMuMjk2LS4xMDIgNi45MDctMi45MDYgOC45NDRsLTEwMS42MjkgNzMuODM4IDkyLjc5My0xMTguOTIxeiIgZmlsbD0iI2ZjYTMyNiIvPgogIDxwYXRoIGQ9Ik0xOTcuODU0NCA4NC43MzQyaC01NC4xNTNsMjMuMjczLTcxLjYyNWMxLjE5Ny0zLjY4NiA2LjQxMS0zLjY4NSA3LjYwOCAwbDIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+Cjwvc3ZnPgo=" /><br />
404
</h1>
<h3>The page you're looking for could not be found.</h3> <h3>The page you're looking for could not be found.</h3>
<hr/> <hr/>
<p>Make sure the address is correct and that the page hasn't moved.</p> <p>Make sure the address is correct and that the page hasn't moved.</p>
......
...@@ -2,12 +2,51 @@ ...@@ -2,12 +2,51 @@
<html> <html>
<head> <head>
<title>The change you requested was rejected (422)</title> <title>The change you requested was rejected (422)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <style>
body {
color: #666;
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
width: 800px;
margin: auto;
font-size: 14px;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 {
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
hr {
margin: 18px 0;
border: 0;
border-top: 1px solid #EEE;
border-bottom: 1px solid white;
}
</style>
</head> </head>
<body> <body>
<!-- This file lives in public/422.html --> <h1>
<h1>422</h1> <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIxMCIgdmlld0JveD0iMCAwIDIxMCAyMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTVsMzguNjQtMTE4LjkyMWgtNzcuMjhsMzguNjQgMTE4LjkyMXoiIGZpbGw9IiNlMjQzMjkiLz4KICA8cGF0aCBkPSJNMTA1LjA2MTQgMjAzLjY1NDhsLTM4LjY0LTExOC45MjFoLTU0LjE1M2w5Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTIuMjY4NSA4NC43MzQxbC0xMS43NDIgMzYuMTM5Yy0xLjA3MSAzLjI5Ni4xMDIgNi45MDcgMi45MDYgOC45NDRsMTAxLjYyOSA3My44MzgtOTIuNzkzLTExOC45MjF6IiBmaWxsPSIjZmNhMzI2Ii8+CiAgPHBhdGggZD0iTTEyLjI2ODUgODQuNzM0Mmg1NC4xNTNsLTIzLjI3My03MS42MjVjLTEuMTk3LTMuNjg2LTYuNDExLTMuNjg1LTcuNjA4IDBsLTIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTQ4bDM4LjY0LTExOC45MjFoNTQuMTUzbC05Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTk3Ljg1NDQgODQuNzM0MWwxMS43NDIgMzYuMTM5YzEuMDcxIDMuMjk2LS4xMDIgNi45MDctMi45MDYgOC45NDRsLTEwMS42MjkgNzMuODM4IDkyLjc5My0xMTguOTIxeiIgZmlsbD0iI2ZjYTMyNiIvPgogIDxwYXRoIGQ9Ik0xOTcuODU0NCA4NC43MzQyaC01NC4xNTNsMjMuMjczLTcxLjYyNWMxLjE5Ny0zLjY4NiA2LjQxMS0zLjY4NSA3LjYwOCAwbDIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+Cjwvc3ZnPgo=" /><br />
422
</h1>
<h3>The change you requested was rejected.</h3> <h3>The change you requested was rejected.</h3>
<hr /> <hr />
<p>Make sure you have access to the thing you tried to change.</p> <p>Make sure you have access to the thing you tried to change.</p>
......
...@@ -2,10 +2,50 @@ ...@@ -2,10 +2,50 @@
<html> <html>
<head> <head>
<title>Something went wrong (500)</title> <title>Something went wrong (500)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <style>
body {
color: #666;
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
width: 800px;
margin: auto;
font-size: 14px;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 {
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
hr {
margin: 18px 0;
border: 0;
border-top: 1px solid #EEE;
border-bottom: 1px solid white;
}
</style>
</head> </head>
<body> <body>
<h1>500</h1> <h1>
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIxMCIgdmlld0JveD0iMCAwIDIxMCAyMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTVsMzguNjQtMTE4LjkyMWgtNzcuMjhsMzguNjQgMTE4LjkyMXoiIGZpbGw9IiNlMjQzMjkiLz4KICA8cGF0aCBkPSJNMTA1LjA2MTQgMjAzLjY1NDhsLTM4LjY0LTExOC45MjFoLTU0LjE1M2w5Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTIuMjY4NSA4NC43MzQxbC0xMS43NDIgMzYuMTM5Yy0xLjA3MSAzLjI5Ni4xMDIgNi45MDcgMi45MDYgOC45NDRsMTAxLjYyOSA3My44MzgtOTIuNzkzLTExOC45MjF6IiBmaWxsPSIjZmNhMzI2Ii8+CiAgPHBhdGggZD0iTTEyLjI2ODUgODQuNzM0Mmg1NC4xNTNsLTIzLjI3My03MS42MjVjLTEuMTk3LTMuNjg2LTYuNDExLTMuNjg1LTcuNjA4IDBsLTIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTQ4bDM4LjY0LTExOC45MjFoNTQuMTUzbC05Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTk3Ljg1NDQgODQuNzM0MWwxMS43NDIgMzYuMTM5YzEuMDcxIDMuMjk2LS4xMDIgNi45MDctMi45MDYgOC45NDRsLTEwMS42MjkgNzMuODM4IDkyLjc5My0xMTguOTIxeiIgZmlsbD0iI2ZjYTMyNiIvPgogIDxwYXRoIGQ9Ik0xOTcuODU0NCA4NC43MzQyaC01NC4xNTNsMjMuMjczLTcxLjYyNWMxLjE5Ny0zLjY4NiA2LjQxMS0zLjY4NSA3LjYwOCAwbDIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+Cjwvc3ZnPgo=" /><br />
500
</h1>
<h3>Whoops, something went wrong on our end.</h3> <h3>Whoops, something went wrong on our end.</h3>
<hr/> <hr/>
<p>Try refreshing the page, or going back and attempting the action again.</p> <p>Try refreshing the page, or going back and attempting the action again.</p>
......
...@@ -2,10 +2,50 @@ ...@@ -2,10 +2,50 @@
<html> <html>
<head> <head>
<title>GitLab is not responding (502)</title> <title>GitLab is not responding (502)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <style>
body {
color: #666;
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
width: 800px;
margin: auto;
font-size: 14px;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 {
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
hr {
margin: 18px 0;
border: 0;
border-top: 1px solid #EEE;
border-bottom: 1px solid white;
}
</style>
</head> </head>
<body> <body>
<h1>502</h1> <h1>
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIxMCIgdmlld0JveD0iMCAwIDIxMCAyMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTVsMzguNjQtMTE4LjkyMWgtNzcuMjhsMzguNjQgMTE4LjkyMXoiIGZpbGw9IiNlMjQzMjkiLz4KICA8cGF0aCBkPSJNMTA1LjA2MTQgMjAzLjY1NDhsLTM4LjY0LTExOC45MjFoLTU0LjE1M2w5Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTIuMjY4NSA4NC43MzQxbC0xMS43NDIgMzYuMTM5Yy0xLjA3MSAzLjI5Ni4xMDIgNi45MDcgMi45MDYgOC45NDRsMTAxLjYyOSA3My44MzgtOTIuNzkzLTExOC45MjF6IiBmaWxsPSIjZmNhMzI2Ii8+CiAgPHBhdGggZD0iTTEyLjI2ODUgODQuNzM0Mmg1NC4xNTNsLTIzLjI3My03MS42MjVjLTEuMTk3LTMuNjg2LTYuNDExLTMuNjg1LTcuNjA4IDBsLTIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTQ4bDM4LjY0LTExOC45MjFoNTQuMTUzbC05Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTk3Ljg1NDQgODQuNzM0MWwxMS43NDIgMzYuMTM5YzEuMDcxIDMuMjk2LS4xMDIgNi45MDctMi45MDYgOC45NDRsLTEwMS42MjkgNzMuODM4IDkyLjc5My0xMTguOTIxeiIgZmlsbD0iI2ZjYTMyNiIvPgogIDxwYXRoIGQ9Ik0xOTcuODU0NCA4NC43MzQyaC01NC4xNTNsMjMuMjczLTcxLjYyNWMxLjE5Ny0zLjY4NiA2LjQxMS0zLjY4NSA3LjYwOCAwbDIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+Cjwvc3ZnPgo=" /><br />
502
</h1>
<h3>Whoops, GitLab is taking too much time to respond.</h3> <h3>Whoops, GitLab is taking too much time to respond.</h3>
<hr/> <hr/>
<p>Try refreshing the page, or going back and attempting the action again.</p> <p>Try refreshing the page, or going back and attempting the action again.</p>
......
...@@ -2,12 +2,49 @@ ...@@ -2,12 +2,49 @@
<html> <html>
<head> <head>
<title>Deploy in progress</title> <title>Deploy in progress</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <style>
body {
color: #666;
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
width: 800px;
margin: auto;
font-size: 14px;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 {
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
hr {
margin: 18px 0;
border: 0;
border-top: 1px solid #EEE;
border-bottom: 1px solid white;
}
</style>
</head> </head>
<body> <body>
<h1> <h1>
<img src="/logo.svg" /><br /> <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIxMCIgdmlld0JveD0iMCAwIDIxMCAyMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTVsMzguNjQtMTE4LjkyMWgtNzcuMjhsMzguNjQgMTE4LjkyMXoiIGZpbGw9IiNlMjQzMjkiLz4KICA8cGF0aCBkPSJNMTA1LjA2MTQgMjAzLjY1NDhsLTM4LjY0LTExOC45MjFoLTU0LjE1M2w5Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTIuMjY4NSA4NC43MzQxbC0xMS43NDIgMzYuMTM5Yy0xLjA3MSAzLjI5Ni4xMDIgNi45MDcgMi45MDYgOC45NDRsMTAxLjYyOSA3My44MzgtOTIuNzkzLTExOC45MjF6IiBmaWxsPSIjZmNhMzI2Ii8+CiAgPHBhdGggZD0iTTEyLjI2ODUgODQuNzM0Mmg1NC4xNTNsLTIzLjI3My03MS42MjVjLTEuMTk3LTMuNjg2LTYuNDExLTMuNjg1LTcuNjA4IDBsLTIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTQ4bDM4LjY0LTExOC45MjFoNTQuMTUzbC05Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTk3Ljg1NDQgODQuNzM0MWwxMS43NDIgMzYuMTM5YzEuMDcxIDMuMjk2LS4xMDIgNi45MDctMi45MDYgOC45NDRsLTEwMS42MjkgNzMuODM4IDkyLjc5My0xMTguOTIxeiIgZmlsbD0iI2ZjYTMyNiIvPgogIDxwYXRoIGQ9Ik0xOTcuODU0NCA4NC43MzQyaC01NC4xNTNsMjMuMjczLTcxLjYyNWMxLjE5Ny0zLjY4NiA2LjQxMS0zLjY4NSA3LjYwOCAwbDIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+Cjwvc3ZnPgo=" /><br />
Deploy in progress Deploy in progress
</h1> </h1>
<h3>Please try again in a few minutes.</h3> <h3>Please try again in a few minutes.</h3>
......
<svg width="210" height="210" viewBox="0 0 210 210" xmlns="http://www.w3.org/2000/svg">
<path d="M105.0614 203.655l38.64-118.921h-77.28l38.64 118.921z" fill="#e24329"/>
<path d="M105.0614 203.6548l-38.64-118.921h-54.153l92.793 118.921z" fill="#fc6d26"/>
<path d="M12.2685 84.7341l-11.742 36.139c-1.071 3.296.102 6.907 2.906 8.944l101.629 73.838-92.793-118.921z" fill="#fca326"/>
<path d="M12.2685 84.7342h54.153l-23.273-71.625c-1.197-3.686-6.411-3.685-7.608 0l-23.272 71.625z" fill="#e24329"/>
<path d="M105.0614 203.6548l38.64-118.921h54.153l-92.793 118.921z" fill="#fc6d26"/>
<path d="M197.8544 84.7341l11.742 36.139c1.071 3.296-.102 6.907-2.906 8.944l-101.629 73.838 92.793-118.921z" fill="#fca326"/>
<path d="M197.8544 84.7342h-54.153l23.273-71.625c1.197-3.686 6.411-3.685 7.608 0l23.272 71.625z" fill="#e24329"/>
</svg>
body {
color: #666;
text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
width: 800px;
margin: auto;
font-size: 14px;
}
h1 {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 {
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
hr {
margin: 18px 0;
border: 0;
border-top: 1px solid #EEE;
border-bottom: 1px solid white;
}
...@@ -597,9 +597,9 @@ describe Repository, models: true do ...@@ -597,9 +597,9 @@ describe Repository, models: true do
describe '#after_push_commit' do describe '#after_push_commit' do
it 'flushes the cache' do it 'flushes the cache' do
expect(repository).to receive(:expire_cache).with('master') expect(repository).to receive(:expire_cache).with('master', '123')
repository.after_push_commit('master') repository.after_push_commit('master', '123')
end end
end end
...@@ -703,4 +703,81 @@ describe Repository, models: true do ...@@ -703,4 +703,81 @@ describe Repository, models: true do
repository.rm_tag('8.5') repository.rm_tag('8.5')
end end
end end
describe '#avatar' do
it 'returns the first avatar file found in the repository' do
expect(repository).to receive(:blob_at_branch).
with('master', 'logo.png').
and_return(true)
expect(repository.avatar).to eq('logo.png')
end
it 'caches the output' do
allow(repository).to receive(:blob_at_branch).
with('master', 'logo.png').
and_return(true)
expect(repository.avatar).to eq('logo.png')
expect(repository).to_not receive(:blob_at_branch)
expect(repository.avatar).to eq('logo.png')
end
end
describe '#expire_avatar_cache' do
let(:cache) { repository.send(:cache) }
before do
allow(repository).to receive(:cache).and_return(cache)
end
context 'without a branch or revision' do
it 'flushes the cache' do
expect(cache).to receive(:expire).with(:avatar)
repository.expire_avatar_cache
end
end
context 'with a branch' do
it 'does not flush the cache if the branch is not the default branch' do
expect(cache).not_to receive(:expire)
repository.expire_avatar_cache('cats')
end
it 'flushes the cache if the branch equals the default branch' do
expect(cache).to receive(:expire).with(:avatar)
repository.expire_avatar_cache(repository.root_ref)
end
end
context 'with a branch and revision' do
let(:commit) { double(:commit) }
before do
allow(repository).to receive(:commit).and_return(commit)
end
it 'does not flush the cache if the commit does not change any logos' do
diff = double(:diff, new_path: 'test.txt')
expect(commit).to receive(:diffs).and_return([diff])
expect(cache).not_to receive(:expire)
repository.expire_avatar_cache(repository.root_ref, '123')
end
it 'flushes the cache if the commit changes any of the logos' do
diff = double(:diff, new_path: Repository::AVATAR_FILES[0])
expect(commit).to receive(:diffs).and_return([diff])
expect(cache).to receive(:expire).with(:avatar)
repository.expire_avatar_cache(repository.root_ref, '123')
end
end
end
end end
...@@ -29,7 +29,8 @@ describe GitPushService, services: true do ...@@ -29,7 +29,8 @@ describe GitPushService, services: true do
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
it 'flushes general cached data' do it 'flushes general cached data' do
expect(project.repository).to receive(:expire_cache).with('master') expect(project.repository).to receive(:expire_cache).
with('master', newrev)
subject subject
end end
...@@ -46,7 +47,8 @@ describe GitPushService, services: true do ...@@ -46,7 +47,8 @@ describe GitPushService, services: true do
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
it 'flushes general cached data' do it 'flushes general cached data' do
expect(project.repository).to receive(:expire_cache).with('master') expect(project.repository).to receive(:expire_cache).
with('master', newrev)
subject subject
end end
...@@ -65,7 +67,8 @@ describe GitPushService, services: true do ...@@ -65,7 +67,8 @@ describe GitPushService, services: true do
end end
it 'flushes general cached data' do it 'flushes general cached data' do
expect(project.repository).to receive(:expire_cache).with('master') expect(project.repository).to receive(:expire_cache).
with('master', newrev)
subject subject
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