diff options
-rw-r--r-- | CHANGELOG | 3 | ||||
-rw-r--r-- | Gemfile | 4 | ||||
-rw-r--r-- | Gemfile.lock | 10 | ||||
-rw-r--r-- | app/assets/javascripts/notes.js.coffee | 1 | ||||
-rw-r--r-- | app/assets/stylesheets/generic/filters.scss | 55 | ||||
-rw-r--r-- | app/assets/stylesheets/generic/selects.scss | 13 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/issuable.scss | 8 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/issues.scss | 38 | ||||
-rw-r--r-- | app/helpers/labels_helper.rb | 3 | ||||
-rw-r--r-- | app/helpers/milestones_helper.rb | 3 | ||||
-rw-r--r-- | app/views/projects/commit/_commit_box.html.haml | 3 | ||||
-rw-r--r-- | app/views/projects/issues/index.html.haml | 10 | ||||
-rw-r--r-- | app/views/projects/merge_requests/show/_state_widget.html.haml | 2 | ||||
-rw-r--r-- | app/views/shared/_issuable_filter.html.haml | 44 | ||||
-rw-r--r-- | config/gitlab.yml.example | 34 | ||||
-rw-r--r-- | config/initializers/acts_as_taggable_on_patch.rb | 131 | ||||
-rw-r--r-- | doc/ssh/README.md | 2 |
17 files changed, 109 insertions, 255 deletions
diff --git a/CHANGELOG b/CHANGELOG index 3a5749b5e36..d7381261639 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.10.0 (unreleased) - extend the commit calendar to show the actual commits made on a date (Hannes Rosenögger) - Fix a link in the patch update guide - Add a service to support external wikis (Hannes Rosenögger) + - Omit the "email patches" link and fix plain diff view for merge commits - List new commits for newly pushed branch in activity view. - Add sidetiq gem dependency to match EE - Add changelog, license and contribution guide links to project sidebar. @@ -24,6 +25,7 @@ v 7.10.0 (unreleased) - Fix alignment of navbar toggle button (Cody Mize) - Fix checkbox rendering for nested task lists - Identical look of selectboxes in UI + - Upgrade the gitlab_git gem to version 7.1.3 - Move "Import existing repository by URL" option to button. - Improve error message when save profile has error. - Passing the name of pushed ref to CI service (requires GitLab CI 7.9+) @@ -46,6 +48,7 @@ v 7.10.0 (unreleased) - Refactor issue filtering - AJAX selectbox for issue assignee and author filters - Fix issue with missing options in issue filtering dropdown if selected one + - Prevent holding Control-Enter or Command-Enter from posting comment multiple times. - Prevent note form from being cleared when submitting failed. v 7.9.0 @@ -39,7 +39,7 @@ gem "browser" # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.1.2' +gem "gitlab_git", '~> 7.1.3' # Ruby/Rack Git Smart-HTTP Server Handler gem 'gitlab-grack', '~> 2.0.0.rc2', require: 'grack' @@ -115,7 +115,7 @@ end gem "state_machine" # Issue tags -gem "acts-as-taggable-on" +gem 'acts-as-taggable-on', '~> 3.4' # Background jobs gem 'slim' diff --git a/Gemfile.lock b/Gemfile.lock index 7da4d3c3583..ed8663b358b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -33,8 +33,8 @@ GEM minitest (~> 5.1) thread_safe (~> 0.1) tzinfo (~> 1.1) - acts-as-taggable-on (2.4.1) - rails (>= 3, < 5) + acts-as-taggable-on (3.5.0) + activerecord (>= 3.2, < 5) addressable (2.3.5) annotate (2.6.0) activerecord (>= 2.3.0) @@ -212,7 +212,7 @@ GEM mime-types (~> 1.19) gitlab_emoji (0.1.0) gemojione (~> 2.0) - gitlab_git (7.1.2) + gitlab_git (7.1.3) activesupport (~> 4.0) charlock_holmes (~> 0.6) gitlab-linguist (~> 3.0) @@ -662,7 +662,7 @@ PLATFORMS DEPENDENCIES RedCloth ace-rails-ap - acts-as-taggable-on + acts-as-taggable-on (~> 3.4) addressable annotate (~> 2.6.0.beta2) asana (~> 0.0.6) @@ -703,7 +703,7 @@ DEPENDENCIES gitlab-grack (~> 2.0.0.rc2) gitlab-linguist (~> 3.0.1) gitlab_emoji (~> 0.1) - gitlab_git (~> 7.1.2) + gitlab_git (~> 7.1.3) gitlab_meta (= 7.0) gitlab_omniauth-ldap (= 1.2.1) gollum-lib (~> 4.0.2) diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index dc43a06dbe7..6dfe10f0006 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -58,6 +58,7 @@ class @Notes @notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea' # Chrome doesn't fire keypress or keyup for Command+Enter, so we need keydown. $(document).on('keydown', @notes_forms, (e) -> + return if e.originalEvent.repeat if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13) $(@).parents('form').submit() ) diff --git a/app/assets/stylesheets/generic/filters.scss b/app/assets/stylesheets/generic/filters.scss new file mode 100644 index 00000000000..bd93a79722d --- /dev/null +++ b/app/assets/stylesheets/generic/filters.scss @@ -0,0 +1,55 @@ +.filter-item { + margin-right: 15px; +} + +.issues-state-filters { + li.active a { + border-color: #DDD !important; + + &, &:hover, &:active, &.active { + background: #f5f5f5 !important; + border-bottom: 1px solid #f5f5f5 !important; + } + } +} + +.issues-details-filters { + font-size: 13px; + background: #f5f5f5; + margin: -10px 0; + padding: 10px 15px; + margin-top: -15px; + border-left: 1px solid #DDD; + border-right: 1px solid #DDD; + + .btn { + font-size: 13px; + } +} + +@media (min-width: 800px) { + .issues-filters, + .issues_bulk_update { + select, .select2-container { + width: 120px !important; + display: inline-block; + } + } +} + +@media (min-width: 1200px) { + .issues-filters, + .issues_bulk_update { + select, .select2-container { + width: 150px !important; + display: inline-block; + } + } +} + +.issues-filters, +.issues_bulk_update { + .select2-container .select2-choice { + color: #444 !important; + } +} diff --git a/app/assets/stylesheets/generic/selects.scss b/app/assets/stylesheets/generic/selects.scss index 69613608c82..d8e0dc028d1 100644 --- a/app/assets/stylesheets/generic/selects.scss +++ b/app/assets/stylesheets/generic/selects.scss @@ -2,20 +2,25 @@ .select2-container, .select2-container.select2-drop-above { .select2-choice { background: #FFF; - border-color: #CCC; + border-color: #DDD; + height: 34px; padding: 6px 14px; + font-size: 14px; line-height: 1.42857143; - height: auto; + + @include border-radius(4px); .select2-arrow { background: #FFF; - border-left: 1px solid #DDD; + border-left: none; + padding-top: 3px; } } } .select2-container-multi .select2-choices { - @include border-radius(4px) + @include border-radius(4px); + border-color: #CCC; } .select2-container-multi .select2-choices .select2-search-field input { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 13e09d5596f..a640a4e2051 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -45,11 +45,3 @@ .btn { font-size: 13px; } } - -.filter-item { - margin-right: 15px; - - > span { - margin-right: 4px; - } -} diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index 55e648a568f..cd86a9be8b2 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -41,12 +41,9 @@ } .check-all-holder { - height: 36px; + line-height: 36px; float: left; - margin-right: 12px; - padding: 6px 15px; - border: 1px solid #ccc; - @include border-radius(4px); + margin-right: 15px; } .issues_content { @@ -59,33 +56,6 @@ } } -@media (min-width: 800px) { - .issues-filters, - .issues_bulk_update { - select, .select2-container { - width: 120px !important; - display: inline-block; - } - } -} - -@media (min-width: 1200px) { - .issues-filters, - .issues_bulk_update { - select, .select2-container { - width: 140px !important; - display: inline-block; - } - } -} - -.issues-filters, -.issues_bulk_update { - .select2-container .select2-choice { - color: #444 !important; - } -} - .participants { margin-bottom: 20px; } @@ -123,12 +93,12 @@ form.edit-issue { } &.closed { - background: #F5f5f5; + background: #F9F9F9; border-color: #E5E5E5; } &.merged { - background: #F5f5f5; + background: #F9F9F9; border-color: #E5E5E5; } } diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index aa98ead43f1..32ef2e7ca84 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -49,7 +49,6 @@ module LabelsHelper end def project_labels_options(project) - options_for_select([['Any', nil]]) + - options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name]) + options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name]) end end diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index e1dec3ec628..282bdf744d2 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -28,7 +28,6 @@ module MilestonesHelper Milestone.where(project_id: @projects) end.active - options_for_select([['Any', nil]]) + - options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id]) + options_from_collection_for_select(milestones, 'id', 'title', params[:milestone_id]) end end diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index 2579f2cac92..3f645b81397 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -10,7 +10,8 @@ Download as %span.caret %ul.dropdown-menu - %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) + - unless @commit.parents.length > 1 + %li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch) %li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff) = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-primary btn-grouped" do %span Browse Code » diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 210b77a6b15..d3c7ae24a75 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -15,15 +15,5 @@ = render 'shared/issuable_filter' - .clearfix - .issues_bulk_update.hide - = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do - = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control') - = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true) - = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone") - = hidden_field_tag 'update[issues_ids]', [] - = hidden_field_tag :state_event, params[:state_event] - = button_tag "Update issues", class: "btn update_selected_issues btn-save" - .issues-holder = render "issues" diff --git a/app/views/projects/merge_requests/show/_state_widget.html.haml b/app/views/projects/merge_requests/show/_state_widget.html.haml index a4f2a890969..44bd9347f51 100644 --- a/app/views/projects/merge_requests/show/_state_widget.html.haml +++ b/app/views/projects/merge_requests/show/_state_widget.html.haml @@ -29,7 +29,7 @@ %h4 Merge in progress... %p - GitLab tries to merge it right now. During this time merge request is locked and can not be closed. + Merging is in progress. While merging this request is locked and cannot be closed. - unless @commits.any? %h4 Nothing to merge diff --git a/app/views/shared/_issuable_filter.html.haml b/app/views/shared/_issuable_filter.html.haml index 686a3389bb4..f169733f2e9 100644 --- a/app/views/shared/_issuable_filter.html.haml +++ b/app/views/shared/_issuable_filter.html.haml @@ -14,7 +14,7 @@ %i.fa.fa-compass All - %div + .issues-details-filters = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_id, :label_name]), method: :get, class: 'filter-form' do - if controller.controller_name == 'issues' .check-all-holder @@ -23,39 +23,33 @@ disabled: !can?(current_user, :modify_issue, @project) .issues-other-filters .filter-item.inline - %span.light - %i.fa.fa-user - Assignee - %strong - = users_select_tag(:assignee_id, selected: params[:assignee_id], - placeholder: 'Any', class: 'trigger-submit', any_user: true, null_user: true) + = users_select_tag(:assignee_id, selected: params[:assignee_id], + placeholder: 'Assignee', class: 'trigger-submit', any_user: true, null_user: true) .filter-item.inline - %span.light - %i.fa.fa-user - Author - %strong - = users_select_tag(:author_id, selected: params[:author_id], - placeholder: 'Any', class: 'trigger-submit', any_user: true) + = users_select_tag(:author_id, selected: params[:author_id], + placeholder: 'Author', class: 'trigger-submit', any_user: true) - .filter-item.inline - %span.light - %i.fa.fa-clock-o - Milestone - %strong - = select_tag('milestone_id', projects_milestones_options, class: "select2 trigger-submit") + .filter-item.inline.milestone-filter + = select_tag('milestone_id', projects_milestones_options, class: "select2 trigger-submit", prompt: 'Milestone') - if @project - .filter-item.inline - %span.light - %i.fa.fa-tag - Label - %strong - = select_tag('label_name', project_labels_options(@project), class: "select2 trigger-submit") + .filter-item.inline.labels-filter + = select_tag('label_name', project_labels_options(@project), class: "select2 trigger-submit", prompt: 'Label') .pull-right = render 'shared/sort_dropdown' + - if controller.controller_name == 'issues' + .issues_bulk_update.hide + = form_tag bulk_update_namespace_project_issues_path(@project.namespace, @project), method: :post do + = select_tag('update[state_event]', options_for_select([['Open', 'reopen'], ['Closed', 'close']]), prompt: "Status", class: 'form-control') + = users_select_tag('update[assignee_id]', placeholder: 'Assignee', null_user: true) + = select_tag('update[milestone_id]', bulk_update_milestone_options, prompt: "Milestone") + = hidden_field_tag 'update[issues_ids]', [] + = hidden_field_tag :state_event, params[:state_event] + = button_tag "Update issues", class: "btn update_selected_issues btn-save" + :coffeescript new UsersSelect() diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c4a0fefb7ab..3f1ca34a667 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -2,6 +2,11 @@ # GitLab application config file # # # # # # # # # # # # # # # # # # # # +########################### NOTE ##################################### +# This file should not receive new settings. All configuration options # +# are being moved to ApplicationSetting model! # +######################################################################## +# # How to use: # 1. Copy file as gitlab.yml # 2. Update gitlab -> host with your fully qualified domain name @@ -81,35 +86,6 @@ production: &base # The default is 'tmp/repositories' relative to the root of the Rails app. # repository_downloads_path: tmp/repositories - ## External issues trackers - issues_tracker: - # redmine: - # title: "Redmine" - # ## If not nil, link 'Issues' on project page will be replaced with this - # ## Use placeholders: - # ## :project_id - GitLab project identifier - # ## :issues_tracker_id - Project Name or Id in external issue tracker - # project_url: "http://redmine.sample/projects/:issues_tracker_id" - # - # ## If not nil, links from /#\d/ entities from commit messages will replaced with this - # ## Use placeholders: - # ## :project_id - GitLab project identifier - # ## :issues_tracker_id - Project Name or Id in external issue tracker - # ## :id - Issue id (from commit messages) - # issues_url: "http://redmine.sample/issues/:id" - # - # ## If not nil, links to creating new issues will be replaced with this - # ## Use placeholders: - # ## :project_id - GitLab project identifier - # ## :issues_tracker_id - Project Name or Id in external issue tracker - # new_issue_url: "http://redmine.sample/projects/:issues_tracker_id/issues/new" - # - # jira: - # title: "Atlassian Jira" - # project_url: "http://jira.sample/issues/?jql=project=:issues_tracker_id" - # issues_url: "http://jira.sample/browse/:id" - # new_issue_url: "http://jira.sample/secure/CreateIssue.jspa" - ## Gravatar ## For Libravatar see: http://doc.gitlab.com/ce/customization/libravatar.html gravatar: diff --git a/config/initializers/acts_as_taggable_on_patch.rb b/config/initializers/acts_as_taggable_on_patch.rb deleted file mode 100644 index 0d535cb5cac..00000000000 --- a/config/initializers/acts_as_taggable_on_patch.rb +++ /dev/null @@ -1,131 +0,0 @@ -# This is a patch to address the issue in https://github.com/mbleigh/acts-as-taggable-on/issues/427 caused by -# https://github.com/rails/rails/commit/31a43ebc107fbd50e7e62567e5208a05909ec76c -# gem 'acts-as-taggable-on' has the fix included https://github.com/mbleigh/acts-as-taggable-on/commit/89bbed3864a9252276fb8dd7d535fce280454b90 -# but not in the currently used version of gem ('2.4.1') -# With replacement of 'acts-as-taggable-on' gem this file will become obsolete - -module ActsAsTaggableOn::Taggable - module Core - module ClassMethods - def tagged_with(tags, options = {}) - tag_list = ActsAsTaggableOn::TagList.from(tags) - empty_result = where("1 = 0") - - return empty_result if tag_list.empty? - - joins = [] - conditions = [] - having = [] - select_clause = [] - - context = options.delete(:on) - owned_by = options.delete(:owned_by) - alias_base_name = undecorated_table_name.gsub('.','_') - quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : '' - - if options.delete(:exclude) - if options.delete(:wild) - tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(" OR ") - else - tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ") - end - - conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)})" - - if owned_by - joins << "JOIN #{ActsAsTaggableOn::Tagging.table_name}" + - " ON #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + - " AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)}" + - " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = #{owned_by.id}" + - " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = #{quote_value(owned_by.class.base_class.to_s, nil)}" - end - - elsif options.delete(:any) - # get tags, drop out if nothing returned (we need at least one) - tags = - if options.delete(:wild) - ActsAsTaggableOn::Tag.named_like_any(tag_list) - else - ActsAsTaggableOn::Tag.named_any(tag_list) - end - - return empty_result unless tags.length > 0 - - # setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123 - # avoid ambiguous column name - taggings_context = context ? "_#{context}" : '' - - taggings_alias = adjust_taggings_alias( - "#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:name).join('_'))}" - ) - - tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" + - " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + - " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" - tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context - - # don't need to sanitize sql, map all ids and join with OR logic - conditions << tags.map { |t| "#{taggings_alias}.tag_id = #{t.id}" }.join(" OR ") - select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one? - - if owned_by - tagging_join << " AND " + - sanitize_sql([ - "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", - owned_by.id, - owned_by.class.base_class.to_s - ]) - end - - joins << tagging_join - else - tags = ActsAsTaggableOn::Tag.named_any(tag_list) - - return empty_result unless tags.length == tag_list.length - - tags.each do |tag| - taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}") - tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" + - " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + - " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" + - " AND #{taggings_alias}.tag_id = #{tag.id}" - - tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context - - if owned_by - tagging_join << " AND " + - sanitize_sql([ - "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?", - owned_by.id, - owned_by.class.base_class.to_s - ]) - end - - joins << tagging_join - end - end - - taggings_alias, tags_alias = adjust_taggings_alias("#{alias_base_name}_taggings_group"), "#{alias_base_name}_tags_group" - - if options.delete(:match_all) - joins << "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" + - " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" + - " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" - - - group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" - group = group_columns - having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}" - end - - select(select_clause) \ - .joins(joins.join(" ")) \ - .where(conditions.join(" AND ")) \ - .group(group) \ - .having(having) \ - .order(options[:order]) \ - .readonly(false) - end - end - end -end diff --git a/doc/ssh/README.md b/doc/ssh/README.md index 66941521c2e..0acb15896d3 100644 --- a/doc/ssh/README.md +++ b/doc/ssh/README.md @@ -68,6 +68,6 @@ You can't add the same deploy key twice with the 'New Deploy Key' option. If you want to add the same key to another project, please enable it in the list that says 'Deploy keys from projects available to you'. All the deploy keys of all the projects you have access to are available. This project -access can happen through being a direct member of the projecti, or through +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. |