Commit f40ad6ce403e4365e4b5515cfa593437babb1298
Exists in
master
and in
4 other branches
Merge pull request #5841 from Popl7/archiving_old_projects
Archiving old projects for feature request
Showing
18 changed files
with
251 additions
and
16 deletions
Show diff stats
app/controllers/dashboard_controller.rb
| @@ -73,6 +73,6 @@ class DashboardController < ApplicationController | @@ -73,6 +73,6 @@ class DashboardController < ApplicationController | ||
| 73 | protected | 73 | protected |
| 74 | 74 | ||
| 75 | def load_projects | 75 | def load_projects |
| 76 | - @projects = current_user.authorized_projects.sorted_by_activity | 76 | + @projects = current_user.authorized_projects.sorted_by_activity.non_archived |
| 77 | end | 77 | end |
| 78 | end | 78 | end |
app/controllers/projects_controller.rb
| @@ -5,7 +5,7 @@ class ProjectsController < ApplicationController | @@ -5,7 +5,7 @@ class ProjectsController < ApplicationController | ||
| 5 | 5 | ||
| 6 | # Authorize | 6 | # Authorize |
| 7 | before_filter :authorize_read_project!, except: [:index, :new, :create] | 7 | before_filter :authorize_read_project!, except: [:index, :new, :create] |
| 8 | - before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer] | 8 | + before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] |
| 9 | before_filter :require_non_empty_project, only: [:blob, :tree, :graph] | 9 | before_filter :require_non_empty_project, only: [:blob, :tree, :graph] |
| 10 | 10 | ||
| 11 | layout 'navless', only: [:new, :create, :fork] | 11 | layout 'navless', only: [:new, :create, :fork] |
| @@ -116,6 +116,24 @@ class ProjectsController < ApplicationController | @@ -116,6 +116,24 @@ class ProjectsController < ApplicationController | ||
| 116 | end | 116 | end |
| 117 | end | 117 | end |
| 118 | 118 | ||
| 119 | + def archive | ||
| 120 | + return access_denied! unless can?(current_user, :archive_project, project) | ||
| 121 | + project.archive! | ||
| 122 | + | ||
| 123 | + respond_to do |format| | ||
| 124 | + format.html { redirect_to @project } | ||
| 125 | + end | ||
| 126 | + end | ||
| 127 | + | ||
| 128 | + def unarchive | ||
| 129 | + return access_denied! unless can?(current_user, :archive_project, project) | ||
| 130 | + project.unarchive! | ||
| 131 | + | ||
| 132 | + respond_to do |format| | ||
| 133 | + format.html { redirect_to @project } | ||
| 134 | + end | ||
| 135 | + end | ||
| 136 | + | ||
| 119 | private | 137 | private |
| 120 | 138 | ||
| 121 | def set_title | 139 | def set_title |
app/helpers/search_helper.rb
| @@ -73,14 +73,14 @@ module SearchHelper | @@ -73,14 +73,14 @@ module SearchHelper | ||
| 73 | 73 | ||
| 74 | # Autocomplete results for the current user's projects | 74 | # Autocomplete results for the current user's projects |
| 75 | def projects_autocomplete | 75 | def projects_autocomplete |
| 76 | - current_user.authorized_projects.map do |p| | 76 | + current_user.authorized_projects.non_archived.map do |p| |
| 77 | { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } | 77 | { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } |
| 78 | end | 78 | end |
| 79 | end | 79 | end |
| 80 | 80 | ||
| 81 | # Autocomplete results for the current user's projects | 81 | # Autocomplete results for the current user's projects |
| 82 | def public_projects_autocomplete | 82 | def public_projects_autocomplete |
| 83 | - Project.public_or_internal_only(current_user).map do |p| | 83 | + Project.public_or_internal_only(current_user).non_archived.map do |p| |
| 84 | { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } | 84 | { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } |
| 85 | end | 85 | end |
| 86 | end | 86 | end |
app/models/ability.rb
| @@ -59,31 +59,35 @@ class Ability | @@ -59,31 +59,35 @@ class Ability | ||
| 59 | 59 | ||
| 60 | # Rules based on role in project | 60 | # Rules based on role in project |
| 61 | if team.masters.include?(user) | 61 | if team.masters.include?(user) |
| 62 | - rules << project_master_rules | 62 | + rules += project_master_rules |
| 63 | 63 | ||
| 64 | elsif team.developers.include?(user) | 64 | elsif team.developers.include?(user) |
| 65 | - rules << project_dev_rules | 65 | + rules += project_dev_rules |
| 66 | 66 | ||
| 67 | elsif team.reporters.include?(user) | 67 | elsif team.reporters.include?(user) |
| 68 | - rules << project_report_rules | 68 | + rules += project_report_rules |
| 69 | 69 | ||
| 70 | elsif team.guests.include?(user) | 70 | elsif team.guests.include?(user) |
| 71 | - rules << project_guest_rules | 71 | + rules += project_guest_rules |
| 72 | end | 72 | end |
| 73 | 73 | ||
| 74 | if project.public? || project.internal? | 74 | if project.public? || project.internal? |
| 75 | - rules << public_project_rules | 75 | + rules += public_project_rules |
| 76 | end | 76 | end |
| 77 | 77 | ||
| 78 | if project.owner == user || user.admin? | 78 | if project.owner == user || user.admin? |
| 79 | - rules << project_admin_rules | 79 | + rules += project_admin_rules |
| 80 | end | 80 | end |
| 81 | 81 | ||
| 82 | if project.group && project.group.has_owner?(user) | 82 | if project.group && project.group.has_owner?(user) |
| 83 | - rules << project_admin_rules | 83 | + rules += project_admin_rules |
| 84 | end | 84 | end |
| 85 | 85 | ||
| 86 | - rules.flatten | 86 | + if project.archived? |
| 87 | + rules -= project_archived_rules | ||
| 88 | + end | ||
| 89 | + | ||
| 90 | + rules | ||
| 87 | end | 91 | end |
| 88 | 92 | ||
| 89 | def public_project_rules | 93 | def public_project_rules |
| @@ -125,6 +129,16 @@ class Ability | @@ -125,6 +129,16 @@ class Ability | ||
| 125 | ] | 129 | ] |
| 126 | end | 130 | end |
| 127 | 131 | ||
| 132 | + def project_archived_rules | ||
| 133 | + [ | ||
| 134 | + :write_merge_request, | ||
| 135 | + :push_code, | ||
| 136 | + :push_code_to_protected_branches, | ||
| 137 | + :modify_merge_request, | ||
| 138 | + :admin_merge_request | ||
| 139 | + ] | ||
| 140 | + end | ||
| 141 | + | ||
| 128 | def project_master_rules | 142 | def project_master_rules |
| 129 | project_dev_rules + [ | 143 | project_dev_rules + [ |
| 130 | :push_code_to_protected_branches, | 144 | :push_code_to_protected_branches, |
| @@ -147,7 +161,8 @@ class Ability | @@ -147,7 +161,8 @@ class Ability | ||
| 147 | :change_namespace, | 161 | :change_namespace, |
| 148 | :change_visibility_level, | 162 | :change_visibility_level, |
| 149 | :rename_project, | 163 | :rename_project, |
| 150 | - :remove_project | 164 | + :remove_project, |
| 165 | + :archive_project | ||
| 151 | ] | 166 | ] |
| 152 | end | 167 | end |
| 153 | 168 | ||
| @@ -160,7 +175,7 @@ class Ability | @@ -160,7 +175,7 @@ class Ability | ||
| 160 | 175 | ||
| 161 | # Only group owner and administrators can manage group | 176 | # Only group owner and administrators can manage group |
| 162 | if group.has_owner?(user) || user.admin? | 177 | if group.has_owner?(user) || user.admin? |
| 163 | - rules << [ | 178 | + rules += [ |
| 164 | :manage_group, | 179 | :manage_group, |
| 165 | :manage_namespace | 180 | :manage_namespace |
| 166 | ] | 181 | ] |
| @@ -174,7 +189,7 @@ class Ability | @@ -174,7 +189,7 @@ class Ability | ||
| 174 | 189 | ||
| 175 | # Only namespace owner and administrators can manage it | 190 | # Only namespace owner and administrators can manage it |
| 176 | if namespace.owner == user || user.admin? | 191 | if namespace.owner == user || user.admin? |
| 177 | - rules << [ | 192 | + rules += [ |
| 178 | :manage_namespace | 193 | :manage_namespace |
| 179 | ] | 194 | ] |
| 180 | end | 195 | end |
app/models/project.rb
| @@ -116,6 +116,8 @@ class Project < ActiveRecord::Base | @@ -116,6 +116,8 @@ class Project < ActiveRecord::Base | ||
| 116 | scope :public_only, -> { where(visibility_level: PUBLIC) } | 116 | scope :public_only, -> { where(visibility_level: PUBLIC) } |
| 117 | scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) } | 117 | scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) } |
| 118 | 118 | ||
| 119 | + scope :non_archived, -> { where(archived: false) } | ||
| 120 | + | ||
| 119 | enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab | 121 | enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab |
| 120 | 122 | ||
| 121 | class << self | 123 | class << self |
| @@ -132,7 +134,7 @@ class Project < ActiveRecord::Base | @@ -132,7 +134,7 @@ class Project < ActiveRecord::Base | ||
| 132 | end | 134 | end |
| 133 | 135 | ||
| 134 | def search query | 136 | def search query |
| 135 | - joins(:namespace).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%") | 137 | + joins(:namespace).where("projects.archived = ?", false).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%") |
| 136 | end | 138 | end |
| 137 | 139 | ||
| 138 | def find_with_namespace(id) | 140 | def find_with_namespace(id) |
| @@ -472,4 +474,12 @@ class Project < ActiveRecord::Base | @@ -472,4 +474,12 @@ class Project < ActiveRecord::Base | ||
| 472 | def visibility_level_field | 474 | def visibility_level_field |
| 473 | visibility_level | 475 | visibility_level |
| 474 | end | 476 | end |
| 477 | + | ||
| 478 | + def archive! | ||
| 479 | + update_attribute(:archived, true) | ||
| 480 | + end | ||
| 481 | + | ||
| 482 | + def unarchive! | ||
| 483 | + update_attribute(:archived, false) | ||
| 484 | + end | ||
| 475 | end | 485 | end |
app/views/dashboard/projects.html.haml
| @@ -82,6 +82,10 @@ | @@ -82,6 +82,10 @@ | ||
| 82 | = link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project) | 82 | = link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project) |
| 83 | .project-info | 83 | .project-info |
| 84 | .pull-right | 84 | .pull-right |
| 85 | + - if project.archived? | ||
| 86 | + %span.label | ||
| 87 | + %i.icon-book | ||
| 88 | + Archived | ||
| 85 | - project.labels.each do |label| | 89 | - project.labels.each do |label| |
| 86 | %span.label.label-info | 90 | %span.label.label-info |
| 87 | %i.icon-tag | 91 | %i.icon-tag |
app/views/projects/_home_panel.html.haml
| @@ -7,6 +7,10 @@ | @@ -7,6 +7,10 @@ | ||
| 7 | %span.visibility-level-label | 7 | %span.visibility-level-label |
| 8 | = visibility_level_icon(@project.visibility_level) | 8 | = visibility_level_icon(@project.visibility_level) |
| 9 | = visibility_level_label(@project.visibility_level) | 9 | = visibility_level_label(@project.visibility_level) |
| 10 | + - if @project.archived? | ||
| 11 | + %span.visibility-level-label | ||
| 12 | + %i.icon-book | ||
| 13 | + Archived | ||
| 10 | 14 | ||
| 11 | .span7 | 15 | .span7 |
| 12 | - unless empty_repo | 16 | - unless empty_repo |
app/views/projects/edit.html.haml
| @@ -98,6 +98,33 @@ | @@ -98,6 +98,33 @@ | ||
| 98 | %i.icon-chevron-down | 98 | %i.icon-chevron-down |
| 99 | 99 | ||
| 100 | .js-toggle-visibility-container.hide | 100 | .js-toggle-visibility-container.hide |
| 101 | + - if can? current_user, :archive_project, @project | ||
| 102 | + .ui-box.ui-box-danger | ||
| 103 | + .title | ||
| 104 | + - if @project.archived? | ||
| 105 | + Unarchive project | ||
| 106 | + - else | ||
| 107 | + Archive project | ||
| 108 | + .ui-box-body | ||
| 109 | + - if @project.archived? | ||
| 110 | + %p | ||
| 111 | + Unarchiving the project will mark its repository as active. | ||
| 112 | + %br | ||
| 113 | + The project can be committed to. | ||
| 114 | + %br | ||
| 115 | + %strong Once active this project shows up in the search and on the dashboard. | ||
| 116 | + = link_to 'Unarchive', unarchive_project_path(@project), confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be comitted to again.", method: :post, class: "btn btn-remove" | ||
| 117 | + - else | ||
| 118 | + %p | ||
| 119 | + Archiving the project will mark its repository as read-only. | ||
| 120 | + %br | ||
| 121 | + It is hidden from the dashboard and doesn't show up in searches. | ||
| 122 | + %br | ||
| 123 | + %strong Archived projects cannot be committed to! | ||
| 124 | + = link_to 'Archive', archive_project_path(@project), confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to.", method: :post, class: "btn btn-remove" | ||
| 125 | + - else | ||
| 126 | + %p.nothing_here_message Only the project owner can archive a project | ||
| 127 | + | ||
| 101 | - if can?(current_user, :change_namespace, @project) | 128 | - if can?(current_user, :change_namespace, @project) |
| 102 | .ui-box.ui-box-danger | 129 | .ui-box.ui-box-danger |
| 103 | .title Transfer project | 130 | .title Transfer project |
config/routes.rb
| @@ -170,6 +170,8 @@ Gitlab::Application.routes.draw do | @@ -170,6 +170,8 @@ Gitlab::Application.routes.draw do | ||
| 170 | member do | 170 | member do |
| 171 | put :transfer | 171 | put :transfer |
| 172 | post :fork | 172 | post :fork |
| 173 | + post :archive | ||
| 174 | + post :unarchive | ||
| 173 | get :autocomplete_sources | 175 | get :autocomplete_sources |
| 174 | end | 176 | end |
| 175 | 177 |
db/schema.rb
| @@ -192,6 +192,7 @@ ActiveRecord::Schema.define(version: 20131214224427) do | @@ -192,6 +192,7 @@ ActiveRecord::Schema.define(version: 20131214224427) do | ||
| 192 | t.boolean "imported", default: false, null: false | 192 | t.boolean "imported", default: false, null: false |
| 193 | t.string "import_url" | 193 | t.string "import_url" |
| 194 | t.integer "visibility_level", default: 0, null: false | 194 | t.integer "visibility_level", default: 0, null: false |
| 195 | + t.boolean "archived", default: false, null: false | ||
| 195 | end | 196 | end |
| 196 | 197 | ||
| 197 | add_index "projects", ["creator_id"], name: "index_projects_on_owner_id", using: :btree | 198 | add_index "projects", ["creator_id"], name: "index_projects_on_owner_id", using: :btree |
| @@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
| 1 | +Feature: Dashboard with archived projects | ||
| 2 | + Background: | ||
| 3 | + Given I sign in as a user | ||
| 4 | + And I own project "Shop" | ||
| 5 | + And I own project "Forum" | ||
| 6 | + And project "Forum" is archived | ||
| 7 | + And I visit dashboard page | ||
| 8 | + | ||
| 9 | + Scenario: I should see non-archived projects on dashboard | ||
| 10 | + Then I should see "Shop" project link | ||
| 11 | + And I should not see "Forum" project link | ||
| 12 | + | ||
| 13 | + Scenario: I should see all projects on projects page | ||
| 14 | + And I visit dashboard projects page | ||
| 15 | + Then I should see "Shop" project link | ||
| 16 | + And I should see "Forum" project link |
| @@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
| 1 | +Feature: Project Archived | ||
| 2 | + Background: | ||
| 3 | + Given I sign in as a user | ||
| 4 | + And I own project "Shop" | ||
| 5 | + And I own project "Forum" | ||
| 6 | + | ||
| 7 | + Scenario: I should not see archived on project page of not-archive project | ||
| 8 | + And project "Forum" is archived | ||
| 9 | + And I visit project "Shop" page | ||
| 10 | + Then I should not see "Archived" | ||
| 11 | + | ||
| 12 | + Scenario: I should see archived on project page of archive project | ||
| 13 | + And project "Forum" is archived | ||
| 14 | + And I visit project "Forum" page | ||
| 15 | + Then I should see "Archived" | ||
| 16 | + | ||
| 17 | + Scenario: I should not see archived on projects page with no archived projects | ||
| 18 | + And I visit dashboard projects page | ||
| 19 | + Then I should not see "Archived" | ||
| 20 | + | ||
| 21 | + Scenario: I should see archived on projects page with archived projects | ||
| 22 | + And project "Forum" is archived | ||
| 23 | + And I visit dashboard projects page | ||
| 24 | + Then I should see "Archived" | ||
| 25 | + | ||
| 26 | + Scenario: I archive project | ||
| 27 | + When project "Shop" has push event | ||
| 28 | + And I visit project "Shop" page | ||
| 29 | + And I visit edit project "Shop" page | ||
| 30 | + And I set project archived | ||
| 31 | + Then I should see "Archived" | ||
| 32 | + | ||
| 33 | + Scenario: I unarchive project | ||
| 34 | + When project "Shop" has push event | ||
| 35 | + And project "Shop" is archived | ||
| 36 | + And I visit project "Shop" page | ||
| 37 | + And I visit edit project "Shop" page | ||
| 38 | + And I set project unarchived | ||
| 39 | + Then I should not see "Archived" |
features/steps/dashboard/dashboard_with_archived_projects.rb
0 → 100644
| @@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
| 1 | +class DashboardWithArchivedProjects < Spinach::FeatureSteps | ||
| 2 | + include SharedAuthentication | ||
| 3 | + include SharedPaths | ||
| 4 | + include SharedProject | ||
| 5 | + | ||
| 6 | + When 'project "Forum" is archived' do | ||
| 7 | + project = Project.find_by_name "Forum" | ||
| 8 | + project.update_attribute(:archived, true) | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + Then 'I should see "Shop" project link' do | ||
| 12 | + page.should have_link "Shop" | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + Then 'I should not see "Forum" project link' do | ||
| 16 | + page.should_not have_link "Forum" | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + Then 'I should see "Forum" project link' do | ||
| 20 | + page.should have_link "Forum" | ||
| 21 | + end | ||
| 22 | +end |
| @@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
| 1 | +class ProjectArchived < Spinach::FeatureSteps | ||
| 2 | + include SharedAuthentication | ||
| 3 | + include SharedProject | ||
| 4 | + include SharedPaths | ||
| 5 | + | ||
| 6 | + When 'project "Forum" is archived' do | ||
| 7 | + project = Project.find_by_name "Forum" | ||
| 8 | + project.update_attribute(:archived, true) | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + When 'project "Shop" is archived' do | ||
| 12 | + project = Project.find_by_name "Shop" | ||
| 13 | + project.update_attribute(:archived, true) | ||
| 14 | + end | ||
| 15 | + | ||
| 16 | + When 'I visit project "Forum" page' do | ||
| 17 | + project = Project.find_by_name "Forum" | ||
| 18 | + visit project_path(project) | ||
| 19 | + end | ||
| 20 | + | ||
| 21 | + Then 'I should not see "Archived"' do | ||
| 22 | + page.should_not have_content "Archived" | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + Then 'I should see "Archived"' do | ||
| 26 | + page.should have_content "Archived" | ||
| 27 | + end | ||
| 28 | + | ||
| 29 | + When 'I set project archived' do | ||
| 30 | + click_link "Archive" | ||
| 31 | + end | ||
| 32 | + | ||
| 33 | + When 'I set project unarchived' do | ||
| 34 | + click_link "Unarchive" | ||
| 35 | + end | ||
| 36 | + | ||
| 37 | +end | ||
| 0 | \ No newline at end of file | 38 | \ No newline at end of file |
features/steps/shared/project.rb
| @@ -14,6 +14,13 @@ module SharedProject | @@ -14,6 +14,13 @@ module SharedProject | ||
| 14 | @project.team << [@user, :master] | 14 | @project.team << [@user, :master] |
| 15 | end | 15 | end |
| 16 | 16 | ||
| 17 | + # Create another specific project called "Forum" | ||
| 18 | + And 'I own project "Forum"' do | ||
| 19 | + @project = Project.find_by_name "Forum" | ||
| 20 | + @project ||= create(:project_with_code, name: "Forum", namespace: @user.namespace, path: 'forum_project') | ||
| 21 | + @project.team << [@user, :master] | ||
| 22 | + end | ||
| 23 | + | ||
| 17 | And 'project "Shop" has push event' do | 24 | And 'project "Shop" has push event' do |
| 18 | @project = Project.find_by_name("Shop") | 25 | @project = Project.find_by_name("Shop") |
| 19 | 26 |
spec/models/project_spec.rb
| @@ -21,6 +21,7 @@ | @@ -21,6 +21,7 @@ | ||
| 21 | # imported :boolean default(FALSE), not null | 21 | # imported :boolean default(FALSE), not null |
| 22 | # import_url :string(255) | 22 | # import_url :string(255) |
| 23 | # visibility_level :integer default(0), not null | 23 | # visibility_level :integer default(0), not null |
| 24 | +# archived :boolean default(FALSE), not null | ||
| 24 | # | 25 | # |
| 25 | 26 | ||
| 26 | require 'spec_helper' | 27 | require 'spec_helper' |
spec/requests/api/internal_spec.rb
| @@ -103,6 +103,33 @@ describe API::API do | @@ -103,6 +103,33 @@ describe API::API do | ||
| 103 | end | 103 | end |
| 104 | end | 104 | end |
| 105 | 105 | ||
| 106 | + context "archived project" do | ||
| 107 | + let(:personal_project) { create(:project, namespace: user.namespace) } | ||
| 108 | + | ||
| 109 | + before do | ||
| 110 | + project.team << [user, :developer] | ||
| 111 | + project.archive! | ||
| 112 | + end | ||
| 113 | + | ||
| 114 | + context "git pull" do | ||
| 115 | + it do | ||
| 116 | + pull(key, project) | ||
| 117 | + | ||
| 118 | + response.status.should == 200 | ||
| 119 | + response.body.should == 'true' | ||
| 120 | + end | ||
| 121 | + end | ||
| 122 | + | ||
| 123 | + context "git push" do | ||
| 124 | + it do | ||
| 125 | + push(key, project) | ||
| 126 | + | ||
| 127 | + response.status.should == 200 | ||
| 128 | + response.body.should == 'false' | ||
| 129 | + end | ||
| 130 | + end | ||
| 131 | + end | ||
| 132 | + | ||
| 106 | context "deploy key" do | 133 | context "deploy key" do |
| 107 | let(:key) { create(:deploy_key) } | 134 | let(:key) { create(:deploy_key) } |
| 108 | 135 |