diff options
198 files changed, 1092 insertions, 1088 deletions
diff --git a/CHANGELOG b/CHANGELOG index 884e4258db0..31b2a759d40 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.0.0 (unreleased) + - Fix Markdown links not showing up in dashboard activity feed (Stan Hu) + - Fix HTML link that was improperly escaped in new user e-mail (Stan Hu) - Fix broken sort in merge request API (Stan Hu) - Bump rouge to 1.10.1 to remove warning noise and fix other syntax highlighting bugs (Stan Hu) - Gracefully handle errors in syntax highlighting by leaving the block unformatted (Stan Hu) @@ -17,6 +19,7 @@ v 8.0.0 (unreleased) - Improve dropdown positioning on the project home page (Hannes Rosenögger) - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu) - Remove user OAuth tokens from the database and request new tokens each session (Stan Hu) + - Restrict users API endpoints to use integer IDs (Stan Hu) - Only show recent push event if the branch still exists or a recent merge request has not been created (Stan Hu) - Remove satellites - Better performance for web editor (switched from satellites to rugged) @@ -40,6 +43,7 @@ v 8.0.0 (unreleased) - Retrieving oauth token with LDAP credentials - Load Application settings from running database unless env var USE_DB=false - Added Drone CI integration (Kirill Zaitsev) + - Fail builds if no .gitlab-ci.yml is found - Refactored service API and added automatically service docs generator (Kirill Zaitsev) - Added web_url key project hook_attrs (Kirill Zaitsev) - Add ability to get user information by ID of an SSH key via the API @@ -51,6 +55,10 @@ v 8.0.0 (unreleased) - Added service API endpoint to retrieve service parameters (PetheÅ‘ Bence) - Add FogBugz project import (Jared Szechy) - Sort users autocomplete lists by user (Allister Antosik) + - Webhook for issue now contains repository field (Jungkook Park) + - Add ability to add custom text to the help page (Jeroen van Baarsen) + - Add pg_schema to backup config + - Removed API calls from CE to CI v 7.14.3 - No changes @@ -22,7 +22,7 @@ gem "mysql2", '~> 0.3.16', group: :mysql gem "pg", '~> 0.18.2', group: :postgres # Authentication libraries -gem "devise", '~> 3.2.4' +gem "devise", '~> 3.5.2' gem "devise-async", '~> 0.9.0' gem 'omniauth', "~> 1.2.2" gem 'omniauth-google-oauth2', '~> 0.2.5' @@ -38,7 +38,7 @@ gem 'omniauth_crowd' gem "rack-oauth2", "~> 1.0.5" # Two-factor authentication -gem 'devise-two-factor', '~> 1.0.1' +gem 'devise-two-factor', '~> 2.0.0' gem 'rqrcode-rails3', '~> 0.1.7' gem 'attr_encrypted', '~> 1.3.4' @@ -286,7 +286,7 @@ gem "newrelic_rpm", '~> 3.9.4.245' gem 'octokit', '~> 3.7.0' -gem "mail_room", "~> 0.4.2" +gem "mail_room", "~> 0.5.1" gem 'email_reply_parser', '~> 0.5.8' diff --git a/Gemfile.lock b/Gemfile.lock index a4a0762bdd8..320f7629fb6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -136,21 +136,21 @@ GEM activerecord (>= 3.2.0, < 5.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (3.2.4) + devise (3.5.2) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 3.2.6, < 5) + responders thread_safe (~> 0.1) warden (~> 1.2.3) devise-async (0.9.0) devise (~> 3.2) - devise-two-factor (1.0.2) - activemodel + devise-two-factor (2.0.0) activesupport attr_encrypted (~> 1.3.2) - devise (>= 3.2.4, < 3.5) + devise (~> 3.5.0) railties - rotp (< 2) + rotp (~> 2) diff-lcs (1.2.5) diffy (3.0.7) docile (1.1.5) @@ -384,7 +384,7 @@ GEM systemu (~> 2.6.2) mail (2.6.3) mime-types (>= 1.16, < 3) - mail_room (0.4.2) + mail_room (0.5.1) method_source (0.8.2) mime-types (1.25.1) mimemagic (0.3.0) @@ -558,12 +558,14 @@ GEM request_store (1.2.0) rerun (0.10.0) listen (~> 2.7, >= 2.7.3) + responders (1.1.2) + railties (>= 3.2, < 4.2) rest-client (1.8.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) rinku (1.7.3) - rotp (1.6.1) + rotp (2.1.1) rouge (1.10.1) rqrcode (0.7.0) chunky_png @@ -806,9 +808,9 @@ DEPENDENCIES d3_rails (~> 3.5.5) database_cleaner (~> 1.4.0) default_value_for (~> 3.0.0) - devise (~> 3.2.4) + devise (~> 3.5.2) devise-async (~> 0.9.0) - devise-two-factor (~> 1.0.1) + devise-two-factor (~> 2.0.0) diffy (~> 3.0.3) doorkeeper (~> 2.1.3) dropzonejs-rails (~> 0.7.1) @@ -846,7 +848,7 @@ DEPENDENCIES jquery-ui-rails (~> 4.2.1) kaminari (~> 0.15.1) letter_opener (~> 1.1.2) - mail_room (~> 0.4.2) + mail_room (~> 0.5.1) minitest (~> 5.7.0) mousetrap-rails (~> 1.4.6) mysql2 (~> 0.3.16) diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index 176d9cabefa..c4d3e619f5e 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -11,12 +11,13 @@ class @IssuableContext $(this).submit() $('.issuable-details').waitForImages -> + $('.issuable-affix').on 'affix.bs.affix', -> + $(@).width($(@).outerWidth()) + .on 'affixed-top.bs.affix affixed-bottom.bs.affix', -> + $(@).width('') + $('.issuable-affix').affix offset: top: -> @top = ($('.issuable-affix').offset().top - 70) bottom: -> @bottom = $('.footer').outerHeight(true) - $('.issuable-affix').on 'affix.bs.affix', -> - $(@).width($(@).outerWidth()) - .on 'affixed-top.bs.affix affixed-bottom.bs.affix', -> - $(@).width('') diff --git a/app/assets/stylesheets/base/gl_variables.scss b/app/assets/stylesheets/base/gl_variables.scss index bfef5f78f83..7378d404008 100644 --- a/app/assets/stylesheets/base/gl_variables.scss +++ b/app/assets/stylesheets/base/gl_variables.scss @@ -65,20 +65,20 @@ $legend-color: $text-color; // //## -$pagination-color: #fff; -$pagination-bg: $brand-success; +$pagination-color: $gl-gray; +$pagination-bg: $background-color; $pagination-border: transparent; $pagination-hover-color: #fff; -$pagination-hover-bg: darken($brand-success, 15%); +$pagination-hover-bg: $brand-info; $pagination-hover-border: transparent; $pagination-active-color: #fff; -$pagination-active-bg: darken($brand-success, 15%); +$pagination-active-bg: $brand-info; $pagination-active-border: transparent; -$pagination-disabled-color: #b4bcc2; -$pagination-disabled-bg: lighten($brand-success, 15%); +$pagination-disabled-color: #fff; +$pagination-disabled-bg: lighten($brand-info, 15%); $pagination-disabled-border: transparent; diff --git a/app/assets/stylesheets/ci/projects.scss b/app/assets/stylesheets/ci/projects.scss index e5d69360c2c..c63a67ab720 100644 --- a/app/assets/stylesheets/ci/projects.scss +++ b/app/assets/stylesheets/ci/projects.scss @@ -13,31 +13,6 @@ .builds, .projects-table { - .alert-success { - background-color: #6fc995; - border-color: #5bba83; - } - - .alert-danger { - background-color: #eb897f; - border-color: #d4776e; - } - - .alert-info { - background-color: #3498db; - border-color: #2e8ece; - } - - .alert-warning { - background-color: #EB974E; - border-color: #E87E04; - } - - .alert-disabled { - background: $background-color; - border-color: $border-color; - } - .light { border-color: $border-color; } @@ -47,8 +22,8 @@ } td { + color: $gl-gray; vertical-align: middle !important; - border-color: inherit !important; a { font-weight: normal; @@ -58,23 +33,16 @@ } .commit-info { - font-size: 14px; - .attr-name { - font-weight: 300; - color: #666; margin-right: 5px; } pre.commit-message { - font-size: 14px; background: none; padding: 0; margin: 0; border: none; margin: 20px 0; - border-bottom: 1px solid #EEE; - padding-bottom: 20px; border-radius: 0; } } @@ -88,4 +56,38 @@ margin-bottom: 16px; } } + + .ci-status { + padding: 2px 7px; + margin-right: 5px; + border: 1px solid #EEE; + white-space: nowrap; + @include border-radius(4px); + + &.ci-failed { + color: $gl-danger; + border-color: $gl-danger; + } + + &.ci-success { + color: $gl-success; + border-color: $gl-success; + } + + &.ci-info { + color: $gl-info; + border-color: $gl-info; + } + + &.ci-disabled { + color: $gl-gray; + border-color: $gl-gray; + } + + &.ci-pending, + &.ci-running { + color: $gl-warning; + border-color: $gl-warning; + } + } } diff --git a/app/assets/stylesheets/generic/blocks.scss b/app/assets/stylesheets/generic/blocks.scss index ce024272a30..6ce34b5c3e8 100644 --- a/app/assets/stylesheets/generic/blocks.scss +++ b/app/assets/stylesheets/generic/blocks.scss @@ -20,11 +20,11 @@ .gray-content-block { margin: -$gl-padding; - background-color: #f8fafc; + background-color: $background-color; padding: $gl-padding; margin-bottom: 0px; - border-top: 1px solid #e7e9ed; - border-bottom: 1px solid #e7e9ed; + border-top: 1px solid $border-color; + border-bottom: 1px solid $border-color; color: $gl-gray; &.top-block { @@ -48,6 +48,7 @@ &.footer-block { margin-top: 0; + border-bottom: none; margin-bottom: -$gl-padding; } diff --git a/app/assets/stylesheets/generic/callout.scss b/app/assets/stylesheets/generic/callout.scss new file mode 100644 index 00000000000..f1699d21c9b --- /dev/null +++ b/app/assets/stylesheets/generic/callout.scss @@ -0,0 +1,45 @@ +/* + * Callouts from Bootstrap3 docs + * + * Not quite alerts, but custom and helpful notes for folks reading the docs. + * Requires a base and modifier class. + */ + +/* Common styles for all types */ +.bs-callout { + margin: 20px 0; + padding: 20px; + border-left: 3px solid #eee; + color: #666; + background: #f9f9f9; +} +.bs-callout h4 { + margin-top: 0; + margin-bottom: 5px; +} +.bs-callout p:last-child { + margin-bottom: 0; +} + +/* Variations */ +.bs-callout-danger { + background-color: #fdf7f7; + border-color: #eed3d7; + color: #b94a48; +} +.bs-callout-warning { + background-color: #faf8f0; + border-color: #faebcc; + color: #8a6d3b; +} +.bs-callout-info { + background-color: #f4f8fa; + border-color: #bce8f1; + color: #34789a; +} +.bs-callout-success { + background-color: #dff0d8; + border-color: #5cA64d; + color: #3c763d; +} + diff --git a/app/assets/stylesheets/generic/pagination.scss b/app/assets/stylesheets/generic/pagination.scss new file mode 100644 index 00000000000..a937677ebdc --- /dev/null +++ b/app/assets/stylesheets/generic/pagination.scss @@ -0,0 +1,32 @@ +.gl-pagination { + border-top: 1px solid $border-color; + background-color: $background-color; + margin: -$gl-padding; + margin-top: 0; + + .pagination { + padding: 0; + margin: 0; + display: block; + + li.next, + li.prev { + > a { + color: $link-color; + + &:hover { + color: #fff; + } + } + } + + li > a, + li > span { + border: none; + margin: 0; + @include border-radius(0 !important); + padding: 13px 19px; + border-right: 1px solid $border-color; + } + } +} diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 73034c84f9a..41189432bf6 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -89,6 +89,10 @@ a > code { } } +.md-area { + @include md-typography; +} + .md { @include md-typography; } diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index f38e07af84b..5f70582cbb7 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -46,6 +46,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :gravatar_enabled, :twitter_sharing_enabled, :sign_in_text, + :help_page_text, :home_page_url, :after_sign_out_path, :max_attachment_size, @@ -55,6 +56,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :restricted_signup_domains_raw, :version_check_enabled, :user_oauth_applications, + :ci_enabled, restricted_visibility_levels: [], import_sources: [] ) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 6092c79c254..a19b1abee27 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -56,7 +56,7 @@ class Admin::UsersController < Admin::ApplicationController end def confirm - if user.confirm! + if user.confirm redirect_to :back, notice: "Successfully confirmed" else redirect_to :back, alert: "Error occurred. User was not confirmed" diff --git a/app/controllers/ci/application_controller.rb b/app/controllers/ci/application_controller.rb index a5868da377f..8d8ff75ff72 100644 --- a/app/controllers/ci/application_controller.rb +++ b/app/controllers/ci/application_controller.rb @@ -1,5 +1,7 @@ module Ci class ApplicationController < ::ApplicationController + before_action :check_enable_flag! + def self.railtie_helpers_paths "app/helpers/ci" end @@ -8,11 +10,16 @@ module Ci private + def check_enable_flag! + unless current_application_settings.ci_enabled + redirect_to(disabled_ci_projects_path) + return + end + end + def authenticate_public_page! unless project.public - unless current_user - redirect_to(new_user_sessions_path) and return - end + authenticate_user! return access_denied! unless can?(current_user, :read_project, gl_project) end diff --git a/app/controllers/ci/helps_controller.rb b/app/controllers/ci/helps_controller.rb deleted file mode 100644 index a1ee4111614..00000000000 --- a/app/controllers/ci/helps_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -module Ci - class HelpsController < Ci::ApplicationController - skip_filter :check_config - - def show - end - - def oauth2 - if valid_config? - redirect_to ci_root_path - else - render layout: 'ci/empty' - end - end - end -end diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb index 6483a84ee91..40b61edb0a9 100644 --- a/app/controllers/ci/projects_controller.rb +++ b/app/controllers/ci/projects_controller.rb @@ -5,38 +5,36 @@ module Ci before_action :authenticate_user!, except: [:build, :badge, :index, :show] before_action :authenticate_public_page!, only: :show before_action :project, only: [:build, :integration, :show, :badge, :edit, :update, :destroy, :toggle_shared_runners, :dumped_yaml] - before_action :authorize_access_project!, except: [:build, :gitlab, :badge, :index, :show, :new, :create] + before_action :authorize_access_project!, except: [:build, :badge, :index, :show, :new, :create, :disabled] before_action :authorize_manage_project!, only: [:edit, :integration, :update, :destroy, :toggle_shared_runners, :dumped_yaml] before_action :authenticate_token!, only: [:build] before_action :no_cache, only: [:badge] + skip_before_action :check_enable_flag!, only: [:disabled] protect_from_forgery except: :build - layout 'ci/project', except: [:index, :gitlab] + layout 'ci/project', except: [:index, :disabled] - def index - @projects = Ci::Project.ordered_by_last_commit_date.public_only.page(params[:page]) unless current_user + def disabled end - def gitlab + def index @limit, @offset = (params[:limit] || PROJECTS_BATCH).to_i, (params[:offset] || 0).to_i @page = @offset == 0 ? 1 : (@offset / @limit + 1) - @gl_projects = current_user.authorized_projects - @gl_projects = @gl_projects.where("name LIKE ?", "%#{params[:search]}%") if params[:search] - @gl_projects = @gl_projects.page(@page).per(@limit) + if current_user + @projects = ProjectListBuilder.new.execute(current_user, params[:search]) - @projects = Ci::Project.where(gitlab_id: @gl_projects.map(&:id)).ordered_by_last_commit_date - @total_count = @gl_projects.size + @projects = @projects.page(@page).per(@limit) - @gl_projects = @gl_projects.where.not(id: @projects.map(&:gitlab_id)) + @total_count = @projects.size + end respond_to do |format| format.json do - pager_json("ci/projects/gitlab", @total_count) + pager_json("ci/projects/index", @total_count) end + format.html end - rescue - @error = 'Failed to fetch GitLab projects' end def show @@ -57,7 +55,7 @@ module Ci return redirect_to ci_root_path, alert: 'You have to have at least master role to enable CI for this project' end - @project = Ci::CreateProjectService.new.execute(current_user, project_data, ci_project_url(":project_id")) + @project = Ci::CreateProjectService.new.execute(current_user, project_data) if @project.persisted? redirect_to ci_project_path(@project, show_guide: true), notice: 'Project was successfully created.' @@ -88,16 +86,6 @@ module Ci redirect_to ci_projects_url end - def build - @commit = Ci::CreateCommitService.new.execute(@project, params.dup) - - if @commit && @commit.valid? - head 201 - else - head 400 - end - end - # Project status badge # Image with build status for sha or ref def badge diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index f9af0871cf1..e6b99be37fb 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -9,7 +9,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController end def create - if current_user.valid_otp?(params[:pin_code]) + if current_user.validate_and_consume_otp!(params[:pin_code]) current_user.two_factor_enabled = true @codes = current_user.generate_otp_backup_codes! current_user.save! diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index d7be212c33a..8776721d243 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -18,12 +18,6 @@ class Projects::BlobController < Projects::ApplicationController before_action :after_edit_path, only: [:edit, :update] def new - @title = 'Upload' - @placeholder = 'Upload new file' - @button_title = 'Upload file' - @form_path = namespace_project_create_blob_path(@project.namespace, @project, @id) - @method = :post - commit unless @repository.empty? end @@ -46,11 +40,6 @@ class Projects::BlobController < Projects::ApplicationController end def show - @title = "Replace #{@blob.name}" - @placeholder = @title - @button_title = 'Replace file' - @form_path = namespace_project_update_blob_path(@project.namespace, @project, @id) - @method = :put end def edit diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 9efe9704d1e..86f4a02a6e9 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -66,12 +66,7 @@ class Projects::MilestonesController < Projects::ApplicationController def destroy return access_denied! unless can?(current_user, :admin_milestone, @project) - update_params = { milestone: nil } - @milestone.issues.each do |issue| - Issues::UpdateService.new(@project, current_user, update_params).execute(issue) - end - - @milestone.destroy + Milestones::DestroyService.new(project, current_user).execute(milestone) respond_to do |format| format.html { redirect_to namespace_project_milestones_path } diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index cfa565cd03e..1b60d3e27d0 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -99,7 +99,7 @@ class SessionsController < Devise::SessionsController end def valid_otp_attempt?(user) - user.valid_otp?(user_params[:otp_attempt]) || + user.validate_and_consume_otp!(user_params[:otp_attempt]) || user.invalidate_otp_backup_code!(user_params[:otp_attempt]) end diff --git a/app/finders/trending_projects_finder.rb b/app/finders/trending_projects_finder.rb index f3f4d461efa..9ea342cb26d 100644 --- a/app/finders/trending_projects_finder.rb +++ b/app/finders/trending_projects_finder.rb @@ -2,21 +2,12 @@ class TrendingProjectsFinder def execute(current_user, start_date = nil) start_date ||= Date.today - 1.month + projects = projects_for(current_user) + # Determine trending projects based on comments count # for period of time - ex. month - trending_project_ids = Note. - select("notes.project_id, count(notes.project_id) as pcount"). - where('notes.created_at > ?', start_date). - group("project_id"). - reorder("pcount DESC"). - map(&:project_id) - - sql_order_ids = trending_project_ids.reverse. - map { |project_id| "id = #{project_id}" }.join(", ") - - # Get list of projects that user allowed to see - projects = projects_for(current_user) - projects.where(id: trending_project_ids).reorder(sql_order_ids) + projects.joins(:notes).where('notes.created_at > ?', start_date). + group("projects.id").reorder("count(notes.id) DESC") end private diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b049bd9fcc2..39ab83ccf12 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -13,7 +13,9 @@ module ApplicationHelper # current_controller?(:commits) # => false # current_controller?(:commits, :tree) # => true def current_controller?(*args) - args.any? { |v| v.to_s.downcase == controller.controller_name } + args.any? do |v| + v.to_s.downcase == controller.controller_name || v.to_s.downcase == controller.controller_path + end end # Check if a particular action is the current one diff --git a/app/helpers/ci/application_helper.rb b/app/helpers/ci/application_helper.rb index 3198fe55f91..9fe6282bb81 100644 --- a/app/helpers/ci/application_helper.rb +++ b/app/helpers/ci/application_helper.rb @@ -4,118 +4,10 @@ module Ci image_tag 'ci/loader.gif', alt: 'Loading' end - # Navigation link helper - # - # Returns an `li` element with an 'active' class if the supplied - # controller(s) and/or action(s) are currently active. The content of the - # element is the value passed to the block. - # - # options - The options hash used to determine if the element is "active" (default: {}) - # :controller - One or more controller names to check (optional). - # :action - One or more action names to check (optional). - # :path - A shorthand path, such as 'dashboard#index', to check (optional). - # :html_options - Extra options to be passed to the list element (optional). - # block - An optional block that will become the contents of the returned - # `li` element. - # - # When both :controller and :action are specified, BOTH must match in order - # to be marked as active. When only one is given, either can match. - # - # Examples - # - # # Assuming we're on TreeController#show - # - # # Controller matches, but action doesn't - # nav_link(controller: [:tree, :refs], action: :edit) { "Hello" } - # # => '<li>Hello</li>' - # - # # Controller matches - # nav_link(controller: [:tree, :refs]) { "Hello" } - # # => '<li class="active">Hello</li>' - # - # # Shorthand path - # nav_link(path: 'tree#show') { "Hello" } - # # => '<li class="active">Hello</li>' - # - # # Supplying custom options for the list element - # nav_link(controller: :tree, html_options: {class: 'home'}) { "Hello" } - # # => '<li class="home active">Hello</li>' - # - # Returns a list item element String - def nav_link(options = {}, &block) - if path = options.delete(:path) - if path.respond_to?(:each) - c = path.map { |p| p.split('#').first } - a = path.map { |p| p.split('#').last } - else - c, a, _ = path.split('#') - end - else - c = options.delete(:controller) - a = options.delete(:action) - end - - if c && a - # When given both options, make sure BOTH are active - klass = current_controller?(*c) && current_action?(*a) ? 'active' : '' - else - # Otherwise check EITHER option - klass = current_controller?(*c) || current_action?(*a) ? 'active' : '' - end - - # Add our custom class into the html_options, which may or may not exist - # and which may or may not already have a :class key - o = options.delete(:html_options) || {} - o[:class] ||= '' - o[:class] += ' ' + klass - o[:class].strip! - - if block_given? - content_tag(:li, capture(&block), o) - else - content_tag(:li, nil, o) - end - end - - # Check if a particular controller is the current one - # - # args - One or more controller names to check - # - # Examples - # - # # On TreeController - # current_controller?(:tree) # => true - # current_controller?(:commits) # => false - # current_controller?(:commits, :tree) # => true - def current_controller?(*args) - args.any? { |v| v.to_s.downcase == controller.controller_name } - end - - # Check if a particular action is the current one - # - # args - One or more action names to check - # - # Examples - # - # # On Projects#new - # current_action?(:new) # => true - # current_action?(:create) # => false - # current_action?(:new, :create) # => true - def current_action?(*args) - args.any? { |v| v.to_s.downcase == action_name } - end - def date_from_to(from, to) "#{from.to_s(:short)} - #{to.to_s(:short)}" end - def body_data_page - path = controller.controller_path.split('/') - namespace = path.first if path.second - - [namespace, controller.controller_name, controller.action_name].compact.join(":") - end - def duration_in_words(finished_at, started_at) if finished_at && started_at interval_in_seconds = finished_at.to_i - started_at.to_i @@ -136,5 +28,27 @@ module Ci "#{pluralize(seconds, "second")}" end end + + def ci_icon_for_status(status) + icon_name = + case status + when 'success' + 'check-square' + when 'failed' + 'close' + when 'running', 'pending' + 'clock-o' + else + 'circle' + end + + icon(icon_name) + end + + def ci_status_with_icon(status) + content_tag :span, class: "ci-status ci-#{status}" do + ci_icon_for_status(status) + ' '.html_safe + status + end + end end end diff --git a/app/helpers/ci/builds_helper.rb b/app/helpers/ci/builds_helper.rb index cdabdad17d2..5d6e785d951 100644 --- a/app/helpers/ci/builds_helper.rb +++ b/app/helpers/ci/builds_helper.rb @@ -15,27 +15,5 @@ module Ci def build_url(build) ci_project_build_url(build.project, build) end - - def build_status_alert_class(build) - if build.success? - 'alert-success' - elsif build.failed? - 'alert-danger' - elsif build.canceled? - 'alert-disabled' - else - 'alert-warning' - end - end - - def build_icon_css_class(build) - if build.success? - 'fa-circle cgreen' - elsif build.failed? - 'fa-circle cred' - else - 'fa-circle light' - end - end end end diff --git a/app/helpers/ci/commits_helper.rb b/app/helpers/ci/commits_helper.rb index 74de30e006e..9069aed5b4d 100644 --- a/app/helpers/ci/commits_helper.rb +++ b/app/helpers/ci/commits_helper.rb @@ -1,20 +1,5 @@ module Ci module CommitsHelper - def commit_status_alert_class(commit) - return 'alert-info' unless commit - - case commit.status - when 'success' - 'alert-success' - when 'failed', 'canceled' - 'alert-danger' - when 'skipped' - 'alert-disabled' - else - 'alert-warning' - end - end - def ci_commit_path(commit) ci_project_ref_commits_path(commit.project, commit.ref, commit.sha) end diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 76602614bcd..6f69c2a9f32 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -46,6 +46,14 @@ module EventsHelper } end + def event_preposition(event) + if event.push? || event.commented? || event.target + "at" + elsif event.milestone? + "in" + end + end + def event_feed_title(event) words = [] words << event.author_name @@ -62,6 +70,9 @@ module EventsHelper words << "##{truncate event.note_target_iid}" end words << "at" + elsif event.milestone? + words << "##{event.target_iid}" if event.target_iid + words << "in" elsif event.target words << "##{event.target_iid}:" words << event.target.title if event.target.respond_to?(:title) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 1ebfd92f119..78bf25f55e7 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -45,7 +45,7 @@ module GitlabMarkdownHelper end def markdown(text, context = {}) - context.merge!( + context.reverse_merge!( current_user: current_user, path: @path, project: @project, @@ -59,7 +59,7 @@ module GitlabMarkdownHelper # TODO (rspeicher): Remove all usages of this helper and just call `markdown` # with a custom pipeline depending on the content being rendered def gfm(text, options = {}) - options.merge!( + options.reverse_merge!( current_user: current_user, path: @path, project: @project, diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 5e70de23f29..1d36969cd62 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -31,12 +31,12 @@ module GroupsHelper end end - def group_title(group, name, url) + def group_title(group, name = nil, url = nil) + full_title = link_to(simple_sanitize(group.name), group_path(group)) + full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name + content_tag :span do - link_to( - simple_sanitize(group.name), group_path(group) - ) + ' · '.html_safe + - link_to(simple_sanitize(name), url) + full_title end end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6a2de0de77c..a2b83c50c2e 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -317,41 +317,6 @@ module ProjectsHelper @ref || @repository.try(:root_ref) end - def detect_project_title(project) - name, url = - if current_controller? 'wikis' - ['Wiki', get_project_wiki_path(project)] - elsif current_controller? 'project_members' - ['Members', namespace_project_project_members_path(project.namespace, project)] - elsif current_controller? 'labels' - ['Labels', namespace_project_labels_path(project.namespace, project)] - elsif current_controller? 'members' - ['Members', project_files_path(project)] - elsif current_controller? 'commits' - ['Commits', project_commits_path(project)] - elsif current_controller? 'graphs' - ['Graphs', namespace_project_graph_path(project.namespace, project, current_ref)] - elsif current_controller? 'network' - ['Network', namespace_project_network_path(project.namespace, project, current_ref)] - elsif current_controller? 'milestones' - ['Milestones', namespace_project_milestones_path(project.namespace, project)] - elsif current_controller? 'snippets' - ['Snippets', namespace_project_snippets_path(project.namespace, project)] - elsif current_controller? 'issues' - ['Issues', namespace_project_issues_path(project.namespace, project)] - elsif current_controller? 'merge_requests' - ['Merge Requests', namespace_project_merge_requests_path(project.namespace, project)] - elsif current_controller? 'tree', 'blob' - ['Files', project_files_path(project)] - elsif current_path? 'projects#activity' - ['Activity', activity_project_path(project)] - else - [nil, nil] - end - - project_title(project, name, url) - end - private def filename_path(project, filename) diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 63d4aca61af..87ba94a583d 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -12,7 +12,7 @@ module Emails to: recipient(recipient_id), subject: subject("#{@commit.title} (#{@commit.short_id})")) - SentNotification.record(@commit, recipient_id, reply_key) + SentNotification.record_note(@note, recipient_id, reply_key) end def note_issue_email(recipient_id, note_id) @@ -27,7 +27,7 @@ module Emails to: recipient(recipient_id), subject: subject("#{@issue.title} (##{@issue.iid})")) - SentNotification.record(@issue, recipient_id, reply_key) + SentNotification.record_note(@note, recipient_id, reply_key) end def note_merge_request_email(recipient_id, note_id) @@ -43,7 +43,7 @@ module Emails to: recipient(recipient_id), subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) - SentNotification.record(@merge_request, recipient_id, reply_key) + SentNotification.record_note(@note, recipient_id, reply_key) end end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index c8841178e93..784f5c96a0a 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -83,7 +83,8 @@ class ApplicationSetting < ActiveRecord::Base default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], restricted_signup_domains: Settings.gitlab['restricted_signup_domains'], - import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'] + import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'], + ci_enabled: Settings.gitlab_ci['enabled'] ) end diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index 23cd47dfe37..f102d0a7679 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -236,7 +236,7 @@ module Ci end def config_processor - @config_processor ||= Ci::GitlabCiYamlProcessor.new(push_data[:ci_yaml_file] || project.generated_yaml_config) + @config_processor ||= Ci::GitlabCiYamlProcessor.new(push_data[:ci_yaml_file]) rescue Ci::GitlabCiYamlProcessor::ValidationError => e save_yaml_error(e.message) nil diff --git a/app/models/ci/project.rb b/app/models/ci/project.rb index ae901d4ccd0..37fbcc287bb 100644 --- a/app/models/ci/project.rb +++ b/app/models/ci/project.rb @@ -92,21 +92,6 @@ module Ci project end - # TODO: remove - def from_gitlab(user, scope = :owned, options) - opts = user.authenticate_options - opts.merge! options - - raise 'Implement me of fix' - #projects = Ci::Network.new.projects(opts.compact, scope) - - if projects - projects.map { |pr| OpenStruct.new(pr) } - else - [] - end - end - def already_added?(project) where(gitlab_id: project.id).any? end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 40642dc63ba..4db4ffb2e79 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -140,6 +140,12 @@ module Issuable { object_kind: self.class.name.underscore, user: user.hook_attrs, + repository: { + name: project.name, + url: project.url_to_repo, + description: project.description, + homepage: project.web_url + }, object_attributes: hook_attrs } end diff --git a/app/models/event.rb b/app/models/event.rb index 78f16c6304e..47600c57e35 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -27,6 +27,7 @@ class Event < ActiveRecord::Base MERGED = 7 JOINED = 8 # User joined project LEFT = 9 # User left project + DESTROYED = 10 delegate :name, :email, to: :author, prefix: true, allow_nil: true delegate :title, to: :issue, prefix: true, allow_nil: true @@ -48,6 +49,7 @@ class Event < ActiveRecord::Base scope :code_push, -> { where(action: PUSHED) } scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent } scope :with_associations, -> { includes(project: :namespace) } + scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) } class << self def reset_event_cache_for(target) @@ -71,7 +73,7 @@ class Event < ActiveRecord::Base elsif created_project? true else - (issue? || merge_request? || note? || milestone?) && target + ((issue? || merge_request? || note?) && target) || milestone? end end @@ -115,6 +117,10 @@ class Event < ActiveRecord::Base action == LEFT end + def destroyed? + action == DESTROYED + end + def commented? action == COMMENTED end @@ -124,7 +130,7 @@ class Event < ActiveRecord::Base end def created_project? - created? && !target + created? && !target && target_type.nil? end def created_target? @@ -180,6 +186,8 @@ class Event < ActiveRecord::Base 'joined' elsif left? 'left' + elsif destroyed? + 'destroyed' elsif commented? "commented on" elsif created_project? diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 9a8251bdad5..a078accbdbd 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -25,7 +25,7 @@ class WebHook < ActiveRecord::Base default_value_for :note_events, false default_value_for :merge_requests_events, false default_value_for :tag_push_events, false - default_value_for :enable_ssl_verification, false + default_value_for :enable_ssl_verification, true # HTTParty timeout default_timeout Gitlab.config.gitlab.webhook_timeout diff --git a/app/models/milestone.rb b/app/models/milestone.rb index c6aff6f709f..d979a35084b 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -61,7 +61,7 @@ class Milestone < ActiveRecord::Base false end end - + def open_items_count self.issues.opened.count + self.merge_requests.opened.count end diff --git a/app/models/project.rb b/app/models/project.rb index 6e2f9645661..1a5c1c978c9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -428,7 +428,7 @@ class Project < ActiveRecord::Base end def gitlab_ci? - gitlab_ci_service && gitlab_ci_service.active + gitlab_ci_service && gitlab_ci_service.active && gitlab_ci_project.present? end def ci_services diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb index 9e5da6f45d2..40058b53df5 100644 --- a/app/models/project_services/buildkite_service.rb +++ b/app/models/project_services/buildkite_service.rb @@ -69,14 +69,6 @@ class BuildkiteService < CiService "#{project_url}/builds?commit=#{sha}" end - def builds_path - "#{project_url}/builds?branch=#{project.default_branch}" - end - - def status_img_path - "#{buildkite_endpoint('badge')}/#{status_token}.svg" - end - def title 'Buildkite' end diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index 3e2b7faecdb..c73c4b058a1 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -26,7 +26,7 @@ class DroneCiService < CiService format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated? validates :token, presence: true, - format: { with: /\A([A-Za-z0-9]+)\z/ }, if: :activated? + if: :activated? after_save :compose_service_hook, if: :activated? @@ -135,20 +135,6 @@ class DroneCiService < CiService commit_page(sha, ref) end - def builds_path - url = [drone_url, "#{project.namespace.path}/#{project.path}"] - - URI.join(*url).to_s - end - - def status_img_path - url = [drone_url, - "api/badges/#{project.namespace.path}/#{project.path}/status.svg", - "?branch=#{URI::encode(project.default_branch)}"] - - URI.join(*url).to_s - end - def title 'Drone CI' end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index acbbc9935b6..820dd3f567c 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -19,22 +19,12 @@ # class GitlabCiService < CiService - API_PREFIX = "api/v1" - - prop_accessor :project_url, :token, :enable_ssl_verification - validates :project_url, - presence: true, - format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated? - validates :token, - presence: true, - format: { with: /\A([A-Za-z0-9]+)\z/ }, if: :activated? + prop_accessor :token after_save :compose_service_hook, if: :activated? def compose_service_hook hook = service_hook || build_service_hook - hook.url = [project_url, "/build", "?token=#{token}"].join("") - hook.enable_ssl_verification = enable_ssl_verification hook.save end @@ -55,71 +45,47 @@ class GitlabCiService < CiService end end - service_hook.execute(data) - end - - def commit_status_path(sha, ref) - URI::encode(project_url + "/refs/#{ref}/commits/#{sha}/status.json?token=#{token}") + ci_project = Ci::Project.find_by(gitlab_id: project.id) + Ci::CreateCommitService.new.execute(ci_project, data) end - def get_ci_build(sha, ref) - @ci_builds ||= {} - @ci_builds[sha] ||= HTTParty.get(commit_status_path(sha, ref), verify: false) + def get_ci_commit(sha, ref) + Ci::Project.find(project.gitlab_ci_project).commits.find_by_sha_and_ref!(sha, ref) end def commit_status(sha, ref) - response = get_ci_build(sha, ref) - - if response.code == 200 and response["status"] - response["status"] - else - :error - end - rescue Errno::ECONNREFUSED + get_ci_commit(sha, ref).status + rescue ActiveRecord::RecordNotFound :error end - def fork_registration(new_project, private_token) - params = { + def fork_registration(new_project, current_user) + params = OpenStruct.new({ id: new_project.id, name_with_namespace: new_project.name_with_namespace, path_with_namespace: new_project.path_with_namespace, web_url: new_project.web_url, default_branch: new_project.default_branch, ssh_url_to_repo: new_project.ssh_url_to_repo - } - - HTTParty.post( - fork_registration_path, - body: { - project_id: project.id, - project_token: token, - private_token: private_token, - data: params }, - verify: false + }) + + ci_project = Ci::Project.find_by!(gitlab_id: project.id) + + Ci::CreateProjectService.new.execute( + current_user, + params, + ci_project ) end def commit_coverage(sha, ref) - response = get_ci_build(sha, ref) - - if response.code == 200 and response["coverage"] - response["coverage"] - end - rescue Errno::ECONNREFUSED - nil + get_ci_commit(sha, ref).coverage + rescue ActiveRecord::RecordNotFound + :error end def build_page(sha, ref) - URI::encode(project_url + "/refs/#{ref}/commits/#{sha}") - end - - def builds_path - project_url + "?ref=" + project.default_branch - end - - def status_img_path - project_url + "/status.png?ref=" + project.default_branch + Ci::RoutesHelper.ci_project_ref_commits_path(project.gitlab_ci_project, ref, sha) end def title @@ -135,11 +101,7 @@ class GitlabCiService < CiService end def fields - [ - { type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' }, - { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' }, - { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" } - ] + [] end private @@ -148,10 +110,6 @@ class GitlabCiService < CiService repository.blob_at(sha, '.gitlab-ci.yml') end - def fork_registration_path - project_url.sub(/projects\/\d*/, "#{API_PREFIX}/forks") - end - def repository project.repository end diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb index 33b113a2a27..03425389dd3 100644 --- a/app/models/sent_notification.rb +++ b/app/models/sent_notification.rb @@ -8,6 +8,7 @@ # noteable_type :string(255) # recipient_id :integer # commit_id :string(255) +# line_code :string(255) # reply_key :string(255) not null # @@ -21,13 +22,14 @@ class SentNotification < ActiveRecord::Base validates :noteable_id, presence: true, unless: :for_commit? validates :commit_id, presence: true, if: :for_commit? + validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true class << self def for(reply_key) find_by(reply_key: reply_key) end - def record(noteable, recipient_id, reply_key) + def record(noteable, recipient_id, reply_key, params = {}) return unless reply_key noteable_id = nil @@ -38,7 +40,7 @@ class SentNotification < ActiveRecord::Base noteable_id = noteable.id end - create( + params.reverse_merge!( project: noteable.project, noteable_type: noteable.class.name, noteable_id: noteable_id, @@ -46,6 +48,14 @@ class SentNotification < ActiveRecord::Base recipient_id: recipient_id, reply_key: reply_key ) + + create(params) + end + + def record_note(note, recipient_id, reply_key, params = {}) + params[:line_code] = note.line_code + + record(note.noteable, recipient_id, reply_key, params) end end diff --git a/app/services/ci/create_project_service.rb b/app/services/ci/create_project_service.rb index 0419612d521..839d3f6b444 100644 --- a/app/services/ci/create_project_service.rb +++ b/app/services/ci/create_project_service.rb @@ -2,20 +2,15 @@ module Ci class CreateProjectService include Gitlab::Application.routes.url_helpers - def execute(current_user, params, project_route, forked_project = nil) + def execute(current_user, params, forked_project = nil) @project = Ci::Project.parse(params) Ci::Project.transaction do @project.save! - data = { - token: @project.token, - project_url: project_route.gsub(":project_id", @project.id.to_s), - } - gl_project = ::Project.find(@project.gitlab_id) gl_project.build_missing_services - gl_project.gitlab_ci_service.update_attributes(data.merge(active: true)) + gl_project.gitlab_ci_service.update_attributes(active: true, token: @project.token) end if forked_project diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb index 103d6b0a08b..07fc77001a5 100644 --- a/app/services/event_create_service.rb +++ b/app/services/event_create_service.rb @@ -46,6 +46,10 @@ class EventCreateService create_record_event(milestone, current_user, Event::REOPENED) end + def destroy_milestone(milestone, current_user) + create_record_event(milestone, current_user, Event::DESTROYED) + end + def leave_note(note, current_user) create_record_event(note, current_user, Event::COMMENTED) end diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb new file mode 100644 index 00000000000..7ce7d259d0b --- /dev/null +++ b/app/services/milestones/destroy_service.rb @@ -0,0 +1,22 @@ +module Milestones + class DestroyService < Milestones::BaseService + def execute(milestone) + + Milestone.transaction do + update_params = { milestone: nil } + milestone.issues.each do |issue| + Issues::UpdateService.new(project, current_user, update_params).execute(issue) + end + + event_service.destroy_milestone(milestone, current_user) + + Event.for_milestone_id(milestone.id).each do |event| + event.target_id = nil + event.save + end + + milestone.destroy + end + end + end +end diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index 50f208b11d1..2e995d6fd51 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -18,7 +18,7 @@ module Projects if new_project.persisted? if @project.gitlab_ci? - ForkRegistrationWorker.perform_async(@project.id, new_project.id, @current_user.private_token) + @project.gitlab_ci_service.fork_registration(new_project, @current_user) end end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 330b8bbf9d2..143cd10c543 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -118,6 +118,20 @@ .col-sm-10 = f.text_area :sign_in_text, class: 'form-control', rows: 4 .help-block Markdown enabled + .form-group + = f.label :help_page_text, class: 'control-label col-sm-2' + .col-sm-10 + = f.text_area :help_page_text, class: 'form-control', rows: 4 + .help-block Markdown enabled + + %fieldset + %legend Continuous Integration + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :ci_enabled do + = f.check_box :ci_enabled + Disable to prevent CI usage until rake ci:migrate is run (8.0 only) .form-actions = f.submit 'Save', class: 'btn btn-primary' diff --git a/app/views/ci/admin/builds/_build.html.haml b/app/views/ci/admin/builds/_build.html.haml index 47f8df8f98e..778d51d03be 100644 --- a/app/views/ci/admin/builds/_build.html.haml +++ b/app/views/ci/admin/builds/_build.html.haml @@ -1,11 +1,11 @@ - if build.commit && build.project - %tr.build.alert{class: build_status_alert_class(build)} + %tr.build %td.build-link = link_to ci_project_build_url(build.project, build) do %strong #{build.id} %td.status - = build.status + = ci_status_with_icon(build.status) %td.commit-link = commit_link(build.commit) diff --git a/app/views/ci/admin/projects/_project.html.haml b/app/views/ci/admin/projects/_project.html.haml index 505dd4b3fdc..c461206c72a 100644 --- a/app/views/ci/admin/projects/_project.html.haml +++ b/app/views/ci/admin/projects/_project.html.haml @@ -1,5 +1,5 @@ - last_commit = project.last_commit -%tr.alert{class: commit_status_alert_class(last_commit) } +%tr %td = project.id %td @@ -7,8 +7,9 @@ %strong= project.name %td - if last_commit - #{last_commit.status} (#{commit_link(last_commit)}) + = ci_status_with_icon(last_commit.status) - if project.last_commit_date + · = time_ago_in_words project.last_commit_date ago - else diff --git a/app/views/ci/admin/runners/show.html.haml b/app/views/ci/admin/runners/show.html.haml index 24e0ad3b070..09905e0eb47 100644 --- a/app/views/ci/admin/runners/show.html.haml +++ b/app/views/ci/admin/runners/show.html.haml @@ -102,9 +102,9 @@ %th Finished at - @builds.each do |build| - %tr.build.alert{class: build_status_alert_class(build)} + %tr.build %td.status - = build.status + = ci_status_with_icon(build.status) %td.status = build.project.name diff --git a/app/views/ci/builds/_build.html.haml b/app/views/ci/builds/_build.html.haml index da306c9f020..515b862e992 100644 --- a/app/views/ci/builds/_build.html.haml +++ b/app/views/ci/builds/_build.html.haml @@ -1,6 +1,6 @@ -%tr.build.alert{class: build_status_alert_class(build)} +%tr.build %td.status - = build.status + = ci_status_with_icon(build.status) %td.build-link = link_to ci_project_build_path(build.project, build) do diff --git a/app/views/ci/builds/show.html.haml b/app/views/ci/builds/show.html.haml index d1e955b5012..839dbf5c554 100644 --- a/app/views/ci/builds/show.html.haml +++ b/app/views/ci/builds/show.html.haml @@ -1,15 +1,16 @@ #up-build-trace - if @commit.matrix? - %ul.nav.nav-tabs.append-bottom-10 + %ul.center-top-menu - @commit.builds_without_retry_sorted.each do |build| %li{class: ('active' if build == @build) } = link_to ci_project_build_url(@project, build) do - %i{class: build_icon_css_class(build)} + = ci_icon_for_status(build.status) %span - Build ##{build.id} - if build.name - · = build.name + - else + = build.id + - unless @commit.builds_without_retry.include?(@build) %li.active @@ -19,34 +20,33 @@ %i.fa.fa-warning-sign This build was retried. -.row - .col-md-9 - .build-head.alert{class: build_status_alert_class(@build)} - %h4 - - if @build.commit.tag? - Build for tag - %code #{@build.ref} - - else - Build for commit - %code #{@build.short_sha} - from - - = link_to ci_project_path(@build.project, ref: @build.ref) do - %span.label.label-primary= "#{@build.ref}" - - - if @build.duration - .pull-right - %span - %i.fa.fa-time - #{duration_in_words(@build.finished_at, @build.started_at)} +.gray-content-block + .build-head + %h4 + - if @build.commit.tag? + Build for tag + %code #{@build.ref} + - else + Build for commit + %strong.monospace= commit_link(@build.commit) + from - .clearfix - = @build.status - .pull-right - = @build.updated_at.stamp('19:00 Aug 27') + = link_to ci_project_path(@build.project, ref: @build.ref) do + %strong.monospace= "#{@build.ref}" + - if @build.duration + .pull-right + %span + %i.fa.fa-time + #{duration_in_words(@build.finished_at, @build.started_at)} + .clearfix + = ci_status_with_icon(@build.status) + .pull-right + = @build.updated_at.stamp('19:00 Aug 27') +.row.prepend-top-default + .col-md-9 .clearfix - if @build.active? .autoscroll-container @@ -150,13 +150,16 @@ %h4.title #{pluralize(@builds.count, "other build")} for #{@build.short_sha}: %table.builds - @builds.each_with_index do |build, i| - %tr.build.alert{class: build_status_alert_class(build)} + %tr.build %td - = link_to ci_project_build_url(@project, build) do - %span ##{build.id} + = ci_icon_for_status(build.status) %td - - if build.name - = build.name + = link_to ci_project_build_url(@project, build) do + - if build.name + = build.name + - else + %span ##{build.id} + %td.status= build.status diff --git a/app/views/ci/commits/_commit.html.haml b/app/views/ci/commits/_commit.html.haml index c1b1988d147..1eacfca944f 100644 --- a/app/views/ci/commits/_commit.html.haml +++ b/app/views/ci/commits/_commit.html.haml @@ -1,6 +1,6 @@ -%tr.build.alert{class: commit_status_alert_class(commit)} +%tr.build %td.status - = commit.status + = ci_status_with_icon(commit.status) - if commit.running? · = commit.stage diff --git a/app/views/ci/commits/show.html.haml b/app/views/ci/commits/show.html.haml index 1aeb557314a..8f38aa84676 100644 --- a/app/views/ci/commits/show.html.haml +++ b/app/views/ci/commits/show.html.haml @@ -1,29 +1,34 @@ .commit-info - %pre.commit-message - #{@commit.git_commit_message} + .append-bottom-20 + = ci_status_with_icon(@commit.status) - .row - .col-sm-6 - - if @commit.compare? - %p - %span.attr-name Compare: - #{gitlab_compare_link(@project, @commit.short_before_sha, @commit.short_sha)} - - else - %p - %span.attr-name Commit: - #{gitlab_commit_link(@project, @commit.sha)} + .gray-content-block.middle-block + %pre.commit-message + #{@commit.git_commit_message} + + .gray-content-block.second-block + .row + .col-sm-6 + - if @commit.compare? + %p + %span.attr-name Compare: + #{gitlab_compare_link(@project, @commit.short_before_sha, @commit.short_sha)} + - else + %p + %span.attr-name Commit: + #{gitlab_commit_link(@project, @commit.sha)} - %p - %span.attr-name Branch: - #{gitlab_ref_link(@project, @commit.ref)} - .col-sm-6 - %p - %span.attr-name Author: - #{@commit.git_author_name} (#{@commit.git_author_email}) - - if @commit.created_at %p - %span.attr-name Created at: - #{@commit.created_at.to_s(:short)} + %span.attr-name Branch: + #{gitlab_ref_link(@project, @commit.ref)} + .col-sm-6 + %p + %span.attr-name Author: + #{@commit.git_author_name} (#{@commit.git_author_email}) + - if @commit.created_at + %p + %span.attr-name Created at: + #{@commit.created_at.to_s(:short)} - if current_user && can?(current_user, :manage_builds, gl_project) .pull-right @@ -42,12 +47,6 @@ .bs-callout.bs-callout-warning \.gitlab-ci.yml not found in this commit -%h3 Status - -.build.alert{class: commit_status_alert_class(@commit)} - .status - = @commit.status.titleize - %h3 Builds - if @commit.duration > 0 diff --git a/app/views/ci/helps/oauth2.html.haml b/app/views/ci/helps/oauth2.html.haml deleted file mode 100644 index 2031b7340d4..00000000000 --- a/app/views/ci/helps/oauth2.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -.welcome-block - %h1 - Welcome to GitLab CI - %p - GitLab CI integrates with your GitLab installation and runs tests for your projects. - - %h3 You need only 2 steps to set it up - - %ol - %li - In the GitLab admin area under OAuth applications create a new entry. The redirect url should be - %code= callback_ci_user_sessions_url - %li - Update the GitLab CI config with the application id and the application secret from GitLab. - %li - Restart your GitLab CI instance - %li - Refresh this page when GitLab CI has started again - - diff --git a/app/views/ci/helps/show.html.haml b/app/views/ci/helps/show.html.haml deleted file mode 100644 index 9b32d529c60..00000000000 --- a/app/views/ci/helps/show.html.haml +++ /dev/null @@ -1,40 +0,0 @@ -.jumbotron - %h2 - GitLab CI - %span= GitlabCi::VERSION - %small= GitlabCi::REVISION - %p - GitLab CI integrates with your GitLab installation and run tests for your projects. - %br - Login with your GitLab account, add a project with one click and enjoy running your tests. - %br - Read more about GitLab CI at #{link_to "about.gitlab.com/gitlab-ci", "https://about.gitlab.com/gitlab-ci/", target: "_blank"}. - - -.bs-callout.bs-callout-success - %h4 - = link_to 'https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/api' do - %i.fa.fa-cogs - API - %p Explore how you can access GitLab CI via the API. - -.bs-callout.bs-callout-info - %h4 - = link_to 'https://gitlab.com/gitlab-org/gitlab-ci/tree/master/doc/examples' do - %i.fa.fa-info-sign - Build script examples - %p This includes the build script we use to test GitLab CE. - -.bs-callout.bs-callout-danger - %h4 - = link_to 'https://gitlab.com/gitlab-org/gitlab-ci/issues' do - %i.fa.fa-bug - Issue tracker - %p Reports about recent bugs and problems.. - -.bs-callout.bs-callout-warning - %h4 - = link_to 'http://feedback.gitlab.com/forums/176466-general/category/64310-gitlab-ci' do - %i.fa.fa-thumbs-up - Feedback forum - %p Suggest improvements or new features for GitLab CI. diff --git a/app/views/ci/projects/_form.html.haml b/app/views/ci/projects/_form.html.haml index d50e1a83b06..e782fd8a0f7 100644 --- a/app/views/ci/projects/_form.html.haml +++ b/app/views/ci/projects/_form.html.haml @@ -96,6 +96,5 @@ .form-actions = f.submit 'Save changes', class: 'btn btn-save' - = link_to 'Cancel', projects_path, class: 'btn' - unless @project.new_record? = link_to 'Remove Project', ci_project_path(@project), method: :delete, data: { confirm: 'Project will be removed. Are you sure?' }, class: 'btn btn-danger pull-right' diff --git a/app/views/ci/projects/_gl_projects.html.haml b/app/views/ci/projects/_gl_projects.html.haml deleted file mode 100644 index 7bd30b37caf..00000000000 --- a/app/views/ci/projects/_gl_projects.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -- @gl_projects.sort_by(&:name_with_namespace).each do |project| - %tr.light - %td - = project.name_with_namespace - %td - %small Not added to CI - %td - %td - - if Ci::Project.already_added?(project) - %strong.cgreen - Added - - else - = form_tag ci_projects_path do - = hidden_field_tag :project, project.to_json(methods: [:name_with_namespace, :path_with_namespace, :ssh_url_to_repo]) - = submit_tag 'Add project to CI', class: 'btn btn-default btn-sm' diff --git a/app/views/ci/projects/_project.html.haml b/app/views/ci/projects/_project.html.haml index e4a811119e1..844b6677b3d 100644 --- a/app/views/ci/projects/_project.html.haml +++ b/app/views/ci/projects/_project.html.haml @@ -1,22 +1,37 @@ -- last_commit = project.last_commit -%tr.alert{class: commit_status_alert_class(last_commit) } - %td - = link_to [:ci, project] do - = project.name - %td - - if last_commit - #{last_commit.status} (#{commit_link(last_commit)}) - - if project.last_commit_date - = time_ago_in_words project.last_commit_date - ago - - else - No builds yet - %td - - if project.public - %i.fa.fa-globe - Public - - else - %i.fa.fa-lock - Private - %td - = project.commits.count +- if project.gitlab_ci_project + - ci_project = project.gitlab_ci_project + - last_commit = ci_project.last_commit + %tr + %td + = link_to [:ci, ci_project] do + = ci_project.name + %td + - if last_commit + = ci_status_with_icon(last_commit.status) + = commit_link(last_commit) + · + - if ci_project.last_commit_date + = time_ago_in_words ci_project.last_commit_date + ago + - else + No builds yet + %td + - if ci_project.public + %i.fa.fa-globe + Public + - else + %i.fa.fa-lock + Private + %td + = ci_project.commits.count +- else + %tr.light + %td + = project.name_with_namespace + %td + %small Not added to CI + %td + %td + = form_tag ci_projects_path do + = hidden_field_tag :project, project.to_json(methods: [:name_with_namespace, :path_with_namespace, :ssh_url_to_repo]) + = submit_tag 'Add project to CI', class: 'btn btn-default btn-sm' diff --git a/app/views/ci/projects/_public.html.haml b/app/views/ci/projects/_public.html.haml index c2157ab741a..bcbd60b83f0 100644 --- a/app/views/ci/projects/_public.html.haml +++ b/app/views/ci/projects/_public.html.haml @@ -2,11 +2,6 @@ %h3.project-title Public projects -.bs-callout - = link_to new_ci_user_sessions_path(state: generate_oauth_state(request.fullpath)) do - %strong Login with GitLab - to see your private projects - - if @projects.present? .projects %table.table diff --git a/app/views/ci/projects/_search.html.haml b/app/views/ci/projects/_search.html.haml index 6d84b25a6af..4ab43a403f7 100644 --- a/app/views/ci/projects/_search.html.haml +++ b/app/views/ci/projects/_search.html.haml @@ -5,13 +5,7 @@ .input-group-addon %i.fa.fa-search - :coffeescript $('.ci-search-form').submit -> - NProgress.start() - query = $('.ci-search-form .search-input').val() - $.get '#{gitlab_ci_projects_path}', { search: query }, (data) -> - $(".projects").html data.html - NProgress.done() - CiPager.init "#{gitlab_ci_projects_path}" + "?search=" + query, #{Ci::ProjectsController::PROJECTS_BATCH}, false + CiPager.init "#{ci_projects_path}" + "?search=" + query, #{Ci::ProjectsController::PROJECTS_BATCH}, false false diff --git a/app/views/ci/projects/disabled.html.haml b/app/views/ci/projects/disabled.html.haml new file mode 100644 index 00000000000..83b0d8329e1 --- /dev/null +++ b/app/views/ci/projects/disabled.html.haml @@ -0,0 +1 @@ +Continuous Integration has been disabled for time of the migration. diff --git a/app/views/ci/projects/edit.html.haml b/app/views/ci/projects/edit.html.haml index 79e8fd3a295..876ae5182d4 100644 --- a/app/views/ci/projects/edit.html.haml +++ b/app/views/ci/projects/edit.html.haml @@ -1,6 +1,6 @@ - if @project.generated_yaml_config %p.alert.alert-danger - CI Jobs are deprecated now, you can #{link_to "download", dumped_yaml_ci_project(@project)} + CI Jobs are deprecated now, you can #{link_to "download", dumped_yaml_ci_project_path(@project)} or %a.preview-yml{:href => "#yaml-content", "data-toggle" => "modal"} preview yaml file which is based on your old jobs. diff --git a/app/views/ci/projects/gitlab.html.haml b/app/views/ci/projects/gitlab.html.haml deleted file mode 100644 index 2101aa932a4..00000000000 --- a/app/views/ci/projects/gitlab.html.haml +++ /dev/null @@ -1,27 +0,0 @@ -- if @offset == 0 - .gray-content-block.clearfix.light.second-block - .pull-left.fetch-status - - if params[:search].present? - by keyword: "#{params[:search]}", - #{@total_count} projects, #{@projects.size} of them added to CI - - .wide-table-holder - %table.table.projects-table.content-list - %thead - %tr - %th Project Name - %th Last commit - %th Access - %th Commits - - = render @projects - - = render "gl_projects" - - %p.text-center.hide.loading - %i.fa.fa-refresh.fa-spin - -- else - = render @projects - - = render "gl_projects" diff --git a/app/views/ci/projects/index.html.haml b/app/views/ci/projects/index.html.haml index 60ab29a66cf..2b618d61f79 100644 --- a/app/views/ci/projects/index.html.haml +++ b/app/views/ci/projects/index.html.haml @@ -1,13 +1,30 @@ - if current_user - .gray-content-block.top-block - = render "search" - .projects - %p.fetch-status.light - %i.fa.fa-refresh.fa-spin + - if @offset > 0 + = render @projects + - else + .gray-content-block.top-block + = render "search" + .projects + .gray-content-block.clearfix.light.second-block + .pull-left.fetch-status + - if params[:search].present? + by keyword: "#{params[:search]}", + #{@total_count} projects + + .wide-table-holder + %table.table.projects-table.content-list + %thead + %tr + %th Project Name + %th Last commit + %th Access + %th Commits + + = render @projects + %p.text-center.hide.loading + %i.fa.fa-refresh.fa-spin :coffeescript - $.get '#{gitlab_ci_projects_path}', (data) -> - $(".projects").html data.html - CiPager.init "#{gitlab_ci_projects_path}", #{Ci::ProjectsController::PROJECTS_BATCH}, false + CiPager.init "#{ci_projects_path}", #{Ci::ProjectsController::PROJECTS_BATCH}, false - else = render 'public' diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml index a39e62e9dac..4ecf1c33d2a 100644 --- a/app/views/events/event/_common.html.haml +++ b/app/views/events/event/_common.html.haml @@ -5,13 +5,14 @@ - if event.target %strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target] - at + + = event_preposition(event) - if event.project = link_to_project event.project - else = event.project_name - + - if event.target.respond_to?(:title) .event-body .event-note diff --git a/app/views/groups/milestones/_header_title.html.haml b/app/views/groups/milestones/_header_title.html.haml new file mode 100644 index 00000000000..d7fabf53587 --- /dev/null +++ b/app/views/groups/milestones/_header_title.html.haml @@ -0,0 +1 @@ +- header_title group_title(@group, "Milestones", group_milestones_path(@group)) diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index 8f2decb851f..0c213f42186 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,4 +1,6 @@ - page_title @group_milestone.title, "Milestones" += render "header_title" + %h4.page-title .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } - if @group_milestone.closed? diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index bf4b7234b21..f492aaf4c0a 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -17,6 +17,9 @@ Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises. %br Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank'}. + - if current_application_settings.help_page_text.present? + %hr + = markdown(current_application_settings.help_page_text) %hr diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml index 4f7996e4996..b8d419b5894 100644 --- a/app/views/kaminari/gitlab/_paginator.html.haml +++ b/app/views/kaminari/gitlab/_paginator.html.haml @@ -7,7 +7,7 @@ -# paginator: the paginator that renders the pagination tags inside = paginator.render do %div.gl-pagination - %ul.pagination + %ul.pagination.clearfix = prev_page_tag unless current_page.first? - each_page do |page| - if page.left_outer? || page.right_outer? || page.inside_window? diff --git a/app/views/layouts/ci/_nav_admin.html.haml b/app/views/layouts/ci/_nav_admin.html.haml index c987ab876a3..e9974c85733 100644 --- a/app/views/layouts/ci/_nav_admin.html.haml +++ b/app/views/layouts/ci/_nav_admin.html.haml @@ -1,9 +1,9 @@ %ul.nav.nav-sidebar = nav_link do - = link_to ci_root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do + = link_to admin_root_path, title: 'Back to admin', data: {placement: 'right'}, class: 'back-link' do = icon('caret-square-o-left fw') %span - Back to Dashboard + Back to admin %li.separate-item = nav_link path: 'projects#index' do diff --git a/app/views/layouts/ci/_nav_dashboard.html.haml b/app/views/layouts/ci/_nav_dashboard.html.haml deleted file mode 100644 index fcff405d19d..00000000000 --- a/app/views/layouts/ci/_nav_dashboard.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -%ul.nav.nav-sidebar - = nav_link do - = link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do - = icon('caret-square-o-left fw') - %span - Back to GitLab - %li.separate-item - = nav_link path: 'projects#index' do - = link_to ci_root_path do - %i.fa.fa-home - %span - Projects - - if current_user && current_user.is_admin? - %li - = link_to ci_admin_projects_path do - %i.fa.fa-cogs - %span - Admin - %li - = link_to ci_help_path do - %i.fa.fa-info - %span - Help - diff --git a/app/views/layouts/ci/application.html.haml b/app/views/layouts/ci/application.html.haml index b9f871d5447..38023468d0b 100644 --- a/app/views/layouts/ci/application.html.haml +++ b/app/views/layouts/ci/application.html.haml @@ -2,10 +2,10 @@ %html{ lang: "en"} = render 'layouts/head' %body{class: "ci-body #{user_application_theme}", 'data-page' => body_data_page} - - header_title = "CI Projects" + - header_title = "Continuous Integration" - if current_user = render "layouts/header/default", title: header_title - else = render "layouts/header/public", title: header_title - = render 'layouts/ci/page', sidebar: 'nav_dashboard' + = render 'layouts/ci/page' diff --git a/app/views/layouts/dashboard.html.haml b/app/views/layouts/dashboard.html.haml index fad7de69432..cb96bcc2cf4 100644 --- a/app/views/layouts/dashboard.html.haml +++ b/app/views/layouts/dashboard.html.haml @@ -1,6 +1,5 @@ - page_title "Dashboard" -- unless @header_title - - header_title "Dashboard", root_path +- header_title "Dashboard", root_path unless header_title - sidebar "dashboard" = render template: "layouts/application" diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index 4f00d01d4cd..31888c5580e 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -1,6 +1,5 @@ - page_title @group.name -- unless @header_title - - header_title @group.name, group_path(@group) -- sidebar "group" unless sidebar +- header_title group_title(@group) unless header_title +- sidebar "group" unless sidebar = render template: "layouts/application" diff --git a/app/views/layouts/group_settings.html.haml b/app/views/layouts/group_settings.html.haml index e303a561628..a1a1fc2f858 100644 --- a/app/views/layouts/group_settings.html.haml +++ b/app/views/layouts/group_settings.html.haml @@ -1,4 +1,5 @@ - page_title "Settings" +- header_title group_title(@group, "Settings", edit_group_path(@group)) - sidebar "group_settings" = render template: "layouts/group" diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 3fe0127041e..2079feeeab6 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -4,7 +4,7 @@ = icon('dashboard fw') %span Overview - = nav_link(controller: :projects) do + = nav_link(controller: [:admin, :projects]) do = link_to admin_namespaces_projects_path, title: 'Projects', data: {placement: 'right'} do = icon('cube fw') %span @@ -24,6 +24,11 @@ = icon('key fw') %span Deploy Keys + = nav_link do + = link_to ci_admin_projects_path, title: 'Continuous Integration', data: {placement: 'right'} do + = icon('building fw') + %span + Continuous Integration = nav_link(controller: :logs) do = link_to admin_logs_path, title: 'Logs', data: {placement: 'right'} do = icon('file-text fw') diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index 56283cba6bd..b94165aac39 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -1,5 +1,5 @@ %ul.nav.nav-sidebar - = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do + = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do = link_to root_path, title: 'Projects', data: {placement: 'right'} do = icon('home fw') %span @@ -31,6 +31,11 @@ %span Merge Requests %span.count= current_user.assigned_merge_requests.opened.count + = nav_link(path: ['ci/projects#index', 'ci/projects#disabled']) do + = link_to ci_projects_path, title: 'Continuous Integration', data: {placement: 'right'} do + = icon('building fw') + %span + Continuous Integration = nav_link(controller: :snippets) do = link_to dashboard_snippets_path, title: 'Your snippets', data: {placement: 'right'} do = icon('clipboard fw') @@ -41,13 +46,10 @@ = icon('question-circle fw') %span Help + + %li.separate-item = nav_link(controller: :profile) do = link_to profile_path, title: 'Profile settings', data: {placement: 'bottom'} do = icon('user fw') %span Profile Settings - = nav_link(controller: :ci) do - = link_to ci_root_path, title: 'Continuous Integration', data: {placement: 'right'} do - = icon('building fw') - %span - CI diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 8ce46d4865b..a218ec7486c 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -76,6 +76,13 @@ Merge Requests %span.count.merge_counter= @project.merge_requests.opened.count + - if @project.gitlab_ci? + = nav_link(controller: [:ci, :project]) do + = link_to ci_project_path(@project.gitlab_ci_project), title: 'Continuous Integration', data: {placement: 'right'} do + = icon('building fw') + %span + Continuous Integration + - if project_nav_tab? :settings = nav_link(controller: [:project_members, :teams]) do = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index b80ce0dfc75..dfa6cc5702e 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -1,6 +1,5 @@ - page_title "Profile Settings" -- unless @header_title - - header_title "Profile Settings", profile_path +- header_title "Profile Settings", profile_path unless header_title - sidebar "profile" = render template: "layouts/application" diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 5c4dd67f0ec..78dafcd8bfa 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -1,6 +1,6 @@ - page_title @project.name_with_namespace -- header_title detect_project_title(@project) -- sidebar "project" unless sidebar +- header_title project_title(@project) unless header_title +- sidebar "project" unless sidebar - content_for :scripts_body_top do - if current_user diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml index 43401668334..59ce38f67bb 100644 --- a/app/views/layouts/project_settings.html.haml +++ b/app/views/layouts/project_settings.html.haml @@ -1,4 +1,5 @@ - page_title "Settings" +- header_title project_title(@project, "Settings", edit_project_path(@project)) - sidebar "project_settings" = render template: "layouts/project" diff --git a/app/views/notify/new_user_email.html.haml b/app/views/notify/new_user_email.html.haml index 4feacdaacff..6b9b42dcf37 100644 --- a/app/views/notify/new_user_email.html.haml +++ b/app/views/notify/new_user_email.html.haml @@ -13,4 +13,4 @@ %p = link_to "Click here to set your password", edit_password_url(@user, reset_password_token: @token) %p - = reset_token_expire_message + = raw reset_token_expire_message diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml index 5f6e5f3b644..555ed76426d 100644 --- a/app/views/projects/activity.html.haml +++ b/app/views/projects/activity.html.haml @@ -1,2 +1,4 @@ - page_title "Activity" +- header_title project_title(@project, "Activity", activity_project_path(@project)) + = render 'projects/activity' diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index c1ec42aefca..6518c4173e1 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,4 +1,6 @@ - page_title "Blame", @blob.path, @ref +- header_title project_title(@project, "Files", project_files_path(@project)) + %h3.page-title Blame view #tree-holder.tree-holder diff --git a/app/views/projects/blob/_header_title.html.haml b/app/views/projects/blob/_header_title.html.haml new file mode 100644 index 00000000000..78c5ef20a5f --- /dev/null +++ b/app/views/projects/blob/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Files", project_files_path(@project)) diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml index 2cfb79486dc..1a1df127703 100644 --- a/app/views/projects/blob/_upload.html.haml +++ b/app/views/projects/blob/_upload.html.haml @@ -3,12 +3,12 @@ .modal-content .modal-header %a.close{href: "#", "data-dismiss" => "modal"} × - %h3.page-title #{@title} + %h3.page-title #{title} %p.light From branch %strong= @ref .modal-body - = form_tag @form_path, method: @method, class: 'blob-file-upload-form-js form-horizontal' do + = form_tag form_path, method: method, class: 'blob-file-upload-form-js form-horizontal' do .dropzone .dropzone-previews.blob-upload-dropzone-previews %p.dz-message.light @@ -17,12 +17,12 @@ %br .dropzone-alerts{class: "alert alert-danger data", style: "display:none"} = render 'shared/commit_message_container', params: params, - placeholder: @placeholder + placeholder: placeholder .form-group .col-sm-offset-2.col-sm-10 - = button_tag @button_title, class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all' + = button_tag button_title, class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" :coffeescript disableButtonIfEmptyField $('.blob-file-upload-form-js').find('#commit_message'), '.btn-upload-file' - new BlobFileDropzone($('.blob-file-upload-form-js'), '#{@method}') + new BlobFileDropzone($('.blob-file-upload-form-js'), '#{method}') diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 648f15418e0..a811adc5094 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -1,4 +1,6 @@ - page_title "Edit", @blob.path, @ref += render "header_title" + .file-editor %ul.center-top-menu.no-bottom.js-edit-mode %li.active diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index 68c9ec7f802..1950586b112 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,10 +1,13 @@ +- page_title "New File", @path.presence, @ref += render "header_title" + .gray-content-block.top-block Create a new file or = link_to 'upload', '#modal-upload-blob', { class: 'upload-link', 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} an existing one -= render 'projects/blob/upload' += render 'projects/blob/upload', title: 'Upload', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post .file-editor = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file js-requires-input') do diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 4e66a43bbd5..fa4be4a1bc4 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -1,4 +1,5 @@ - page_title @blob.path, @ref += render "header_title" = render 'projects/last_push' @@ -10,4 +11,8 @@ - if allowed_tree_edit? = render 'projects/blob/remove' - = render 'projects/blob/upload' + + - title = "Replace #{@blob.name}" + = render 'projects/blob/upload', title: title, placeholder: title, + button_title: 'Replace file', form_path: namespace_project_update_blob_path(@project.namespace, @project, @id), + method: :put diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index 6e2dc2d2710..03ade02a0c8 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,4 +1,5 @@ - page_title "Branches" += render "projects/commits/header_title" = render "projects/commits/head" .gray-content-block .pull-right diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index 29e82b93883..f5577042ca4 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -1,4 +1,6 @@ - page_title "New Branch" += render "projects/commits/header_title" + - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 60b112e67d4..f8681024d1b 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,4 +1,5 @@ - page_title "#{@commit.title} (#{@commit.short_id})", "Commits" += render "projects/commits/header_title" = render "commit_box" = render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/notes/notes_with_form", view: params[:view] diff --git a/app/views/projects/commits/_header_title.html.haml b/app/views/projects/commits/_header_title.html.haml new file mode 100644 index 00000000000..e4385893dd9 --- /dev/null +++ b/app/views/projects/commits/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Commits", project_commits_path(@project)) diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index a01a99458a0..2dd99cc8215 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -1,4 +1,5 @@ - page_title "Commits", @ref += render "header_title" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 43d00726c48..02be5a2d07f 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -1,4 +1,5 @@ - page_title "Compare" += render "projects/commits/header_title" = render "projects/commits/head" .gray-content-block diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 8800ffdf482..39755efd2fd 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -1,4 +1,5 @@ - page_title "#{params[:from]}...#{params[:to]}" += render "projects/commits/header_title" = render "projects/commits/head" diff --git a/app/views/projects/graphs/_header_title.html.haml b/app/views/projects/graphs/_header_title.html.haml new file mode 100644 index 00000000000..1e2f61cd22b --- /dev/null +++ b/app/views/projects/graphs/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Graphs", namespace_project_graph_path(@project.namespace, @project, current_ref)) diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index a357736bf52..bf0cac539b8 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -1,4 +1,5 @@ -- page_title "Commit statistics" +- page_title "Commits", "Graphs" += render "header_title" .tree-ref-holder = render 'shared/ref_switcher', destination: 'graphs_commits' = render 'head' diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index ecdd0eaf52f..bd342911e49 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,4 +1,5 @@ -- page_title "Contributor statistics" +- page_title "Contributors", "Graphs" += render "header_title" .tree-ref-holder = render 'shared/ref_switcher', destination: 'graphs' = render 'head' diff --git a/app/views/projects/issues/_header_title.html.haml b/app/views/projects/issues/_header_title.html.haml new file mode 100644 index 00000000000..99f03549c44 --- /dev/null +++ b/app/views/projects/issues/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project)) diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 24314d11404..d6260ab2900 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,4 +1,6 @@ - page_title "Issues" += render "header_title" + = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml index da6edd5c2d2..153447baa1b 100644 --- a/app/views/projects/issues/new.html.haml +++ b/app/views/projects/issues/new.html.haml @@ -1,2 +1,4 @@ - page_title "New Issue" += render "header_title" + = render "form" diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 09080642293..5cb814c9ea8 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -1,4 +1,6 @@ - page_title "#{@issue.title} (##{@issue.iid})", "Issues" += render "header_title" + .issue .issue-details.issuable-details .page-title diff --git a/app/views/projects/labels/_header_title.html.haml b/app/views/projects/labels/_header_title.html.haml new file mode 100644 index 00000000000..abe28da483b --- /dev/null +++ b/app/views/projects/labels/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Labels", namespace_project_labels_path(@project.namespace, @project)) diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index 645402667fd..bc4ab0ca27c 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,4 +1,6 @@ - page_title "Edit", @label.name, "Labels" += render "header_title" + %h3 Edit label %span.light #{@label.name} diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 284adb40e97..97175f8232b 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,4 +1,5 @@ - page_title "Labels" += render "header_title" .gray-content-block.top-block - if can? current_user, :admin_label, @project diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index b3ef17025c3..342ad4f3f95 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,4 +1,6 @@ - page_title "New Label" += render "header_title" + %h3 New label .back-link = link_to namespace_project_labels_path(@project.namespace, @project) do diff --git a/app/views/projects/merge_requests/_header_title.html.haml b/app/views/projects/merge_requests/_header_title.html.haml new file mode 100644 index 00000000000..669a9b06bdf --- /dev/null +++ b/app/views/projects/merge_requests/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project)) diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 61e04dce5ab..0b0f52c653c 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -1,4 +1,6 @@ - page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" += render "header_title" + - if params[:view] == 'parallel' - fluid_layout true diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml index 7e5cb07f249..303ca0a880b 100644 --- a/app/views/projects/merge_requests/edit.html.haml +++ b/app/views/projects/merge_requests/edit.html.haml @@ -1,4 +1,6 @@ - page_title "Edit", "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" += render "header_title" + %h3.page-title = "Edit merge request ##{@merge_request.iid}" %hr diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index d3a576977c2..086298e5af1 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -1,4 +1,6 @@ - page_title "Merge Requests" += render "header_title" + = render 'projects/last_push' .project-issuable-filter .controls diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml index 15bd4e2fafd..fc03ee73a3d 100644 --- a/app/views/projects/merge_requests/invalid.html.haml +++ b/app/views/projects/merge_requests/invalid.html.haml @@ -1,4 +1,6 @@ - page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" += render "header_title" + .merge-request = render "projects/merge_requests/show/mr_title" = render "projects/merge_requests/show/mr_box" diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml index b038a640f67..9fdde80c6d9 100644 --- a/app/views/projects/merge_requests/new.html.haml +++ b/app/views/projects/merge_requests/new.html.haml @@ -1,4 +1,6 @@ - page_title "New Merge Request" += render "header_title" + - if @merge_request.can_be_created = render 'new_submit' - else diff --git a/app/views/projects/milestones/_header_title.html.haml b/app/views/projects/milestones/_header_title.html.haml new file mode 100644 index 00000000000..5f4b6982a6d --- /dev/null +++ b/app/views/projects/milestones/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Milestones", namespace_project_milestones_path(@project.namespace, @project)) diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index c09815a212a..e9dc0b77462 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1,2 +1,3 @@ - page_title "Edit", @milestone.title, "Milestones" += render "header_title" = render "form" diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 2b8fd671587..a207385bd43 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,4 +1,5 @@ - page_title "Milestones" += render "header_title" = render 'shared/milestones_filter' .gray-content-block diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index 47149dfea41..9ba9acb6f77 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,2 +1,3 @@ - page_title "New Milestone" += render "header_title" = render "form" diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 7b1681df336..4eeb0621e52 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,4 +1,6 @@ - page_title @milestone.title, "Milestones" += render "header_title" + %h4.page-title .issue-box{ class: issue_box_class(@milestone) } - if @milestone.closed? diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index 52b5b8b877e..16005161df6 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,4 +1,5 @@ - page_title "Network", @ref += header_title project_title(@project, "Network", namespace_project_network_path(@project.namespace, @project, current_ref)) = render "head" .project-network .controls diff --git a/app/views/projects/project_members/_header_title.html.haml b/app/views/projects/project_members/_header_title.html.haml new file mode 100644 index 00000000000..a31f0a37fa2 --- /dev/null +++ b/app/views/projects/project_members/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Members", namespace_project_project_members_path(@project.namespace, @project)) diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml index 6914543f6da..189906498cb 100644 --- a/app/views/projects/project_members/import.html.haml +++ b/app/views/projects/project_members/import.html.haml @@ -1,4 +1,6 @@ - page_title "Import members" += render "header_title" + %h3.page-title Import members from another project %p.light diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index a40d1513671..9a0a824b811 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,4 +1,5 @@ - page_title "Members" += render "header_title" .gray-content-block.top-block .clearfix.js-toggle-container diff --git a/app/views/projects/snippets/_header_title.html.haml b/app/views/projects/snippets/_header_title.html.haml new file mode 100644 index 00000000000..04f0bbe9853 --- /dev/null +++ b/app/views/projects/snippets/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, "Snippets", namespace_project_snippets_path(@project.namespace, @project)) diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml index 945f0084dff..e69f2d99709 100644 --- a/app/views/projects/snippets/edit.html.haml +++ b/app/views/projects/snippets/edit.html.haml @@ -1,4 +1,6 @@ - page_title "Edit", @snippet.title, "Snippets" += render "header_title" + %h3.page-title Edit snippet %hr diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml index 45d4de6a385..3fed2c9949d 100644 --- a/app/views/projects/snippets/index.html.haml +++ b/app/views/projects/snippets/index.html.haml @@ -1,4 +1,6 @@ - page_title "Snippets" += render "header_title" + %h3.page-title Snippets - if can? current_user, :create_project_snippet, @project diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index e38d95c45e7..67cd69fd215 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -1,4 +1,6 @@ - page_title "New Snippets" += render "header_title" + %h3.page-title New snippet %hr diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index 8cbb813c758..be7d4d486fa 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -1,4 +1,6 @@ - page_title @snippet.title, "Snippets" += render "header_title" + %h3.page-title = @snippet.title diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 1503a4330f4..85d76eae3b5 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,4 +1,5 @@ - page_title "Tags" += render "projects/commits/header_title" = render "projects/commits/head" .gray-content-block diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 172fafdeeff..9f5c1be125c 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -1,4 +1,6 @@ - page_title "New Tag" += render "projects/commits/header_title" + - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index c9e59428e78..dec4677f830 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,4 +1,5 @@ - page_title @path.presence || "Files", @ref +- header_title project_title(@project, "Files", project_files_path(@project)) = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/wikis/_header_title.html.haml b/app/views/projects/wikis/_header_title.html.haml new file mode 100644 index 00000000000..408adc36ca6 --- /dev/null +++ b/app/views/projects/wikis/_header_title.html.haml @@ -0,0 +1 @@ +- header_title project_title(@project, 'Wiki', get_project_wiki_path(@project)) diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 3f1dce1050c..0b709c3695b 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -1,4 +1,6 @@ - page_title "Edit", @page.title, "Wiki" += render "header_title" + = render 'nav' .pull-right = render 'main_links' diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml index ead99412406..c7e490c3cd1 100644 --- a/app/views/projects/wikis/empty.html.haml +++ b/app/views/projects/wikis/empty.html.haml @@ -1,4 +1,6 @@ - page_title "Wiki" += render "header_title" + %h3.page-title Empty page %hr .error_message diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index 226fd3b2290..6417ef4a38b 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -1,4 +1,6 @@ - page_title "Git Access", "Wiki" += render "header_title" + = render 'nav' .gray-content-block .row diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml index 7c81ad53d32..bfbef823b35 100644 --- a/app/views/projects/wikis/history.html.haml +++ b/app/views/projects/wikis/history.html.haml @@ -1,4 +1,6 @@ -- page_title "History", @page.title, "Wiki" +- page_title "History", @page.title.capitalize, "Wiki" += render "header_title" + = render 'nav' .gray-content-block %h3.page-title diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index 7fb91507eb2..03e6a522b25 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,4 +1,6 @@ - page_title "All Pages", "Wiki" += render "header_title" + = render 'nav' .gray-content-block %h3.page-title diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index 126810811ec..55fbf5a8b6e 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -1,4 +1,6 @@ -- page_title @page.title, "Wiki" +- page_title @page.title.capitalize, "Wiki" += render "header_title" + = render 'nav' .gray-content-block diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index 021e3b689a1..330b0626d63 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -8,7 +8,7 @@ = render "shared/projects/project", project: project, avatar: avatar, stars: stars, css_class: css_class - - if projects.count > projects_limit + - if projects.size > projects_limit %li.bottom.center .light #{projects_limit} of #{pluralize(projects.count, 'project')} displayed. diff --git a/app/workers/fork_registration_worker.rb b/app/workers/fork_registration_worker.rb deleted file mode 100644 index fffa8b3a659..00000000000 --- a/app/workers/fork_registration_worker.rb +++ /dev/null @@ -1,12 +0,0 @@ -class ForkRegistrationWorker - include Sidekiq::Worker - - sidekiq_options queue: :default - - def perform(from_project_id, to_project_id, private_token) - from_project = Project.find(from_project_id) - to_project = Project.find(to_project_id) - - from_project.gitlab_ci_service.fork_registration(to_project, private_token) - end -end diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 0005d44e0f2..69cdf497a84 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -96,7 +96,7 @@ production: &base ## Reply by email # Allow users to comment on issues and merge requests by replying to notification emails. - # For documentation on how to set this up, see http://doc.gitlab.com/ce/reply_by_email/README.md + # For documentation on how to set this up, see http://doc.gitlab.com/ce/reply_by_email/README.html reply_by_email: enabled: false address: "replies+%{reply_key}@gitlab.example.com" @@ -306,6 +306,7 @@ production: &base path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) # archive_permissions: 0640 # Permissions for the resulting backup.tar file (default: 0600) # keep_time: 604800 # default: 0 (forever) (in seconds) + # pg_schema: public # default: nil, it means that all schemas will be backed up # upload: # # Fog storage connection settings, see http://fog.io/storage/ . # connection: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index fe81ffd4205..ddc9bbf5dfd 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -178,6 +178,7 @@ Settings.gitlab['import_sources'] ||= ['github','bitbucket','gitlab','gitorious' # CI # Settings['gitlab_ci'] ||= Settingslogic.new({}) +Settings.gitlab_ci['enabled'] = true if Settings.gitlab_ci['enabled'].nil? Settings.gitlab_ci['all_broken_builds'] = true if Settings.gitlab_ci['all_broken_builds'].nil? Settings.gitlab_ci['add_pusher'] = false if Settings.gitlab_ci['add_pusher'].nil? Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url) @@ -219,6 +220,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s # Settings['backup'] ||= Settingslogic.new({}) Settings.backup['keep_time'] ||= 0 +Settings.backup['pg_schema'] = nil Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) Settings.backup['archive_permissions'] ||= 0600 Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil }) diff --git a/config/routes.rb b/config/routes.rb index 41970d2af8a..512dda7b547 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,20 +9,15 @@ Gitlab::Application.routes.draw do resource :lint, only: [:show, :create] - resource :help do - get :oauth2 - end - resources :projects do collection do post :add - get :gitlab + get :disabled end member do get :status, to: 'projects#badge' get :integration - post :build post :toggle_shared_runners get :dumped_yaml end diff --git a/db/fixtures/production/001_admin.rb b/db/fixtures/production/001_admin.rb index 1c8740f6ba9..b0c0b6450f6 100644 --- a/db/fixtures/production/001_admin.rb +++ b/db/fixtures/production/001_admin.rb @@ -19,7 +19,7 @@ admin = User.create( admin.projects_limit = 10000 admin.admin = true admin.save! -admin.confirm! +admin.confirm if admin.valid? puts %Q[ diff --git a/db/migrate/20150817163600_deduplicate_user_identities.rb b/db/migrate/20150817163600_deduplicate_user_identities.rb index fab669c2905..fceffc48018 100644 --- a/db/migrate/20150817163600_deduplicate_user_identities.rb +++ b/db/migrate/20150817163600_deduplicate_user_identities.rb @@ -1,7 +1,7 @@ class DeduplicateUserIdentities < ActiveRecord::Migration def change execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;' - execute 'CREATE TEMPORARY TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;' + execute 'CREATE TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;' execute 'DELETE FROM identities WHERE id NOT IN ( SELECT MIN(id) FROM tt_migration_DeduplicateUserIdentities GROUP BY user_id, provider);' execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;' end diff --git a/db/migrate/20150915001905_enable_ssl_verification_by_default.rb b/db/migrate/20150915001905_enable_ssl_verification_by_default.rb new file mode 100644 index 00000000000..6e924262a13 --- /dev/null +++ b/db/migrate/20150915001905_enable_ssl_verification_by_default.rb @@ -0,0 +1,5 @@ +class EnableSslVerificationByDefault < ActiveRecord::Migration + def change + change_column :web_hooks, :enable_ssl_verification, :boolean, default: true + end +end diff --git a/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb b/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb new file mode 100644 index 00000000000..90ce6c2db3d --- /dev/null +++ b/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb @@ -0,0 +1,8 @@ +class EnableSslVerificationForWebHooks < ActiveRecord::Migration + def up + execute("UPDATE web_hooks SET enable_ssl_verification = true") + end + + def down + end +end diff --git a/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb b/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb new file mode 100644 index 00000000000..37a27f11935 --- /dev/null +++ b/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddHelpPageTextToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :help_page_text, :text + end +end diff --git a/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb b/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb new file mode 100644 index 00000000000..6cf668a170e --- /dev/null +++ b/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb @@ -0,0 +1,5 @@ +class AddCiEnabledToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :ci_enabled, :boolean, null: false, default: true + end +end diff --git a/db/migrate/20150920010715_add_consumed_timestep_to_users.rb b/db/migrate/20150920010715_add_consumed_timestep_to_users.rb new file mode 100644 index 00000000000..c8438b3f6aa --- /dev/null +++ b/db/migrate/20150920010715_add_consumed_timestep_to_users.rb @@ -0,0 +1,5 @@ +class AddConsumedTimestepToUsers < ActiveRecord::Migration + def change + add_column :users, :consumed_timestep, :integer + end +end diff --git a/db/migrate/20150920161119_add_line_code_to_sent_notification.rb b/db/migrate/20150920161119_add_line_code_to_sent_notification.rb new file mode 100644 index 00000000000..d9af4e71751 --- /dev/null +++ b/db/migrate/20150920161119_add_line_code_to_sent_notification.rb @@ -0,0 +1,5 @@ +class AddLineCodeToSentNotification < ActiveRecord::Migration + def change + add_column :sent_notifications, :line_code, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 48314b8db6a..01ccda7a75e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150916145038) do +ActiveRecord::Schema.define(version: 20150920161119) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -45,6 +45,8 @@ ActiveRecord::Schema.define(version: 20150916145038) do t.string "after_sign_out_path" t.integer "session_expire_delay", default: 10080, null: false t.text "import_sources" + t.text "help_page_text" + t.boolean "ci_enabled", default: true, null: false end create_table "audit_events", force: true do |t| @@ -621,6 +623,7 @@ ActiveRecord::Schema.define(version: 20150916145038) do t.integer "recipient_id" t.string "commit_id" t.string "reply_key", null: false + t.string "line_code" end add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree @@ -747,6 +750,7 @@ ActiveRecord::Schema.define(version: 20150916145038) do t.string "public_email", default: "", null: false t.integer "dashboard", default: 0 t.integer "project_view", default: 0 + t.integer "consumed_timestep" end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree @@ -782,7 +786,7 @@ ActiveRecord::Schema.define(version: 20150916145038) do t.boolean "merge_requests_events", default: false, null: false t.boolean "tag_push_events", default: false t.boolean "note_events", default: false, null: false - t.boolean "enable_ssl_verification", default: false + t.boolean "enable_ssl_verification", default: true end add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree diff --git a/doc/ci/api/README.md b/doc/ci/api/README.md index e47e5c46732..33c5b172e98 100644 --- a/doc/ci/api/README.md +++ b/doc/ci/api/README.md @@ -6,7 +6,6 @@ - [Runners](runners.md) - [Commits](commits.md) - [Builds](builds.md) -- [Forks](forks.md) ## Authentication diff --git a/doc/ci/api/forks.md b/doc/ci/api/forks.md deleted file mode 100644 index 8f32e2d3b40..00000000000 --- a/doc/ci/api/forks.md +++ /dev/null @@ -1,23 +0,0 @@ -# Forks API - -This API is intended to aid in the setup and configuration of -forked projects on Gitlab CI. - -__Authentication is done by GitLab user token & GitLab project token__ - -## Forks - -### Create fork for project - - - -``` -POST /ci/forks -``` - -Parameters: - - project_id (required) - The ID of a project - project_token (requires) - Project token - private_token(required) - User private token - data (required) - GitLab project data (name_with_namespace, web_url, default_branch, ssh_url_to_repo) diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md index 362c492d0ac..c565e90da2f 100644 --- a/doc/install/database_mysql.md +++ b/doc/install/database_mysql.md @@ -36,7 +36,7 @@ We do not recommend using MySQL due to various issues. For example, case [(in)se mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; # Grant the GitLab user necessary permissions on the database - mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost'; + mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `gitlabhq_production`.* TO 'git'@'localhost'; # Quit the database session mysql> \q diff --git a/doc/integration/README.md b/doc/integration/README.md index 6d856951d4e..eff39a626ae 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -10,7 +10,7 @@ See the documentation below for details on how to configure these services. - [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider - [Slack](slack.md) Integrate with the Slack chat service - [OAuth2 provider](oauth_provider.md) OAuth2 application creation -- [Gmail](gitlab_buttons_in_gmail.md) Adds GitLab actions to messages +- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html) and [advanced Jenkins support](http://doc.gitlab.com/ee/integration/jenkins.html). diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md new file mode 100644 index 00000000000..de45f25ad62 --- /dev/null +++ b/doc/integration/gmail_action_buttons_for_gitlab.md @@ -0,0 +1,22 @@ +# Gmail actions buttons for GitLab + +GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview). + +If correctly setup, emails that require an action will be marked in Gmail. + +![gmail_actions_button.png](gmail_actions_button.png) + +To get this functioning, you need to be registered with Google. +[See how to register with Google in this document.](https://developers.google.com/gmail/markup/registering-with-google) + +*This process has a lot of steps so make sure that you fulfill all requirements set by Google.* +*Your application will be rejected by Google if you fail to do so.* + +Pay close attention to: + +* Email account used by GitLab to send notification emails needs to have "Consistent history of sending a high volume of mail from your domain (order of hundred emails a day minimum to Gmail) for a few weeks at least". +* "A very very low rate of spam complaints from users." +* Emails must be authenticated via DKIM or SPF +* Before sending the final form("Gmail Schema Whitelist Request"), you must send a real email from your production server. This means that you will have to find a way to send this email from the email address you are registering. You can do this by, for example, forwarding the real email from the email address you are registering or going into the rails console on the GitLab server and triggering the email sending from there. + +You can check how it looks going through all the steps laid out in the "Registering with Google" doc in [this GitLab.com issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/1517). diff --git a/doc/integration/gmail_actions_button.png b/doc/integration/gmail_actions_button.png Binary files differnew file mode 100644 index 00000000000..b08f54d137b --- /dev/null +++ b/doc/integration/gmail_actions_button.png diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md index 13efc8442d2..1e45f29dbb2 100644 --- a/doc/migrate_ci_to_ce/README.md +++ b/doc/migrate_ci_to_ce/README.md @@ -52,7 +52,14 @@ This also breaks your database structure disallowing you to use it anymore. ALTER TABLE web_hooks RENAME TO ci_web_hooks; EOF -### 4. Dump GitLab CI database [CI] +### 4. Remove CI cronjob + +``` +cd /home/gitlab_ci/gitlab-ci +sudo -u gitlab_ci -H bundle exec whenever --clear-crontab +``` + +### 5. Dump GitLab CI database [CI] First check used database and credentials on GitLab CI and GitLab CE/EE: @@ -125,18 +132,18 @@ You will need to put these credentials into commands executed below.** # Filter to only include INSERT statements grep "^\(START\|SET\|INSERT\|COMMIT\)" gitlab_ci.sql.tmp2 > gitlab_ci.sql -### 5. Make sure that your GitLab CE/EE is 8.0 [CE] +### 6. Make sure that your GitLab CE/EE is 8.0 [CE] Please verify that you use GitLab CE/EE 8.0. If not, please follow the update guide: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.14-to-8.0.md -### 6. Stop GitLab CE/EE [CE] +### 7. Stop GitLab CE/EE [CE] Before you can migrate data you need to stop GitLab CE/EE first. sudo service gitlab stop -### 7. Backup GitLab CE/EE [CE] +### 8. Backup GitLab CE/EE [CE] This migration poses a **significant risk** of breaking your GitLab CE/EE. **You should create the GitLab CI/EE backup before doing it.** @@ -144,7 +151,7 @@ This migration poses a **significant risk** of breaking your GitLab CE/EE. cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production -### 8. Copy secret tokens [CE] +### 9. Copy secret tokens [CE] The `secrets.yml` file stores encryption keys for secure variables. @@ -154,7 +161,7 @@ You need to copy the content of `config/secrets.yml` to the same file in GitLab sudo chown git:git /home/git/gitlab/config/secrets.yml sudo chown 0600 /home/git/gitlab/config/secrets.yml -### 9. New configuration options for `gitlab.yml` [CE] +### 10. New configuration options for `gitlab.yml` [CE] There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`: @@ -165,7 +172,7 @@ git diff origin/7-14-stable:config/gitlab.yml.example origin/8-0-stable:config/g The new options include configuration of GitLab CI that are now being part of GitLab CE and EE. -### 10. Copy build logs [CE] +### 11. Copy build logs [CE] You need to copy the contents of `builds/` to the same directory in GitLab CE/EE. @@ -174,7 +181,7 @@ You need to copy the contents of `builds/` to the same directory in GitLab CE/EE The build traces are usually quite big so it will take a significant amount of time. -### 11. Import GitLab CI database [CE] +### 12. Import GitLab CI database [CE] The one of the last steps is to import existing GitLab CI database. @@ -189,13 +196,13 @@ The task does: 1. Fix tags assigned to Builds and Runners 1. Fix services used by CI -### 12. Start GitLab [CE] +### 13. Start GitLab [CE] You can start GitLab CI/EE now and see if everything is working. sudo service gitlab start -### 13. Update nginx [CI] +### 14. Update nginx [CI] Now get back to GitLab CI and update **Nginx** configuration in order to: 1. Have all existing runners able to communicate with a migrated GitLab CI. @@ -263,7 +270,7 @@ You should also make sure that you can do: sudo /etc/init.d/nginx restart -### 14. Done! +### 15. Done! If everything went OK you should be able to access all your GitLab CI data by pointing your browser to: https://gitlab.example.com/ci/. diff --git a/doc/reply_by_email/postfix.md b/doc/reply_by_email/postfix.md index b8ab07d9fe1..c0ac59bb922 100644 --- a/doc/reply_by_email/postfix.md +++ b/doc/reply_by_email/postfix.md @@ -303,8 +303,8 @@ Courier, which we will install later to add IMAP authentication, requires mailbo ## Done! -If all the tests were successfull, Postfix is all set up and ready to receive email! Continue with the [Reply by email](./README.md) guide to configure GitLab. +If all the tests were successful, Postfix is all set up and ready to receive email! Continue with the [Reply by email](./README.md) guide to configure GitLab. --------- -_This document was adapted from https://help.ubuntu.com/community/PostfixBasicSetupHowto, by contributors to the Ubuntu documentation wiki._ +_This document was adapted from https://help.ubuntu.com/community/PostfixBasicSetupHowto, by contributors to the Ubuntu documentation wiki._
\ No newline at end of file diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 7cdcd11c04c..7b294a70fe7 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -72,6 +72,8 @@ access can happen through being a direct member of the project, or through a group. See `def accessible_deploy_keys` in `app/models/user.rb` for more information. +Deploy keys can be shared between projects, you just need to add them to each project. + ## Applications ### Eclipse diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 09400d9b163..f4701bb6db2 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -121,6 +121,12 @@ X-Gitlab-Event: Issue Hook "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" }, + "repository": { + "name": "Gitlab Test", + "url": "http://example.com/gitlabhq/gitlab-test.git", + "description": "Aut reprehenderit ut est.", + "homepage": "http://example.com/gitlabhq/gitlab-test" + }, "object_attributes": { "id": 301, "title": "New API: create/update/delete file", diff --git a/features/project/issues/milestones.feature b/features/project/issues/milestones.feature index bfbaaec5a35..c1a20e9b488 100644 --- a/features/project/issues/milestones.feature +++ b/features/project/issues/milestones.feature @@ -12,13 +12,17 @@ Feature: Project Issues Milestones Given I click link "v2.2" Then I should see milestone "v2.2" - Scenario: I create new milestone + @javascript + Scenario: I create and delete new milestone Given I click link "New Milestone" And I submit new milestone "v2.3" Then I should see milestone "v2.3" + Given I click link to remove milestone + When I visit project "Shop" activity page + Then I should see deleted milestone activity Scenario: I delete new milestone - Given I click link to remove milestone "v2.2" + Given I click link to remove milestone And I should see no milestones @javascript diff --git a/features/steps/admin/settings.rb b/features/steps/admin/settings.rb index 7a6aec23af8..6acbf46eb20 100644 --- a/features/steps/admin/settings.rb +++ b/features/steps/admin/settings.rb @@ -7,6 +7,7 @@ class Spinach::Features::AdminSettings < Spinach::FeatureSteps step 'I modify settings and save form' do uncheck 'Gravatar enabled' fill_in 'Home page URL', with: 'https://about.gitlab.com/' + fill_in 'Help page text', with: 'Example text' click_button 'Save' end diff --git a/features/steps/project/issues/milestones.rb b/features/steps/project/issues/milestones.rb index 61e62c2adbd..c8708572ec6 100644 --- a/features/steps/project/issues/milestones.rb +++ b/features/steps/project/issues/milestones.rb @@ -49,6 +49,11 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps create(:closed_issue, project: project, milestone: milestone) end + step 'I should see deleted milestone activity' do + expect(page).to have_content('opened milestone in') + expect(page).to have_content('destroyed milestone in') + end + When 'I click link "All Issues"' do click_link 'All Issues' end @@ -57,7 +62,7 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps expect(page).to have_selector('#tab-issues li.issue-row', count: 4) end - step 'I click link to remove milestone "v2.2"' do + step 'I click link to remove milestone' do click_link 'Remove' end diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb index 0327fd61981..d3b462bfd31 100644 --- a/features/steps/project/services.rb +++ b/features/steps/project/services.rb @@ -26,13 +26,11 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps step 'I fill gitlab-ci settings' do check 'Active' - fill_in 'Project url', with: 'http://ci.gitlab.org/projects/3' - fill_in 'Token', with: 'verySecret' click_button 'Save' end step 'I should see service settings saved' do - expect(find_field('Project url').value).to eq 'http://ci.gitlab.org/projects/3' + expect(find_field('Active').value).to eq '1' end step 'I click hipchat service link' do diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index ccbe8f96a4c..a9cf426852e 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -51,6 +51,11 @@ module SharedProject visit namespace_project_path(project.namespace, project) end + step 'I visit project "Shop" activity page' do + project = Project.find_by(name: 'Shop') + visit namespace_project_path(project.namespace, project) + end + step 'project "Shop" has push event' do @project = Project.find_by(name: "Shop") diff --git a/lib/api/users.rb b/lib/api/users.rb index ee29f952246..813cc379e43 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -3,7 +3,7 @@ module API class Users < Grape::API before { authenticate! } - resource :users do + resource :users, requirements: { uid: /[0-9]*/, id: /[0-9]*/ } do # Get a users list # # Example Request: diff --git a/lib/backup/database.rb b/lib/backup/database.rb index ce75476a09b..959ac4b7868 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -25,8 +25,12 @@ module Backup when "postgresql" then $progress.print "Dumping PostgreSQL database #{config['database']} ... " pg_env - # Pass '--clean' to include 'DROP TABLE' statements in the DB dump. - system('pg_dump', '--clean', config['database'], out: db_file_name) + pgsql_args = ["--clean"] # Pass '--clean' to include 'DROP TABLE' statements in the DB dump. + if Gitlab.config.backup.pg_schema + pgsql_args << "-n" + pgsql_args << Gitlab.config.backup.pg_schema + end + system('pg_dump', *pgsql_args, config['database'], out: db_file_name) end report_success(success) abort 'Backup failed' unless success diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb index 172c6f22164..5109c84e0ea 100644 --- a/lib/ci/api/api.rb +++ b/lib/ci/api/api.rb @@ -23,6 +23,10 @@ module Ci rack_response({ 'message' => '500 Internal Server Error' }, 500) end + before do + check_enable_flag! + end + format :json helpers Helpers @@ -32,7 +36,6 @@ module Ci mount Commits mount Runners mount Projects - mount Forks mount Triggers end end diff --git a/lib/ci/api/forks.rb b/lib/ci/api/forks.rb deleted file mode 100644 index 152883a599f..00000000000 --- a/lib/ci/api/forks.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Ci - module API - class Forks < Grape::API - resource :forks do - # Create a fork - # - # Parameters: - # project_id (required) - The ID of a project - # project_token (requires) - Project token - # private_token(required) - User private token - # data (required) - GitLab project data (name_with_namespace, web_url, default_branch, ssh_url_to_repo) - # - # - # Example Request: - # POST /forks - post do - required_attributes! [:project_id, :data, :project_token, :private_token] - project = Ci::Project.find_by!(gitlab_id: params[:project_id]) - authenticate_project_token!(project) - - fork = Ci::CreateProjectService.new.execute( - current_user, - params[:data], - Ci::RoutesHelper.ci_project_url(":project_id"), - project - ) - - if fork - present fork, with: Entities::Project - else - not_found! - end - end - end - end - end -end diff --git a/lib/ci/api/helpers.rb b/lib/ci/api/helpers.rb index e602cda81d6..8e893aa5cc6 100644 --- a/lib/ci/api/helpers.rb +++ b/lib/ci/api/helpers.rb @@ -3,6 +3,12 @@ module Ci module Helpers UPDATE_RUNNER_EVERY = 60 + def check_enable_flag! + unless current_application_settings.ci_enabled + render_api_error!('400 (Bad request) CI is disabled', 400) + end + end + def authenticate_runners! forbidden! unless params[:token] == GitlabCi::REGISTRATION_TOKEN end diff --git a/lib/ci/migrate/builds.rb b/lib/ci/migrate/builds.rb new file mode 100644 index 00000000000..fdc143cfad5 --- /dev/null +++ b/lib/ci/migrate/builds.rb @@ -0,0 +1,29 @@ +module Ci + module Migrate + class Builds + attr_reader :app_builds_dir, :backup_builds_tarball, :backup_dir + + def initialize + @app_builds_dir = Settings.gitlab_ci.builds_path + @backup_dir = Gitlab.config.backup.path + @backup_builds_tarball = File.join(backup_dir, 'builds/builds.tar.gz') + end + + def restore + backup_existing_builds_dir + + FileUtils.mkdir_p(app_builds_dir, mode: 0700) + unless system('tar', '-C', app_builds_dir, '-zxvf', backup_builds_tarball) + abort 'Restore failed'.red + end + end + + def backup_existing_builds_dir + timestamped_builds_path = File.join(app_builds_dir, '..', "builds.#{Time.now.to_i}") + if File.exists?(app_builds_dir) + FileUtils.mv(app_builds_dir, File.expand_path(timestamped_builds_path)) + end + end + end + end +end diff --git a/lib/ci/migrate/database.rb b/lib/ci/migrate/database.rb index 74f592dcaea..bf9b80f1f62 100644 --- a/lib/ci/migrate/database.rb +++ b/lib/ci/migrate/database.rb @@ -9,32 +9,32 @@ module Ci @config = YAML.load_file(File.join(Rails.root, 'config', 'database.yml'))[Rails.env] end - def restore(ci_dump) - puts 'Deleting all CI related data ... ' - truncate_ci_tables + def restore + decompress_rd, decompress_wr = IO.pipe + decompress_pid = spawn(*%W(gzip -cd), out: decompress_wr, in: db_file_name) + decompress_wr.close - puts 'Restoring CI data ... ' - case config["adapter"] - when /^mysql/ then - print "Restoring MySQL database #{config['database']} ... " - # Workaround warnings from MySQL 5.6 about passwords on cmd line - ENV['MYSQL_PWD'] = config["password"].to_s if config["password"] - system('mysql', *mysql_args, config['database'], in: ci_dump) - when "postgresql" then - puts "Restoring PostgreSQL database #{config['database']} ... " - pg_env - system('psql', config['database'], '-f', ci_dump) - end + restore_pid = case config["adapter"] + when /^mysql/ then + $progress.print "Restoring MySQL database #{config['database']} ... " + # Workaround warnings from MySQL 5.6 about passwords on cmd line + ENV['MYSQL_PWD'] = config["password"].to_s if config["password"] + spawn('mysql', *mysql_args, config['database'], in: decompress_rd) + when "postgresql" then + $progress.print "Restoring PostgreSQL database #{config['database']} ... " + pg_env + spawn('psql', config['database'], in: decompress_rd) + end + decompress_rd.close + + success = [decompress_pid, restore_pid].all? { |pid| Process.waitpid(pid); $?.success? } + abort 'Restore failed' unless success end protected - def truncate_ci_tables - c = ActiveRecord::Base.connection - c.tables.select { |t| t.start_with?('ci_') }.each do |table| - puts "Deleting data from #{table}..." - c.execute("DELETE FROM #{table}") - end + def db_file_name + File.join(Gitlab.config.backup.path, 'db', 'database.sql.gz') end def mysql_args diff --git a/lib/ci/migrate/manager.rb b/lib/ci/migrate/manager.rb new file mode 100644 index 00000000000..4205809368d --- /dev/null +++ b/lib/ci/migrate/manager.rb @@ -0,0 +1,70 @@ +module Ci + module Migrate + class Manager + def cleanup + $progress.print "Deleting tmp directories ... " + + backup_contents.each do |dir| + next unless File.exist?(File.join(Gitlab.config.backup.path, dir)) + + if FileUtils.rm_rf(File.join(Gitlab.config.backup.path, dir)) + $progress.puts "done".green + else + puts "deleting tmp directory '#{dir}' failed".red + abort 'Backup failed' + end + end + end + + def unpack + Dir.chdir(Gitlab.config.backup.path) + + # check for existing backups in the backup dir + file_list = Dir.glob("*_gitlab_ci_backup.tar").each.map { |f| f.split(/_/).first.to_i } + puts "no backups found" if file_list.count == 0 + + if file_list.count > 1 && ENV["BACKUP"].nil? + puts "Found more than one backup, please specify which one you want to restore:" + puts "rake gitlab:backup:restore BACKUP=timestamp_of_backup" + exit 1 + end + + tar_file = ENV["BACKUP"].nil? ? File.join("#{file_list.first}_gitlab_ci_backup.tar") : File.join(ENV["BACKUP"] + "_gitlab_ci_backup.tar") + + unless File.exists?(tar_file) + puts "The specified CI backup doesn't exist!" + exit 1 + end + + $progress.print "Unpacking backup ... " + + unless Kernel.system(*%W(tar -xf #{tar_file})) + puts "unpacking backup failed".red + exit 1 + else + $progress.puts "done".green + end + + ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0 + + # restoring mismatching backups can lead to unexpected problems + if settings[:gitlab_version] != GitlabCi::VERSION + puts "GitLab CI version mismatch:".red + puts " Your current GitLab CI version (#{GitlabCi::VERSION}) differs from the GitLab CI (#{settings[:gitlab_version]}) version in the backup!".red + exit 1 + end + end + + private + + def backup_contents + ["db", "builds", "backup_information.yml"] + end + + def settings + @settings ||= YAML.load_file("backup_information.yml") + end + end + end +end + diff --git a/lib/ci/migrate/tags.rb b/lib/ci/migrate/tags.rb index 125a535e9a9..97e043ece27 100644 --- a/lib/ci/migrate/tags.rb +++ b/lib/ci/migrate/tags.rb @@ -4,45 +4,38 @@ module Ci module Migrate class Tags def restore - puts 'Migrating tags for Runners... ' - list_objects('Runner').each do |id| - putc '.' - runner = Ci::Runner.find_by_id(id) - if runner - tags = list_tags('Runner', id) - runner.update_attributes(tag_list: tags) + puts 'Inserting tags...' + connection.select_all('SELECT ci_tags.name FROM ci_tags').each do |tag| + begin + connection.execute("INSERT INTO tags (name) VALUES(#{ActiveRecord::Base::sanitize(tag['name'])})") + rescue ActiveRecord::RecordNotUnique end end - puts '' - puts 'Migrating tags for Builds... ' - list_objects('Build').each do |id| - putc '.' - build = Ci::Build.find_by_id(id) - if build - tags = list_tags('Build', id) - build.update_attributes(tag_list: tags) - end + ActiveRecord::Base.transaction do + puts 'Deleting old taggings...' + connection.execute "DELETE FROM taggings WHERE context = 'tags' AND taggable_type LIKE 'Ci::%'" + + puts 'Inserting taggings...' + connection.execute( + 'INSERT INTO taggings (taggable_type, taggable_id, tag_id, context) ' + + "SELECT CONCAT('Ci::', ci_taggings.taggable_type), ci_taggings.taggable_id, tags.id, 'tags' FROM ci_taggings " + + 'JOIN ci_tags ON ci_tags.id = ci_taggings.tag_id ' + + 'JOIN tags ON tags.name = ci_tags.name ' + ) + + puts 'Resetting counters... ' + connection.execute( + 'UPDATE tags SET ' + + 'taggings_count = (SELECT COUNT(*) FROM taggings WHERE tags.id = taggings.tag_id)' + ) end - puts '' end protected - def list_objects(type) - ids = ActiveRecord::Base.connection.select_all( - "select distinct taggable_id from ci_taggings where taggable_type = #{ActiveRecord::Base::sanitize(type)}" - ) - ids.map { |id| id['taggable_id'] } - end - - def list_tags(type, id) - tags = ActiveRecord::Base.connection.select_all( - 'select ci_tags.name from ci_tags ' + - 'join ci_taggings on ci_tags.id = ci_taggings.tag_id ' + - "where taggable_type = #{ActiveRecord::Base::sanitize(type)} and taggable_id = #{ActiveRecord::Base::sanitize(id)} and context = 'tags'" - ) - tags.map { |tag| tag['name'] } + def connection + ActiveRecord::Base.connection end end end diff --git a/lib/ci/project_list_builder.rb b/lib/ci/project_list_builder.rb new file mode 100644 index 00000000000..da26f9a9f47 --- /dev/null +++ b/lib/ci/project_list_builder.rb @@ -0,0 +1,21 @@ +module Ci + class ProjectListBuilder + def execute(current_user, search = nil) + projects = current_user.authorized_projects + projects = projects.search(search) if search + + projects. + joins("LEFT JOIN ci_projects ON projects.id = ci_projects.gitlab_id + LEFT JOIN #{last_commit_subquery} AS last_commit ON #{Ci::Project.table_name}.id = last_commit.project_id"). + reorder("ci_projects.id is NULL ASC, + CASE WHEN last_commit.committed_at IS NULL THEN 1 ELSE 0 END, + last_commit.committed_at DESC") + end + + private + + def last_commit_subquery + "(SELECT project_id, MAX(committed_at) committed_at FROM #{Ci::Commit.table_name} GROUP BY project_id)" + end + end +end diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb index 355fbd27898..341b557858f 100644 --- a/lib/gitlab/email/receiver.rb +++ b/lib/gitlab/email/receiver.rb @@ -98,7 +98,8 @@ module Gitlab note: reply, noteable_type: sent_notification.noteable_type, noteable_id: sent_notification.noteable_id, - commit_id: sent_notification.commit_id + commit_id: sent_notification.commit_id, + line_code: sent_notification.line_code ).execute end end diff --git a/lib/tasks/ci/migrate.rake b/lib/tasks/ci/migrate.rake index e7d41874a11..1de664c85e1 100644 --- a/lib/tasks/ci/migrate.rake +++ b/lib/tasks/ci/migrate.rake @@ -1,40 +1,56 @@ namespace :ci do desc 'GitLab | Import and migrate CI database' task migrate: :environment do + warn_user_is_not_gitlab + configure_cron_mode + unless ENV['force'] == 'yes' - puts "This will truncate all CI tables and restore it from provided backup." - puts "You will lose any previous CI data stored in the database." + puts 'This will remove all CI related data and restore it from the provided backup.' ask_to_continue - puts "" + puts '' end - Rake::Task["ci:migrate:db"].invoke - Rake::Task["ci:migrate:autoincrements"].invoke - Rake::Task["ci:migrate:tags"].invoke - Rake::Task["ci:migrate:services"].invoke + # disable CI for time of migration + enable_ci(false) + + # unpack archives + migrate = Ci::Migrate::Manager.new + migrate.unpack + + Rake::Task['ci:migrate:db'].invoke + Rake::Task['ci:migrate:builds'].invoke + Rake::Task['ci:migrate:tags'].invoke + Rake::Task['ci:migrate:services'].invoke + + # enable CI for time of migration + enable_ci(true) + + migrate.cleanup end namespace :migrate do desc 'GitLab | Import CI database' task db: :environment do - if ENV["CI_DUMP"].nil? - puts "No CI SQL dump specified:" - puts "rake gitlab:backup:restore CI_DUMP=ci_dump.sql" - exit 1 - end - - ci_dump = ENV["CI_DUMP"] - unless File.exists?(ci_dump) - puts "The specified sql dump doesn't exist!" - exit 1 - end + configure_cron_mode + $progress.puts 'Restoring database ... '.blue + Ci::Migrate::Database.new.restore + $progress.puts 'done'.green + end - ::Ci::Migrate::Database.new.restore(ci_dump) + desc 'GitLab | Import CI builds' + task builds: :environment do + configure_cron_mode + $progress.puts 'Restoring builds ... '.blue + Ci::Migrate::Builds.new.restore + $progress.puts 'done'.green end desc 'GitLab | Migrate CI tags' task tags: :environment do + configure_cron_mode + $progress.puts 'Migrating tags ... '.blue ::Ci::Migrate::Tags.new.restore + $progress.puts 'done'.green end desc 'GitLab | Migrate CI auto-increments' @@ -56,8 +72,16 @@ namespace :ci do desc 'GitLab | Migrate CI services' task services: :environment do + $progress.puts 'Migrating services ... '.blue c = ActiveRecord::Base.connection c.execute("UPDATE ci_services SET type=CONCAT('Ci::', type) WHERE type NOT LIKE 'Ci::%'") + $progress.puts 'done'.green end end + + def enable_ci(enabled) + settings = ApplicationSetting.current || ApplicationSetting.create_from_defaults + settings.ci_enabled = enabled + settings.save! + end end diff --git a/spec/controllers/ci/projects_controller_spec.rb b/spec/controllers/ci/projects_controller_spec.rb index 015788a05e1..3e579f9a7d6 100644 --- a/spec/controllers/ci/projects_controller_spec.rb +++ b/spec/controllers/ci/projects_controller_spec.rb @@ -5,49 +5,6 @@ describe Ci::ProjectsController do @project = FactoryGirl.create :ci_project end - describe "POST #build" do - it 'should respond 200 if params is ok' do - post :build, { - id: @project.id, - ref: 'master', - before: '2aa371379db71ac89ae20843fcff3b3477cf1a1d', - after: '1c8a9df454ef68c22c2a33cca8232bb50849e5c5', - token: @project.token, - ci_yaml_file: gitlab_ci_yaml, - commits: [ { message: "Message" } ] - } - - expect(response).to be_success - expect(response.code).to eq('201') - end - - it 'should respond 400 if push about removed branch' do - post :build, { - id: @project.id, - ref: 'master', - before: '2aa371379db71ac89ae20843fcff3b3477cf1a1d', - after: '0000000000000000000000000000000000000000', - token: @project.token, - ci_yaml_file: gitlab_ci_yaml - } - - expect(response).not_to be_success - expect(response.code).to eq('400') - end - - it 'should respond 400 if some params missed' do - post :build, id: @project.id, token: @project.token, ci_yaml_file: gitlab_ci_yaml - expect(response).not_to be_success - expect(response.code).to eq('400') - end - - it 'should respond 403 if token is wrong' do - post :build, id: @project.id, token: 'invalid-token' - expect(response).not_to be_success - expect(response.code).to eq('403') - end - end - describe "POST /projects" do let(:project_dump) { OpenStruct.new({ id: @project.gitlab_id }) } @@ -84,7 +41,7 @@ describe Ci::ProjectsController do end it "searches projects" do - xhr :get, :gitlab, { search: "str", format: "js" }.with_indifferent_access + xhr :get, :index, { search: "str", format: "json" }.with_indifferent_access expect(response).to be_success expect(response.code).to eq('200') diff --git a/spec/controllers/profiles/two_factor_auths_controller_spec.rb b/spec/controllers/profiles/two_factor_auths_controller_spec.rb index f54706e3aa3..4fb1473c2d2 100644 --- a/spec/controllers/profiles/two_factor_auths_controller_spec.rb +++ b/spec/controllers/profiles/two_factor_auths_controller_spec.rb @@ -37,7 +37,7 @@ describe Profiles::TwoFactorAuthsController do context 'with valid pin' do before do - expect(user).to receive(:valid_otp?).with(pin).and_return(true) + expect(user).to receive(:validate_and_consume_otp!).with(pin).and_return(true) end it 'sets two_factor_enabled' do @@ -63,7 +63,7 @@ describe Profiles::TwoFactorAuthsController do context 'with invalid pin' do before do - expect(user).to receive(:valid_otp?).with(pin).and_return(false) + expect(user).to receive(:validate_and_consume_otp!).with(pin).and_return(false) end it 'assigns error' do diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index d3868c13202..35446640929 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -15,8 +15,12 @@ describe Projects::MilestonesController do describe "#destroy" do it "should remove milestone" do expect(issue.milestone_id).to eq(milestone.id) + delete :destroy, namespace_id: project.namespace.id, project_id: project.id, id: milestone.id, format: :js expect(response).to be_success + + expect(Event.first.action).to eq(Event::DESTROYED) + expect { Milestone.find(milestone.id) }.to raise_exception(ActiveRecord::RecordNotFound) issue.reload expect(issue.milestone_id).to eq(nil) diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 5639b3db913..b8101ae77ec 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -38,6 +38,17 @@ describe GitlabMarkdownHelper do expect(markdown(actual)).to match(expected) end end + + describe "override default project" do + let(:actual) { issue.to_reference } + let(:second_project) { create(:project) } + let(:second_issue) { create(:issue, project: second_project) } + + it 'should link to the issue' do + expected = namespace_project_issue_path(second_project.namespace, second_project, second_issue) + expect(markdown(actual, project: second_project)).to match(expected) + end + end end describe '#link_to_gfm' do diff --git a/spec/lib/gitlab/backend/grack_auth_spec.rb b/spec/lib/gitlab/backend/grack_auth_spec.rb index d9676445908..9bed8f8ee5c 100644 --- a/spec/lib/gitlab/backend/grack_auth_spec.rb +++ b/spec/lib/gitlab/backend/grack_auth_spec.rb @@ -180,7 +180,6 @@ describe Grack::Auth do gitlab_ci_service = project.build_gitlab_ci_service gitlab_ci_service.active = true gitlab_ci_service.token = token - gitlab_ci_service.project_url = "http://google.com" gitlab_ci_service.save env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials("gitlab-ci-token", token) diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 97c07ad7d55..2c97a521d96 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -712,7 +712,7 @@ describe Notify do before do user.update_attribute(:email, "user@company.com") - user.confirm! + user.confirm end it "is sent from the committer email" do @@ -730,7 +730,7 @@ describe Notify do before do user.update_attribute(:email, "user@something.company.com") - user.confirm! + user.confirm end it "is sent from the default email" do @@ -748,7 +748,7 @@ describe Notify do before do user.update_attribute(:email, "user@mpany.com") - user.confirm! + user.confirm end it "is sent from the default email" do diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index b6d80451d2e..8f706f8934b 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe Issue, "Issuable" do let(:issue) { create(:issue) } + let(:user) { create(:user) } describe "Associations" do it { is_expected.to belong_to(:project) } @@ -66,4 +67,19 @@ describe Issue, "Issuable" do expect(issue.new?).to be_falsey end end + + + describe "#to_hook_data" do + let(:hook_data) { issue.to_hook_data(user) } + + it "returns correct hook data" do + expect(hook_data[:object_kind]).to eq("issue") + expect(hook_data[:user]).to eq(user.hook_attrs) + expect(hook_data[:repository][:name]).to eq(issue.project.name) + expect(hook_data[:repository][:url]).to eq(issue.project.url_to_repo) + expect(hook_data[:repository][:description]).to eq(issue.project.description) + expect(hook_data[:repository][:homepage]).to eq(issue.project.web_url) + expect(hook_data[:object_attributes]).to eq(issue.hook_attrs) + end + end end diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb index 9445d96c337..230807ea672 100644 --- a/spec/models/project_services/buildkite_service_spec.rb +++ b/spec/models/project_services/buildkite_service_spec.rb @@ -63,19 +63,5 @@ describe BuildkiteService do ) end end - - describe :builds_page do - it 'returns the correct path to the builds page' do - expect(@service.builds_path).to eq( - 'https://buildkite.com/account-name/example-project/builds?branch=default-brancho' - ) - end - end - - describe :status_img_path do - it 'returns the correct path to the status image' do - expect(@service.status_img_path).to eq('https://badge.buildkite.com/secret-sauce-status-token.svg') - end - end end end diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb index bad9a9e6e1a..e9967f5fe0b 100644 --- a/spec/models/project_services/drone_ci_service_spec.rb +++ b/spec/models/project_services/drone_ci_service_spec.rb @@ -34,8 +34,6 @@ describe DroneCiService do it { is_expected.to validate_presence_of(:drone_url) } it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } it { is_expected.to allow_value('http://ci.example.com').for(:drone_url) } - it { is_expected.not_to allow_value('token with spaces').for(:token) } - it { is_expected.not_to allow_value('token/with%spaces').for(:token) } it { is_expected.not_to allow_value('this is not url').for(:drone_url) } it { is_expected.not_to allow_value('http//noturl').for(:drone_url) } it { is_expected.not_to allow_value('ftp://ci.example.com').for(:drone_url) } @@ -48,7 +46,6 @@ describe DroneCiService do it { is_expected.not_to validate_presence_of(:drone_url) } it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } it { is_expected.to allow_value('http://drone.example.com').for(:drone_url) } - it { is_expected.to allow_value('token with spaces').for(:token) } it { is_expected.to allow_value('ftp://drone.example.com').for(:drone_url) } end end diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb index a14384c87b4..e0da04a3f40 100644 --- a/spec/models/project_services/gitlab_ci_service_spec.rb +++ b/spec/models/project_services/gitlab_ci_service_spec.rb @@ -26,51 +26,21 @@ describe GitlabCiService do it { is_expected.to have_one(:service_hook) } end - describe 'validations' do - context 'active' do - before { allow(subject).to receive(:activated?).and_return(true) } - - it { is_expected.to validate_presence_of(:token) } - it { is_expected.to validate_presence_of(:project_url) } - it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } - it { is_expected.to allow_value('http://ci.example.com/project/1').for(:project_url) } - it { is_expected.not_to allow_value('token with spaces').for(:token) } - it { is_expected.not_to allow_value('token/with%spaces').for(:token) } - it { is_expected.not_to allow_value('this is not url').for(:project_url) } - it { is_expected.not_to allow_value('http//noturl').for(:project_url) } - it { is_expected.not_to allow_value('ftp://ci.example.com/projects/3').for(:project_url) } - end - - context 'inactive' do - before { allow(subject).to receive(:activated?).and_return(false) } - - it { is_expected.not_to validate_presence_of(:token) } - it { is_expected.not_to validate_presence_of(:project_url) } - it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) } - it { is_expected.to allow_value('http://ci.example.com/project/1').for(:project_url) } - it { is_expected.to allow_value('token with spaces').for(:token) } - it { is_expected.to allow_value('ftp://ci.example.com/projects/3').for(:project_url) } - end - end - describe 'commits methods' do before do + @ci_project = create(:ci_project) @service = GitlabCiService.new allow(@service).to receive_messages( service_hook: true, project_url: 'http://ci.gitlab.org/projects/2', - token: 'verySecret' + token: 'verySecret', + project: @ci_project.gl_project ) end - describe :commit_status_path do - it { expect(@service.commit_status_path("2ab7834c", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/2ab7834c/status.json?token=verySecret")} - it { expect(@service.commit_status_path("issue#2", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/issue%232/status.json?token=verySecret")} - end - describe :build_page do - it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/2ab7834c")} - it { expect(@service.build_page("issue#2", 'master')).to eq("http://ci.gitlab.org/projects/2/refs/master/commits/issue%232")} + it { expect(@service.build_page("2ab7834c", 'master')).to eq("/ci/projects/#{@ci_project.id}/refs/master/commits/2ab7834c")} + it { expect(@service.build_page("issue#2", 'master')).to eq("/ci/projects/#{@ci_project.id}/refs/master/commits/issue%232")} end describe "execute" do @@ -80,8 +50,6 @@ describe GitlabCiService do it "calls ci_yaml_file" do service_hook = double - expect(service_hook).to receive(:execute) - expect(@service).to receive(:service_hook).and_return(service_hook) expect(@service).to receive(:ci_yaml_file).with(push_sample_data[:checkout_sha]) @service.execute(push_sample_data) @@ -91,7 +59,7 @@ describe GitlabCiService do describe "Fork registration" do before do - @old_project = create(:empty_project) + @old_project = create(:ci_project).gl_project @project = create(:empty_project) @user = create(:user) @@ -104,9 +72,9 @@ describe GitlabCiService do ) end - it "performs http reuquest to ci" do - stub_request(:post, "http://ci.gitlab.org/api/v1/forks") - @service.fork_registration(@project, @user.private_token) + it "creates fork on CI" do + expect_any_instance_of(Ci::CreateProjectService).to receive(:execute) + @service.fork_registration(@project, @user) end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index eeb9069aa17..480950859a2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -188,7 +188,7 @@ describe User do end it 'confirms a user' do - user.confirm! + user.confirm expect(user.confirmed?).to be_truthy end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5bd8206b890..3007a15b0b1 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -89,7 +89,7 @@ describe API::API, api: true do it 'returns projects in the correct order when ci_enabled_first parameter is passed' do [project, project2, project3].each{ |project| project.build_missing_services } - project2.gitlab_ci_service.update(active: true, token: "token", project_url: "http://ci.example.com/projects/1") + project2.gitlab_ci_service.update(active: true, token: "token") get api('/projects', user), { ci_enabled_first: 'true' } expect(response.status).to eq(200) expect(json_response).to be_an Array diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index fb3b235446f..9aa60826f21 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -17,9 +17,9 @@ describe API::API, api: true do it "should return if required fields missing" do attrs = service_attrs - + required_attributes = service_attrs_list.select do |attr| - service_klass.validators_on(attr).any? do |v| + service_klass.validators_on(attr).any? do |v| v.class == ActiveRecord::Validations::PresenceValidator end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index f2aa369985e..f9bc63680ba 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -58,6 +58,11 @@ describe API::API, api: true do expect(response.status).to eq(404) expect(json_response['message']).to eq('404 Not found') end + + it "should return a 404 if invalid ID" do + get api("/users/1ASDF", user) + expect(response.status).to eq(404) + end end describe "POST /users" do @@ -257,6 +262,10 @@ describe API::API, api: true do expect(json_response['message']).to eq('404 Not found') end + it "should raise error for invalid ID" do + expect{put api("/users/ASDF", admin) }.to raise_error(ActionController::RoutingError) + end + it 'should return 400 error if user does not validate' do put api("/users/#{user.id}", admin), password: 'pass', @@ -319,6 +328,10 @@ describe API::API, api: true do post api("/users/#{user.id}/keys", admin), key_attrs end.to change{ user.keys.count }.by(1) end + + it "should raise error for invalid ID" do + expect{post api("/users/ASDF/keys", admin) }.to raise_error(ActionController::RoutingError) + end end describe 'GET /user/:uid/keys' do @@ -346,6 +359,11 @@ describe API::API, api: true do expect(json_response).to be_an Array expect(json_response.first['title']).to eq(key.title) end + + it "should return 404 for invalid ID" do + get api("/users/ASDF/keys", admin) + expect(response.status).to eq(404) + end end end @@ -400,6 +418,10 @@ describe API::API, api: true do post api("/users/#{user.id}/emails", admin), email_attrs end.to change{ user.emails.count }.by(1) end + + it "should raise error for invalid ID" do + expect{post api("/users/ASDF/emails", admin) }.to raise_error(ActionController::RoutingError) + end end describe 'GET /user/:uid/emails' do @@ -427,6 +449,10 @@ describe API::API, api: true do expect(json_response).to be_an Array expect(json_response.first['email']).to eq(email.email) end + + it "should raise error for invalid ID" do + expect{put api("/users/ASDF/emails", admin) }.to raise_error(ActionController::RoutingError) + end end end @@ -463,6 +489,10 @@ describe API::API, api: true do expect(response.status).to eq(404) expect(json_response['message']).to eq('404 Email Not Found') end + + it "should raise error for invalid ID" do + expect{delete api("/users/ASDF/emails/bar", admin) }.to raise_error(ActionController::RoutingError) + end end end @@ -491,6 +521,10 @@ describe API::API, api: true do expect(response.status).to eq(404) expect(json_response['message']).to eq('404 User Not Found') end + + it "should raise error for invalid ID" do + expect{delete api("/users/ASDF", admin) }.to raise_error(ActionController::RoutingError) + end end describe "GET /user" do @@ -553,6 +587,11 @@ describe API::API, api: true do expect(response.status).to eq(404) expect(json_response['message']).to eq('404 Not found') end + + it "should return 404 for invalid ID" do + get api("/users/keys/ASDF", admin) + expect(response.status).to eq(404) + end end describe "POST /user/keys" do @@ -608,6 +647,10 @@ describe API::API, api: true do delete api("/user/keys/#{key.id}") expect(response.status).to eq(401) end + + it "should raise error for invalid ID" do + expect{delete api("/users/keys/ASDF", admin) }.to raise_error(ActionController::RoutingError) + end end describe "GET /user/emails" do @@ -653,6 +696,11 @@ describe API::API, api: true do expect(response.status).to eq(404) expect(json_response['message']).to eq('404 Not found') end + + it "should return 404 for invalid ID" do + get api("/users/emails/ASDF", admin) + expect(response.status).to eq(404) + end end describe "POST /user/emails" do @@ -697,6 +745,10 @@ describe API::API, api: true do delete api("/user/emails/#{email.id}") expect(response.status).to eq(401) end + + it "should raise error for invalid ID" do + expect{delete api("/users/emails/ASDF", admin) }.to raise_error(ActionController::RoutingError) + end end describe 'PUT /user/:id/block' do @@ -748,5 +800,9 @@ describe API::API, api: true do expect(response.status).to eq(404) expect(json_response['message']).to eq('404 User Not Found') end + + it "should raise error for invalid ID" do + expect{put api("/users/ASDF/block", admin) }.to raise_error(ActionController::RoutingError) + end end end diff --git a/spec/requests/ci/api/forks_spec.rb b/spec/requests/ci/api/forks_spec.rb deleted file mode 100644 index 37fa1e82f25..00000000000 --- a/spec/requests/ci/api/forks_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -require 'spec_helper' - -describe Ci::API::API do - include ApiHelpers - - let(:project) { FactoryGirl.create(:ci_project) } - let(:private_token) { create(:user).private_token } - - let(:options) do - { - private_token: private_token, - url: GitlabCi.config.gitlab_ci.url - } - end - - before do - stub_gitlab_calls - end - - - describe "POST /forks" do - let(:project_info) do - { - project_id: project.gitlab_id, - project_token: project.token, - data: { - id: create(:empty_project).id, - name_with_namespace: "Gitlab.org / Underscore", - path_with_namespace: "gitlab-org/underscore", - default_branch: "master", - ssh_url_to_repo: "git@example.com:gitlab-org/underscore" - } - } - end - - context "with valid info" do - before do - options.merge!(project_info) - end - - it "should create a project with valid data" do - post ci_api("/forks"), options - expect(response.status).to eq(201) - expect(json_response['name']).to eq("Gitlab.org / Underscore") - end - end - - context "with invalid project info" do - before do - options.merge!({}) - end - - it "should error with invalid data" do - post ci_api("/forks"), options - expect(response.status).to eq(400) - end - end - end -end diff --git a/spec/services/ci/create_commit_service_spec.rb b/spec/services/ci/create_commit_service_spec.rb index 38d9943765a..84ab0a615dd 100644 --- a/spec/services/ci/create_commit_service_spec.rb +++ b/spec/services/ci/create_commit_service_spec.rb @@ -50,6 +50,19 @@ module Ci end end + it 'fails commits without .gitlab-ci.yml' do + result = service.execute(project, + ref: 'refs/heads/0_1', + before: '00000000', + after: '31das312', + ci_yaml_file: config, + commits: [ { message: 'Message' } ] + ) + expect(result).to be_persisted + expect(result.builds.any?).to be_falsey + expect(result.status).to eq('failed') + end + describe :ci_skip? do it "skips builds creation if there is [ci skip] tag in commit message" do commits = [{ message: "some message[ci skip]" }] diff --git a/spec/services/ci/create_project_service_spec.rb b/spec/services/ci/create_project_service_spec.rb index 64041b8d5a2..c0af515aa8f 100644 --- a/spec/services/ci/create_project_service_spec.rb +++ b/spec/services/ci/create_project_service_spec.rb @@ -7,7 +7,7 @@ describe Ci::CreateProjectService do describe :execute do context 'valid params' do - subject { service.execute(current_user, project, 'http://localhost/projects/:project_id') } + subject { service.execute(current_user, project) } it { is_expected.to be_kind_of(Ci::Project) } it { is_expected.to be_persisted } @@ -24,7 +24,7 @@ describe Ci::CreateProjectService do FactoryGirl.create(:ci_project, shared_runners_enabled: true, public: true, allow_git_fetch: true) end - subject { service.execute(current_user, project, 'http://localhost/projects/:project_id', ci_origin_project) } + subject { service.execute(current_user, project, ci_origin_project) } it "uses project as a template for settings and jobs" do expect(subject.shared_runners_enabled).to be_truthy diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb index 007a9eed192..7756b973ecd 100644 --- a/spec/services/event_create_service_spec.rb +++ b/spec/services/event_create_service_spec.rb @@ -99,5 +99,15 @@ describe EventCreateService do expect { service.close_milestone(milestone, user) }.to change { Event.count } end end + + describe :destroy_mr do + let(:milestone) { create(:milestone) } + + it { expect(service.destroy_milestone(milestone, user)).to be_truthy } + + it "should create new event" do + expect { service.destroy_milestone(milestone, user) }.to change { Event.count } + end + end end end diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index 7c4bb74b77f..18ab333c1d1 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -44,10 +44,11 @@ describe Projects::ForkService do context 'GitLab CI is enabled' do it "calls fork registrator for CI" do + create(:ci_project, gl_project: @from_project) @from_project.build_missing_services @from_project.gitlab_ci_service.update_attributes(active: true) - expect(ForkRegistrationWorker).to receive(:perform_async) + expect_any_instance_of(Ci::CreateProjectService).to receive(:execute) fork_project(@from_project, @to_user) end diff --git a/spec/workers/fork_registration_worker_spec.rb b/spec/workers/fork_registration_worker_spec.rb deleted file mode 100644 index cc6f574b29c..00000000000 --- a/spec/workers/fork_registration_worker_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ - -require 'spec_helper' - -describe ForkRegistrationWorker do - context "as a resque worker" do - it "reponds to #perform" do - expect(ForkRegistrationWorker.new).to respond_to(:perform) - end - end -end |