Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6e81d7f628
commit
eca3cd3a9e
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
import setupToggleButtons from '~/toggle_buttons';
|
||||
|
||||
function updateVisibility(selector, isVisible) {
|
||||
Array.from(document.querySelectorAll(selector)).forEach(el => {
|
||||
if (isVisible) {
|
||||
el.classList.remove('d-none');
|
||||
} else {
|
||||
el.classList.add('d-none');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const toggleContainer = document.querySelector('.js-auto-ssl-toggle-container');
|
||||
|
||||
if (toggleContainer) {
|
||||
const onToggleButtonClicked = isAutoSslEnabled => {
|
||||
Array.from(document.querySelectorAll('.js-shown-unless-auto-ssl')).forEach(el => {
|
||||
if (isAutoSslEnabled) {
|
||||
el.classList.add('d-none');
|
||||
} else {
|
||||
el.classList.remove('d-none');
|
||||
}
|
||||
});
|
||||
updateVisibility('.js-shown-unless-auto-ssl', !isAutoSslEnabled);
|
||||
|
||||
updateVisibility('.js-shown-if-auto-ssl', isAutoSslEnabled);
|
||||
|
||||
Array.from(document.querySelectorAll('.js-enabled-unless-auto-ssl')).forEach(el => {
|
||||
if (isAutoSslEnabled) {
|
||||
|
|
|
@ -64,14 +64,14 @@ export default {
|
|||
v-for="(testSuite, index) in getTestSuites"
|
||||
:key="index"
|
||||
role="row"
|
||||
class="gl-responsive-table-row test-reports-summary-row rounded cursor-pointer js-suite-row"
|
||||
class="gl-responsive-table-row gl-responsive-table-row-clickable test-reports-summary-row rounded cursor-pointer js-suite-row"
|
||||
@click="tableRowClick(testSuite)"
|
||||
>
|
||||
<div class="table-section section-25">
|
||||
<div role="rowheader" class="table-mobile-header font-weight-bold">
|
||||
{{ __('Suite') }}
|
||||
</div>
|
||||
<div class="table-mobile-content test-reports-summary-suite cgray pl-3">
|
||||
<div class="table-mobile-content underline cgray pl-3">
|
||||
{{ testSuite.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ import createStore from './store';
|
|||
export default () => {
|
||||
const el = document.getElementById('js-edit-release-page');
|
||||
|
||||
const store = createStore(el.dataset);
|
||||
const store = createStore();
|
||||
store.dispatch('setInitialState', el.dataset);
|
||||
|
||||
return new Vue({
|
||||
|
|
|
@ -109,7 +109,7 @@ export default {
|
|||
class="text-expander"
|
||||
@click="toggleShowDescription"
|
||||
>
|
||||
<icon name="ellipsis_h" />
|
||||
<icon name="ellipsis_h" :size="10" />
|
||||
</gl-button>
|
||||
<div class="committer">
|
||||
<gl-link
|
||||
|
@ -124,7 +124,7 @@ export default {
|
|||
</div>
|
||||
<pre
|
||||
v-if="commit.description"
|
||||
v-show="showDescription"
|
||||
:class="{ 'd-block': showDescription }"
|
||||
class="commit-row-description append-bottom-8"
|
||||
>
|
||||
{{ commit.description }}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
import { normalizeData } from 'ee_else_ce/repository/utils/commit';
|
||||
import getCommits from './queries/getCommits.query.graphql';
|
||||
import getProjectPath from './queries/getProjectPath.query.graphql';
|
||||
import getRef from './queries/getRef.query.graphql';
|
||||
|
@ -6,19 +7,6 @@ import getRef from './queries/getRef.query.graphql';
|
|||
let fetchpromise;
|
||||
let resolvers = [];
|
||||
|
||||
export function normalizeData(data) {
|
||||
return data.map(d => ({
|
||||
sha: d.commit.id,
|
||||
message: d.commit.message,
|
||||
committedDate: d.commit.committed_date,
|
||||
commitPath: d.commit_path,
|
||||
fileName: d.file_name,
|
||||
type: d.type,
|
||||
lockLabel: d.lock_label,
|
||||
__typename: 'LogTreeCommit',
|
||||
}));
|
||||
}
|
||||
|
||||
export function resolveCommit(commits, { resolve, entry }) {
|
||||
const commit = commits.find(c => c.fileName === entry.name && c.type === entry.type);
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fragment TreeEntryCommit on LogTreeCommit {
|
||||
sha
|
||||
message
|
||||
committedDate
|
||||
commitPath
|
||||
fileName
|
||||
type
|
||||
}
|
|
@ -1,11 +1,7 @@
|
|||
#import "ee_else_ce/repository/queries/commit.fragment.graphql"
|
||||
|
||||
query getCommit($fileName: String!, $type: String!, $path: String!) {
|
||||
commit(path: $path, fileName: $fileName, type: $type) @client {
|
||||
sha
|
||||
message
|
||||
committedDate
|
||||
commitPath
|
||||
fileName
|
||||
type
|
||||
lockLabel
|
||||
...TreeEntryCommit
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#import "ee_else_ce/repository/queries/commit.fragment.graphql"
|
||||
|
||||
query getCommits {
|
||||
commits @client {
|
||||
sha
|
||||
message
|
||||
committedDate
|
||||
commitPath
|
||||
fileName
|
||||
type
|
||||
lockLabel
|
||||
...TreeEntryCommit
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
|
|||
lastCommit {
|
||||
sha
|
||||
title
|
||||
message
|
||||
description
|
||||
webUrl
|
||||
authoredDate
|
||||
author {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function normalizeData(data, extra = () => {}) {
|
||||
return data.map(d => ({
|
||||
sha: d.commit.id,
|
||||
message: d.commit.message,
|
||||
committedDate: d.commit.committed_date,
|
||||
commitPath: d.commit_path,
|
||||
fileName: d.file_name,
|
||||
type: d.type,
|
||||
__typename: 'LogTreeCommit',
|
||||
...extra(d),
|
||||
}));
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
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);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import initSourcegraph from './index';
|
||||
|
||||
/**
|
||||
* Load sourcegraph in it's own listener so that it's isolated from failures.
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', initSourcegraph);
|
|
@ -168,7 +168,7 @@ export default {
|
|||
:prepend="true"
|
||||
tag="* [ ] "
|
||||
:button-title="__('Add a task list')"
|
||||
icon="task-done"
|
||||
icon="list-task"
|
||||
/>
|
||||
<toolbar-button
|
||||
:tag="mdTable"
|
||||
|
|
|
@ -572,3 +572,10 @@ img.emoji {
|
|||
.gl-font-size-20 { font-size: $gl-font-size-20; }
|
||||
.gl-font-size-28 { font-size: $gl-font-size-28; }
|
||||
.gl-font-size-42 { font-size: $gl-font-size-42; }
|
||||
|
||||
.border-section {
|
||||
@include gl-py-6;
|
||||
@include gl-m-0;
|
||||
|
||||
border-top: 1px solid $border-color;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,17 @@
|
|||
@extend .gl-responsive-table-row-layout;
|
||||
margin-top: 10px;
|
||||
border: 1px solid $border-color;
|
||||
color: $gray-700;
|
||||
|
||||
&.gl-responsive-table-row-clickable {
|
||||
&:hover {
|
||||
background-color: $gray-light;
|
||||
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin: 0;
|
||||
|
|
|
@ -1084,18 +1084,6 @@ button.mini-pipeline-graph-dropdown-toggle {
|
|||
}
|
||||
|
||||
.test-reports-table {
|
||||
color: $gray-700;
|
||||
|
||||
.test-reports-summary-row {
|
||||
&:hover {
|
||||
background-color: $gray-light;
|
||||
|
||||
.test-reports-summary-suite {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.build-trace {
|
||||
@include build-trace();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# 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]
|
||||
|
|
|
@ -8,6 +8,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
before_action :domain, except: [:new, :create]
|
||||
|
||||
def show
|
||||
redirect_to edit_project_pages_domain_path(@project, @domain)
|
||||
end
|
||||
|
||||
def new
|
||||
|
@ -23,7 +24,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
flash[:alert] = 'Failed to verify domain ownership'
|
||||
end
|
||||
|
||||
redirect_to project_pages_domain_path(@project, @domain)
|
||||
redirect_to edit_project_pages_domain_path(@project, @domain)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -33,7 +34,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
@domain = @project.pages_domains.create(create_params)
|
||||
|
||||
if @domain.valid?
|
||||
redirect_to project_pages_domain_path(@project, @domain)
|
||||
redirect_to edit_project_pages_domain_path(@project, @domain)
|
||||
else
|
||||
render 'new'
|
||||
end
|
||||
|
@ -77,7 +78,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def update_params
|
||||
params.require(:pages_domain).permit(:user_provided_key, :user_provided_certificate, :auto_ssl_enabled)
|
||||
params.fetch(:pages_domain, {}).permit(:user_provided_key, :user_provided_certificate, :auto_ssl_enabled)
|
||||
end
|
||||
|
||||
def domain
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# 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
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Git
|
||||
module Logger
|
||||
def log_error(message, save_message_on_model: false)
|
||||
Gitlab::GitLogger.error("#{self.class.name} error (#{merge_request.to_reference(full: true)}): #{message}")
|
||||
merge_request.update(merge_error: message) if save_message_on_model
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,6 +29,19 @@ module MergeRequests
|
|||
.execute_for_merge_request(merge_request)
|
||||
end
|
||||
|
||||
def source_project
|
||||
@source_project ||= merge_request.source_project
|
||||
end
|
||||
|
||||
def target_project
|
||||
@target_project ||= merge_request.target_project
|
||||
end
|
||||
|
||||
# Don't try to print expensive instance variables.
|
||||
def inspect
|
||||
"#<#{self.class} #{merge_request.to_reference(full: true)}>"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create(merge_request)
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MergeRequests
|
||||
class RebaseService < MergeRequests::WorkingCopyBaseService
|
||||
class RebaseService < MergeRequests::BaseService
|
||||
include Git::Logger
|
||||
|
||||
REBASE_ERROR = 'Rebase failed. Please rebase locally'
|
||||
|
||||
attr_reader :merge_request
|
||||
|
||||
def execute(merge_request)
|
||||
@merge_request = merge_request
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MergeRequests
|
||||
class SquashService < MergeRequests::WorkingCopyBaseService
|
||||
class SquashService < MergeRequests::BaseService
|
||||
include Git::Logger
|
||||
|
||||
def execute
|
||||
# If performing a squash would result in no change, then
|
||||
# immediately return a success message without performing a squash
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MergeRequests
|
||||
class WorkingCopyBaseService < MergeRequests::BaseService
|
||||
attr_reader :merge_request
|
||||
|
||||
def source_project
|
||||
@source_project ||= merge_request.source_project
|
||||
end
|
||||
|
||||
def target_project
|
||||
@target_project ||= merge_request.target_project
|
||||
end
|
||||
|
||||
def log_error(message, save_message_on_model: false)
|
||||
Gitlab::GitLogger.error("#{self.class.name} error (#{merge_request.to_reference(full: true)}): #{message}")
|
||||
|
||||
merge_request.update(merge_error: message) if save_message_on_model
|
||||
end
|
||||
|
||||
# Don't try to print expensive instance variables.
|
||||
def inspect
|
||||
"#<#{self.class} #{merge_request.to_reference(full: true)}>"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
- 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'
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
- 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
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
= markdown_toolbar_button({ icon: "link", data: { "md-tag" => "[{text}](url)", "md-select" => "url" }, title: _("Add a link") })
|
||||
= markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "* ", "md-prepend" => true }, title: _("Add a bullet list") })
|
||||
= markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: _("Add a numbered list") })
|
||||
= markdown_toolbar_button({ icon: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: _("Add a task list") })
|
||||
= markdown_toolbar_button({ icon: "list-task", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: _("Add a task list") })
|
||||
= markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: _("Add a table") })
|
||||
- if show_fullscreen_button
|
||||
%button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: _("Go full screen"), data: { container: "body" } }
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
%span.badge.badge-danger
|
||||
= s_('GitLabPages|Expired')
|
||||
%div
|
||||
= link_to s_('GitLabPages|Details'), project_pages_domain_path(@project, domain), class: "btn btn-sm btn-grouped"
|
||||
= link_to s_('GitLabPages|Edit'), edit_project_pages_domain_path(@project, domain), class: "btn btn-sm btn-grouped btn-success btn-inverted"
|
||||
= link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?')}, method: :delete, class: "btn btn-remove btn-sm btn-grouped"
|
||||
- if verification_enabled && domain.unverified?
|
||||
%li.list-group-item.bs-callout-warning
|
||||
- details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
|
||||
- details_link_start = "<a href='#{edit_project_pages_domain_path(@project, domain)}'>".html_safe
|
||||
- details_link_end = '</a>'.html_safe
|
||||
= s_('GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}.').html_safe % { domain: domain.domain,
|
||||
link_start: details_link_start,
|
||||
|
|
|
@ -1,18 +1,63 @@
|
|||
- if @domain.auto_ssl_enabled?
|
||||
- if @domain.enabled?
|
||||
- if @domain.certificate_text
|
||||
%pre
|
||||
= @domain.certificate_text
|
||||
- else
|
||||
.bs-callout.bs-callout-info
|
||||
= _("GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.")
|
||||
- auto_ssl_available = ::Gitlab::LetsEncrypt.enabled?
|
||||
- auto_ssl_enabled = @domain.auto_ssl_enabled?
|
||||
- auto_ssl_available_and_enabled = auto_ssl_available && auto_ssl_enabled
|
||||
- has_user_defined_certificate = @domain.certificate && @domain.certificate_user_provided?
|
||||
|
||||
- if auto_ssl_available
|
||||
.form-group.border-section
|
||||
.row
|
||||
.col-sm-2
|
||||
= _('Certificate')
|
||||
.col-sm-10.js-auto-ssl-toggle-container
|
||||
%label{ for: "pages_domain_auto_ssl_enabled_button" }
|
||||
- lets_encrypt_link_url = "https://letsencrypt.org/"
|
||||
- lets_encrypt_link_start = "<a href=\"%{lets_encrypt_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { lets_encrypt_link_url: lets_encrypt_link_url }
|
||||
- lets_encrypt_link_end = "</a>".html_safe
|
||||
= _("Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: lets_encrypt_link_end }
|
||||
%button{ type: "button", id: "pages_domain_auto_ssl_enabled_button",
|
||||
class: "js-project-feature-toggle project-feature-toggle mt-2 #{"is-checked" if auto_ssl_available_and_enabled}",
|
||||
"aria-label": _("Automatic certificate management using Let's Encrypt") }
|
||||
= f.hidden_field :auto_ssl_enabled?, class: "js-project-feature-toggle-input"
|
||||
%span.toggle-icon
|
||||
= sprite_icon("status_success_borderless", size: 16, css_class: "toggle-icon-svg toggle-status-checked")
|
||||
= sprite_icon("status_failed_borderless", size: 16, css_class: "toggle-icon-svg toggle-status-unchecked")
|
||||
%p.text-secondary.mt-3
|
||||
- docs_link_url = help_page_path("user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md")
|
||||
- docs_link_start = "<a href=\"%{docs_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { docs_link_url: docs_link_url }
|
||||
- docs_link_end = "</a>".html_safe
|
||||
= _("Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}.").html_safe % { docs_link_url: docs_link_url, docs_link_start: docs_link_start, docs_link_end: docs_link_end }
|
||||
|
||||
.form-group.border-section.js-shown-unless-auto-ssl{ class: ("d-none" if auto_ssl_available_and_enabled) }
|
||||
- if has_user_defined_certificate
|
||||
.row
|
||||
.col-sm-10.offset-sm-2
|
||||
.card
|
||||
.card-header
|
||||
= _('Certificate')
|
||||
.d-flex.justify-content-between.align-items-center.p-3
|
||||
%span
|
||||
= @domain.subject || _('missing')
|
||||
= link_to _('Remove'),
|
||||
clean_certificate_project_pages_domain_path(@project, @domain),
|
||||
data: { confirm: _('Are you sure?') },
|
||||
class: 'btn btn-remove btn-sm',
|
||||
method: :delete
|
||||
- else
|
||||
.bs-callout.bs-callout-warning
|
||||
= _("A Let's Encrypt SSL certificate can not be obtained until your domain is verified.")
|
||||
- else
|
||||
- if @domain.certificate_text
|
||||
%pre
|
||||
= @domain.certificate_text
|
||||
- else
|
||||
.light
|
||||
= _("missing")
|
||||
.row
|
||||
.col-sm-10.offset-sm-2
|
||||
= f.label :user_provided_certificate, _("Certificate (PEM)")
|
||||
= f.text_area :user_provided_certificate,
|
||||
rows: 5,
|
||||
class: "form-control js-enabled-unless-auto-ssl",
|
||||
disabled: auto_ssl_available_and_enabled
|
||||
%span.help-inline.text-muted= _("Upload a certificate for your domain with all intermediates")
|
||||
.row
|
||||
.col-sm-10.offset-sm-2
|
||||
= f.label :user_provided_key, _("Key (PEM)")
|
||||
= f.text_area :user_provided_key,
|
||||
rows: 5,
|
||||
class: "form-control js-enabled-unless-auto-ssl",
|
||||
disabled: auto_ssl_available_and_enabled
|
||||
%span.help-inline.text-muted= _("Upload a private key for your certificate")
|
||||
|
||||
= render 'lets_encrypt_callout', auto_ssl_available_and_enabled: auto_ssl_available_and_enabled
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
|
||||
- dns_record = "#{@domain.domain} CNAME #{@domain.project.pages_subdomain}.#{Settings.pages.host}."
|
||||
|
||||
.form-group.border-section
|
||||
.row
|
||||
.col-sm-2
|
||||
= _("DNS")
|
||||
.col-sm-10
|
||||
.input-group
|
||||
= text_field_tag :domain_dns, dns_record , class: "monospace js-select-on-focus form-control", readonly: true
|
||||
.input-group-append
|
||||
= clipboard_button(target: '#domain_dns', class: 'btn-default input-group-text d-none d-sm-block')
|
||||
%p.form-text.text-muted
|
||||
= _("To access this domain create a new DNS record")
|
||||
- if verification_enabled
|
||||
- verification_record = "#{@domain.verification_domain} TXT #{@domain.keyed_verification_code}"
|
||||
.form-group.border-section
|
||||
.row
|
||||
.col-sm-2
|
||||
= _("Verification status")
|
||||
.col-sm-10
|
||||
.status-badge
|
||||
- text, status = @domain.unverified? ? [_('Unverified'), 'badge-danger'] : [_('Verified'), 'badge-success']
|
||||
.badge{ class: status }
|
||||
= text
|
||||
= link_to sprite_icon("redo"), verify_project_pages_domain_path(@project, @domain), method: :post, class: "btn has-tooltip", title: _("Retry verification")
|
||||
.input-group
|
||||
= text_field_tag :domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true
|
||||
.input-group-append
|
||||
= clipboard_button(target: '#domain_verification', class: 'btn-default d-none d-sm-block')
|
||||
%p.form-text.text-muted
|
||||
- link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
|
||||
= _("To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration.").html_safe % { link_to_help: link_to_help }
|
|
@ -3,62 +3,25 @@
|
|||
- @domain.errors.full_messages.each do |msg|
|
||||
= msg
|
||||
|
||||
.form-group.row
|
||||
.col-sm-2.col-form-label
|
||||
= f.label :domain, _("Domain")
|
||||
.col-sm-10
|
||||
= f.text_field :domain, required: true, autocomplete: "off", class: "form-control", disabled: @domain.persisted?
|
||||
.form-group.border-section
|
||||
.row
|
||||
- if @domain.persisted?
|
||||
.col-sm-2
|
||||
= _("Domain")
|
||||
.col-sm-10
|
||||
= external_link(@domain.url, @domain.url)
|
||||
- else
|
||||
.col-sm-2
|
||||
= f.label :domain, _("Domain")
|
||||
.col-sm-10
|
||||
.input-group
|
||||
= f.text_field :domain, required: true, autocomplete: "off", class: "form-control"
|
||||
|
||||
- if @domain.persisted?
|
||||
= render 'dns'
|
||||
|
||||
- if Gitlab.config.pages.external_https
|
||||
|
||||
- auto_ssl_available = ::Gitlab::LetsEncrypt.enabled?
|
||||
- auto_ssl_enabled = @domain.auto_ssl_enabled?
|
||||
- auto_ssl_available_and_enabled = auto_ssl_available && auto_ssl_enabled
|
||||
|
||||
- if auto_ssl_available
|
||||
.form-group.row
|
||||
.col-sm-2.col-form-label
|
||||
%label{ for: "pages_domain_auto_ssl_enabled_button" }
|
||||
- lets_encrypt_link_url = "https://letsencrypt.org/"
|
||||
- lets_encrypt_link_start = "<a href=\"%{lets_encrypt_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { lets_encrypt_link_url: lets_encrypt_link_url }
|
||||
- lets_encrypt_link_end = "</a>".html_safe
|
||||
= _("Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: lets_encrypt_link_end }
|
||||
|
||||
.col-sm-10.js-auto-ssl-toggle-container
|
||||
%button{ type: "button", id: "pages_domain_auto_ssl_enabled_button",
|
||||
class: "js-project-feature-toggle project-feature-toggle mt-2 #{"is-checked" if auto_ssl_available_and_enabled}",
|
||||
"aria-label": _("Automatic certificate management using Let's Encrypt") }
|
||||
= f.hidden_field :auto_ssl_enabled?, class: "js-project-feature-toggle-input"
|
||||
%span.toggle-icon
|
||||
= sprite_icon("status_success_borderless", size: 16, css_class: "toggle-icon-svg toggle-status-checked")
|
||||
= sprite_icon("status_failed_borderless", size: 16, css_class: "toggle-icon-svg toggle-status-unchecked")
|
||||
%p.text-secondary.mt-3
|
||||
- docs_link_url = help_page_path("user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md")
|
||||
- docs_link_start = "<a href=\"%{docs_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { docs_link_url: docs_link_url }
|
||||
- docs_link_end = "</a>".html_safe
|
||||
= _("Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}.").html_safe % { docs_link_url: docs_link_url, docs_link_start: docs_link_start, docs_link_end: docs_link_end }
|
||||
|
||||
.js-shown-unless-auto-ssl{ class: ("d-none" if auto_ssl_available_and_enabled) }
|
||||
.form-group.row
|
||||
.col-sm-2.col-form-label
|
||||
= f.label :user_provided_certificate, _("Certificate (PEM)")
|
||||
.col-sm-10
|
||||
= f.text_area :user_provided_certificate,
|
||||
rows: 5,
|
||||
class: "form-control js-enabled-unless-auto-ssl",
|
||||
disabled: auto_ssl_available_and_enabled
|
||||
%span.help-inline.text-muted= _("Upload a certificate for your domain with all intermediates")
|
||||
|
||||
.form-group.row
|
||||
.col-sm-2.col-form-label
|
||||
= f.label :user_provided_key, _("Key (PEM)")
|
||||
.col-sm-10
|
||||
= f.text_area :user_provided_key,
|
||||
rows: 5,
|
||||
class: "form-control js-enabled-unless-auto-ssl",
|
||||
disabled: auto_ssl_available_and_enabled
|
||||
%span.help-inline.text-muted= _("Upload a private key for your certificate")
|
||||
|
||||
= render 'certificate', f: f
|
||||
- else
|
||||
.nothing-here-block
|
||||
.border-section.nothing-here-block
|
||||
= _("Support for custom certificates is disabled. Ask your system's administrator to enable it.")
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
- if @domain.enabled?
|
||||
- if @domain.auto_ssl_enabled && !@domain.certificate
|
||||
.form-group.border-section.js-shown-if-auto-ssl{ class: ("d-none" unless auto_ssl_available_and_enabled) }
|
||||
.row
|
||||
.col-sm-10.offset-sm-2
|
||||
.bs-callout.bs-callout-info.mt-0
|
||||
= _("GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.")
|
||||
- else
|
||||
.form-group.border-section.js-shown-if-auto-ssl{ class: ("d-none" unless auto_ssl_available_and_enabled) }
|
||||
.row
|
||||
.col-sm-10.offset-sm-2
|
||||
.bs-callout.bs-callout-warning.mt-0
|
||||
= _("A Let's Encrypt SSL certificate can not be obtained until your domain is verified.")
|
|
@ -1,12 +1,21 @@
|
|||
- add_to_breadcrumbs _("Pages"), project_pages_path(@project)
|
||||
- breadcrumb_title @domain.domain
|
||||
- page_title @domain.domain
|
||||
|
||||
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
|
||||
|
||||
- if verification_enabled && @domain.unverified?
|
||||
= content_for :flash_message do
|
||||
.alert.alert-warning
|
||||
.container-fluid.container-limited
|
||||
= _("This domain is not verified. You will need to verify ownership before access is enabled.")
|
||||
|
||||
%h3.page-title
|
||||
= @domain.domain
|
||||
= _('Pages Domain')
|
||||
= render 'projects/pages_domains/helper_text'
|
||||
%hr.clearfix
|
||||
%div
|
||||
= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f|
|
||||
= render 'form', { f: f }
|
||||
.form-actions
|
||||
.form-actions.d-flex.justify-content-between
|
||||
= f.submit _('Save Changes'), class: "btn btn-success"
|
||||
= link_to _('Cancel'), project_pages_path(@project), class: 'btn btn-default btn-inverse'
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
%h3.page-title
|
||||
= _("New Pages Domain")
|
||||
= render 'projects/pages_domains/helper_text'
|
||||
%hr.clearfix
|
||||
%div
|
||||
= form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f|
|
||||
= render 'form', { f: f }
|
||||
|
|
|
@ -58,4 +58,4 @@
|
|||
%td
|
||||
= _("Certificate")
|
||||
%td
|
||||
= render 'certificate'
|
||||
= render 'lets_encrypt_callout', auto_ssl_available_and_enabled: false
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
= render 'shared/issuable/form/branch_chooser', issuable: issuable, form: form
|
||||
|
||||
%hr
|
||||
.form-group.row
|
||||
= form.label :title, class: 'col-form-label col-sm-2'
|
||||
|
||||
|
|
|
@ -20,3 +20,4 @@
|
|||
= form.hidden_field(:target_branch,
|
||||
{ class: 'target_branch js-target-branch-select ref-name mw-xl',
|
||||
data: { placeholder: _('Select branch'), endpoint: refs_project_path(@project, sort: 'updated_desc', find: 'branches') }})
|
||||
%hr
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Require explicit null parameters to remove pages domain certificate and allow to use Let's Encrypt certificates through API
|
||||
merge_request:
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Replace task-done icon with list-task icon to better align with other toolbar
|
||||
list icons
|
||||
merge_request:
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add documentation for sign-in application setting
|
||||
merge_request: 19561
|
||||
author: Horatiu Eugen Vlad
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Merge Details Page and Edit Page for Page Domains
|
||||
merge_request: 16687
|
||||
author:
|
||||
type: added
|
|
@ -255,8 +255,8 @@ module Gitlab
|
|||
caching_config_hash[:compress] = false
|
||||
caching_config_hash[:namespace] = Gitlab::Redis::Cache::CACHE_NAMESPACE
|
||||
caching_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
|
||||
if Sidekiq.server? # threaded context
|
||||
caching_config_hash[:pool_size] = Sidekiq.options[:concurrency] + 5
|
||||
if Sidekiq.server? || defined?(::Puma) # threaded context
|
||||
caching_config_hash[:pool_size] = Gitlab::Redis::Cache.pool_size
|
||||
caching_config_hash[:pool_timeout] = 1
|
||||
end
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -86,6 +86,12 @@ def unicode_emoji_regex
|
|||
))x
|
||||
end
|
||||
|
||||
def count_filtered_commits(commits)
|
||||
commits.count do |commit|
|
||||
!commit.message.start_with?('fixup!', 'squash!')
|
||||
end
|
||||
end
|
||||
|
||||
def lint_commit(commit) # rubocop:disable Metrics/AbcSize
|
||||
# For now we'll ignore merge commits, as getting rid of those is a problem
|
||||
# separate from enforcing good commit messages.
|
||||
|
@ -285,7 +291,7 @@ def lint_commits(commits)
|
|||
end
|
||||
end
|
||||
|
||||
if git.commits.length > 10 && !ce_upstream?
|
||||
if count_filtered_commits(git.commits) > 10 && !ce_upstream?
|
||||
warn(
|
||||
'This merge request includes more than 10 commits. ' \
|
||||
'Please rebase these commits into a smaller number of commits.'
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# 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
|
|
@ -0,0 +1,17 @@
|
|||
# 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
|
||||
|
|
|
@ -120,7 +120,7 @@ The Pages daemon doesn't listen to the outside world.
|
|||
|
||||
1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
pages_external_url 'http://example.io'
|
||||
```
|
||||
|
||||
|
@ -145,7 +145,7 @@ outside world.
|
|||
1. Place the certificate and key inside `/etc/gitlab/ssl`
|
||||
1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
pages_external_url 'https://example.io'
|
||||
|
||||
pages_nginx['redirect_http_to_https'] = true
|
||||
|
@ -167,7 +167,7 @@ behavior:
|
|||
1. Edit `/etc/gitlab/gitlab.rb`.
|
||||
1. Set the `inplace_chroot` to `true` for GitLab Pages:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
gitlab_pages['inplace_chroot'] = true
|
||||
```
|
||||
|
||||
|
@ -202,7 +202,7 @@ world. Custom domains are supported, but no TLS.
|
|||
|
||||
1. Edit `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
pages_external_url "http://example.io"
|
||||
nginx['listen_addresses'] = ['192.0.2.1']
|
||||
pages_nginx['enable'] = false
|
||||
|
@ -233,7 +233,7 @@ world. Custom domains and TLS are supported.
|
|||
|
||||
1. Edit `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
pages_external_url "https://example.io"
|
||||
nginx['listen_addresses'] = ['192.0.2.1']
|
||||
pages_nginx['enable'] = false
|
||||
|
@ -332,7 +332,7 @@ Follow the steps below to configure verbose logging of GitLab Pages daemon.
|
|||
If you wish to make it log events with level `DEBUG` you must configure this in
|
||||
`/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
gitlab_pages['log_verbose'] = true
|
||||
```
|
||||
|
||||
|
@ -347,7 +347,7 @@ are stored.
|
|||
If you wish to store them in another location you must set it up in
|
||||
`/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
gitlab_rails['pages_path'] = "/mnt/storage/pages"
|
||||
```
|
||||
|
||||
|
@ -363,14 +363,14 @@ Omnibus GitLab 11.1.
|
|||
If you wish to disable it you must configure this in
|
||||
`/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
gitlab_pages['listen_proxy'] = nil
|
||||
```
|
||||
|
||||
If you wish to make it listen on a different port you must configure this also in
|
||||
`/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```shell
|
||||
```ruby
|
||||
gitlab_pages['listen_proxy'] = "localhost:10080"
|
||||
```
|
||||
|
||||
|
@ -382,21 +382,26 @@ The maximum size of the unpacked archive per project can be configured in the
|
|||
Admin area under the Application settings in the **Maximum size of pages (MB)**.
|
||||
The default is 100MB.
|
||||
|
||||
## Running GitLab Pages in a separate server
|
||||
## Running GitLab Pages on a separate server
|
||||
|
||||
You may want to run GitLab Pages daemon on a separate server in order to decrease the load on your main application server.
|
||||
Follow the steps below to configure GitLab Pages in a separate server.
|
||||
You can run the GitLab Pages daemon on a separate server in order to decrease the load on your main application server.
|
||||
|
||||
1. Suppose you have the main GitLab application server named `app1`. Prepare
|
||||
new Linux server (let's call it `app2`), create NFS share there and configure access to
|
||||
this share from `app1`. Let's use the default GitLab Pages folder `/var/opt/gitlab/gitlab-rails/shared/pages`
|
||||
as the shared folder on `app2` and mount it to `/mnt/pages` on `app1`.
|
||||
To configure GitLab Pages on a separate server:
|
||||
|
||||
1. On `app2` install GitLab omnibus and modify `/etc/gitlab/gitlab.rb` this way:
|
||||
1. Set up a new server. This will become the **Pages server**.
|
||||
|
||||
```shell
|
||||
1. Create an NFS share on the new server and configure this share to
|
||||
allow access from your main **GitLab server**. For this example, we use the
|
||||
default GitLab Pages folder `/var/opt/gitlab/gitlab-rails/shared/pages`
|
||||
as the shared folder on the new server and we will mount it to `/mnt/pages`
|
||||
on the **GitLab server**.
|
||||
|
||||
1. On the **Pages server**, install Omnibus GitLab and modify `/etc/gitlab/gitlab.rb`
|
||||
to include:
|
||||
|
||||
```ruby
|
||||
external_url 'http://<ip-address-of-the-server>'
|
||||
pages_external_url "http://<your-pages-domain>"
|
||||
pages_external_url "http://<your-pages-server-URL>"
|
||||
postgresql['enable'] = false
|
||||
redis['enable'] = false
|
||||
prometheus['enable'] = false
|
||||
|
@ -409,20 +414,82 @@ Follow the steps below to configure GitLab Pages in a separate server.
|
|||
gitlab_rails['auto_migrate'] = false
|
||||
```
|
||||
|
||||
1. Run `sudo gitlab-ctl reconfigure`.
|
||||
1. On `app1` apply the following changes to `/etc/gitlab/gitlab.rb`:
|
||||
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||
|
||||
```shell
|
||||
1. On the **GitLab server**, make the following changes to `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_pages['enable'] = false
|
||||
pages_external_url "http://<your-pages-domain>"
|
||||
pages_external_url "http://<your-pages-server-URL>"
|
||||
gitlab_rails['pages_path'] = "/mnt/pages"
|
||||
```
|
||||
|
||||
1. Run `sudo gitlab-ctl reconfigure`.
|
||||
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||
|
||||
It is possible to run GitLab Pages on multiple servers if you wish to distribute
|
||||
the load. You can do this through standard load balancing practices such as
|
||||
configuring your DNS server to return multiple IPs for your Pages server,
|
||||
configuring a load balancer to work at the IP level, and so on. If you wish to
|
||||
set up GitLab Pages on multiple servers, perform the above procedure for each
|
||||
Pages server.
|
||||
|
||||
### Access control when running GitLab Pages on a separate server
|
||||
|
||||
If you are [running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server),
|
||||
then you must use the following procedure to configure [access control](#access-control):
|
||||
|
||||
1. On the **GitLab server**, add the following to `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_pages['enable'] = true
|
||||
gitlab_pages['access_control'] = true
|
||||
```
|
||||
|
||||
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the
|
||||
changes to take effect. The `gitlab-secrets.json` file is now updated with the
|
||||
new configuration.
|
||||
|
||||
DANGER: **Danger:**
|
||||
The `gitlab-secrets.json` file contains secrets that control database encryption.
|
||||
Do not edit or replace this file on the **GitLab server** or you might
|
||||
experience permanent data loss. Make a backup copy of this file before proceeding,
|
||||
as explained in the following steps.
|
||||
|
||||
1. Create a backup of the secrets file on the **GitLab server**:
|
||||
|
||||
```shell
|
||||
cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak
|
||||
```
|
||||
|
||||
1. Create a backup of the secrets file on the **Pages server**:
|
||||
|
||||
```shell
|
||||
cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak
|
||||
```
|
||||
|
||||
1. Disable Pages on the **GitLab server** by setting the following in
|
||||
`/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_pages['enable'] = false
|
||||
```
|
||||
|
||||
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||
|
||||
1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the **GitLab server**
|
||||
to the **Pages server**.
|
||||
|
||||
1. On your **Pages server**, add the following to `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_pages['gitlab_server'] = "https://<your-gitlab-server-URL>"
|
||||
```
|
||||
|
||||
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
|
||||
|
||||
## Backup
|
||||
|
||||
Pages are part of the [regular backup][backup] so there is nothing to configure.
|
||||
GitLab Pages are part of the [regular backup][backup], so there is no separate backup to configure.
|
||||
|
||||
## Security
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/ap
|
|||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"project_id": 1337,
|
||||
"auto_ssl_enabled": false,
|
||||
"certificate": {
|
||||
"expired": false,
|
||||
"expiration": "2020-04-12T14:32:00.000Z"
|
||||
|
@ -55,6 +56,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/ap
|
|||
{
|
||||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"auto_ssl_enabled": false,
|
||||
"certificate": {
|
||||
"subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate",
|
||||
"expired": false,
|
||||
|
@ -76,7 +78,7 @@ GET /projects/:id/pages/domains/:domain
|
|||
| Attribute | Type | Required | Description |
|
||||
| --------- | -------------- | -------- | ---------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `domain` | string | yes | The domain |
|
||||
| `domain` | string | yes | The custom domain indicated by the user |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/pages/domains/www.domain.example
|
||||
|
@ -97,6 +99,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/ap
|
|||
{
|
||||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"auto_ssl_enabled": false,
|
||||
"certificate": {
|
||||
"subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate",
|
||||
"expired": false,
|
||||
|
@ -114,12 +117,13 @@ Creates a new pages domain. The user must have permissions to create new pages d
|
|||
POST /projects/:id/pages/domains
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------- | -------------- | -------- | ---------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `domain` | string | yes | The domain |
|
||||
| `certificate` | file/string | no | The certificate in PEM format with intermediates following in most specific to least specific order.|
|
||||
| `key` | file/string | no | The certificate key in PEM format. |
|
||||
| Attribute | Type | Required | Description |
|
||||
| -------------------| -------------- | -------- | ---------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `domain` | string | yes | The custom domain indicated by the user |
|
||||
| `auto_ssl_enabled` | boolean | no | Enables [automatic generation](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md) of SSL certificates issued by Let's Encrypt for custom domains. |
|
||||
| `certificate` | file/string | no | The certificate in PEM format with intermediates following in most specific to least specific order.|
|
||||
| `key` | file/string | no | The certificate key in PEM format. |
|
||||
|
||||
```bash
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
|
@ -129,10 +133,15 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain
|
|||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "auto_ssl_enabled=true" https://gitlab.example.com/api/v4/projects/5/pages/domains
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"auto_ssl_enabled": true,
|
||||
"certificate": {
|
||||
"subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate",
|
||||
"expired": false,
|
||||
|
@ -150,12 +159,15 @@ Updates an existing project pages domain. The user must have permissions to chan
|
|||
PUT /projects/:id/pages/domains/:domain
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------- | -------------- | -------- | ---------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `domain` | string | yes | The domain |
|
||||
| `certificate` | file/string | no | The certificate in PEM format with intermediates following in most specific to least specific order.|
|
||||
| `key` | file/string | no | The certificate key in PEM format. |
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------ | -------------- | -------- | ---------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `domain` | string | yes | The custom domain indicated by the user |
|
||||
| `auto_ssl_enabled` | boolean | no | Enables [automatic generation](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md) of SSL certificates issued by Let's Encrypt for custom domains. |
|
||||
| `certificate` | file/string | no | The certificate in PEM format with intermediates following in most specific to least specific order.|
|
||||
| `key` | file/string | no | The certificate key in PEM format. |
|
||||
|
||||
### Adding certificate
|
||||
|
||||
```bash
|
||||
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
|
@ -169,6 +181,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certifi
|
|||
{
|
||||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"auto_ssl_enabled": false,
|
||||
"certificate": {
|
||||
"subject": "/O=Example, Inc./OU=Example Origin CA/CN=Example Origin Certificate",
|
||||
"expired": false,
|
||||
|
@ -178,6 +191,36 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certifi
|
|||
}
|
||||
```
|
||||
|
||||
### Enabling Let's Encrypt integration for Pages custom domains
|
||||
|
||||
```bash
|
||||
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "auto_ssl_enabled=true" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"auto_ssl_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
### Removing certificate
|
||||
|
||||
To remove the SSL certificate attached to the Pages domain, run:
|
||||
|
||||
```bash
|
||||
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=" --form "key=" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"domain": "ssl.domain.example",
|
||||
"url": "https://ssl.domain.example",
|
||||
"auto_ssl_enabled": false
|
||||
}
|
||||
```
|
||||
|
||||
## Delete pages domain
|
||||
|
||||
Deletes an existing project pages domain.
|
||||
|
@ -189,7 +232,7 @@ DELETE /projects/:id/pages/domains/:domain
|
|||
| Attribute | Type | Required | Description |
|
||||
| --------- | -------------- | -------- | ---------------------------------------- |
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `domain` | string | yes | The domain |
|
||||
| `domain` | string | yes | The custom domain indicated by the user |
|
||||
|
||||
```bash
|
||||
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example
|
||||
|
|
|
@ -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). |
|
||||
|
|
|
@ -61,7 +61,7 @@ you'd want to explicitly disable that flag until the frontend half is also ready
|
|||
to be shipped. To make sure this feature is disabled for both GitLab.com and
|
||||
self-managed instances you'd need to explicitly call `Feature.enabled?` method
|
||||
before the `feature_available` method. This ensures the feature_flag is defaulting
|
||||
to `true`.
|
||||
to `false`.
|
||||
|
||||
## Feature groups
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
After Width: | Height: | Size: 95 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
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.
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -14,6 +14,7 @@ include:
|
|||
- [Continuous Integration and Deployment](continuous_integration.md)
|
||||
- [Email](email.md)
|
||||
- [Sign up restrictions](sign_up_restrictions.md)
|
||||
- [Sign in restrictions](sign_in_restrictions.md)
|
||||
- [Terms](terms.md)
|
||||
- [Third party offers](third_party_offers.md)
|
||||
- [Usage statistics](usage_statistics.md)
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
type: reference
|
||||
---
|
||||
|
||||
# Sign-in restrictions **(CORE ONLY)**
|
||||
|
||||
You can use sign-in restrictions to limit the authentication with password
|
||||
for web interface and Git over HTTP(S), two-factor authentication enforcing, as well as
|
||||
as configuring the home page URL and after sign-out path.
|
||||
|
||||
## Password authentication enabled
|
||||
|
||||
You can restrict the password authentication for web interface and Git over HTTP(S):
|
||||
|
||||
- **Web interface**: When this feature is disabled, an [external authentication provider](../../../administration/auth/README.md) must be used.
|
||||
- **Git over HTTP(S)**: When this feature is disabled, a [Personal Access Token](../../profile/personal_access_tokens.md) must be used to authenticate.
|
||||
|
||||
## Two-factor authentication
|
||||
|
||||
When this feature enabled, all users will have to use the [two-factor authentication](../../profile/account/two_factor_authentication.md).
|
||||
|
||||
Once the two-factor authentication is configured as mandatory, the users will be allowed
|
||||
to skip forced configuration of two-factor authentication for the configurable grace
|
||||
period in hours.
|
||||
|
||||
![Two-factor grace period](img/two_factor_grace_period.png)
|
||||
|
||||
## Sign-in information
|
||||
|
||||
All users that are not logged-in will be redirected to the page represented by the configured
|
||||
"Home page URL" if value is not empty.
|
||||
|
||||
All users will be redirect to the page represented by the configured "After sign out path"
|
||||
after sign out if value is not empty.
|
||||
|
||||
If a "Sign in text" in Markdown format is provided, then every user will be presented with
|
||||
this message after logging-in.
|
||||
|
||||
## Settings
|
||||
|
||||
To access this feature:
|
||||
|
||||
1. Navigate to the **Settings > General** in the Admin area.
|
||||
1. Expand the **Sign-in restrictions** section.
|
||||
|
||||
<!-- ## Troubleshooting
|
||||
|
||||
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
|
||||
one might have when setting this up, or when something is changed, or on upgrading, it's
|
||||
important to describe those, too. Think of things that may go wrong and include them here.
|
||||
This is important to minimize requests for support, and to avoid doc comments with
|
||||
questions that you know someone might ask.
|
||||
|
||||
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
|
||||
If you have none to add when creating a doc, leave this section in place
|
||||
but commented out to help encourage others to add to it in the future. -->
|
|
@ -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
|
||||
|
|
|
@ -1681,6 +1681,7 @@ module API
|
|||
expose :verified?, as: :verified
|
||||
expose :verification_code, as: :verification_code
|
||||
expose :enabled_until
|
||||
expose :auto_ssl_enabled
|
||||
|
||||
expose :certificate,
|
||||
as: :certificate_expiration,
|
||||
|
@ -1696,6 +1697,7 @@ module API
|
|||
expose :verified?, as: :verified
|
||||
expose :verification_code, as: :verification_code
|
||||
expose :enabled_until
|
||||
expose :auto_ssl_enabled
|
||||
|
||||
expose :certificate,
|
||||
if: ->(pages_domain, _) { pages_domain.certificate? },
|
||||
|
|
|
@ -92,8 +92,10 @@ module API
|
|||
requires :domain, type: String, desc: 'The domain'
|
||||
# rubocop:disable Scalability/FileUploads
|
||||
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
|
||||
optional :certificate, allow_blank: false, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
|
||||
optional :key, allow_blank: false, types: [File, String], desc: 'The key', as: :user_provided_key
|
||||
optional :certificate, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
|
||||
optional :key, types: [File, String], desc: 'The key', as: :user_provided_key
|
||||
optional :auto_ssl_enabled, allow_blank: false, type: Boolean, default: false,
|
||||
desc: "Enables automatic generation of SSL certificates issued by Let's Encrypt for custom domains."
|
||||
# rubocop:enable Scalability/FileUploads
|
||||
all_or_none_of :user_provided_certificate, :user_provided_key
|
||||
end
|
||||
|
@ -116,14 +118,16 @@ module API
|
|||
requires :domain, type: String, desc: 'The domain'
|
||||
# rubocop:disable Scalability/FileUploads
|
||||
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
|
||||
optional :certificate, allow_blank: false, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
|
||||
optional :key, allow_blank: false, types: [File, String], desc: 'The key', as: :user_provided_key
|
||||
optional :certificate, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
|
||||
optional :key, types: [File, String], desc: 'The key', as: :user_provided_key
|
||||
optional :auto_ssl_enabled, allow_blank: true, type: Boolean,
|
||||
desc: "Enables automatic generation of SSL certificates issued by Let's Encrypt for custom domains."
|
||||
# rubocop:enable Scalability/FileUploads
|
||||
end
|
||||
put ":id/pages/domains/:domain", requirements: PAGES_DOMAINS_ENDPOINT_REQUIREMENTS do
|
||||
authorize! :update_pages, user_project
|
||||
|
||||
pages_domain_params = declared(params, include_parent_namespaces: false)
|
||||
pages_domain_params = declared(params, include_parent_namespaces: false, include_missing: false)
|
||||
|
||||
# Remove empty private key if certificate is not empty.
|
||||
if pages_domain_params[:user_provided_certificate] && !pages_domain_params[:user_provided_key]
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -25,6 +25,8 @@ module Gitlab
|
|||
if Sidekiq.server?
|
||||
# the pool will be used in a multi-threaded context
|
||||
size += Sidekiq.options[:concurrency]
|
||||
elsif defined?(::Puma)
|
||||
size += Puma.cli_config.options[:max_threads]
|
||||
end
|
||||
|
||||
size
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# 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
|
|
@ -8232,10 +8232,10 @@ msgstr ""
|
|||
msgid "GitLabPages|Configure pages"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLabPages|Details"
|
||||
msgid "GitLabPages|Domains"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLabPages|Domains"
|
||||
msgid "GitLabPages|Edit"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLabPages|Expired"
|
||||
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
"@gitlab/svgs": "^1.82.0",
|
||||
"@gitlab/ui": "7.11.0",
|
||||
"@gitlab/visual-review-tools": "1.2.0",
|
||||
"@sourcegraph/code-host-integration": "^0.0.13",
|
||||
"@sentry/browser": "^5.7.1",
|
||||
"apollo-cache-inmemory": "^1.6.3",
|
||||
"apollo-client": "^2.6.4",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[[ "$TRACE" ]] && set -x
|
||||
export TILLER_NAMESPACE="$KUBE_NAMESPACE"
|
||||
|
||||
function deploy_exists() {
|
||||
local namespace="${1}"
|
||||
|
@ -14,16 +13,18 @@ function deploy_exists() {
|
|||
}
|
||||
|
||||
function previous_deploy_failed() {
|
||||
local deploy="${1}"
|
||||
local namespace="${1}"
|
||||
local deploy="${2}"
|
||||
|
||||
echoinfo "Checking for previous deployment of ${deploy}" true
|
||||
|
||||
helm status "${deploy}" >/dev/null 2>&1
|
||||
helm status --tiller-namespace "${namespace}" "${deploy}" >/dev/null 2>&1
|
||||
local status=$?
|
||||
|
||||
# if `status` is `0`, deployment exists, has a status
|
||||
if [ $status -eq 0 ]; then
|
||||
echoinfo "Previous deployment found, checking status..."
|
||||
deployment_status=$(helm status "${deploy}" | grep ^STATUS | cut -d' ' -f2)
|
||||
deployment_status=$(helm status --tiller-namespace "${namespace}" "${deploy}" | grep ^STATUS | cut -d' ' -f2)
|
||||
echoinfo "Previous deployment state: ${deployment_status}"
|
||||
if [[ "$deployment_status" == "FAILED" || "$deployment_status" == "PENDING_UPGRADE" || "$deployment_status" == "PENDING_INSTALL" ]]; then
|
||||
status=0;
|
||||
|
@ -37,16 +38,17 @@ function previous_deploy_failed() {
|
|||
}
|
||||
|
||||
function delete_release() {
|
||||
if [ -z "$CI_ENVIRONMENT_SLUG" ]; then
|
||||
local namespace="${KUBE_NAMESPACE}"
|
||||
local deploy="${CI_ENVIRONMENT_SLUG}"
|
||||
|
||||
if [ -z "$deploy" ]; then
|
||||
echoerr "No release given, aborting the delete!"
|
||||
return
|
||||
fi
|
||||
|
||||
local name="$CI_ENVIRONMENT_SLUG"
|
||||
echoinfo "Deleting release '$deploy'..." true
|
||||
|
||||
echoinfo "Deleting release '$name'..." true
|
||||
|
||||
helm delete --purge "$name"
|
||||
helm delete --purge --tiller-namespace "${namespace}" "${deploy}"
|
||||
}
|
||||
|
||||
function delete_failed_release() {
|
||||
|
@ -59,7 +61,7 @@ function delete_failed_release() {
|
|||
echoinfo "No Review App with ${CI_ENVIRONMENT_SLUG} is currently deployed."
|
||||
else
|
||||
# Cleanup and previous installs, as FAILED and PENDING_UPGRADE will cause errors with `upgrade`
|
||||
if previous_deploy_failed "$CI_ENVIRONMENT_SLUG" ; then
|
||||
if previous_deploy_failed "${KUBE_NAMESPACE}" "$CI_ENVIRONMENT_SLUG" ; then
|
||||
echoinfo "Review App deployment in bad state, cleaning up $CI_ENVIRONMENT_SLUG"
|
||||
delete_release
|
||||
else
|
||||
|
@ -117,6 +119,7 @@ function ensure_namespace() {
|
|||
}
|
||||
|
||||
function install_tiller() {
|
||||
local TILLER_NAMESPACE="$KUBE_NAMESPACE"
|
||||
echoinfo "Checking deployment/tiller-deploy status in the ${TILLER_NAMESPACE} namespace..." true
|
||||
|
||||
echoinfo "Initiating the Helm client..."
|
||||
|
@ -131,11 +134,12 @@ function install_tiller() {
|
|||
--override "spec.template.spec.tolerations[0].key"="dedicated" \
|
||||
--override "spec.template.spec.tolerations[0].operator"="Equal" \
|
||||
--override "spec.template.spec.tolerations[0].value"="helm" \
|
||||
--override "spec.template.spec.tolerations[0].effect"="NoSchedule"
|
||||
--override "spec.template.spec.tolerations[0].effect"="NoSchedule" \
|
||||
--tiller-namespace "${TILLER_NAMESPACE}"
|
||||
|
||||
kubectl rollout status -n "$TILLER_NAMESPACE" -w "deployment/tiller-deploy"
|
||||
|
||||
if ! helm version --debug; then
|
||||
if ! helm version --debug --tiller-namespace "${TILLER_NAMESPACE}"; then
|
||||
echo "Failed to init Tiller."
|
||||
return 1
|
||||
fi
|
||||
|
@ -147,7 +151,7 @@ function install_external_dns() {
|
|||
domain=$(echo "${REVIEW_APPS_DOMAIN}" | awk -F. '{printf "%s.%s", $(NF-1), $NF}')
|
||||
echoinfo "Installing external DNS for domain ${domain}..." true
|
||||
|
||||
if ! deploy_exists "${KUBE_NAMESPACE}" "${release_name}" || previous_deploy_failed "${release_name}" ; then
|
||||
if ! deploy_exists "${KUBE_NAMESPACE}" "${release_name}" || previous_deploy_failed "${KUBE_NAMESPACE}" "${release_name}" ; then
|
||||
echoinfo "Installing external-dns Helm chart"
|
||||
helm repo update
|
||||
# Default requested: CPU => 0, memory => 0
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# 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
|
|
@ -32,10 +32,10 @@ describe Projects::PagesDomainsController do
|
|||
get(:show, params: request_params.merge(id: pages_domain.domain))
|
||||
end
|
||||
|
||||
it "displays the 'show' page" do
|
||||
it "redirects to the 'edit' page" do
|
||||
make_request
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to render_template('show')
|
||||
|
||||
expect(response).to redirect_to(edit_project_pages_domain_path(project, pages_domain.domain))
|
||||
end
|
||||
|
||||
context 'when user is developer' do
|
||||
|
@ -69,7 +69,7 @@ describe Projects::PagesDomainsController do
|
|||
created_domain = PagesDomain.reorder(:id).last
|
||||
|
||||
expect(created_domain).to be_present
|
||||
expect(response).to redirect_to(project_pages_domain_path(project, created_domain))
|
||||
expect(response).to redirect_to(edit_project_pages_domain_path(project, created_domain))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -160,7 +160,7 @@ describe Projects::PagesDomainsController do
|
|||
|
||||
post :verify, params: params
|
||||
|
||||
expect(response).to redirect_to project_pages_domain_path(project, pages_domain)
|
||||
expect(response).to redirect_to edit_project_pages_domain_path(project, pages_domain)
|
||||
expect(flash[:notice]).to eq('Successfully verified domain ownership')
|
||||
end
|
||||
|
||||
|
@ -169,7 +169,7 @@ describe Projects::PagesDomainsController do
|
|||
|
||||
post :verify, params: params
|
||||
|
||||
expect(response).to redirect_to project_pages_domain_path(project, pages_domain)
|
||||
expect(response).to redirect_to edit_project_pages_domain_path(project, pages_domain)
|
||||
expect(flash[:alert]).to eq('Failed to verify domain ownership')
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
describe "Pages with Let's Encrypt", :https_pages_enabled do
|
||||
include LetsEncryptHelpers
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:project) { create(:project, pages_https_only: false) }
|
||||
let(:user) { create(:user) }
|
||||
let(:role) { :maintainer }
|
||||
let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
|
||||
|
@ -34,14 +34,14 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do
|
|||
expect(domain.auto_ssl_enabled).to eq false
|
||||
|
||||
expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
|
||||
expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
|
||||
expect(page).to have_field 'Key (PEM)', type: 'textarea'
|
||||
expect(page).to have_selector '.card-header', text: 'Certificate'
|
||||
expect(page).to have_text domain.subject
|
||||
|
||||
find('.js-auto-ssl-toggle-container .project-feature-toggle').click
|
||||
|
||||
expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
|
||||
expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
|
||||
expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
|
||||
expect(page).not_to have_selector '.card-header', text: 'Certificate'
|
||||
expect(page).not_to have_text domain.subject
|
||||
|
||||
click_on 'Save Changes'
|
||||
|
||||
|
@ -67,9 +67,6 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do
|
|||
expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
|
||||
expect(page).to have_field 'Key (PEM)', type: 'textarea'
|
||||
|
||||
fill_in 'Certificate (PEM)', with: certificate_pem
|
||||
fill_in 'Key (PEM)', with: certificate_key
|
||||
|
||||
click_on 'Save Changes'
|
||||
|
||||
expect(domain.reload.auto_ssl_enabled).to eq false
|
||||
|
@ -81,7 +78,8 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do
|
|||
it 'user do not see private key' do
|
||||
visit edit_project_pages_domain_path(project, domain)
|
||||
|
||||
expect(find_field('Key (PEM)', visible: :all, disabled: :all).value).to be_blank
|
||||
expect(page).not_to have_selector '.card-header', text: 'Certificate'
|
||||
expect(page).not_to have_text domain.subject
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -100,10 +98,21 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do
|
|||
context 'when certificate is provided by user' do
|
||||
let(:domain) { create(:pages_domain, project: project) }
|
||||
|
||||
it 'user sees private key' do
|
||||
it 'user sees certificate subject' do
|
||||
visit edit_project_pages_domain_path(project, domain)
|
||||
|
||||
expect(find_field('Key (PEM)').value).not_to be_blank
|
||||
expect(page).to have_selector '.card-header', text: 'Certificate'
|
||||
expect(page).to have_text domain.subject
|
||||
end
|
||||
|
||||
it 'user can delete the certificate', :js do
|
||||
visit edit_project_pages_domain_path(project, domain)
|
||||
|
||||
expect(page).to have_selector '.card-header', text: 'Certificate'
|
||||
expect(page).to have_text domain.subject
|
||||
within('.card') { accept_confirm { click_on 'Remove' } }
|
||||
expect(page).to have_field 'Certificate (PEM)', with: ''
|
||||
expect(page).to have_field 'Key (PEM)', with: ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
shared_examples 'pages settings editing' do
|
||||
let(:project) { create(:project) }
|
||||
let_it_be(:project) { create(:project, pages_https_only: false) }
|
||||
let(:user) { create(:user) }
|
||||
let(:role) { :maintainer }
|
||||
|
||||
|
@ -185,6 +185,21 @@ shared_examples 'pages settings editing' do
|
|||
expect(page).to have_content('my.test.domain.com')
|
||||
end
|
||||
|
||||
describe 'with dns verification enabled' do
|
||||
before do
|
||||
stub_application_setting(pages_domain_verification_enabled: true)
|
||||
end
|
||||
|
||||
it 'shows the DNS verification record' do
|
||||
domain = create(:pages_domain, project: project)
|
||||
|
||||
visit project_pages_path(project)
|
||||
|
||||
within('#content-body') { click_link 'Edit' }
|
||||
expect(page).to have_field :domain_verification, with: "#{domain.verification_domain} TXT #{domain.keyed_verification_code}"
|
||||
end
|
||||
end
|
||||
|
||||
describe 'updating the certificate for an existing domain' do
|
||||
let!(:domain) do
|
||||
create(:pages_domain, project: project)
|
||||
|
@ -193,19 +208,22 @@ shared_examples 'pages settings editing' do
|
|||
it 'allows the certificate to be updated' do
|
||||
visit project_pages_path(project)
|
||||
|
||||
within('#content-body') { click_link 'Details' }
|
||||
click_link 'Edit'
|
||||
within('#content-body') { click_link 'Edit' }
|
||||
click_button 'Save Changes'
|
||||
|
||||
expect(page).to have_content('Domain was updated')
|
||||
end
|
||||
|
||||
context 'when the certificate is invalid' do
|
||||
let_it_be(:domain) do
|
||||
create(:pages_domain, :without_certificate, :without_key, project: project)
|
||||
end
|
||||
|
||||
it 'tells the user what the problem is' do
|
||||
visit project_pages_path(project)
|
||||
|
||||
within('#content-body') { click_link 'Details' }
|
||||
click_link 'Edit'
|
||||
within('#content-body') { click_link 'Edit' }
|
||||
|
||||
fill_in 'Certificate (PEM)', with: 'invalid data'
|
||||
click_button 'Save Changes'
|
||||
|
||||
|
@ -214,6 +232,27 @@ shared_examples 'pages settings editing' do
|
|||
expect(page).to have_content("Key doesn't match the certificate")
|
||||
end
|
||||
end
|
||||
|
||||
it 'allows the certificate to be removed', :js do
|
||||
visit project_pages_path(project)
|
||||
|
||||
within('#content-body') { click_link 'Edit' }
|
||||
|
||||
accept_confirm { click_link 'Remove' }
|
||||
|
||||
expect(page).to have_field('Certificate (PEM)', with: '')
|
||||
expect(page).to have_field('Key (PEM)', with: '')
|
||||
domain.reload
|
||||
expect(domain.certificate).to be_nil
|
||||
expect(domain.key).to be_nil
|
||||
end
|
||||
|
||||
it 'shows the DNS CNAME record' do
|
||||
visit project_pages_path(project)
|
||||
|
||||
within('#content-body') { click_link 'Edit' }
|
||||
expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -250,7 +289,7 @@ shared_examples 'pages settings editing' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'HTTPS settings', :js, :https_pages_enabled do
|
||||
describe 'HTTPS settings', :https_pages_enabled do
|
||||
before do
|
||||
project.namespace.update(owner: user)
|
||||
|
||||
|
@ -358,18 +397,21 @@ shared_examples 'pages settings editing' do
|
|||
|
||||
expect(page).to have_link('Remove pages')
|
||||
|
||||
click_link 'Remove pages'
|
||||
accept_confirm { click_link 'Remove pages' }
|
||||
|
||||
expect(project.pages_deployed?).to be_falsey
|
||||
expect(page).to have_content('Pages were removed')
|
||||
expect(project.reload.pages_deployed?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Pages' do
|
||||
describe 'Pages', :js do
|
||||
include LetsEncryptHelpers
|
||||
|
||||
include_examples 'pages settings editing'
|
||||
context 'when editing normally' do
|
||||
include_examples 'pages settings editing'
|
||||
end
|
||||
|
||||
context 'when letsencrypt support is enabled' do
|
||||
before do
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"verified": { "type": "boolean" },
|
||||
"verification_code": { "type": ["string", "null"] },
|
||||
"enabled_until": { "type": ["date", "null"] },
|
||||
"auto_ssl_enabled": { "type": "boolean" },
|
||||
"certificate_expiration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -17,6 +18,6 @@
|
|||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["domain", "url", "project_id", "verified", "verification_code", "enabled_until"],
|
||||
"required": ["domain", "url", "project_id", "verified", "verification_code", "enabled_until", "auto_ssl_enabled"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"verified": { "type": "boolean" },
|
||||
"verification_code": { "type": ["string", "null"] },
|
||||
"enabled_until": { "type": ["date", "null"] },
|
||||
"auto_ssl_enabled": { "type": "boolean" },
|
||||
"certificate": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -18,6 +19,6 @@
|
|||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["domain", "url", "verified", "verification_code", "enabled_until"],
|
||||
"required": ["domain", "url", "verified", "verification_code", "enabled_until", "auto_ssl_enabled"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { normalizeData, resolveCommit, fetchLogsTree } from '~/repository/log_tree';
|
||||
import { resolveCommit, fetchLogsTree } from '~/repository/log_tree';
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
|
@ -15,22 +15,6 @@ const mockData = [
|
|||
},
|
||||
];
|
||||
|
||||
describe('normalizeData', () => {
|
||||
it('normalizes data into LogTreeCommit object', () => {
|
||||
expect(normalizeData(mockData)).toEqual([
|
||||
{
|
||||
sha: '123',
|
||||
message: 'testing message',
|
||||
committedDate: '2019-01-01',
|
||||
commitPath: 'https://test.com',
|
||||
fileName: 'index.js',
|
||||
type: 'blob',
|
||||
__typename: 'LogTreeCommit',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveCommit', () => {
|
||||
it('calls resolve when commit found', () => {
|
||||
const resolver = {
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import { normalizeData } from '~/repository/utils/commit';
|
||||
|
||||
const mockData = [
|
||||
{
|
||||
commit: {
|
||||
id: '123',
|
||||
message: 'testing message',
|
||||
committed_date: '2019-01-01',
|
||||
},
|
||||
commit_path: `https://test.com`,
|
||||
file_name: 'index.js',
|
||||
type: 'blob',
|
||||
},
|
||||
];
|
||||
|
||||
describe('normalizeData', () => {
|
||||
it('normalizes data into LogTreeCommit object', () => {
|
||||
expect(normalizeData(mockData)).toEqual([
|
||||
{
|
||||
sha: '123',
|
||||
message: 'testing message',
|
||||
committedDate: '2019-01-01',
|
||||
commitPath: 'https://test.com',
|
||||
fileName: 'index.js',
|
||||
type: 'blob',
|
||||
__typename: 'LogTreeCommit',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,64 @@
|
|||
# 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
|
|
@ -0,0 +1,66 @@
|
|||
# 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
|
||||
|
|
|
@ -3,15 +3,20 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe API::PagesDomains do
|
||||
set(:project) { create(:project, path: 'my.project', pages_https_only: false) }
|
||||
set(:user) { create(:user) }
|
||||
set(:admin) { create(:admin) }
|
||||
let_it_be(:project) { create(:project, path: 'my.project', pages_https_only: false) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:admin) { create(:admin) }
|
||||
|
||||
set(:pages_domain) { create(:pages_domain, :without_key, :without_certificate, domain: 'www.domain.test', project: project) }
|
||||
set(:pages_domain_secure) { create(:pages_domain, domain: 'ssl.domain.test', project: project) }
|
||||
set(:pages_domain_expired) { create(:pages_domain, :with_expired_certificate, domain: 'expired.domain.test', project: project) }
|
||||
let_it_be(:pages_domain) { create(:pages_domain, :without_key, :without_certificate, domain: 'www.domain.test', project: project) }
|
||||
let_it_be(:pages_domain_secure) { create(:pages_domain, domain: 'ssl.domain.test', project: project) }
|
||||
let_it_be(:pages_domain_with_letsencrypt) { create(:pages_domain, :letsencrypt, domain: 'letsencrypt.domain.test', project: project) }
|
||||
let_it_be(:pages_domain_expired) { create(:pages_domain, :with_expired_certificate, domain: 'expired.domain.test', project: project) }
|
||||
|
||||
let(:pages_domain_params) { build(:pages_domain, :without_key, :without_certificate, domain: 'www.other-domain.test').slice(:domain) }
|
||||
let(:pages_domain_with_letsencrypt_params) do
|
||||
build(:pages_domain, :without_key, :without_certificate, domain: 'www.other-domain.test', auto_ssl_enabled: true)
|
||||
.slice(:domain, :auto_ssl_enabled)
|
||||
end
|
||||
let(:pages_domain_secure_params) { build(:pages_domain, domain: 'ssl.other-domain.test', project: project).slice(:domain, :certificate, :key) }
|
||||
let(:pages_domain_secure_key_missmatch_params) {build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
|
||||
let(:pages_domain_secure_missing_chain_params) {build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
|
||||
|
@ -22,6 +27,7 @@ describe API::PagesDomains do
|
|||
let(:route_secure_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain_secure.domain}" }
|
||||
let(:route_expired_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain_expired.domain}" }
|
||||
let(:route_vacant_domain) { "/projects/#{project.id}/pages/domains/www.vacant-domain.test" }
|
||||
let(:route_letsencrypt_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain_with_letsencrypt.domain}" }
|
||||
|
||||
before do
|
||||
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
|
||||
|
@ -47,9 +53,10 @@ describe API::PagesDomains do
|
|||
expect(response).to match_response_schema('public_api/v4/pages_domain_basics')
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.size).to eq(3)
|
||||
expect(json_response.size).to eq(4)
|
||||
expect(json_response.last).to have_key('domain')
|
||||
expect(json_response.last).to have_key('project_id')
|
||||
expect(json_response.last).to have_key('auto_ssl_enabled')
|
||||
expect(json_response.last).to have_key('certificate_expiration')
|
||||
expect(json_response.last['certificate_expiration']['expired']).to be true
|
||||
expect(json_response.first).not_to have_key('certificate_expiration')
|
||||
|
@ -73,7 +80,7 @@ describe API::PagesDomains do
|
|||
expect(response).to match_response_schema('public_api/v4/pages_domains')
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.size).to eq(3)
|
||||
expect(json_response.size).to eq(4)
|
||||
expect(json_response.map { |pages_domain| pages_domain['domain'] }).to include(pages_domain.domain)
|
||||
expect(json_response.last).to have_key('domain')
|
||||
end
|
||||
|
@ -166,6 +173,7 @@ describe API::PagesDomains do
|
|||
expect(json_response['url']).to eq(pages_domain_secure.url)
|
||||
expect(json_response['certificate']['subject']).to eq(pages_domain_secure.subject)
|
||||
expect(json_response['certificate']['expired']).to be false
|
||||
expect(json_response['auto_ssl_enabled']).to be false
|
||||
end
|
||||
|
||||
it 'returns pages domain with an expired certificate' do
|
||||
|
@ -175,6 +183,18 @@ describe API::PagesDomains do
|
|||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(json_response['certificate']['expired']).to be true
|
||||
end
|
||||
|
||||
it 'returns pages domain with letsencrypt' do
|
||||
get api(route_letsencrypt_domain, user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(json_response['domain']).to eq(pages_domain_with_letsencrypt.domain)
|
||||
expect(json_response['url']).to eq(pages_domain_with_letsencrypt.url)
|
||||
expect(json_response['certificate']['subject']).to eq(pages_domain_with_letsencrypt.subject)
|
||||
expect(json_response['certificate']['expired']).to be false
|
||||
expect(json_response['auto_ssl_enabled']).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when domain is vacant' do
|
||||
|
@ -246,6 +266,7 @@ describe API::PagesDomains do
|
|||
expect(pages_domain.domain).to eq(params[:domain])
|
||||
expect(pages_domain.certificate).to be_nil
|
||||
expect(pages_domain.key).to be_nil
|
||||
expect(pages_domain.auto_ssl_enabled).to be false
|
||||
end
|
||||
|
||||
it 'creates a new secure pages domain' do
|
||||
|
@ -257,6 +278,29 @@ describe API::PagesDomains do
|
|||
expect(pages_domain.domain).to eq(params_secure[:domain])
|
||||
expect(pages_domain.certificate).to eq(params_secure[:certificate])
|
||||
expect(pages_domain.key).to eq(params_secure[:key])
|
||||
expect(pages_domain.auto_ssl_enabled).to be false
|
||||
end
|
||||
|
||||
it 'creates domain with letsencrypt enabled' do
|
||||
post api(route, user), params: pages_domain_with_letsencrypt_params
|
||||
pages_domain = PagesDomain.find_by(domain: json_response['domain'])
|
||||
|
||||
expect(response).to have_gitlab_http_status(201)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(pages_domain.domain).to eq(pages_domain_with_letsencrypt_params[:domain])
|
||||
expect(pages_domain.auto_ssl_enabled).to be true
|
||||
end
|
||||
|
||||
it 'creates domain with letsencrypt enabled and provided certificate' do
|
||||
post api(route, user), params: params_secure.merge(auto_ssl_enabled: true)
|
||||
pages_domain = PagesDomain.find_by(domain: json_response['domain'])
|
||||
|
||||
expect(response).to have_gitlab_http_status(201)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(pages_domain.domain).to eq(params_secure[:domain])
|
||||
expect(pages_domain.certificate).to eq(params_secure[:certificate])
|
||||
expect(pages_domain.key).to eq(params_secure[:key])
|
||||
expect(pages_domain.auto_ssl_enabled).to be true
|
||||
end
|
||||
|
||||
it 'fails to create pages domain without key' do
|
||||
|
@ -323,13 +367,14 @@ describe API::PagesDomains do
|
|||
|
||||
shared_examples_for 'put pages domain' do
|
||||
it 'updates pages domain removing certificate' do
|
||||
put api(route_secure_domain, user)
|
||||
put api(route_secure_domain, user), params: { certificate: nil, key: nil }
|
||||
pages_domain_secure.reload
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(pages_domain_secure.certificate).to be_nil
|
||||
expect(pages_domain_secure.key).to be_nil
|
||||
expect(pages_domain_secure.auto_ssl_enabled).to be false
|
||||
end
|
||||
|
||||
it 'updates pages domain adding certificate' do
|
||||
|
@ -342,6 +387,37 @@ describe API::PagesDomains do
|
|||
expect(pages_domain.key).to eq(params_secure[:key])
|
||||
end
|
||||
|
||||
it 'updates pages domain adding certificate with letsencrypt' do
|
||||
put api(route_domain, user), params: params_secure.merge(auto_ssl_enabled: true)
|
||||
pages_domain.reload
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(pages_domain.certificate).to eq(params_secure[:certificate])
|
||||
expect(pages_domain.key).to eq(params_secure[:key])
|
||||
expect(pages_domain.auto_ssl_enabled).to be true
|
||||
end
|
||||
|
||||
it 'updates pages domain enabling letsencrypt' do
|
||||
put api(route_domain, user), params: { auto_ssl_enabled: true }
|
||||
pages_domain.reload
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(pages_domain.auto_ssl_enabled).to be true
|
||||
end
|
||||
|
||||
it 'updates pages domain disabling letsencrypt while preserving the certificate' do
|
||||
put api(route_letsencrypt_domain, user), params: { auto_ssl_enabled: false }
|
||||
pages_domain_with_letsencrypt.reload
|
||||
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(response).to match_response_schema('public_api/v4/pages_domain/detail')
|
||||
expect(pages_domain_with_letsencrypt.auto_ssl_enabled).to be false
|
||||
expect(pages_domain_with_letsencrypt.key).to be
|
||||
expect(pages_domain_with_letsencrypt.certificate).to be
|
||||
end
|
||||
|
||||
it 'updates pages domain with expired certificate' do
|
||||
put api(route_expired_domain, user), params: params_secure
|
||||
pages_domain_expired.reload
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# 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
|
|
@ -0,0 +1,72 @@
|
|||
# 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
|
|
@ -30,39 +30,5 @@ describe 'projects/pages_domains/show' do
|
|||
expect(rendered).to have_content("GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when certificate is present' do
|
||||
let(:domain) { create(:pages_domain, :letsencrypt, project: project) }
|
||||
|
||||
it 'shows certificate info' do
|
||||
render
|
||||
|
||||
# test just a random part of cert represenations(X509v3 Subject Key Identifier:)
|
||||
expect(rendered).to have_content("C6:5F:56:4B:10:69:AC:1D:33:D2:26:C9:B3:7A:D7:12:4D:3E:F7:90")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when auto_ssl is disabled' do
|
||||
context 'when certificate is present' do
|
||||
let(:domain) { create(:pages_domain, project: project) }
|
||||
|
||||
it 'shows certificate info' do
|
||||
render
|
||||
|
||||
# test just a random part of cert represenations(X509v3 Subject Key Identifier:)
|
||||
expect(rendered).to have_content("C6:5F:56:4B:10:69:AC:1D:33:D2:26:C9:B3:7A:D7:12:4D:3E:F7:90")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when certificate is absent' do
|
||||
let(:domain) { create(:pages_domain, :without_certificate, :without_key, project: project) }
|
||||
|
||||
it 'shows missing certificate' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_content("missing")
|
||||
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"
|
||||
|
|
Loading…
Reference in New Issue