diff --git a/config/routes.rb b/config/routes.rb index 6f0318c029744b4be5a68e0b8d11d35f4f89e9be..a345b007b2393d79c4fae91fa120f1b23639ff4d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,10 +27,14 @@ Rails.application.routes.draw do authorizations: 'oauth/authorizations' end - scope path: '/-/jira/login/oauth', controller: 'oauth/jira/authorizations', as: :oauth_jira do + # This prefixless path is required because Jira gets confused if we set it up with a path + # More information: https://gitlab.com/gitlab-org/gitlab-ee/issues/6752 + scope path: '/login/oauth', controller: 'oauth/jira/authorizations', as: :oauth_jira do get :authorize, action: :new get :callback post :access_token + # This helps minimize merge conflicts with CE for this scope block + match ':action', via: [:get, :post], to: proc { [404, {}, ['']] } end namespace :oauth do diff --git a/db/post_migrate/20180816193530_rename_login_root_namespaces.rb b/db/post_migrate/20180816193530_rename_login_root_namespaces.rb new file mode 100644 index 0000000000000000000000000000000000000000..60cec24eed64335ea689af04ec354914c4148026 --- /dev/null +++ b/db/post_migrate/20180816193530_rename_login_root_namespaces.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +class RenameLoginRootNamespaces < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + include Gitlab::Database::RenameReservedPathsMigration::V1 + + DOWNTIME = false + + # We're taking over the /login namespace as part of a fix for the Jira integration + def up + rename_root_paths 'login' + end + + def down + revert_renames + end +end diff --git a/db/schema.rb b/db/schema.rb index a74882e19e2dc935efde66148824874380166207..49e44b97d394c02aea2d5517425e8091bafc36f2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180809195358) do +ActiveRecord::Schema.define(version: 20180816193530) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" diff --git a/doc/integration/img/jira_dev_panel_gl_setup_1.png b/doc/integration/img/jira_dev_panel_gl_setup_1.png index 1bee7a291a7be2165e4efa5ef100f94c29a66a7e..a8eb37f4b54149449163c25134fa634ce963265d 100644 Binary files a/doc/integration/img/jira_dev_panel_gl_setup_1.png and b/doc/integration/img/jira_dev_panel_gl_setup_1.png differ diff --git a/doc/integration/img/jira_dev_panel_jira_setup_2.png b/doc/integration/img/jira_dev_panel_jira_setup_2.png index 5737785f97200887f4e95f40e2ef74df2b1466f7..535627005ddee8135defadae345a5be5a193b450 100644 Binary files a/doc/integration/img/jira_dev_panel_jira_setup_2.png and b/doc/integration/img/jira_dev_panel_jira_setup_2.png differ diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md index a9f03aea0443b62109be7ff5719d1d9b6ce28a5c..add1e237fe13432cb98ef8bdb297a11d0f487078 100644 --- a/doc/integration/jira_development_panel.md +++ b/doc/integration/jira_development_panel.md @@ -31,9 +31,9 @@ account, in order to maximize the integrated GitLab projects used by your team. Enter a useful name for the `Name` field. - For the `Redirect URI` field, enter `https://<your-gitlab-instance-domain>/-/jira/login/oauth/callback`, + For the `Redirect URI` field, enter `https://<your-gitlab-instance-domain>/login/oauth/callback`, replacing `<your-gitlab-instance-domain>` appropriately. So for example, if you are using GitLab.com, - this would be `https://gitlab.com/-/jira/login/oauth/callback`. + this would be `https://gitlab.com/login/oauth/callback`. ![GitLab Application setup](img/jira_dev_panel_gl_setup_1.png) - Check `api` in the Scopes section. @@ -58,9 +58,9 @@ from the left navigation menu. Click `Link GitHub account` to start creating a n ![Creation of Jira DVCS integration](img/jira_dev_panel_jira_setup_2.png) - For the `Host URL` field, enter `https://<your-gitlab-instance-domain>/-/jira`, + For the `Host URL` field, enter `https://<your-gitlab-instance-domain>/`, replacing `<your-gitlab-instance-domain>` appropriately. So for example, if you are using GitLab.com, - this would be `https://gitlab.com/-/jira`. + this would be `https://gitlab.com/`. For the `Client ID` field, use the `Application ID` value from the previous section. diff --git a/ee/changelogs/unreleased/6752-jira-branches.yml b/ee/changelogs/unreleased/6752-jira-branches.yml new file mode 100644 index 0000000000000000000000000000000000000000..52ed58cc1711344a47556c944dce15dbb7addc3f --- /dev/null +++ b/ee/changelogs/unreleased/6752-jira-branches.yml @@ -0,0 +1,5 @@ +--- +title: Fix Jira integration duplicating branches and MRs +merge_request: 6876 +author: +type: fixed diff --git a/ee/lib/api/v3/github.rb b/ee/lib/api/v3/github.rb index 6f37d4c74f26e320102f6977fd4fa692f8f41c2a..181b04370a121bae4709ceafdc3cd391bc126f2c 100644 --- a/ee/lib/api/v3/github.rb +++ b/ee/lib/api/v3/github.rb @@ -98,30 +98,42 @@ module API # Jira handles the filtering, presenting just MRs mentioning the Jira # issue ID on the MR title / description. resource :repos do + # Keeping for backwards compatibility with old Jira integration instructions + # so that users that do not change it will not suddenly have a broken integration get '/-/jira/pulls' do present find_merge_requests, with: ::API::Github::Entities::PullRequest end + params do + use :project_full_path + end + get ':namespace/:project/pulls', requirements: PROJECT_ENDPOINT_REQUIREMENTS do + user_project = find_project_with_access(params) + + merge_requests = MergeRequestsFinder.new(current_user, authorized_only: true, project_id: user_project.id).execute + + present paginate(merge_requests), with: ::API::Github::Entities::PullRequest + end + # In Github, each Merge Request is automatically also an issue. # Therefore we return its comments here. # It'll present _just_ the comments counting with a link to GitLab on # Jira dev panel, not the actual note content. - # - get '/-/jira/issues/:id/comments' do + get ':namespace/:project/issues/:id/comments' do merge_request = find_merge_request_with_access(params[:id]) present find_notes(merge_request), with: ::API::Github::Entities::NoteableComment end - # This refers to "review" comments but Jira dev panel doesn't seem to + # This refer to "review" comments but Jira dev panel doesn't seem to # present it accordingly. - get '/-/jira/pulls/:id/comments' do + get ':namespace/:project/pulls/:id/comments' do present [] end # Commits are not presented within "Pull Requests" modal on Jira dev # panel. - get '/-/jira/pulls/:id/commits' do + get ':namespace/:project/pulls/:id/commits' do present [] end @@ -129,7 +141,7 @@ module API # after fetching branches. # We need to respond with a 200 request to avoid breaking the # integration flow (fetching merge requests). - get '/-/jira/events' do + get ':namespace/:project/events' do present [] end diff --git a/ee/spec/controllers/oauth/jira/authorizations_controller_spec.rb b/ee/spec/controllers/oauth/jira/authorizations_controller_spec.rb index 0e2b3b07f270d3701592e18c5af34c6113d6700b..c05e0cb78241eb4ad92ce315ea7a0e85aa9d50bd 100644 --- a/ee/spec/controllers/oauth/jira/authorizations_controller_spec.rb +++ b/ee/spec/controllers/oauth/jira/authorizations_controller_spec.rb @@ -35,7 +35,7 @@ describe Oauth::Jira::AuthorizationsController do 'client_id' => 'client-123', 'client_secret' => 'secret-123', 'grant_type' => 'authorization_code', - 'redirect_uri' => 'http://test.host/-/jira/login/oauth/callback' } + 'redirect_uri' => 'http://test.host/login/oauth/callback' } expect(Gitlab::HTTP).to receive(:post).with(oauth_token_url, allow_local_requests: true, body: expected_auth_params) do { 'access_token' => 'fake-123', 'scope' => 'foo', 'token_type' => 'bar' } diff --git a/ee/spec/requests/api/v3/github_spec.rb b/ee/spec/requests/api/v3/github_spec.rb index 25f6c8f984bc5cf1a0a67245ff659bdb344844ec..5bc8b9c3829bb650a59a9a35039f0d66b80cb4af 100644 --- a/ee/spec/requests/api/v3/github_spec.rb +++ b/ee/spec/requests/api/v3/github_spec.rb @@ -3,10 +3,12 @@ require 'spec_helper' describe API::V3::Github do let(:user) { create(:user) } let!(:project) { create(:project, :repository, creator: user) } + let!(:project2) { create(:project, :repository, creator: user) } before do allow(Gitlab::Jira::Middleware).to receive(:jira_dvcs_connector?) { true } project.add_maintainer(user) + project2.add_maintainer(user) end describe 'GET /orgs/:namespace/repos' do @@ -37,91 +39,125 @@ describe API::V3::Github do end end - describe 'GET /repos/-/jira/events' do - it 'returns an empty array' do - get v3_api('/repos/-/jira/events', user) + shared_examples_for 'Jira-specific mimicked GitHub endpoints' do + describe 'GET /repos/.../events' do + it 'returns an empty array' do + get v3_api("/repos/#{path}/events", user) - expect(response).to have_gitlab_http_status(200) - expect(json_response).to eq([]) - end - end - - describe 'GET /-/jira/pulls' do - let(:assignee) { create(:user) } - let!(:merge_request) do - create(:merge_request, source_project: project, target_project: project, author: user, assignee: assignee) + expect(response).to have_gitlab_http_status(200) + expect(json_response).to eq([]) + end end - it 'returns an array of merge requests with github format' do - stub_licensed_features(jira_dev_panel_integration: true) + describe 'GET /.../issues/:id/comments' do + context 'when user has access to the merge request' do + let(:merge_request) do + create(:merge_request, source_project: project, target_project: project) + end + let!(:note) do + create(:note, project: project, noteable: merge_request) + end - get v3_api('/repos/-/jira/pulls', user) + it 'returns an array of notes' do + stub_licensed_features(jira_dev_panel_integration: true) - expect(response).to have_gitlab_http_status(200) - expect(json_response).to be_an(Array) - expect(json_response.size).to eq(1) - expect(response).to match_response_schema('entities/github/pull_requests', dir: 'ee') - end - end + get v3_api("/repos/#{path}/issues/#{merge_request.id}/comments", user) - describe 'GET /-/jira/issues/:id/comments' do - context 'when user has access to the merge request' do - let(:merge_request) do - create(:merge_request, source_project: project, target_project: project) - end - let!(:note) do - create(:note, project: project, noteable: merge_request) + expect(response).to have_gitlab_http_status(200) + expect(json_response).to be_an(Array) + expect(json_response.size).to eq(1) + end end - it 'returns an array of notes' do - stub_licensed_features(jira_dev_panel_integration: true) + context 'when user has no access to the merge request' do + let(:private_project) { create(:project, :private) } + let(:merge_request) do + create(:merge_request, source_project: private_project, target_project: private_project) + end + let!(:note) do + create(:note, project: private_project, noteable: merge_request) + end - get v3_api("/repos/-/jira/issues/#{merge_request.id}/comments", user) + before do + private_project.add_guest(user) + end - expect(response).to have_gitlab_http_status(200) - expect(json_response).to be_an(Array) - expect(json_response.size).to eq(1) + it 'returns 404' do + stub_licensed_features(jira_dev_panel_integration: true) + + get v3_api("/repos/#{path}/issues/#{merge_request.id}/comments", user) + + expect(response).to have_gitlab_http_status(404) + end end end - context 'when user has no access to the merge request' do - let(:private_project) { create(:project, :private) } - let(:merge_request) do - create(:merge_request, source_project: private_project, target_project: private_project) - end - let!(:note) do - create(:note, project: private_project, noteable: merge_request) - end + describe 'GET /.../pulls/:id/commits' do + it 'returns an empty array' do + get v3_api("/repos/#{path}/pulls/xpto/commits", user) - before do - private_project.add_guest(user) + expect(response).to have_gitlab_http_status(200) + expect(json_response).to eq([]) end + end - it 'returns 404' do - stub_licensed_features(jira_dev_panel_integration: true) - - get v3_api("/repos/-/jira/issues/#{merge_request.id}/comments", user) + describe 'GET /.../pulls/:id/comments' do + it 'returns an empty array' do + get v3_api("/repos/#{path}/pulls/xpto/comments", user) - expect(response).to have_gitlab_http_status(404) + expect(response).to have_gitlab_http_status(200) + expect(json_response).to eq([]) end end end - describe 'GET /-/jira/pulls/:id/commits' do - it 'returns an empty array' do - get v3_api("/repos/-/jira/pulls/xpto/commits", user) + # Here we test that using /-/jira as namespace/project still works, + # since that is how old Jira setups will talk to us + context 'old /-/jira endpoints' do + it_behaves_like 'Jira-specific mimicked GitHub endpoints' do + let(:path) { '-/jira' } + end + end - expect(response).to have_gitlab_http_status(200) - expect(json_response).to eq([]) + context 'new :namespace/:project jira endpoints' do + it_behaves_like 'Jira-specific mimicked GitHub endpoints' do + let(:path) { "#{project.namespace.path}/#{project.path}" } end end - describe 'GET /-/jira/pulls/:id/comments' do - it 'returns an empty array' do - get v3_api("/repos/-/jira/pulls/xpto/comments", user) + describe 'repo pulls' do + let(:assignee) { create(:user) } + let!(:merge_request) do + create(:merge_request, source_project: project, target_project: project, author: user, assignee: assignee) + end + let!(:merge_request_2) do + create(:merge_request, source_project: project2, target_project: project2, author: user, assignee: assignee) + end - expect(response).to have_gitlab_http_status(200) - expect(json_response).to eq([]) + describe 'GET /-/jira/pulls' do + it 'returns an array of merge requests with github format' do + stub_licensed_features(jira_dev_panel_integration: true) + + get v3_api('/repos/-/jira/pulls', user) + + expect(response).to have_gitlab_http_status(200) + expect(json_response).to be_an(Array) + expect(json_response.size).to eq(2) + expect(response).to match_response_schema('entities/github/pull_requests', dir: 'ee') + end + end + + describe 'GET /repos/:namespace/:project/pulls' do + it 'returns an array of merge requests for the proper project in github format' do + stub_licensed_features(jira_dev_panel_integration: true) + + get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls", user) + + expect(response).to have_gitlab_http_status(200) + expect(json_response).to be_an(Array) + expect(json_response.size).to eq(1) + expect(response).to match_response_schema('entities/github/pull_requests', dir: 'ee') + end end end diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb index 91febaaeac9b08b55d239a64112273ba95320243..59504d5af301a088f6420d28b098bf2b640b0d46 100644 --- a/lib/gitlab/path_regex.rb +++ b/lib/gitlab/path_regex.rb @@ -40,6 +40,7 @@ module Gitlab invites jwt koding + login notification_settings oauth profile