Commit 8d418a8d authored by Phil Hughes's avatar Phil Hughes

Merge branch 'sourcegraph' into 'master'

Add Sourcegraph integration

Closes #20642

See merge request gitlab-org/gitlab!16556
parents 037db4be 9576ebd3
......@@ -3,6 +3,7 @@ import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_sta
import BlobViewer from '~/blob/viewer/index';
import initBlob from '~/pages/projects/init_blob';
import GpgBadges from '~/gpg_badges';
import '~/sourcegraph/load';
document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
......
......@@ -9,6 +9,7 @@ import initNotes from '~/init_notes';
import initChangesDropdown from '~/init_changes_dropdown';
import initDiffNotes from '~/diff_notes/diff_notes_bundle';
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
import '~/sourcegraph/load';
document.addEventListener('DOMContentLoaded', () => {
const hasPerfBar = document.querySelector('.with-performance-bar');
......
......@@ -5,6 +5,7 @@ import { handleLocationHash } from '~/lib/utils/common_utils';
import howToMerge from '~/how_to_merge';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
import initVueIssuableSidebarApp from '~/issuable_sidebar/sidebar_bundle';
import initSourcegraph from '~/sourcegraph';
import initWidget from '../../../vue_merge_request_widget';
export default function() {
......@@ -19,4 +20,5 @@ export default function() {
handleLocationHash();
howToMerge();
initWidget();
initSourcegraph();
}
function loadScript(path) {
const script = document.createElement('script');
script.type = 'application/javascript';
script.src = path;
script.defer = true;
document.head.appendChild(script);
}
/**
* Loads the Sourcegraph integration for support for Sourcegraph extensions and
* code intelligence.
*/
export default function initSourcegraph() {
const { url } = gon.sourcegraph || {};
if (!url) {
return;
}
const assetsUrl = new URL('/assets/webpack/sourcegraph/', window.location.href);
const scriptPath = new URL('scripts/integration.bundle.js', assetsUrl).href;
window.SOURCEGRAPH_ASSETS_URL = assetsUrl.href;
window.SOURCEGRAPH_URL = url;
window.SOURCEGRAPH_INTEGRATION = 'gitlab-integration';
loadScript(scriptPath);
}
import initSourcegraph from './index';
/**
* Load sourcegraph in it's own listener so that it's isolated from failures.
*/
document.addEventListener('DOMContentLoaded', initSourcegraph);
# frozen_string_literal: true
module SourcegraphGon
extend ActiveSupport::Concern
included do
before_action :push_sourcegraph_gon, if: :html_request?
end
private
def push_sourcegraph_gon
return unless sourcegraph_enabled?
gon.push({
sourcegraph: { url: Gitlab::CurrentSettings.sourcegraph_url }
})
end
def sourcegraph_enabled?
Gitlab::CurrentSettings.sourcegraph_enabled && sourcegraph_enabled_for_project? && current_user&.sourcegraph_enabled
end
def sourcegraph_enabled_for_project?
return false unless project && Gitlab::Sourcegraph.feature_enabled?(project)
return project.public? if Gitlab::CurrentSettings.sourcegraph_public_only
true
end
end
......@@ -47,7 +47,8 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:preferred_language,
:time_display_relative,
:time_format_in_24h,
:show_whitespace_in_diffs
:show_whitespace_in_diffs,
:sourcegraph_enabled
]
end
end
......
......@@ -8,6 +8,8 @@ class Projects::BlobController < Projects::ApplicationController
include NotesHelper
include ActionView::Helpers::SanitizeHelper
include RedirectsForMissingPathOnTree
include SourcegraphGon
prepend_before_action :authenticate_user!, only: [:edit]
around_action :allow_gitaly_ref_name_caching, only: [:show]
......
......@@ -8,6 +8,7 @@ class Projects::CommitController < Projects::ApplicationController
include CreatesCommit
include DiffForPath
include DiffHelper
include SourcegraphGon
# Authorize
before_action :require_non_empty_project
......
......@@ -9,6 +9,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include ToggleAwardEmoji
include IssuableCollections
include RecordUserLastActivity
include SourcegraphGon
skip_before_action :merge_request, only: [:index, :bulk_update]
before_action :whitelist_query_limiting, only: [:assign_related_issues, :update]
......
......@@ -259,6 +259,9 @@ module ApplicationSettingsHelper
:shared_runners_text,
:sign_in_text,
:signup_enabled,
:sourcegraph_enabled,
:sourcegraph_url,
:sourcegraph_public_only,
:terminal_max_session_time,
:terms,
:throttle_authenticated_api_enabled,
......
# frozen_string_literal: true
module SourcegraphHelper
def sourcegraph_url_message
link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: Gitlab::CurrentSettings.sourcegraph_url }
link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
message =
if Gitlab::CurrentSettings.sourcegraph_url_is_com?
s_('SourcegraphPreferences|Uses %{link_start}Sourcegraph.com%{link_end}.').html_safe
else
s_('SourcegraphPreferences|Uses a custom %{link_start}Sourcegraph instance%{link_end}.').html_safe
end
message % { link_start: link_start, link_end: link_end }
end
def sourcegraph_experimental_message
if Gitlab::Sourcegraph.feature_conditional?
s_("SourcegraphPreferences|This feature is experimental and currently limited to certain projects.")
elsif Gitlab::CurrentSettings.sourcegraph_public_only
s_("SourcegraphPreferences|This feature is experimental and limited to public projects.")
else
s_("SourcegraphPreferences|This feature is experimental.")
end
end
end
......@@ -99,6 +99,10 @@ class ApplicationSetting < ApplicationRecord
presence: true,
if: :plantuml_enabled
validates :sourcegraph_url,
presence: true,
if: :sourcegraph_enabled
validates :snowplow_collector_hostname,
presence: true,
hostname: true,
......@@ -343,6 +347,10 @@ class ApplicationSetting < ApplicationRecord
end
after_commit :expire_performance_bar_allowed_user_ids_cache, if: -> { previous_changes.key?('performance_bar_allowed_group_id') }
def sourcegraph_url_is_com?
!!(sourcegraph_url =~ /\Ahttps:\/\/(www\.)?sourcegraph\.com/)
end
def self.create_from_defaults
transaction(requires_new: true) do
super
......
......@@ -102,6 +102,9 @@ module ApplicationSettingImplementation
shared_runners_text: nil,
sign_in_text: nil,
signup_enabled: Settings.gitlab['signup_enabled'],
sourcegraph_enabled: false,
sourcegraph_url: nil,
sourcegraph_public_only: true,
terminal_max_session_time: 0,
throttle_authenticated_api_enabled: false,
throttle_authenticated_api_period_in_seconds: 3600,
......
......@@ -240,6 +240,7 @@ class User < ApplicationRecord
delegate :time_display_relative, :time_display_relative=, to: :user_preference
delegate :time_format_in_24h, :time_format_in_24h=, to: :user_preference
delegate :show_whitespace_in_diffs, :show_whitespace_in_diffs=, to: :user_preference
delegate :sourcegraph_enabled, :sourcegraph_enabled=, to: :user_preference
delegate :setup_for_company, :setup_for_company=, to: :user_preference
accepts_nested_attributes_for :user_preference, update_only: true
......
- return unless Gitlab::Sourcegraph.feature_available?
- expanded = integration_expanded?('sourcegraph_')
%section.settings.as-sourcegraph.no-animate#js-sourcegraph-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Sourcegraph')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://sourcegraph.com/' }
- link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
= s_('SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance\'s code views and merge requests.').html_safe % { link_start: link_start, link_end: link_end }
%span
= link_to s_('SourcegraphAdmin|More information'), help_page_path('integration/sourcegraph.md'), target: '_blank'
.settings-content
= form_for @application_setting, url: integrations_admin_application_settings_path(anchor: 'js-sourcegraph-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
.form-group
.form-check
= f.check_box :sourcegraph_enabled, class: 'form-check-input'
= f.label :sourcegraph_enabled, s_('SourcegraphAdmin|Enable Sourcegraph'), class: 'form-check-label'
.form-group
.form-check
= f.check_box :sourcegraph_public_only, class: 'form-check-input'
= f.label :sourcegraph_public_only, s_('SourcegraphAdmin|Block on private and internal projects'), class: 'form-check-label'
.form-text.text-muted
= s_('SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph.')
.form-group
= f.label :sourcegraph_url, s_('SourcegraphAdmin|Sourcegraph URL'), class: 'label-bold'
= f.text_field :sourcegraph_url, class: 'form-control', placeholder: s_('SourcegraphAdmin|e.g. https://sourcegraph.example.com')
.form-text.text-muted
= s_('SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects.')
= f.submit s_('SourcegraphAdmin|Save changes'), class: 'btn btn-success'
......@@ -4,6 +4,7 @@
= render_if_exists 'admin/application_settings/elasticsearch_form'
= render 'admin/application_settings/plantuml'
= render 'admin/application_settings/sourcegraph'
= render_if_exists 'admin/application_settings/slack'
= render 'admin/application_settings/third_party_offers'
= render 'admin/application_settings/snowplow'
......
- return unless Gitlab::Sourcegraph::feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
- sourcegraph_url = Gitlab::CurrentSettings.sourcegraph_url
.col-sm-12
%hr
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
= s_('Preferences|Integrations')
%p
= s_('Preferences|Customize integrations with third party services.')
= succeed '.' do
= link_to _('Learn more'), help_page_path('user/profile/preferences.md', anchor: 'integrations'), target: '_blank'
.col-lg-8
%label.label-bold
= s_('Preferences|Sourcegraph')
= link_to icon('question-circle'), help_page_path('user/profile/preferences.md', anchor: 'sourcegraph'), target: '_blank', class: 'has-tooltip', title: _('More information')
.form-group.form-check
= f.check_box :sourcegraph_enabled, class: 'form-check-input'
= f.label :sourcegraph_enabled, class: 'form-check-label' do
- link_start = '<a href="%{url}">'.html_safe % { url: sourcegraph_url }
- link_end = '</a>'.html_safe
= s_('Preferences|Enable integrated code intelligence on code views').html_safe % { link_start: link_start, link_end: link_end }
.form-text.text-muted
= sourcegraph_url_message
= sourcegraph_experimental_message
......@@ -111,6 +111,9 @@
= time_display_label
.form-text.text-muted
= s_('Preferences|For example: 30 mins ago.')
= render 'sourcegraph', f: f
.col-lg-4.profile-settings-sidebar
.col-lg-8
.form-group
......
......@@ -299,6 +299,11 @@ module.exports = {
from: path.join(ROOT_PATH, 'node_modules/pdfjs-dist/cmaps/'),
to: path.join(ROOT_PATH, 'public/assets/webpack/cmaps/'),
},
{
from: path.join(ROOT_PATH, 'node_modules/@sourcegraph/code-host-integration/'),
to: path.join(ROOT_PATH, 'public/assets/webpack/sourcegraph/'),
ignore: ['package.json'],
},
{
from: path.join(
ROOT_PATH,
......
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddSourcegraphConfigurationToApplicationSettings < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
add_column(:application_settings, :sourcegraph_enabled, :boolean, default: false, null: false)
add_column(:application_settings, :sourcegraph_url, :string, null: true, limit: 255)
end
def down
remove_column(:application_settings, :sourcegraph_enabled)
remove_column(:application_settings, :sourcegraph_url)
end
end
# frozen_string_literal: true
class AddSourcegraphAdminAndUserPreferences < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
add_column(:application_settings, :sourcegraph_public_only, :boolean, default: true, null: false)
add_column(:user_preferences, :sourcegraph_enabled, :boolean)
end
def down
remove_column(:application_settings, :sourcegraph_public_only)
remove_column(:user_preferences, :sourcegraph_enabled)
end
end
......@@ -352,6 +352,9 @@ ActiveRecord::Schema.define(version: 2019_11_14_173624) do
t.string "snowplow_app_id"
t.datetime_with_timezone "productivity_analytics_start_date"
t.string "default_ci_config_path", limit: 255
t.boolean "sourcegraph_enabled", default: false, null: false
t.string "sourcegraph_url", limit: 255
t.boolean "sourcegraph_public_only", default: true, null: false
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id"
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id"
t.index ["instance_administration_project_id"], name: "index_applicationsettings_on_instance_administration_project_id"
......@@ -3771,6 +3774,7 @@ ActiveRecord::Schema.define(version: 2019_11_14_173624) do
t.boolean "time_format_in_24h"
t.string "projects_sort", limit: 64
t.boolean "show_whitespace_in_diffs", default: true, null: false
t.boolean "sourcegraph_enabled"
t.boolean "setup_for_company"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true
end
......
......@@ -324,6 +324,9 @@ are listed in the descriptions of the relevant settings.
| `snowplow_enabled` | boolean | no | Enable snowplow tracking. |
| `snowplow_app_id` | string | no | The Snowplow site name / application id. (e.g. `gitlab`) |
| `snowplow_iglu_registry_url` | string | no | The Snowplow base Iglu Schema Registry URL to use for custom context and self describing events'|
| `sourcegraph_enabled` | boolean | no | Enables Sourcegraph integration. Default is `false`. **If enabled, requires** `sourcegraph_url`. |
| `sourcegraph_url` | string | required by: `sourcegraph_enabled` | The Sourcegraph instance URL for integration. |
| `sourcegraph_public_only` | boolean | no | Blocks Sourcegraph from being loaded on private and internal projects. Defaul is `true`. |
| `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to `0` for unlimited time. |
| `terms` | text | required by: `enforce_terms` | (**Required by:** `enforce_terms`) Markdown content for the ToS. |
| `throttle_authenticated_api_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_api_period_in_seconds` and `throttle_authenticated_api_requests_per_period`) Enable authenticated API request rate limit. Helps reduce request volume (e.g. from crawlers or abusive bots). |
......
......@@ -54,6 +54,7 @@ GitLab can be integrated with the following enhancements:
- Add GitLab actions to [Gmail actions buttons](gmail_action_buttons_for_gitlab.md).
- Configure [PlantUML](../administration/integration/plantuml.md) to use diagrams in AsciiDoc documents.
- Attach merge requests to [Trello](trello_power_up.md) cards.
- Enable integrated code intelligence powered by [Sourcegraph](sourcegraph.md).
## Project services
......
---
type: reference, how-to
---
# Sourcegraph integration
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/16556) in GitLab 12.5. Please note that this integration is [behind a feature flag](#enable-the-sourcegraph-feature-flag).
[Sourcegraph](https://sourcegraph.com) provides code intelligence features, natively integrated into the GitLab UI.
For GitLab.com users, see [Sourcegraph for GitLab.com](#sourcegraph-for-gitlabcom).
![Sourcegraph demo](img/sourcegraph_demo_v12_5.png)
NOTE: **Note:**
This feature requires user opt-in. After Sourcegraph has been enabled for your GitLab instance,
you can choose to enable Sourcegraph [through your user preferences](#enable-sourcegraph-in-user-preferences).
## Set up for self-managed GitLab instances **(CORE ONLY)**
Before you can enable Sourcegraph code intelligence in GitLab you will need to:
- Enable the `sourcegraph` feature flag for your GitLab instance.
- Configure a Sourcegraph instance with your GitLab instance as an external service.
### Enable the Sourcegraph feature flag
NOTE: **Note:**
If you are running a self-managed instance, the Sourcegraph integration will not be available
unless the feature flag `sourcegraph` is enabled. This can be done from the Rails console
by instance administrators.
Use these commands to start the Rails console:
```sh
# Omnibus GitLab
gitlab-rails console
# Installation from source
cd /home/git/gitlab
sudo -u git -H bin/rails console RAILS_ENV=production
```
Then run the following command to enable the feature flag:
```
Feature.enable(:sourcegraph)
```
You can also enable the feature flag only for specific projects with:
```
Feature.enable(:sourcegraph, Project.find_by_full_path('my_group/my_project'))
```
### Set up a self-managed Sourcegraph instance
If you are new to Sourcegraph, head over to the [Sourcegraph installation documentation](https://docs.sourcegraph.com/admin) and get your instance up and running.
### Connect your Sourcegraph instance to your GitLab instance
1. Navigate to the site admin area in Sourcegraph.
1. [Configure your GitLab external service](https://docs.sourcegraph.com/admin/external_service/gitlab).
You can skip this step if you already have your GitLab repositories searchable in Sourcegraph.
1. Validate that you can search your repositories from GitLab in your Sourcegraph instance by running a test query.
1. Add your GitLab instance URL to the [`corsOrigin` setting](https://docs.sourcegraph.com/admin/config/site_config#corsOrigin) in your site configuration.
### Configure your GitLab instance with Sourcegraph
1. In GitLab, go to **Admin Area > Settings > Integrations**.
1. Expand the **Sourcegraph** configuration section.
1. Check **Enable Sourcegraph**.
1. Set the Sourcegraph URL to your Sourcegraph instance, e.g., `https://sourcegraph.example.com`.
![Sourcegraph admin settings](img/sourcegraph_admin_v12_5.png)
## Enable Sourcegraph in user preferences
If a GitLab administrator has enabled Sourcegraph, you can enable this feature in your user preferences.
1. In GitLab, click your avatar in the top-right corner, then click **Settings**. On the left-hand nav, click **Preferences**.
1. Under **Integrations**, find the **Sourcegraph** section.
1. Check **Enable Sourcegraph**.
![Sourcegraph user preferences](img/sourcegraph_user_preferences_v12_5.png)
## Using Sourcegraph code intelligence
Once enabled, participating projects will have a code intelligence popover available in
the following code views:
- Merge request diffs
- Commit view
- File view
When visiting one of these views, you can now hover over a code reference to see a popover with:
- Details on how this reference was defined.
- **Go to definition**, which navigates to the line of code where this reference was defined.
- **Find references**, which navigates to the configured Sourcegraph instance, showing a list of references to the hilighted code.
![Sourcegraph demo](img/sourcegraph_popover_v12_5.png)
## Sourcegraph for GitLab.com
Sourcegraph powered code intelligence will be incrementally rolled out on GitLab.com. It will eventually be
available for all public projects, but for now, it is only available for some specific [`gitlab-org` projects](https://gitlab.com/gitlab-org/).
If you have a private or internal project and would like integrated code intelligence, please consider
setting up a self-managed GitLab instance.
## Sourcegraph and Privacy
From Sourcegraph's [extension documentation](https://docs.sourcegraph.com/integration/browser_extension#privacy) which is the
engine behind the native GitLab integration:
> Sourcegraph integrations never send any logs, pings, usage statistics, or telemetry to Sourcegraph.com.
> They will only connect to Sourcegraph.com as required to provide code intelligence or other functionality on public code.
> As a result, no private code, private repository names, usernames, or any other specific data is sent to Sourcegraph.com.
......@@ -128,6 +128,19 @@ You can choose one of the following options as the first day of the week:
If you select **System Default**, the system-wide default setting will be used.
## Integrations
Configure your preferences with third-party services which provide enhancements to your GitLab experience.
### Sourcegraph
NOTE: **Note:**
This setting is only visible if Sourcegraph has been enabled by a GitLab administrator.
Manage the availability of integrated code intelligence features powered by
Sourcegraph. View [the Sourcegraph feature documentation](../../integration/sourcegraph.md#enable-sourcegraph-in-user-preferences)
for more information.
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
......
......@@ -136,6 +136,11 @@ module API
optional :sign_in_text, type: String, desc: 'The sign in text of the GitLab application'
optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' # support legacy names, can be removed in v5
optional :signup_enabled, type: Boolean, desc: 'Flag indicating if sign up is enabled'
optional :sourcegraph_enabled, type: Boolean, desc: 'Enable Sourcegraph'
optional :sourcegraph_public_only, type: Boolean, desc: 'Only allow public projects to communicate with Sourcegraph'
given sourcegraph_enabled: ->(val) { val } do
requires :sourcegraph_url, type: String, desc: 'The configured Sourcegraph instance URL'
end
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
optional :instance_statistics_visibility_private, type: Boolean, desc: 'When set to `true` Instance statistics will only be available to admins'
......
# frozen_string_literal: true
module Gitlab
class Sourcegraph
class << self
def feature_conditional?
feature.conditional?
end
def feature_available?
# The sourcegraph_bundle feature could be conditionally applied, so check if `!off?`
!feature.off?
end
def feature_enabled?(thing = nil)
feature.enabled?(thing)
end
private
def feature
Feature.get(:sourcegraph)
end
end
end
end
......@@ -12541,6 +12541,9 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
......@@ -12550,9 +12553,15 @@ msgstr ""
msgid "Preferences|Display time in 24-hour format"
msgstr ""
msgid "Preferences|Enable integrated code intelligence on code views"
msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
msgid "Preferences|Integrations"
msgstr ""
msgid "Preferences|Layout width"
msgstr ""
......@@ -12565,6 +12574,9 @@ msgstr ""
msgid "Preferences|Show whitespace in diffs"
msgstr ""
msgid "Preferences|Sourcegraph"
msgstr ""
msgid "Preferences|Syntax highlighting theme"
msgstr ""
......@@ -16172,6 +16184,51 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
msgid "Sourcegraph"
msgstr ""
msgid "SourcegraphAdmin|Block on private and internal projects"
msgstr ""
msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
msgstr ""
msgid "SourcegraphAdmin|Enable Sourcegraph"
msgstr ""
msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
msgstr ""
msgid "SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph."
msgstr ""
msgid "SourcegraphAdmin|More information"
msgstr ""
msgid "SourcegraphAdmin|Save changes"
msgstr ""
msgid "SourcegraphAdmin|Sourcegraph URL"
msgstr ""
msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
msgstr ""
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
msgstr ""
msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
msgstr ""
msgid "SourcegraphPreferences|This feature is experimental."
msgstr ""
msgid "SourcegraphPreferences|Uses %{link_start}Sourcegraph.com%{link_end}."
msgstr ""
msgid "SourcegraphPreferences|Uses a custom %{link_start}Sourcegraph instance%{link_end}."
msgstr ""
msgid "Spam Logs"
msgstr ""
......
# frozen_string_literal: true
require 'spec_helper'
describe SourcegraphGon do
let_it_be(:enabled_user) { create(:user, sourcegraph_enabled: true) }
let_it_be(:disabled_user) { create(:user, sourcegraph_enabled: false) }
let_it_be(:public_project) { create(:project, :public) }
let_it_be(:internal_project) { create(:project, :internal) }
let(:sourcegraph_url) { 'http://sourcegraph.gitlab.com' }
let(:feature_enabled) { true }
let(:sourcegraph_enabled) { true }
let(:sourcegraph_public_only) { false }
let(:format) { :html }
let(:user) { enabled_user }
let(:project) { internal_project }
controller(ApplicationController) do
include SourcegraphGon # rubocop:disable RSpec/DescribedClass
def index
head :ok
end
end
before do
Feature.get(:sourcegraph).enable(feature_enabled)
stub_application_setting(sourcegraph_url: sourcegraph_url, sourcegraph_enabled: sourcegraph_enabled, sourcegraph_public_only: sourcegraph_public_only)
allow(controller).to receive(:project).and_return(project)
Gon.clear
sign_in user if user
end
after do
Feature.get(:sourcegraph).disable
end
subject do
get :index, format: format
Gon.sourcegraph
end
shared_examples 'enabled' do
it { is_expected.to eq({ url: sourcegraph_url }) }
end
shared_examples 'disabled' do
it { is_expected.to be_nil }
end
context 'with feature enabled, application enabled, and user enabled' do
it_behaves_like 'enabled'
end
context 'with feature enabled for specific project' do
let(:feature_enabled) { project }
it_behaves_like 'enabled'
end
context 'with feature enabled for different project' do
let(:feature_enabled) { create(:project) }
it_behaves_like 'disabled'
end
context 'with feature disabled' do
let(:feature_enabled) { false }
it_behaves_like 'disabled'
end
context 'with admin settings disabled' do
let(:sourcegraph_enabled) { false }
it_behaves_like 'disabled'
end
context 'with public only' do
let(:sourcegraph_public_only) { true }
context 'with internal project' do
let(:project) { internal_project }
it_behaves_like 'disabled'
end
context 'with public project' do
let(:project) { public_project }
it_behaves_like 'enabled'
end
end
context 'with user disabled' do
let(:user) { disabled_user }
it_behaves_like 'disabled'
end
context 'with no user' do
let(:user) { nil }
it_behaves_like 'disabled'
end
context 'with non-html format' do
let(:format) { :json }
it_behaves_like 'disabled'
end
end
# frozen_string_literal: true
require 'spec_helper'
describe SourcegraphHelper do
describe '#sourcegraph_url_message' do
let(:sourcegraph_url) { 'http://sourcegraph.example.com' }
before do
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url)
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url_is_com?).and_return(is_com)
end
subject { helper.sourcegraph_url_message }
context 'with .com sourcegraph url' do
let(:is_com) { true }
it { is_expected.to have_text('Uses Sourcegraph.com') }
it { is_expected.to have_link('Sourcegraph.com', href: sourcegraph_url) }
end
context 'with custom sourcegraph url' do
let(:is_com) { false }
it { is_expected.to have_text('Uses a custom Sourcegraph instance') }
it { is_expected.to have_link('Sourcegraph instance', href: sourcegraph_url) }
context 'with unsafe url' do
let(:sourcegraph_url) { '\" onload=\"alert(1);\"' }
it { is_expected.to have_link('Sourcegraph instance', href: sourcegraph_url) }
end
end
end
context '#sourcegraph_experimental_message' do
let(:feature_conditional) { false }
let(:public_only) { false }
before do
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_public_only).and_return(public_only)
allow(Gitlab::Sourcegraph).to receive(:feature_conditional?).and_return(feature_conditional)
end
subject { helper.sourcegraph_experimental_message }
context 'when not limited by feature or public only' do
it { is_expected.to eq "This feature is experimental." }
end
context 'when limited by feature' do
let(:feature_conditional) { true }
it { is_expected.to eq "This feature is experimental and currently limited to certain projects." }
end
context 'when limited by public only' do
let(:public_only) { true }
it { is_expected.to eq "This feature is experimental and limited to public projects." }
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Sourcegraph do
let_it_be(:user) { create(:user) }
let(:feature_scope) { true }
before do
Feature.enable(:sourcegraph, feature_scope)
end
describe '.feature_conditional?' do
subject { described_class.feature_conditional? }
context 'when feature is enabled globally' do
it { is_expected.to be_falsey }
end
context 'when feature is enabled only to a resource' do
let(:feature_scope) { user }
it { is_expected.to be_truthy }
end
end
describe '.feature_available?' do
subject { described_class.feature_available? }
context 'when feature is enabled globally' do
it { is_expected.to be_truthy }
end
context 'when feature is enabled only to a resource' do
let(:feature_scope) { user }
it { is_expected.to be_truthy }
end
end
describe '.feature_enabled?' do
let(:current_user) { nil }
subject { described_class.feature_enabled?(current_user) }
context 'when feature is enabled globally' do
it { is_expected.to be_truthy }
end
context 'when feature is enabled only to a resource' do
let(:feature_scope) { user }
context 'for the same resource' do
let(:current_user) { user }
it { is_expected.to be_truthy }
end
context 'for a different resource' do
let(:current_user) { create(:user) }
it { is_expected.to be_falsey }
end
end
end
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
describe ApplicationSetting do
using RSpec::Parameterized::TableSyntax
subject(:setting) { described_class.create_from_defaults }
it { include(CacheableAttributes) }
......@@ -495,6 +497,15 @@ describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:static_objects_external_storage_auth_token) }
end
end
context 'sourcegraph settings' do
it 'is invalid if sourcegraph is enabled and no url is provided' do
allow(subject).to receive(:sourcegraph_enabled).and_return(true)
expect(subject.sourcegraph_url).to be_nil
is_expected.to be_invalid
end
end
end
context 'restrict creating duplicates' do
......@@ -583,5 +594,24 @@ describe ApplicationSetting do
end
end
describe '#sourcegraph_url_is_com?' do
where(:url, :is_com) do
'https://sourcegraph.com' | true
'https://sourcegraph.com/' | true
'https://www.sourcegraph.com' | true
'shttps://www.sourcegraph.com' | false
'https://sourcegraph.example.com/' | false
'https://sourcegraph.org/' | false
end
with_them do
it 'matches the url with sourcegraph.com' do
setting.sourcegraph_url = url
expect(setting.sourcegraph_url_is_com?).to eq(is_com)
end
end
end
it_behaves_like 'application settings examples'
end
......@@ -19,6 +19,9 @@ describe API::Settings, 'Settings' do
expect(json_response['plantuml_enabled']).to be_falsey
expect(json_response['plantuml_url']).to be_nil
expect(json_response['default_ci_config_path']).to be_nil
expect(json_response['sourcegraph_enabled']).to be_falsey
expect(json_response['sourcegraph_url']).to be_nil
expect(json_response['sourcegraph_public_only']).to be_truthy
expect(json_response['default_project_visibility']).to be_a String
expect(json_response['default_snippet_visibility']).to be_a String
expect(json_response['default_group_visibility']).to be_a String
......@@ -45,6 +48,7 @@ describe API::Settings, 'Settings' do
storages = Gitlab.config.repositories.storages
.merge({ 'custom' => 'tmp/tests/custom_repositories' })
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
Feature.get(:sourcegraph).enable
end
it "updates application settings" do
......@@ -57,6 +61,9 @@ describe API::Settings, 'Settings' do
repository_storages: ['custom'],
plantuml_enabled: true,
plantuml_url: 'http://plantuml.example.com',
sourcegraph_enabled: true,
sourcegraph_url: 'https://sourcegraph.com',
sourcegraph_public_only: false,
default_snippet_visibility: 'internal',
restricted_visibility_levels: ['public'],
default_artifacts_expire_in: '2 days',
......@@ -89,6 +96,9 @@ describe API::Settings, 'Settings' do
expect(json_response['repository_storages']).to eq(['custom'])
expect(json_response['plantuml_enabled']).to be_truthy
expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
expect(json_response['sourcegraph_enabled']).to be_truthy
expect(json_response['sourcegraph_url']).to eq('https://sourcegraph.com')
expect(json_response['sourcegraph_public_only']).to eq(false)
expect(json_response['default_snippet_visibility']).to eq('internal')
expect(json_response['restricted_visibility_levels']).to eq(['public'])
expect(json_response['default_artifacts_expire_in']).to eq('2 days')
......@@ -355,5 +365,14 @@ describe API::Settings, 'Settings' do
expect(json_response['domain_blacklist']).to eq(['domain3.com', '*.domain4.com'])
end
end
context "missing sourcegraph_url value when sourcegraph_enabled is true" do
it "returns a blank parameter error message" do
put api("/application/settings", admin), params: { sourcegraph_enabled: true }
expect(response).to have_gitlab_http_status(400)
expect(json_response['error']).to eq('sourcegraph_url is missing')
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'admin/application_settings/integrations.html.haml' do
let(:app_settings) { build(:application_setting) }
describe 'sourcegraph integration' do
let(:sourcegraph_flag) { true }
before do
assign(:application_setting, app_settings)
allow(Gitlab::Sourcegraph).to receive(:feature_available?).and_return(sourcegraph_flag)
end
context 'when sourcegraph feature is enabled' do
it 'show the form' do
render
expect(rendered).to have_field('application_setting_sourcegraph_enabled')
end
end
context 'when sourcegraph feature is disabled' do
let(:sourcegraph_flag) { false }
it 'show the form' do
render
expect(rendered).not_to have_field('application_setting_sourcegraph_enabled')
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'profiles/preferences/show' do
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { build(:user) }
before do
assign(:user, user)
allow(controller).to receive(:current_user).and_return(user)
end
context 'sourcegraph' do
def have_sourcegraph_field(*args)
have_field('user_sourcegraph_enabled', *args)
end
def have_integrations_section
have_css('.profile-settings-sidebar', { text: 'Integrations' })
end
before do
# Can't use stub_feature_flags because we use Feature.get to check if conditinally applied
Feature.get(:sourcegraph).enable sourcegraph_feature
stub_application_setting(sourcegraph_enabled: sourcegraph_enabled)
end
context 'when not fully enabled' do
where(:feature, :admin_enabled) do
false | false
false | true
true | false
end
with_them do
let(:sourcegraph_feature) { feature }
let(:sourcegraph_enabled) { admin_enabled }
before do
render
end
it 'does not display sourcegraph field' do
expect(rendered).not_to have_sourcegraph_field
end
it 'does not display integrations settings' do
expect(rendered).not_to have_integrations_section
end
end
end
context 'when fully enabled' do
let(:sourcegraph_feature) { true }
let(:sourcegraph_enabled) { true }
before do
render
end
it 'displays the sourcegraph field' do
expect(rendered).to have_sourcegraph_field
end
it 'displays the integrations section' do
expect(rendered).to have_integrations_section
end
end
end
end
......@@ -970,6 +970,11 @@
"@sentry/types" "5.7.1"
tslib "^1.9.3"
"@sourcegraph/code-host-integration@^0.0.13":
version "0.0.13"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.13.tgz#4fd5fe1e0088c63b2a26be231c5a2a4ca79b1596"
integrity sha512-IjF9gb9e8dG8p12DKg5Z7UMOVQO/ClH3AyMCPfX/qH7DH/0b55WH6stYVqZu6y776quFonO4Z9gWYM8pQZjzKw==
"@types/anymatch@*":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.0.tgz#d1d55958d1fccc5527d4aba29fc9c4b942f563ff"
......
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