BigW Consortium Gitlab

Commit 39ec9bd4 by Lin Jen-Shin (godfat)

Merge branch '10-1-stable-patch-1' into '10-1-stable'

Prepare 10.1.1 release See merge request gitlab-org/gitlab-ce!15027
parents 88c97c19 6ea71325
...@@ -29,11 +29,9 @@ export const fetchList = ({ commit }, { repo, page }) => { ...@@ -29,11 +29,9 @@ export const fetchList = ({ commit }, { repo, page }) => {
}); });
}; };
export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath) export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath);
.then(res => res.json());
export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath) export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath);
.then(res => res.json());
export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data); export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING); export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);
...@@ -286,6 +286,7 @@ export default { ...@@ -286,6 +286,7 @@ export default {
<input <input
id="remove-source-branch-input" id="remove-source-branch-input"
v-model="removeSourceBranch" v-model="removeSourceBranch"
class="js-remove-source-branch-checkbox"
:disabled="isRemoveSourceBranchButtonDisabled" :disabled="isRemoveSourceBranchButtonDisabled"
type="checkbox"/> Remove source branch type="checkbox"/> Remove source branch
</label> </label>
...@@ -311,8 +312,8 @@ export default { ...@@ -311,8 +312,8 @@ export default {
</button> </button>
</template> </template>
<template v-else> <template v-else>
<span class="bold"> <span class="bold js-resolve-mr-widget-items-message">
The pipeline for this merge request has not succeeded yet You can only merge once the items above are resolved
</span> </span>
</template> </template>
</div> </div>
......
...@@ -249,13 +249,12 @@ ...@@ -249,13 +249,12 @@
width: 100%; width: 100%;
padding-right: 5px; padding-right: 5px;
} }
} }
.discussion-actions { .discussion-actions {
display: table; display: table;
.new-issue-for-discussion path { .btn-default path {
fill: $gray-darkest; fill: $gray-darkest;
} }
......
...@@ -466,6 +466,10 @@ ul.notes { ...@@ -466,6 +466,10 @@ ul.notes {
float: right; float: right;
margin-left: 10px; margin-left: 10px;
color: $gray-darkest; color: $gray-darkest;
.btn-group > .discussion-next-btn {
margin-left: -1px;
}
} }
.note-actions { .note-actions {
......
...@@ -16,7 +16,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -16,7 +16,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_create_issue!, only: [:new, :create] before_action :authorize_create_issue!, only: [:new, :create]
# Allow modify issue # 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 # Allow create a new branch and empty WIP merge request from current issue
before_action :authorize_create_merge_request!, only: [:create_merge_request] before_action :authorize_create_merge_request!, only: [:create_merge_request]
...@@ -63,6 +63,10 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -63,6 +63,10 @@ class Projects::IssuesController < Projects::ApplicationController
respond_with(@issue) respond_with(@issue)
end end
def edit
respond_with(@issue)
end
def show def show
@noteable = @issue @noteable = @issue
@note = @project.notes.new(noteable: @issue) @note = @project.notes.new(noteable: @issue)
...@@ -122,6 +126,10 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -122,6 +126,10 @@ class Projects::IssuesController < Projects::ApplicationController
@issue = Issues::UpdateService.new(project, current_user, update_params).execute(issue) @issue = Issues::UpdateService.new(project, current_user, update_params).execute(issue)
respond_to do |format| respond_to do |format|
format.html do
recaptcha_check_with_fallback { render :edit }
end
format.json do format.json do
render_issue_json render_issue_json
end end
......
...@@ -110,7 +110,7 @@ class Environment < ActiveRecord::Base ...@@ -110,7 +110,7 @@ class Environment < ActiveRecord::Base
end end
def ref_path def ref_path
"refs/#{Repository::REF_ENVIRONMENTS}/#{Shellwords.shellescape(name)}" "refs/#{Repository::REF_ENVIRONMENTS}/#{generate_slug}"
end end
def formatted_external_url def formatted_external_url
......
...@@ -153,7 +153,10 @@ class KubernetesService < DeploymentService ...@@ -153,7 +153,10 @@ class KubernetesService < DeploymentService
end end
def default_namespace 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 end
def build_kubeclient!(api_path: 'api', api_version: 'v1') def build_kubeclient!(api_path: 'api', api_version: 'v1')
......
...@@ -16,8 +16,8 @@ module Users ...@@ -16,8 +16,8 @@ module Users
user_cache_key user_cache_key
] ]
if event.project.forked? if forked_from = event.project.forked_from_project
keys << project_cache_key(event.project.forked_from_project) keys << project_cache_key(forked_from)
end end
keys.each { |key| set_key(key, event.id) } keys.each { |key| set_key(key, event.id) }
......
- page_title "Edit", "#{@issue.title} (#{@issue.to_reference})", "Issues"
%h3.page-title
Edit Issue ##{@issue.iid}
%hr
= render "form"
---
title: Update default disabled merge request widget message to reflect a general failure
merge_request: 14960
author:
type: changed
---
title: Fix editing issue description in mobile view
merge_request:
author:
type: fixed
---
title: Fix bitbucket login
merge_request: 15051
author:
type: fixed
---
title: Don't rename paths that were freed up when upgrading
merge_request: 15029
author:
type: fixed
---
title: Only cache last push event for existing projects when pushing to a fork
merge_request: 14989
author:
type: fixed
---
title: Fix broken wiki pages that link to a wiki file
merge_request: 15019
author:
type: fixed
---
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
---
title: Fix deletion of container registry or images returning an error
merge_request:
author:
type: fixed
---
title: Fix the writing of invalid environment refs
merge_request:
author:
type: fixed
...@@ -13,7 +13,6 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration ...@@ -13,7 +13,6 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration
.well-known .well-known
abuse_reports abuse_reports
admin admin
all
api api
assets assets
autocomplete autocomplete
...@@ -24,29 +23,20 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration ...@@ -24,29 +23,20 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration
groups groups
health_check health_check
help help
hooks
import import
invites invites
issues
jwt jwt
koding koding
member
merge_requests
new
notes
notification_settings notification_settings
oauth oauth
profile profile
projects projects
public public
repository
robots.txt robots.txt
s s
search search
sent_notifications sent_notifications
services
snippets snippets
teams
u u
unicorn_test unicorn_test
unsubscribes unsubscribes
...@@ -94,7 +84,6 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration ...@@ -94,7 +84,6 @@ class RenameAllReservedPathsAgain < ActiveRecord::Migration
notification_setting notification_setting
pipeline_quota pipeline_quota
projects projects
subgroups
].freeze ].freeze
def up def up
......
...@@ -18,8 +18,7 @@ other than production, the corresponding logfile is shown here.) ...@@ -18,8 +18,7 @@ other than production, the corresponding logfile is shown here.)
It contains a structured log for Rails controller requests received from It contains a structured log for Rails controller requests received from
GitLab, thanks to [Lograge](https://github.com/roidrage/lograge/). Note that GitLab, thanks to [Lograge](https://github.com/roidrage/lograge/). Note that
requests from the API [are not yet logged to this requests from the API are logged to a separate file in `api_json.log`.
file](https://gitlab.com/gitlab-org/gitlab-ce/issues/36189).
Each line contains a JSON line that can be ingested by Elasticsearch, Splunk, etc. For example: 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 ...@@ -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 19:34:53 +0200. Also we can see that request was processed by
`Projects::TreeController`. `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` ## `application.log`
This file lives in `/var/log/gitlab/gitlab-rails/application.log` for This file lives in `/var/log/gitlab/gitlab-rails/application.log` for
......
...@@ -43,6 +43,7 @@ future GitLab releases.** ...@@ -43,6 +43,7 @@ future GitLab releases.**
| **CI_COMMIT_TAG** | 9.0 | 0.5 | The commit tag name. Present only when building tags. | | **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_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_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_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_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 | | **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job |
...@@ -73,6 +74,7 @@ future GitLab releases.** ...@@ -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_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_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_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 | | **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 | | **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 | | **GITLAB_CI** | all | all | Mark that job is executed in GitLab CI environment |
......
...@@ -3,31 +3,28 @@ ...@@ -3,31 +3,28 @@
Merge requests are useful to integrate separate changes that you've made to a 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 project, on different branches. This is a brief guide on how to create a merge
request. For more information, check the 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) 1. Before you start, you should have already [created a branch](create-branch.md)
and [pushed your changes](basic-git-commands.md) to GitLab. and [pushed your changes](basic-git-commands.md) to GitLab.
1. Go to the project where you'd like to merge your changes and click on the
1. You can then go to the project where you'd like to merge your changes and **Merge requests** tab.
click on the **Merge requests** tab.
![Merge requests](img/project_navbar.png)
1. Click on **New merge request** on the right side of the screen. 1. Click on **New merge request** on the right side of the screen.
1. From there on, you have the option to select the source branch and the target
![New Merge Request](img/merge_request_new.png) 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.
1. Select a source branch and click on the **Compare branches and continue** button.
![Select a branch](img/merge_request_select_branch.png) ![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, 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 select a user to review your merge request and to accept or close it. You may
also select a milestone and labels. also select a milestone and labels.
![New merge request page](img/merge_request_page.png) ![New merge request page](img/merge_request_page.png)
1. When ready, click on the **Submit merge request** button. Your merge request 1. When ready, click on the **Submit merge request** button.
will be ready to be approved and published.
Your merge request will be ready to be approved and merged.
...@@ -34,7 +34,6 @@ With **[GitLab Enterprise Edition][ee]**, you can also: ...@@ -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) - 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) - 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) - [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) - 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 ## Use cases
......
module Gitlab module Gitlab
module Git module Git
class WikiFile 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 # This class is meant to be serializable so that it can be constructed
# by Gitaly and sent over the network to GitLab. # by Gitaly and sent over the network to GitLab.
...@@ -13,6 +13,7 @@ module Gitlab ...@@ -13,6 +13,7 @@ module Gitlab
@mime_type = gollum_file.mime_type @mime_type = gollum_file.mime_type
@raw_data = gollum_file.raw_data @raw_data = gollum_file.raw_data
@name = gollum_file.name @name = gollum_file.name
@path = gollum_file.path
end end
end end
end end
......
...@@ -36,8 +36,8 @@ module Gitlab ...@@ -36,8 +36,8 @@ module Gitlab
end end
def track_query(raw_query, bindings, start, finish) def track_query(raw_query, bindings, start, finish)
query = Gitlab::Sherlock::Query.new(raw_query, start, finish) duration = finish - start
query_info = { duration: query.duration.round(3), sql: query.formatted_query } query_info = { duration: duration.round(3), sql: raw_query }
PEEK_DB_CLIENT.query_details << query_info PEEK_DB_CLIENT.query_details << query_info
end end
......
...@@ -36,6 +36,10 @@ module OmniAuth ...@@ -36,6 +36,10 @@ module OmniAuth
email_response = access_token.get('api/2.0/user/emails').parsed email_response = access_token.get('api/2.0/user/emails').parsed
@emails ||= email_response && email_response['values'] || nil @emails ||= email_response && email_response['values'] || nil
end end
def callback_url
options[:redirect_uri] || (full_host + script_name + callback_path)
end
end end
end end
end end
...@@ -557,6 +557,29 @@ describe Projects::IssuesController do ...@@ -557,6 +557,29 @@ describe Projects::IssuesController do
end end
end 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 end
describe 'POST #create' do describe 'POST #create' do
......
...@@ -218,15 +218,54 @@ describe 'New/edit issue', :js do ...@@ -218,15 +218,54 @@ describe 'New/edit issue', :js do
context 'edit issue' do context 'edit issue' do
before do before do
visit project_issue_path(project, issue) visit edit_project_issue_path(project, issue)
page.within('.content .issuable-actions') do end
click_on 'Edit'
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
end end
it 'description has autocomplete' do it 'description has autocomplete' do
find_field('issue-description').native.send_keys('') find('#issue_description').native.send_keys('')
fill_in 'issue-description', with: '@' fill_in 'issue_description', with: '@'
expect(page).to have_selector('.atwho-view') expect(page).to have_selector('.atwho-view')
end end
......
require 'spec_helper' require 'spec_helper'
describe 'Issues', :js do describe 'Issues' do
include DropzoneHelper include DropzoneHelper
include IssueHelpers include IssueHelpers
include SortingHelper include SortingHelper
...@@ -24,15 +24,109 @@ describe 'Issues', :js do ...@@ -24,15 +24,109 @@ describe 'Issues', :js do
end end
before do before do
visit project_issue_path(project, issue) visit edit_project_issue_path(project, issue)
page.within('.content .issuable-actions') do find('.js-zen-enter').click
find('.issuable-edit').click
end
find('.issue-details .content-block .js-zen-enter').click
end end
it 'opens new issue popup' do 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
end end
......
...@@ -181,6 +181,21 @@ describe "Internal Project Access" do ...@@ -181,6 +181,21 @@ describe "Internal Project Access" do
it { is_expected.to be_denied_for(:visitor) } it { is_expected.to be_denied_for(:visitor) }
end 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 describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) } subject { project_snippets_path(project) }
......
...@@ -181,6 +181,21 @@ describe "Private Project Access" do ...@@ -181,6 +181,21 @@ describe "Private Project Access" do
it { is_expected.to be_denied_for(:visitor) } it { is_expected.to be_denied_for(:visitor) }
end 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 describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) } subject { project_snippets_path(project) }
......
...@@ -394,6 +394,21 @@ describe "Public Project Access" do ...@@ -394,6 +394,21 @@ describe "Public Project Access" do
it { is_expected.to be_allowed_for(:visitor) } it { is_expected.to be_allowed_for(:visitor) }
end 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 describe "GET /:project_path/snippets" do
subject { project_snippets_path(project) } subject { project_snippets_path(project) }
......
...@@ -43,6 +43,10 @@ describe('MRWidgetReadyToMerge', () => { ...@@ -43,6 +43,10 @@ describe('MRWidgetReadyToMerge', () => {
vm = createComponent(); vm = createComponent();
}); });
afterEach(() => {
vm.$destroy();
});
describe('props', () => { describe('props', () => {
it('should have props', () => { it('should have props', () => {
const { mr, service } = readyToMergeComponent.props; const { mr, service } = readyToMergeComponent.props;
...@@ -495,6 +499,48 @@ describe('MRWidgetReadyToMerge', () => { ...@@ -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', () => { describe('Commit message area', () => {
it('when using merge commits, should show "Modify commit message" button', () => { it('when using merge commits, should show "Modify commit message" button', () => {
const customVm = createComponent({ const customVm = createComponent({
......
...@@ -15,9 +15,13 @@ describe Banzai::Filter::GollumTagsFilter do ...@@ -15,9 +15,13 @@ describe Banzai::Filter::GollumTagsFilter do
context 'linking internal images' do context 'linking internal images' do
it 'creates img tag if image exists' do it 'creates img tag if image exists' do
file = Gollum::File.new(project_wiki.wiki) gollum_file_double = double('Gollum::File',
expect(file).to receive(:path).and_return('images/image.jpg') mime_type: 'image/jpeg',
expect(project_wiki).to receive(:find_file).with('images/image.jpg').and_return(file) 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]]' tag = '[[images/image.jpg]]'
doc = filter("See #{tag}", project_wiki: project_wiki) doc = filter("See #{tag}", project_wiki: project_wiki)
......
...@@ -575,6 +575,16 @@ describe Environment do ...@@ -575,6 +575,16 @@ describe Environment do
end end
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 describe '#external_url_for' do
let(:source_path) { 'source/file.html' } let(:source_path) { 'source/file.html' }
let(:sha) { RepoHelpers.sample_commit.id } let(:sha) { RepoHelpers.sample_commit.id }
......
...@@ -99,45 +99,34 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do ...@@ -99,45 +99,34 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
describe '#actual_namespace' do describe '#actual_namespace' do
subject { service.actual_namespace } subject { service.actual_namespace }
it "returns the default namespace" do shared_examples 'a correctly formatted namespace' do
is_expected.to eq(service.send(:default_namespace)) it 'returns a valid Kubernetes namespace name' do
end expect(subject).to match(Gitlab::Regex.kubernetes_namespace_regex)
expect(subject).to eq(expected_namespace)
context 'when namespace is specified' do
before do
service.namespace = 'my-namespace'
end end
end
it "returns the user-namespace" do it_behaves_like 'a correctly formatted namespace' do
is_expected.to eq('my-namespace') let(:expected_namespace) { service.send(:default_namespace) }
end
end end
context 'when service is not assigned to project' do context 'when the project path contains forbidden characters' do
before do before do
service.project = nil project.path = '-a_Strange.Path--forSure'
end end
it "does not return namespace" do it_behaves_like 'a correctly formatted namespace' do
is_expected.to be_nil let(:expected_namespace) { "a-strange-path--forsure-#{project.id}" }
end end
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 context 'when namespace is specified' do
before do before do
service.namespace = 'my-namespace' service.namespace = 'my-namespace'
end end
it "returns the user-namespace" do it_behaves_like 'a correctly formatted namespace' do
is_expected.to eq('my-namespace') let(:expected_namespace) { 'my-namespace' }
end end
end end
...@@ -146,7 +135,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do ...@@ -146,7 +135,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
service.project = nil service.project = nil
end end
it "does not return namespace" do it 'does not return namespace' do
is_expected.to be_nil is_expected.to be_nil
end end
end end
......
...@@ -22,7 +22,6 @@ describe Users::LastPushEventService do ...@@ -22,7 +22,6 @@ describe Users::LastPushEventService do
it 'caches the event for the origin project when pushing to a fork' do it 'caches the event for the origin project when pushing to a fork' do
source = build(:project, id: 5) source = build(:project, id: 5)
allow(project).to receive(:forked?).and_return(true)
allow(project).to receive(:forked_from_project).and_return(source) allow(project).to receive(:forked_from_project).and_return(source)
expect(service).to receive(:set_key) expect(service).to receive(:set_key)
......
...@@ -25,13 +25,11 @@ shared_examples 'update invalid issuable' do |klass| ...@@ -25,13 +25,11 @@ shared_examples 'update invalid issuable' do |klass|
.and_raise(ActiveRecord::StaleObjectError.new(issuable, :save)) .and_raise(ActiveRecord::StaleObjectError.new(issuable, :save))
end end
if klass == MergeRequest it 'renders edit when format is html' do
it 'renders edit when format is html' do put :update, params
put :update, params
expect(response).to render_template(:edit) expect(response).to render_template(:edit)
expect(assigns[:conflict]).to be_truthy expect(assigns[:conflict]).to be_truthy
end
end end
it 'renders json error message when format is json' do it 'renders json error message when format is json' do
...@@ -44,17 +42,16 @@ shared_examples 'update invalid issuable' do |klass| ...@@ -44,17 +42,16 @@ shared_examples 'update invalid issuable' do |klass|
end end
end end
if klass == MergeRequest context 'when updating an invalid issuable' do
context 'when updating an invalid issuable' do before do
before do key = klass == Issue ? :issue : :merge_request
params[:merge_request][:title] = "" params[key][:title] = ""
end end
it 'renders edit when merge request is invalid' do it 'renders edit when merge request is invalid' do
put :update, params put :update, params
expect(response).to render_template(:edit) expect(response).to render_template(:edit)
end
end end
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment