diff options
author | Lin Jen-Shin (godfat) <godfat@godfat.org> | 2017-10-30 12:24:17 +0300 |
---|---|---|
committer | Lin Jen-Shin (godfat) <godfat@godfat.org> | 2017-10-30 12:24:17 +0300 |
commit | 39ec9bd4e635c3f6bc00a2dadd0359619a64236f (patch) | |
tree | fdb5b97e0e866f4ebbf8c9d078277f952f494ef4 | |
parent | 88c97c19edd80ac63b668467942224268851fe7a (diff) | |
parent | 6ea7132559a35c482d642bc79c44cca7482c9054 (diff) |
Merge branch '10-1-stable-patch-1' into '10-1-stable'
Prepare 10.1.1 release
See merge request gitlab-org/gitlab-ce!15027
41 files changed, 423 insertions, 99 deletions
diff --git a/app/assets/javascripts/registry/stores/actions.js b/app/assets/javascripts/registry/stores/actions.js index 34ed40b8b65..795b39bb3dc 100644 --- a/app/assets/javascripts/registry/stores/actions.js +++ b/app/assets/javascripts/registry/stores/actions.js @@ -29,11 +29,9 @@ export const fetchList = ({ commit }, { repo, page }) => { }); }; -export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath) - .then(res => res.json()); +export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath); -export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath) - .then(res => res.json()); +export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath); export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data); export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING); diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js index 61734163b6e..d8e1a462987 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js @@ -286,6 +286,7 @@ export default { <input id="remove-source-branch-input" v-model="removeSourceBranch" + class="js-remove-source-branch-checkbox" :disabled="isRemoveSourceBranchButtonDisabled" type="checkbox"/> Remove source branch </label> @@ -311,8 +312,8 @@ export default { </button> </template> <template v-else> - <span class="bold"> - The pipeline for this merge request has not succeeded yet + <span class="bold js-resolve-mr-widget-items-message"> + You can only merge once the items above are resolved </span> </template> </div> diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 04b132415eb..f0cad30f4f3 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -249,13 +249,12 @@ width: 100%; padding-right: 5px; } - } .discussion-actions { display: table; - .new-issue-for-discussion path { + .btn-default path { fill: $gray-darkest; } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 96b7db3b85d..36a7fc0d3e1 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -466,6 +466,10 @@ ul.notes { float: right; margin-left: 10px; color: $gray-darkest; + + .btn-group > .discussion-next-btn { + margin-left: -1px; + } } .note-actions { diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index b7a108a0ebd..fe1334c0cfe 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -16,7 +16,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action :authorize_create_issue!, only: [:new, :create] # Allow modify issue - before_action :authorize_update_issue!, only: [:update, :move] + before_action :authorize_update_issue!, only: [:edit, :update, :move] # Allow create a new branch and empty WIP merge request from current issue before_action :authorize_create_merge_request!, only: [:create_merge_request] @@ -63,6 +63,10 @@ class Projects::IssuesController < Projects::ApplicationController respond_with(@issue) end + def edit + respond_with(@issue) + end + def show @noteable = @issue @note = @project.notes.new(noteable: @issue) @@ -122,6 +126,10 @@ class Projects::IssuesController < Projects::ApplicationController @issue = Issues::UpdateService.new(project, current_user, update_params).execute(issue) respond_to do |format| + format.html do + recaptcha_check_with_fallback { render :edit } + end + format.json do render_issue_json end diff --git a/app/models/environment.rb b/app/models/environment.rb index b6868ccbe8f..e613d21add6 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -110,7 +110,7 @@ class Environment < ActiveRecord::Base end def ref_path - "refs/#{Repository::REF_ENVIRONMENTS}/#{Shellwords.shellescape(name)}" + "refs/#{Repository::REF_ENVIRONMENTS}/#{generate_slug}" end def formatted_external_url diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index 8ba07173c74..5c0b3338a62 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -153,7 +153,10 @@ class KubernetesService < DeploymentService end def default_namespace - "#{project.path}-#{project.id}" if project.present? + return unless project + + slug = "#{project.path}-#{project.id}".downcase + slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '') end def build_kubeclient!(api_path: 'api', api_version: 'v1') diff --git a/app/services/users/last_push_event_service.rb b/app/services/users/last_push_event_service.rb index f2bfb60604f..57e446d7f30 100644 --- a/app/services/users/last_push_event_service.rb +++ b/app/services/users/last_push_event_service.rb @@ -16,8 +16,8 @@ module Users user_cache_key ] - if event.project.forked? - keys << project_cache_key(event.project.forked_from_project) + if forked_from = event.project.forked_from_project + keys << project_cache_key(forked_from) end keys.each { |key| set_key(key, event.id) } diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml new file mode 100644 index 00000000000..1b7d878c38c --- /dev/null +++ b/app/views/projects/issues/edit.html.haml @@ -0,0 +1,7 @@ +- page_title "Edit", "#{@issue.title} (#{@issue.to_reference})", "Issues" + +%h3.page-title + Edit Issue ##{@issue.iid} +%hr + += render "form" diff --git a/changelogs/unreleased/39188-change-default-disabled-merge-message.yml b/changelogs/unreleased/39188-change-default-disabled-merge-message.yml new file mode 100644 index 00000000000..7de65f5c3f6 --- /dev/null +++ b/changelogs/unreleased/39188-change-default-disabled-merge-message.yml @@ -0,0 +1,5 @@ +--- +title: Update default disabled merge request widget message to reflect a general failure +merge_request: 14960 +author: +type: changed diff --git a/changelogs/unreleased/39441-bring-edit-form-back.yml b/changelogs/unreleased/39441-bring-edit-form-back.yml new file mode 100644 index 00000000000..025417e4da9 --- /dev/null +++ b/changelogs/unreleased/39441-bring-edit-form-back.yml @@ -0,0 +1,5 @@ +--- +title: Fix editing issue description in mobile view +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/39495-fix-bitbucket-login.yml b/changelogs/unreleased/39495-fix-bitbucket-login.yml new file mode 100644 index 00000000000..b48d557108b --- /dev/null +++ b/changelogs/unreleased/39495-fix-bitbucket-login.yml @@ -0,0 +1,5 @@ +--- +title: Fix bitbucket login +merge_request: 15051 +author: +type: fixed diff --git a/changelogs/unreleased/bvl-dont-rename-free-names.yml b/changelogs/unreleased/bvl-dont-rename-free-names.yml new file mode 100644 index 00000000000..60a4ec8afbe --- /dev/null +++ b/changelogs/unreleased/bvl-dont-rename-free-names.yml @@ -0,0 +1,5 @@ +--- +title: Don't rename paths that were freed up when upgrading +merge_request: 15029 +author: +type: fixed diff --git a/changelogs/unreleased/bvl-fix-push-event-service-for-forks.yml b/changelogs/unreleased/bvl-fix-push-event-service-for-forks.yml new file mode 100644 index 00000000000..2a7d80270ac --- /dev/null +++ b/changelogs/unreleased/bvl-fix-push-event-service-for-forks.yml @@ -0,0 +1,5 @@ +--- +title: Only cache last push event for existing projects when pushing to a fork +merge_request: 14989 +author: +type: fixed diff --git a/changelogs/unreleased/fix-add-path-attr-to-wiki-file.yml b/changelogs/unreleased/fix-add-path-attr-to-wiki-file.yml new file mode 100644 index 00000000000..0847b5f6733 --- /dev/null +++ b/changelogs/unreleased/fix-add-path-attr-to-wiki-file.yml @@ -0,0 +1,5 @@ +--- +title: Fix broken wiki pages that link to a wiki file +merge_request: 15019 +author: +type: fixed diff --git a/changelogs/unreleased/mr-14642.yml b/changelogs/unreleased/mr-14642.yml new file mode 100644 index 00000000000..048cc79e323 --- /dev/null +++ b/changelogs/unreleased/mr-14642.yml @@ -0,0 +1,6 @@ +--- +title: Auto Devops kubernetes default namespace is now correctly built out of gitlab + project group-name +merge_request: 14642 +author: Mircea Danila Dumitrescu +type: fixed diff --git a/changelogs/unreleased/sh-fix-container-registry-destroy.yml b/changelogs/unreleased/sh-fix-container-registry-destroy.yml new file mode 100644 index 00000000000..21a463da62a --- /dev/null +++ b/changelogs/unreleased/sh-fix-container-registry-destroy.yml @@ -0,0 +1,5 @@ +--- +title: Fix deletion of container registry or images returning an error +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/sh-fix-environment-write-ref.yml b/changelogs/unreleased/sh-fix-environment-write-ref.yml new file mode 100644 index 00000000000..8f291843ebe --- /dev/null +++ b/changelogs/unreleased/sh-fix-environment-write-ref.yml @@ -0,0 +1,5 @@ +--- +title: Fix the writing of invalid environment refs +merge_request: +author: +type: fixed diff --git a/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb b/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb index 9441b236c8d..2125cc046e5 100644 --- a/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb +++ b/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb @@ -13,7 +13,6 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration .well-known abuse_reports admin - all api assets autocomplete @@ -24,29 +23,20 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration groups health_check help - hooks import invites - issues jwt koding - member - merge_requests - new - notes notification_settings oauth profile projects public - repository robots.txt s search sent_notifications - services snippets - teams u unicorn_test unsubscribes @@ -94,7 +84,6 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration notification_setting pipeline_quota projects - subgroups ].freeze def up diff --git a/doc/administration/logs.md b/doc/administration/logs.md index 76e071dc673..c9ed2d84ccb 100644 --- a/doc/administration/logs.md +++ b/doc/administration/logs.md @@ -18,8 +18,7 @@ other than production, the corresponding logfile is shown here.) It contains a structured log for Rails controller requests received from GitLab, thanks to [Lograge](https://github.com/roidrage/lograge/). Note that -requests from the API [are not yet logged to this -file](https://gitlab.com/gitlab-org/gitlab-ce/issues/36189). +requests from the API are logged to a separate file in `api_json.log`. Each line contains a JSON line that can be ingested by Elasticsearch, Splunk, etc. For example: @@ -73,6 +72,27 @@ In this example we can see that server processed an HTTP request with URL 19:34:53 +0200. Also we can see that request was processed by `Projects::TreeController`. +## `api_json.log` + +Introduced in GitLab 10.0, this file lives in +`/var/log/gitlab/gitlab-rails/api_json.log` for Omnibus GitLab packages or in +`/home/git/gitlab/log/api_json.log` for installations from source. + +It helps you see requests made directly to the API. For example: + +```json +{"time":"2017-10-10T12:30:11.579Z","severity":"INFO","duration":16.84,"db":1.57,"view":15.27,"status":200,"method":"POST","path":"/api/v4/internal/allowed","params":{"action":"git-upload-pack","changes":"_any","gl_repository":null,"project":"root/foobar.git","protocol":"ssh","env":"{}","key_id":"[FILTERED]","secret_token":"[FILTERED]"},"host":"127.0.0.1","ip":"127.0.0.1","ua":"Ruby"} +``` + +This entry above shows an access to an internal endpoint to check whether an +associated SSH key can download the project in question via a `git fetch` or +`git clone`. In this example, we see: + +1. `method`: The HTTP method used to make the request +1. `path`: The relative path of the query +1. `params`: Key-value pairs passed in a query string or HTTP body. Sensitive parameters (e.g. passwords, tokens, etc.) are filtered out. +1. `ua`: The User-Agent of the requester + ## `application.log` This file lives in `/var/log/gitlab/gitlab-rails/application.log` for diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 17839cbaef1..73568757aaa 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -43,6 +43,7 @@ future GitLab releases.** | **CI_COMMIT_TAG** | 9.0 | 0.5 | The commit tag name. Present only when building tags. | | **CI_CONFIG_PATH** | 9.4 | 0.5 | The path to CI config file. Defaults to `.gitlab-ci.yml` | | **CI_DEBUG_TRACE** | all | 1.7 | Whether [debug tracing](#debug-tracing) is enabled | +| **CI_DISPOSABLE_ENVIRONMENT** | all | 10.1 | Mark that job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. | | **CI_ENVIRONMENT_NAME** | 8.15 | all | The name of the environment for this job | | **CI_ENVIRONMENT_SLUG** | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. | | **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job | @@ -73,6 +74,7 @@ future GitLab releases.** | **CI_SERVER_NAME** | all | all | The name of CI server that is used to coordinate jobs | | **CI_SERVER_REVISION** | all | all | GitLab revision that is used to schedule jobs | | **CI_SERVER_VERSION** | all | all | GitLab version that is used to schedule jobs | +| **CI_SHARED_ENVIRONMENT** | all | 10.1 | Mark that job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. | | **ARTIFACT_DOWNLOAD_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to download artifacts running a job | | **GET_SOURCES_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to fetch sources running a job | | **GITLAB_CI** | all | all | Mark that job is executed in GitLab CI environment | diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md index bf01fe51dc3..5cc014419ad 100644 --- a/doc/gitlab-basics/add-merge-request.md +++ b/doc/gitlab-basics/add-merge-request.md @@ -3,31 +3,28 @@ Merge requests are useful to integrate separate changes that you've made to a project, on different branches. This is a brief guide on how to create a merge request. For more information, check the -[merge requests documentation](../user/project/merge_requests.md). +[merge requests documentation](../user/project/merge_requests/index.md). --- 1. Before you start, you should have already [created a branch](create-branch.md) and [pushed your changes](basic-git-commands.md) to GitLab. - -1. You can then go to the project where you'd like to merge your changes and - click on the **Merge requests** tab. - - ![Merge requests](img/project_navbar.png) - +1. Go to the project where you'd like to merge your changes and click on the + **Merge requests** tab. 1. Click on **New merge request** on the right side of the screen. - - ![New Merge Request](img/merge_request_new.png) - -1. Select a source branch and click on the **Compare branches and continue** button. +1. From there on, you have the option to select the source branch and the target + branch you'd like to compare to. The default target project is the upstream + repository, but you can choose to compare across any of its forks. ![Select a branch](img/merge_request_select_branch.png) +1. When ready, click on the **Compare branches and continue** button. 1. At a minimum, add a title and a description to your merge request. Optionally, select a user to review your merge request and to accept or close it. You may also select a milestone and labels. ![New merge request page](img/merge_request_page.png) -1. When ready, click on the **Submit merge request** button. Your merge request - will be ready to be approved and published. +1. When ready, click on the **Submit merge request** button. + +Your merge request will be ready to be approved and merged. diff --git a/doc/gitlab-basics/img/merge_request_new.png b/doc/gitlab-basics/img/merge_request_new.png Binary files differdeleted file mode 100644 index 6fcd7bebada..00000000000 --- a/doc/gitlab-basics/img/merge_request_new.png +++ /dev/null diff --git a/doc/gitlab-basics/img/merge_request_select_branch.png b/doc/gitlab-basics/img/merge_request_select_branch.png Binary files differindex 9f6b93943a9..57ea0e65f34 100644 --- a/doc/gitlab-basics/img/merge_request_select_branch.png +++ b/doc/gitlab-basics/img/merge_request_select_branch.png diff --git a/doc/gitlab-basics/img/project_navbar.png b/doc/gitlab-basics/img/project_navbar.png Binary files differdeleted file mode 100644 index be6f38ede32..00000000000 --- a/doc/gitlab-basics/img/project_navbar.png +++ /dev/null diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 6289fcf3c2b..4b2e042251b 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -34,7 +34,6 @@ With **[GitLab Enterprise Edition][ee]**, you can also: - View the deployment process across projects with [Multi-Project Pipeline Graphs](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html#multi-project-pipeline-graphs) (available only in GitLab Enterprise Edition Premium) - Request [approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers (available in GitLab Enterprise Edition Starter) - [Squash and merge](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html) for a cleaner commit history (available in GitLab Enterprise Edition Starter) -- Enable [semi-linear history merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#semi-linear-history-merge-requests) as another security layer to guarantee the pipeline is passing in the target branch (available in GitLab Enterprise Edition Starter) - Analise the impact of your changes with [Code Quality reports](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality_diff.html) (available in GitLab Enterprise Edition Starter) ## Use cases diff --git a/lib/gitlab/git/wiki_file.rb b/lib/gitlab/git/wiki_file.rb index 527f2a44dea..84335aca4bc 100644 --- a/lib/gitlab/git/wiki_file.rb +++ b/lib/gitlab/git/wiki_file.rb @@ -1,7 +1,7 @@ module Gitlab module Git class WikiFile - attr_reader :mime_type, :raw_data, :name + attr_reader :mime_type, :raw_data, :name, :path # This class is meant to be serializable so that it can be constructed # by Gitaly and sent over the network to GitLab. @@ -13,6 +13,7 @@ module Gitlab @mime_type = gollum_file.mime_type @raw_data = gollum_file.raw_data @name = gollum_file.name + @path = gollum_file.path end end end diff --git a/lib/gitlab/performance_bar/peek_query_tracker.rb b/lib/gitlab/performance_bar/peek_query_tracker.rb index 67fee8c227d..69e117f1da9 100644 --- a/lib/gitlab/performance_bar/peek_query_tracker.rb +++ b/lib/gitlab/performance_bar/peek_query_tracker.rb @@ -36,8 +36,8 @@ module Gitlab end def track_query(raw_query, bindings, start, finish) - query = Gitlab::Sherlock::Query.new(raw_query, start, finish) - query_info = { duration: query.duration.round(3), sql: query.formatted_query } + duration = finish - start + query_info = { duration: duration.round(3), sql: raw_query } PEEK_DB_CLIENT.query_details << query_info end diff --git a/lib/omni_auth/strategies/bitbucket.rb b/lib/omni_auth/strategies/bitbucket.rb index 5a7d67c2390..ce1bdfe6ee4 100644 --- a/lib/omni_auth/strategies/bitbucket.rb +++ b/lib/omni_auth/strategies/bitbucket.rb @@ -36,6 +36,10 @@ module OmniAuth email_response = access_token.get('api/2.0/user/emails').parsed @emails ||= email_response && email_response['values'] || nil end + + def callback_url + options[:redirect_uri] || (full_host + script_name + callback_path) + end end end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index ed8088a46f0..2ab7246e42b 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -557,6 +557,29 @@ describe Projects::IssuesController do end end end + + describe 'GET #edit' do + it_behaves_like 'restricted action', success: 200 + + def go(id:) + get :edit, + namespace_id: project.namespace.to_param, + project_id: project, + id: id + end + end + + describe 'PUT #update' do + it_behaves_like 'restricted action', success: 302 + + def go(id:) + put :update, + namespace_id: project.namespace.to_param, + project_id: project, + id: id, + issue: { title: 'New title' } + end + end end describe 'POST #create' do diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index 8ce470fc288..2db6f9a2982 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -218,15 +218,54 @@ describe 'New/edit issue', :js do context 'edit issue' do before do - visit project_issue_path(project, issue) - page.within('.content .issuable-actions') do - click_on 'Edit' + visit edit_project_issue_path(project, issue) + end + + it 'allows user to update issue' do + expect(find('input[name="issue[assignee_ids][]"]', visible: false).value).to match(user.id.to_s) + expect(find('input[name="issue[milestone_id]"]', visible: false).value).to match(milestone.id.to_s) + expect(find('a', text: 'Assign to me', visible: false)).not_to be_visible + + page.within '.js-user-search' do + expect(page).to have_content user.name + end + + page.within '.js-milestone-select' do + expect(page).to have_content milestone.title + end + + click_button 'Labels' + page.within '.dropdown-menu-labels' do + click_link label.title + click_link label2.title + end + page.within '.js-label-select' do + expect(page).to have_content label.title + end + expect(page.all('input[name="issue[label_ids][]"]', visible: false)[1].value).to match(label.id.to_s) + expect(page.all('input[name="issue[label_ids][]"]', visible: false)[2].value).to match(label2.id.to_s) + + click_button 'Save changes' + + page.within '.issuable-sidebar' do + page.within '.assignee' do + expect(page).to have_content user.name + end + + page.within '.milestone' do + expect(page).to have_content milestone.title + end + + page.within '.labels' do + expect(page).to have_content label.title + expect(page).to have_content label2.title + end end end it 'description has autocomplete' do - find_field('issue-description').native.send_keys('') - fill_in 'issue-description', with: '@' + find('#issue_description').native.send_keys('') + fill_in 'issue_description', with: '@' expect(page).to have_selector('.atwho-view') end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 25e99774575..d4fd3a50008 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Issues', :js do +describe 'Issues' do include DropzoneHelper include IssueHelpers include SortingHelper @@ -24,15 +24,109 @@ describe 'Issues', :js do end before do - visit project_issue_path(project, issue) - page.within('.content .issuable-actions') do - find('.issuable-edit').click - end - find('.issue-details .content-block .js-zen-enter').click + visit edit_project_issue_path(project, issue) + find('.js-zen-enter').click end it 'opens new issue popup' do - expect(page).to have_content(issue.description) + expect(page).to have_content("Issue ##{issue.iid}") + end + end + + describe 'Editing issue assignee' do + let!(:issue) do + create(:issue, + author: user, + assignees: [user], + project: project) + end + + it 'allows user to select unassigned', :js do + visit edit_project_issue_path(project, issue) + + expect(page).to have_content "Assignee #{user.name}" + + first('.js-user-search').click + click_link 'Unassigned' + + click_button 'Save changes' + + page.within('.assignee') do + expect(page).to have_content 'No assignee - assign yourself' + end + + expect(issue.reload.assignees).to be_empty + end + end + + describe 'due date', :js do + context 'on new form' do + before do + visit new_project_issue_path(project) + end + + it 'saves with due date' do + date = Date.today.at_beginning_of_month + + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + find('#issuable-due-date').click + + page.within '.pika-single' do + click_button date.day + end + + expect(find('#issuable-due-date').value).to eq date.to_s + + click_button 'Submit issue' + + page.within '.issuable-sidebar' do + expect(page).to have_content date.to_s(:medium) + end + end + end + + context 'on edit form' do + let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) } + + before do + visit edit_project_issue_path(project, issue) + end + + it 'saves with due date' do + date = Date.today.at_beginning_of_month + + expect(find('#issuable-due-date').value).to eq date.to_s + + date = date.tomorrow + + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + find('#issuable-due-date').click + + page.within '.pika-single' do + click_button date.day + end + + expect(find('#issuable-due-date').value).to eq date.to_s + + click_button 'Save changes' + + page.within '.issuable-sidebar' do + expect(page).to have_content date.to_s(:medium) + end + end + + it 'warns about version conflict' do + issue.update(title: "New title") + + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + + click_button 'Save changes' + + expect(page).to have_content 'Someone edited the issue the same time you did' + end end end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index d70cf1527e7..a7928857b7d 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -181,6 +181,21 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end + describe "GET /:project_path/issues/:id/edit" do + let(:issue) { create(:issue, project: project) } + subject { edit_project_issue_path(project, issue) } + + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } + end + describe "GET /:project_path/snippets" do subject { project_snippets_path(project) } diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index ea130606545..a4396b20afd 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -181,6 +181,21 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end + describe "GET /:project_path/issues/:id/edit" do + let(:issue) { create(:issue, project: project) } + subject { edit_project_issue_path(project, issue) } + + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } + end + describe "GET /:project_path/snippets" do subject { project_snippets_path(project) } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index d15f5af66c9..fccdeb0e5b7 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -394,6 +394,21 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end + describe "GET /:project_path/issues/:id/edit" do + let(:issue) { create(:issue, project: project) } + subject { edit_project_issue_path(project, issue) } + + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } + end + describe "GET /:project_path/snippets" do subject { project_snippets_path(project) } diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js index d7019ea408b..df3d29ee1f9 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js @@ -43,6 +43,10 @@ describe('MRWidgetReadyToMerge', () => { vm = createComponent(); }); + afterEach(() => { + vm.$destroy(); + }); + describe('props', () => { it('should have props', () => { const { mr, service } = readyToMergeComponent.props; @@ -495,6 +499,48 @@ describe('MRWidgetReadyToMerge', () => { }); }); + describe('Merge controls', () => { + describe('when allowed to merge', () => { + beforeEach(() => { + vm = createComponent({ + mr: { isMergeAllowed: true }, + }); + }); + + it('shows remove source branch checkbox', () => { + expect(vm.$el.querySelector('.js-remove-source-branch-checkbox')).toBeDefined(); + }); + + it('shows modify commit message button', () => { + expect(vm.$el.querySelector('.js-modify-commit-message-button')).toBeDefined(); + }); + + it('does not show message about needing to resolve items', () => { + expect(vm.$el.querySelector('.js-resolve-mr-widget-items-message')).toBeNull(); + }); + }); + + describe('when not allowed to merge', () => { + beforeEach(() => { + vm = createComponent({ + mr: { isMergeAllowed: false }, + }); + }); + + it('does not show remove source branch checkbox', () => { + expect(vm.$el.querySelector('.js-remove-source-branch-checkbox')).toBeNull(); + }); + + it('does not show modify commit message button', () => { + expect(vm.$el.querySelector('.js-modify-commit-message-button')).toBeNull(); + }); + + it('shows message to resolve all items before being allowed to merge', () => { + expect(vm.$el.querySelector('.js-resolve-mr-widget-items-message')).toBeDefined(); + }); + }); + }); + describe('Commit message area', () => { it('when using merge commits, should show "Modify commit message" button', () => { const customVm = createComponent({ diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb index 97d612e6347..ca76d6f0881 100644 --- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb +++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb @@ -15,9 +15,13 @@ describe Banzai::Filter::GollumTagsFilter do context 'linking internal images' do it 'creates img tag if image exists' do - file = Gollum::File.new(project_wiki.wiki) - expect(file).to receive(:path).and_return('images/image.jpg') - expect(project_wiki).to receive(:find_file).with('images/image.jpg').and_return(file) + gollum_file_double = double('Gollum::File', + mime_type: 'image/jpeg', + name: 'images/image.jpg', + path: 'images/image.jpg', + raw_data: '') + wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double) + expect(project_wiki).to receive(:find_file).with('images/image.jpg').and_return(wiki_file) tag = '[[images/image.jpg]]' doc = filter("See #{tag}", project_wiki: project_wiki) diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 25e5d155894..e1be23541e8 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -575,6 +575,16 @@ describe Environment do end end + describe '#ref_path' do + subject(:environment) do + create(:environment, name: 'staging / review-1') + end + + it 'returns a path that uses the slug and does not have spaces' do + expect(environment.ref_path).to start_with('refs/environments/staging-review-1-') + end + end + describe '#external_url_for' do let(:source_path) { 'source/file.html' } let(:sha) { RepoHelpers.sample_commit.id } diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index 2298dcab55f..00de536a18b 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -99,45 +99,34 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do describe '#actual_namespace' do subject { service.actual_namespace } - it "returns the default namespace" do - is_expected.to eq(service.send(:default_namespace)) - end - - context 'when namespace is specified' do - before do - service.namespace = 'my-namespace' + shared_examples 'a correctly formatted namespace' do + it 'returns a valid Kubernetes namespace name' do + expect(subject).to match(Gitlab::Regex.kubernetes_namespace_regex) + expect(subject).to eq(expected_namespace) end + end - it "returns the user-namespace" do - is_expected.to eq('my-namespace') - end + it_behaves_like 'a correctly formatted namespace' do + let(:expected_namespace) { service.send(:default_namespace) } end - context 'when service is not assigned to project' do + context 'when the project path contains forbidden characters' do before do - service.project = nil + project.path = '-a_Strange.Path--forSure' end - it "does not return namespace" do - is_expected.to be_nil + it_behaves_like 'a correctly formatted namespace' do + let(:expected_namespace) { "a-strange-path--forsure-#{project.id}" } end end - end - - describe '#actual_namespace' do - subject { service.actual_namespace } - - it "returns the default namespace" do - is_expected.to eq(service.send(:default_namespace)) - end context 'when namespace is specified' do before do service.namespace = 'my-namespace' end - it "returns the user-namespace" do - is_expected.to eq('my-namespace') + it_behaves_like 'a correctly formatted namespace' do + let(:expected_namespace) { 'my-namespace' } end end @@ -146,7 +135,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do service.project = nil end - it "does not return namespace" do + it 'does not return namespace' do is_expected.to be_nil end end diff --git a/spec/services/users/last_push_event_service_spec.rb b/spec/services/users/last_push_event_service_spec.rb index 956358738fe..2b6c0267a0f 100644 --- a/spec/services/users/last_push_event_service_spec.rb +++ b/spec/services/users/last_push_event_service_spec.rb @@ -22,7 +22,6 @@ describe Users::LastPushEventService do it 'caches the event for the origin project when pushing to a fork' do source = build(:project, id: 5) - allow(project).to receive(:forked?).and_return(true) allow(project).to receive(:forked_from_project).and_return(source) expect(service).to receive(:set_key) diff --git a/spec/support/update_invalid_issuable.rb b/spec/support/update_invalid_issuable.rb index 50a1d4a56e2..1490287681b 100644 --- a/spec/support/update_invalid_issuable.rb +++ b/spec/support/update_invalid_issuable.rb @@ -25,13 +25,11 @@ shared_examples 'update invalid issuable' do |klass| .and_raise(ActiveRecord::StaleObjectError.new(issuable, :save)) end - if klass == MergeRequest - it 'renders edit when format is html' do - put :update, params + it 'renders edit when format is html' do + put :update, params - expect(response).to render_template(:edit) - expect(assigns[:conflict]).to be_truthy - end + expect(response).to render_template(:edit) + expect(assigns[:conflict]).to be_truthy end it 'renders json error message when format is json' do @@ -44,17 +42,16 @@ shared_examples 'update invalid issuable' do |klass| end end - if klass == MergeRequest - context 'when updating an invalid issuable' do - before do - params[:merge_request][:title] = "" - end + context 'when updating an invalid issuable' do + before do + key = klass == Issue ? :issue : :merge_request + params[key][:title] = "" + end - it 'renders edit when merge request is invalid' do - put :update, params + it 'renders edit when merge request is invalid' do + put :update, params - expect(response).to render_template(:edit) - end + expect(response).to render_template(:edit) end end end |