Commit cb261abe authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

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

parents 613bcdc6 8959de25
...@@ -2,8 +2,10 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -2,8 +2,10 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.9.0 (unreleased) v 8.9.0 (unreleased)
- Allow enabling wiki page events from Webhook management UI - Allow enabling wiki page events from Webhook management UI
- Fix wiki page events' webhook to point to the wiki repository
- Allow forking projects with restricted visibility level - Allow forking projects with restricted visibility level
- Improve note validation to prevent errors when creating invalid note via API - Improve note validation to prevent errors when creating invalid note via API
- Remove project notification settings associated with deleted projects
- Redesign navigation for project pages - Redesign navigation for project pages
- Fix groups API to list only user's accessible projects - Fix groups API to list only user's accessible projects
- Redesign account and email confirmation emails - Redesign account and email confirmation emails
...@@ -17,6 +19,7 @@ v 8.9.0 (unreleased) ...@@ -17,6 +19,7 @@ v 8.9.0 (unreleased)
- Projects pending deletion will render a 404 page - Projects pending deletion will render a 404 page
- Measure queue duration between gitlab-workhorse and Rails - Measure queue duration between gitlab-workhorse and Rails
- Make authentication service for Container Registry to be compatible with < Docker 1.11 - Make authentication service for Container Registry to be compatible with < Docker 1.11
- Add Application Setting to configure Container Registry token expire delay (default 5min)
v 8.8.3 v 8.8.3
- Fix gitlab importer failing to import new projects due to missing credentials - Fix gitlab importer failing to import new projects due to missing credentials
......
...@@ -73,7 +73,7 @@ gem 'grape-entity', '~> 0.4.2' ...@@ -73,7 +73,7 @@ gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Pagination # Pagination
gem "kaminari", "~> 0.16.3" gem "kaminari", "~> 0.17.0"
# HAML # HAML
gem "haml-rails", '~> 0.9.0' gem "haml-rails", '~> 0.9.0'
......
...@@ -442,7 +442,7 @@ GEM ...@@ -442,7 +442,7 @@ GEM
railties (>= 3.2.16) railties (>= 3.2.16)
json (1.8.3) json (1.8.3)
jwt (1.5.2) jwt (1.5.2)
kaminari (0.16.3) kaminari (0.17.0)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
kgio (2.10.0) kgio (2.10.0)
...@@ -959,7 +959,7 @@ DEPENDENCIES ...@@ -959,7 +959,7 @@ DEPENDENCIES
jquery-turbolinks (~> 2.1.0) jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0) jquery-ui-rails (~> 5.0.0)
jwt jwt
kaminari (~> 0.16.3) kaminari (~> 0.17.0)
letter_opener_web (~> 1.3.0) letter_opener_web (~> 1.3.0)
licensee (~> 8.0.0) licensee (~> 8.0.0)
loofah (~> 2.0.3) loofah (~> 2.0.3)
......
...@@ -16,6 +16,19 @@ ...@@ -16,6 +16,19 @@
@include btn-default; @include btn-default;
} }
@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) {
background-color: $background;
color: $text;
border-color: $border;
&:hover,
&:focus {
background-color: $hover-background;
color: $hover-text;
border-color: $hover-border;;
}
}
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) { @mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
background-color: $light; background-color: $light;
border-color: $border-light; border-color: $border-light;
...@@ -106,11 +119,14 @@ ...@@ -106,11 +119,14 @@
@include btn-blue; @include btn-blue;
} }
&.btn-close,
&.btn-warning { &.btn-warning {
@include btn-orange; @include btn-orange;
} }
&.btn-close {
@include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light);
}
&.btn-danger, &.btn-danger,
&.btn-remove, &.btn-remove,
&.btn-red { &.btn-red {
......
...@@ -104,7 +104,7 @@ $blue-medium-light: #3498cb; ...@@ -104,7 +104,7 @@ $blue-medium-light: #3498cb;
$blue-medium: #2f8ebf; $blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4; $blue-medium-dark: #2d86b4;
$orange-light: rgba(252, 109, 38, 0.80); $orange-light: #fc8a51;
$orange-normal: #e75e40; $orange-normal: #e75e40;
$orange-dark: #ce5237; $orange-dark: #ce5237;
......
...@@ -107,6 +107,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -107,6 +107,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:repository_checks_enabled, :repository_checks_enabled,
:metrics_packet_size, :metrics_packet_size,
:send_user_confirmation_email, :send_user_confirmation_email,
:container_registry_token_expire_delay,
restricted_visibility_levels: [], restricted_visibility_levels: [],
import_sources: [], import_sources: [],
disabled_oauth_sign_in_sources: [] disabled_oauth_sign_in_sources: []
......
...@@ -51,6 +51,10 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -51,6 +51,10 @@ class ApplicationSetting < ActiveRecord::Base
presence: true, presence: true,
numericality: { only_integer: true, greater_than: 0 } numericality: { only_integer: true, greater_than: 0 }
validates :container_registry_token_expire_delay,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
validates_each :restricted_visibility_levels do |record, attr, value| validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil? unless value.nil?
value.each do |level| value.each do |level|
...@@ -121,7 +125,8 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -121,7 +125,8 @@ class ApplicationSetting < ActiveRecord::Base
akismet_enabled: false, akismet_enabled: false,
repository_checks_enabled: true, repository_checks_enabled: true,
disabled_oauth_sign_in_sources: [], disabled_oauth_sign_in_sources: [],
send_user_confirmation_email: false send_user_confirmation_email: false,
container_registry_token_expire_delay: 5,
) )
end end
......
...@@ -27,6 +27,10 @@ class ProjectWiki ...@@ -27,6 +27,10 @@ class ProjectWiki
@project.path_with_namespace + ".wiki" @project.path_with_namespace + ".wiki"
end end
def web_url
Gitlab::Routing.url_helpers.namespace_project_wiki_url(@project.namespace, @project, :home)
end
def url_to_repo def url_to_repo
gitlab_shell.url_to_repo(path_with_namespace) gitlab_shell.url_to_repo(path_with_namespace)
end end
...@@ -142,6 +146,16 @@ class ProjectWiki ...@@ -142,6 +146,16 @@ class ProjectWiki
wiki wiki
end end
def hook_attrs
{
web_url: web_url,
git_ssh_url: ssh_url_to_repo,
git_http_url: http_url_to_repo,
path_with_namespace: path_with_namespace,
default_branch: default_branch
}
end
private private
def init_repo(path_with_namespace) def init_repo(path_with_namespace)
......
module Auth module Auth
class ContainerRegistryAuthenticationService < BaseService class ContainerRegistryAuthenticationService < BaseService
include Gitlab::CurrentSettings
AUDIENCE = 'container_registry' AUDIENCE = 'container_registry'
def execute def execute
...@@ -17,6 +19,7 @@ module Auth ...@@ -17,6 +19,7 @@ module Auth
token = JSONWebToken::RSAToken.new(registry.key) token = JSONWebToken::RSAToken.new(registry.key)
token.issuer = registry.issuer token.issuer = registry.issuer
token.audience = AUDIENCE token.audience = AUDIENCE
token.expire_time = token_expire_at
token[:access] = names.map do |name| token[:access] = names.map do |name|
{ type: 'repository', name: name, actions: %w(*) } { type: 'repository', name: name, actions: %w(*) }
end end
...@@ -30,6 +33,7 @@ module Auth ...@@ -30,6 +33,7 @@ module Auth
token.issuer = registry.issuer token.issuer = registry.issuer
token.audience = params[:service] token.audience = params[:service]
token.subject = current_user.try(:username) token.subject = current_user.try(:username)
token.expire_time = ContainerRegistryAuthenticationService.token_expire_at
token[:access] = accesses.compact token[:access] = accesses.compact
token token
end end
...@@ -75,5 +79,9 @@ module Auth ...@@ -75,5 +79,9 @@ module Auth
def registry def registry
Gitlab.config.registry Gitlab.config.registry
end end
def self.token_expire_at
Time.now + current_application_settings.container_registry_token_expire_delay.minutes
end
end end
end end
...@@ -6,9 +6,8 @@ module WikiPages ...@@ -6,9 +6,8 @@ module WikiPages
object_kind: page.class.name.underscore, object_kind: page.class.name.underscore,
user: current_user.hook_attrs, user: current_user.hook_attrs,
project: @project.hook_attrs, project: @project.hook_attrs,
object_attributes: page.hook_attrs, wiki: @project.wiki.hook_attrs,
# DEPRECATED object_attributes: page.hook_attrs
repository: @project.hook_attrs.slice(:name, :url, :description, :homepage)
} }
page_url = Gitlab::UrlBuilder.build(page) page_url = Gitlab::UrlBuilder.build(page)
......
...@@ -178,6 +178,14 @@ ...@@ -178,6 +178,14 @@
.col-sm-10 .col-sm-10
= f.number_field :max_artifacts_size, class: 'form-control' = f.number_field :max_artifacts_size, class: 'form-control'
- if Gitlab.config.registry.enabled
%fieldset
%legend Container Registry
.form-group
= f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :container_registry_token_expire_delay, class: 'form-control'
%fieldset %fieldset
%legend Metrics %legend Metrics
%p %p
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
= event_action_name(event) = event_action_name(event)
- if event.target - if event.target
%strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], title: event.target_title %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title
= event_preposition(event) = event_preposition(event)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
-# available local variables -# available local variables
-# url: url to the first page -# url: url to the first page
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
%li.first %li.first
......
-# Non-link tag that stands for skipped pages... -# Non-link tag that stands for skipped pages...
-# available local variables -# available local variables
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
%li{class: "page"} %li{class: "page"}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
-# available local variables -# available local variables
-# url: url to the last page -# url: url to the last page
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
%li.last %li.last
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
-# available local variables -# available local variables
-# url: url to the next page -# url: url to the next page
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
- if current_page.last? - if current_page.last?
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
-# page: a page object for "this" page -# page: a page object for "this" page
-# url: url to this page -# url: url to this page
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
%li{class: "page#{' active' if page.current?}"} %li{class: "page#{' active' if page.current?}"}
......
-# The container tag -# The container tag
-# available local variables -# available local variables
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
-# paginator: the paginator that renders the pagination tags inside -# paginator: the paginator that renders the pagination tags inside
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
%div.gl-pagination %div.gl-pagination
%ul.pagination.clearfix %ul.pagination.clearfix
- unless current_page.first? - unless current_page.first?
= first_page_tag unless num_pages < 5 # As kaminari will always show the first 5 pages = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages
= prev_page_tag = prev_page_tag
- each_page do |page| - each_page do |page|
- if page.left_outer? || page.right_outer? || page.inside_window? - if page.left_outer? || page.right_outer? || page.inside_window?
...@@ -18,5 +18,5 @@ ...@@ -18,5 +18,5 @@
= gap_tag = gap_tag
= next_page_tag = next_page_tag
- unless current_page.last? - unless current_page.last?
= last_page_tag unless num_pages < 5 = last_page_tag unless total_pages < 5
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
-# available local variables -# available local variables
-# url: url to the previous page -# url: url to the previous page
-# current_page: a page object for the currently displayed page -# current_page: a page object for the currently displayed page
-# num_pages: total number of pages -# total_pages: total number of pages
-# per_page: number of items to fetch per page -# per_page: number of items to fetch per page
-# remote: data-remote -# remote: data-remote
- if current_page.first? - if current_page.first?
......
class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration
def up
execute <<-SQL
DELETE FROM notification_settings
WHERE notification_settings.source_type = 'Project'
AND NOT EXISTS (
SELECT *
FROM projects
WHERE projects.id = notification_settings.source_id
)
SQL
end
end
# This is ONLINE migration
class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
def change
add_column :application_settings, :container_registry_token_expire_delay, :integer, default: 5
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160528043124) do ActiveRecord::Schema.define(version: 20160530150109) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -43,46 +43,47 @@ ActiveRecord::Schema.define(version: 20160528043124) do ...@@ -43,46 +43,47 @@ ActiveRecord::Schema.define(version: 20160528043124) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "home_page_url" t.string "home_page_url"
t.integer "default_branch_protection", default: 2 t.integer "default_branch_protection", default: 2
t.text "restricted_visibility_levels" t.text "restricted_visibility_levels"
t.boolean "version_check_enabled", default: true t.boolean "version_check_enabled", default: true
t.integer "max_attachment_size", default: 10, null: false t.integer "max_attachment_size", default: 10, null: false
t.integer "default_project_visibility" t.integer "default_project_visibility"
t.integer "default_snippet_visibility" t.integer "default_snippet_visibility"
t.text "restricted_signup_domains" t.text "restricted_signup_domains"
t.boolean "user_oauth_applications", default: true t.boolean "user_oauth_applications", default: true
t.string "after_sign_out_path" t.string "after_sign_out_path"
t.integer "session_expire_delay", default: 10080, null: false t.integer "session_expire_delay", default: 10080, null: false
t.text "import_sources" t.text "import_sources"
t.text "help_page_text" t.text "help_page_text"
t.string "admin_notification_email" t.string "admin_notification_email"
t.boolean "shared_runners_enabled", default: true, null: false t.boolean "shared_runners_enabled", default: true, null: false
t.integer "max_artifacts_size", default: 100, null: false t.integer "max_artifacts_size", default: 100, null: false
t.string "runners_registration_token" t.string "runners_registration_token"
t.boolean "require_two_factor_authentication", default: false t.boolean "require_two_factor_authentication", default: false
t.integer "two_factor_grace_period", default: 48 t.integer "two_factor_grace_period", default: 48
t.boolean "metrics_enabled", default: false t.boolean "metrics_enabled", default: false
t.string "metrics_host", default: "localhost" t.string "metrics_host", default: "localhost"
t.integer "metrics_pool_size", default: 16 t.integer "metrics_pool_size", default: 16
t.integer "metrics_timeout", default: 10 t.integer "metrics_timeout", default: 10
t.integer "metrics_method_call_threshold", default: 10 t.integer "metrics_method_call_threshold", default: 10
t.boolean "recaptcha_enabled", default: false t.boolean "recaptcha_enabled", default: false
t.string "recaptcha_site_key" t.string "recaptcha_site_key"
t.string "recaptcha_private_key" t.string "recaptcha_private_key"
t.integer "metrics_port", default: 8089 t.integer "metrics_port", default: 8089
t.boolean "akismet_enabled", default: false t.boolean "akismet_enabled", default: false
t.string "akismet_api_key" t.string "akismet_api_key"
t.integer "metrics_sample_interval", default: 15 t.integer "metrics_sample_interval", default: 15
t.boolean "sentry_enabled", default: false t.boolean "sentry_enabled", default: false
t.string "sentry_dsn" t.string "sentry_dsn"
t.boolean "email_author_in_body", default: false t.boolean "email_author_in_body", default: false
t.integer "default_group_visibility" t.integer "default_group_visibility"
t.boolean "repository_checks_enabled", default: false t.boolean "repository_checks_enabled", default: false
t.text "shared_runners_text" t.text "shared_runners_text"
t.integer "metrics_packet_size", default: 1 t.integer "metrics_packet_size", default: 1
t.text "disabled_oauth_sign_in_sources" t.text "disabled_oauth_sign_in_sources"
t.string "health_check_access_token" t.string "health_check_access_token"
t.boolean "send_user_confirmation_email", default: false t.boolean "send_user_confirmation_email", default: false
t.integer "container_registry_token_expire_delay", default: 5
end end
create_table "audit_events", force: :cascade do |t| create_table "audit_events", force: :cascade do |t|
......
...@@ -37,7 +37,8 @@ Example response: ...@@ -37,7 +37,8 @@ Example response:
"created_at" : "2016-01-04T15:44:55.176Z", "created_at" : "2016-01-04T15:44:55.176Z",
"default_project_visibility" : 0, "default_project_visibility" : 0,
"gravatar_enabled" : true, "gravatar_enabled" : true,
"sign_in_text" : null "sign_in_text" : null,
"container_registry_token_expire_delay": 5
} }
``` ```
...@@ -64,6 +65,7 @@ PUT /application/settings ...@@ -64,6 +65,7 @@ PUT /application/settings
| `restricted_signup_domains` | array of strings | no | Force people to use only corporate emails for sign-up. Default is null, meaning there is no restriction. | | `restricted_signup_domains` | array of strings | no | Force people to use only corporate emails for sign-up. Default is null, meaning there is no restriction. |
| `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider | | `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider |
| `after_sign_out_path` | string | no | Where to redirect users after logout | | `after_sign_out_path` | string | no | Where to redirect users after logout |
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes |
```bash ```bash
curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1 curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1
...@@ -90,6 +92,7 @@ Example response: ...@@ -90,6 +92,7 @@ Example response:
"default_snippet_visibility": 0, "default_snippet_visibility": 0,
"restricted_signup_domains": [], "restricted_signup_domains": [],
"user_oauth_applications": true, "user_oauth_applications": true,
"after_sign_out_path": "" "after_sign_out_path": "",
"container_registry_token_expire_delay": 5
} }
``` ```
...@@ -720,7 +720,7 @@ X-Gitlab-Event: Wiki Page Hook ...@@ -720,7 +720,7 @@ X-Gitlab-Event: Wiki Page Hook
"description": "This is awesome", "description": "This is awesome",
"web_url": "http://example.com/root/awesome-project", "web_url": "http://example.com/root/awesome-project",
"avatar_url": null, "avatar_url": null,
"git_ssh_url": "git@example.com:root/test-project.git", "git_ssh_url": "git@example.com:root/awesome-project.git",
"git_http_url": "http://example.com/root/awesome-project.git", "git_http_url": "http://example.com/root/awesome-project.git",
"namespace": "root", "namespace": "root",
"visibility_level": 0, "visibility_level": 0,
...@@ -731,6 +731,13 @@ X-Gitlab-Event: Wiki Page Hook ...@@ -731,6 +731,13 @@ X-Gitlab-Event: Wiki Page Hook
"ssh_url": "git@example.com:root/awesome-project.git", "ssh_url": "git@example.com:root/awesome-project.git",
"http_url": "http://example.com/root/awesome-project.git" "http_url": "http://example.com/root/awesome-project.git"
}, },
"wiki": {
"web_url": "http://example.com/root/awesome-project/wikis/home",
"git_ssh_url": "git@example.com:root/awesome-project.wiki.git",
"git_http_url": "http://example.com/root/awesome-project.wiki.git",
"path_with_namespace": "root/awesome-project.wiki",
"default_branch": "master"
},
"object_attributes": { "object_attributes": {
"title": "Awesome", "title": "Awesome",
"content": "awesome content goes here", "content": "awesome content goes here",
...@@ -739,12 +746,6 @@ X-Gitlab-Event: Wiki Page Hook ...@@ -739,12 +746,6 @@ X-Gitlab-Event: Wiki Page Hook
"slug": "awesome", "slug": "awesome",
"url": "http://example.com/root/awesome-project/wikis/awesome", "url": "http://example.com/root/awesome-project/wikis/awesome",
"action": "create" "action": "create"
},
"repository": {
"name": "awesome-project",
"url": "git@example.com:root/awesome-project.git",
"description": "test",
"homepage": "http://example.com/root/awesome-project"
} }
} }
``` ```
......
...@@ -362,6 +362,7 @@ module API ...@@ -362,6 +362,7 @@ module API
expose :restricted_signup_domains expose :restricted_signup_domains
expose :user_oauth_applications expose :user_oauth_applications
expose :after_sign_out_path expose :after_sign_out_path
expose :container_registry_token_expire_delay
end end
class Release < Grape::Entity class Release < Grape::Entity
......
...@@ -48,7 +48,7 @@ module Backup ...@@ -48,7 +48,7 @@ module Backup
end end
connection = ::Fog::Storage.new(connection_settings) connection = ::Fog::Storage.new(connection_settings)
directory = connection.directories.get(remote_directory) directory = connection.directories.create(key: remote_directory)
if directory.files.create(key: tar_file, body: File.open(tar_file), public: false, if directory.files.create(key: tar_file, body: File.open(tar_file), public: false,
multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size, multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size,
......
...@@ -36,6 +36,7 @@ module Gitlab ...@@ -36,6 +36,7 @@ module Gitlab
two_factor_grace_period: 48, two_factor_grace_period: 48,
akismet_enabled: false, akismet_enabled: false,
repository_checks_enabled: true, repository_checks_enabled: true,
container_registry_token_expire_delay: 5,
) )
end end
......
require 'spec_helper' require 'spec_helper'
describe Ci::Build, models: true do describe Ci::Build, models: true do
let(:project) { FactoryGirl.create :project } let(:project) { create(:project) }
let(:commit) { FactoryGirl.create :ci_commit, project: project } let(:commit) { create(:ci_commit, project: project) }
let(:build) { FactoryGirl.create :ci_build, commit: commit } let(:build) { create(:ci_build, commit: commit) }
it { is_expected.to validate_presence_of :ref } it { is_expected.to validate_presence_of :ref }
it { is_expected.to respond_to :trace_html } it { is_expected.to respond_to :trace_html }
describe '#first_pending' do describe '#first_pending' do
let(:first) { FactoryGirl.create :ci_build, commit: commit, status: 'pending', created_at: Date.yesterday } let!(:first) { create(:ci_build, commit: commit, status: 'pending', created_at: Date.yesterday) }
let(:second) { FactoryGirl.create :ci_build, commit: commit, status: 'pending' } let!(:second) { create(:ci_build, commit: commit, status: 'pending') }
before { first; second }
subject { Ci::Build.first_pending } subject { Ci::Build.first_pending }
it { is_expected.to be_a(Ci::Build) } it { is_expected.to be_a(Ci::Build) }
...@@ -219,8 +218,8 @@ describe Ci::Build, models: true do ...@@ -219,8 +218,8 @@ describe Ci::Build, models: true do
it { is_expected.to eq(predefined_variables + yaml_variables + secure_variables) } it { is_expected.to eq(predefined_variables + yaml_variables + secure_variables) }
context 'and trigger variables' do context 'and trigger variables' do
let(:trigger) { FactoryGirl.create :ci_trigger, project: project } let(:trigger) { create(:ci_trigger, project: project) }
let(:trigger_request) { FactoryGirl.create :ci_trigger_request_with_variables, commit: commit, trigger: trigger } let(:trigger_request) { create(:ci_trigger_request_with_variables, commit: commit, trigger: trigger) }
let(:trigger_variables) do let(:trigger_variables) do
[ [
{ key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false } { key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false }
...@@ -329,7 +328,7 @@ describe Ci::Build, models: true do ...@@ -329,7 +328,7 @@ describe Ci::Build, models: true do
end end
context 'if there are runner' do context 'if there are runner' do
let(:runner) { FactoryGirl.create :ci_runner } let(:runner) { create(:ci_runner) }
before do before do
build.project.runners << runner build.project.runners << runner
...@@ -366,7 +365,7 @@ describe Ci::Build, models: true do ...@@ -366,7 +365,7 @@ describe Ci::Build, models: true do
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
context "and there are specific runner" do context "and there are specific runner" do
let(:runner) { FactoryGirl.create :ci_runner, contacted_at: 1.second.ago } let(:runner) { create(:ci_runner, contacted_at: 1.second.ago) }
before do before do
build.project.runners << runner build.project.runners << runner
...@@ -415,7 +414,7 @@ describe Ci::Build, models: true do ...@@ -415,7 +414,7 @@ describe Ci::Build, models: true do
end end
describe '#repo_url' do describe '#repo_url' do
let(:build) { FactoryGirl.create :ci_build } let(:build) { create(:ci_build) }
let(:project) { build.project } let(:project) { build.project }
subject { build.repo_url } subject { build.repo_url }
...@@ -429,10 +428,10 @@ describe Ci::Build, models: true do ...@@ -429,10 +428,10 @@ describe Ci::Build, models: true do
end end
describe '#depends_on_builds' do describe '#depends_on_builds' do
let!(:build) { FactoryGirl.create :ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build' } let!(:build) { create(:ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build') }
let!(:rspec_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test' } let!(:rspec_test) { create(:ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test') }
let!(:rubocop_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test' } let!(:rubocop_test) { create(:ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test') }
let!(:staging) { FactoryGirl.create :ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy' } let!(:staging) { create(:ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy') }
it 'to have no dependents if this is first build' do it 'to have no dependents if this is first build' do
expect(build.depends_on_builds).to be_empty expect(build.depends_on_builds).to be_empty
...@@ -453,11 +452,10 @@ describe Ci::Build, models: true do ...@@ -453,11 +452,10 @@ describe Ci::Build, models: true do
end end
def create_mr(build, commit, factory: :merge_request, created_at: Time.now) def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
FactoryGirl.create(factory, create(factory, source_project_id: commit.gl_project_id,
source_project_id: commit.gl_project_id, target_project_id: commit.gl_project_id,
target_project_id: commit.gl_project_id, source_branch: build.ref,
source_branch: build.ref, created_at: created_at)
created_at: created_at)
end end
describe '#merge_request' do describe '#merge_request' do
...@@ -501,8 +499,8 @@ describe Ci::Build, models: true do ...@@ -501,8 +499,8 @@ describe Ci::Build, models: true do
context 'when a Build is created after the MR' do context 'when a Build is created after the MR' do
before do before do
@merge_request = create_mr(build, commit, factory: :merge_request_with_diffs) @merge_request = create_mr(build, commit, factory: :merge_request_with_diffs)
commit2 = FactoryGirl.create :ci_commit, project: project commit2 = create(:ci_commit, project: project)
@build2 = FactoryGirl.create :ci_build, commit: commit2 @build2 = create(:ci_build, commit: commit2)
commits = [double(id: commit.sha), double(id: commit2.sha)] commits = [double(id: commit.sha), double(id: commit2.sha)]
allow(@merge_request).to receive(:commits).and_return(commits) allow(@merge_request).to receive(:commits).and_return(commits)
......
...@@ -16,6 +16,12 @@ describe ProjectWiki, models: true do ...@@ -16,6 +16,12 @@ describe ProjectWiki, models: true do
end end
end end
describe '#web_url' do
it 'returns the full web URL to the wiki' do
expect(subject.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/wikis/home")
end
end
describe "#url_to_repo" do describe "#url_to_repo" do
it "returns the correct ssh url to the repo" do it "returns the correct ssh url to the repo" do
expect(subject.url_to_repo).to eq(gitlab_shell.url_to_repo(subject.path_with_namespace)) expect(subject.url_to_repo).to eq(gitlab_shell.url_to_repo(subject.path_with_namespace))
...@@ -257,6 +263,13 @@ describe ProjectWiki, models: true do ...@@ -257,6 +263,13 @@ describe ProjectWiki, models: true do
end end
end end
describe '#hook_attrs' do
it 'returns a hash with values' do
expect(subject.hook_attrs).to be_a Hash
expect(subject.hook_attrs.keys).to contain_exactly(:web_url, :git_ssh_url, :git_http_url, :path_with_namespace, :default_branch)
end
end
private private
def create_temp_repo(path) def create_temp_repo(path)
......
...@@ -17,6 +17,21 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do ...@@ -17,6 +17,21 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
shared_examples 'a valid token' do shared_examples 'a valid token' do
it { is_expected.to include(:token) } it { is_expected.to include(:token) }
it { expect(payload).to include('access') } it { expect(payload).to include('access') }
context 'a expirable' do
let(:expires_at) { Time.at(payload['exp']) }
let(:expire_delay) { 10 }
context 'for default configuration' do
it { expect(expires_at).not_to be_within(2.seconds).of(Time.now + expire_delay.minutes) }
end
context 'for changed configuration' do
before { stub_application_setting(container_registry_token_expire_delay: expire_delay) }
it { expect(expires_at).to be_within(2.seconds).of(Time.now + expire_delay.minutes) }
end
end
end end
shared_examples 'a accessible' do shared_examples 'a accessible' do
......
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