提交 eca3cd3a 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 6e81d7f6
......@@ -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();
}
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 }}
......
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);
......
fragment TreeEntryCommit on LogTreeCommit {
sha
message
committedDate
commitPath
fileName
type
}
#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
}
}
#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 {
......
// 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),
}));
}
function loadScript(path) {
const script = document.createElement('script');
script.type = 'application/javascript';
script.src = path;
script.defer = true;
document.head.appendChild(script);
}
/**
* Loads the Sourcegraph integration for support for Sourcegraph extensions and
* code intelligence.
*/
export default function initSourcegraph() {
const { url } = gon.sourcegraph || {};
if (!url) {
return;
}
const assetsUrl = new URL('/assets/webpack/sourcegraph/', window.location.href);
const scriptPath = new URL('scripts/integration.bundle.js', assetsUrl).href;
window.SOURCEGRAPH_ASSETS_URL = assetsUrl.href;
window.SOURCEGRAPH_URL = url;
window.SOURCEGRAPH_INTEGRATION = 'gitlab-integration';
loadScript(scriptPath);
}
import initSourcegraph from './index';
/**
* Load sourcegraph in it's own listener so that it's isolated from failures.
*/
document.addEventListener('DOMContentLoaded', initSourcegraph);
......@@ -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();
}
......
# 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,
......
# 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
......
# 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
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
# Don't try to print expensive instance variables.
def inspect
"#<#{self.class} #{merge_request.to_reference(full: true)}>"
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)
......
# 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
......
# 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
......
- return unless Gitlab::Sourcegraph.feature_available?
- expanded = integration_expanded?('sourcegraph_')
%section.settings.as-sourcegraph.no-animate#js-sourcegraph-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Sourcegraph')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://sourcegraph.com/' }
- link_end = "#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}</a>".html_safe
= s_('SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance\'s code views and merge requests.').html_safe % { link_start: link_start, link_end: link_end }
%span
= link_to s_('SourcegraphAdmin|More information'), help_page_path('integration/sourcegraph.md'), target: '_blank'
.settings-content
= form_for @application_setting, url: integrations_admin_application_settings_path(anchor: 'js-sourcegraph-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
.form-group
.form-check
= f.check_box :sourcegraph_enabled, class: 'form-check-input'
= f.label :sourcegraph_enabled, s_('SourcegraphAdmin|Enable Sourcegraph'), class: 'form-check-label'
.form-group
.form-check
= f.check_box :sourcegraph_public_only, class: 'form-check-input'
= f.label :sourcegraph_public_only, s_('SourcegraphAdmin|Block on private and internal projects'), class: 'form-check-label'
.form-text.text-muted
= s_('SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph.')
.form-group
= f.label :sourcegraph_url, s_('SourcegraphAdmin|Sourcegraph URL'), class: 'label-bold'
= f.text_field :sourcegraph_url, class: 'form-control', placeholder: s_('SourcegraphAdmin|e.g. https://sourcegraph.example.com')
.form-text.text-muted
= s_('SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects.')
= f.submit s_('SourcegraphAdmin|Save changes'), class: 'btn btn-success'
......@@ -4,6 +4,7 @@
= render_if_exists 'admin/application_settings/elasticsearch_form'
= render 'admin/application_settings/plantuml'
= render 'admin/application_settings/sourcegraph'
= render_if_exists 'admin/application_settings/slack'
= render 'admin/application_settings/third_party_offers'
= render 'admin/application_settings/snowplow'
......
- return unless Gitlab::Sourcegraph::feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
- sourcegraph_url = Gitlab::CurrentSettings.sourcegraph_url
.col-sm-12
%hr
.col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
= s_('Preferences|Integrations')
%p
= s_('Preferences|Customize integrations with third party services.')
= succeed '.' do
= link_to _('Learn more'), help_page_path('user/profile/preferences.md', anchor: 'integrations'), target: '_blank'
.col-lg-8
%label.label-bold
= s_('Preferences|Sourcegraph')
= link_to icon('question-circle'), help_page_path('user/profile/preferences.md', anchor: 'sourcegraph'), target: '_blank', class: 'has-tooltip', title: _('More information')
.form-group.form-check
= f.check_box :sourcegraph_enabled, class: 'form-check-input'
= f.label :sourcegraph_enabled, class: 'form-check-label' do
- link_start = '<a href="%{url}">'.html_safe % { url: sourcegraph_url }
- link_end = '</a>'.html_safe
= s_('Preferences|Enable integrated code intelligence on code views').html_safe % { link_start: link_start, link_end: link_end }
.form-text.text-muted
= sourcegraph_url_message
= sourcegraph_experimental_message
......@@ -111,6 +111,9 @@
= time_display_label
.form-text.text-muted
= s_('Preferences|For example: 30 mins ago.')
= render 'sourcegraph', f: f
.col-lg-4.profile-settings-sidebar
.col-lg-8
.form-group
......
......@@ -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,
......
- 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
- 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?
- 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)")
.form-group.border-section
.row
- if @domain.persisted?
.col-sm-2
= _("Domain")
.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)")
= external_link(@domain.url, @domain.url)
- else
.col-sm-2
= f.label :domain, _("Domain")
.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")
.input-group
= f.text_field :domain, required: true, autocomplete: "off", class: "form-control"
- if @domain.persisted?
= render 'dns'
- if Gitlab.config.pages.external_https
= 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.")
- 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.")
- 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
---
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
---
title: Replace task-done icon with list-task icon to better align with other toolbar
list icons
merge_request:
author:
type: other
---
title: Add documentation for sign-in application setting
merge_request: 19561
author: Horatiu Eugen Vlad
type: added
---
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.'
......
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddSourcegraphConfigurationToApplicationSettings < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
add_column(:application_settings, :sourcegraph_enabled, :boolean, default: false, null: false)
add_column(:application_settings, :sourcegraph_url, :string, null: true, limit: 255)
end
def down
remove_column(:application_settings, :sourcegraph_enabled)
remove_column(:application_settings, :sourcegraph_url)
end
end
# frozen_string_literal: true
class AddSourcegraphAdminAndUserPreferences < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
add_column(:application_settings, :sourcegraph_public_only, :boolean, default: true, null: false)
add_column(:user_preferences, :sourcegraph_enabled, :boolean)
end
def down
remove_column(:application_settings, :sourcegraph_public_only)
remove_column(:user_preferences, :sourcegraph_enabled)
end
end
......@@ -352,6 +352,9 @@ ActiveRecord::Schema.define(version: 2019_11_14_173624) do
t.string "snowplow_app_id"
t.datetime_with_timezone "productivity_analytics_start_date"
t.string "default_ci_config_path", limit: 255
t.boolean "sourcegraph_enabled", default: false, null: false
t.string "sourcegraph_url", limit: 255
t.boolean "sourcegraph_public_only", default: true, null: false
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id"
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id"
t.index ["instance_administration_project_id"], name: "index_applicationsettings_on_instance_administration_project_id"
......@@ -3771,6 +3774,7 @@ ActiveRecord::Schema.define(version: 2019_11_14_173624) do
t.boolean "time_format_in_24h"
t.string "projects_sort", limit: 64
t.boolean "show_whitespace_in_diffs", default: true, null: false
t.boolean "sourcegraph_enabled"
t.boolean "setup_for_company"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true
end
......
......@@ -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
......
---
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.
......@@ -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)
......
---
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
......
# 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 ""
......
[[ "$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 '$name'..." true
echoinfo "Deleting release '$deploy'..." 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
......
# 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(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(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
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
}
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 = {
......
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',
},
]);
});
});
# frozen_string_literal: true
require 'spec_helper'
describe SourcegraphHelper do
describe '#sourcegraph_url_message' do
let(:sourcegraph_url) { 'http://sourcegraph.example.com' }
before do
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url)
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url_is_com?).and_return(is_com)
end
subject { helper.sourcegraph_url_message }
context 'with .com sourcegraph url' do
let(:is_com) { true }
it { is_expected.to have_text('Uses Sourcegraph.com') }
it { is_expected.to have_link('Sourcegraph.com', href: sourcegraph_url) }
end
context 'with custom sourcegraph url' do
let(:is_com) { false }
it { is_expected.to have_text('Uses a custom Sourcegraph instance') }
it { is_expected.to have_link('Sourcegraph instance', href: sourcegraph_url) }
context 'with unsafe url' do
let(:sourcegraph_url) { '\" onload=\"alert(1);\"' }
it { is_expected.to have_link('Sourcegraph instance', href: sourcegraph_url) }
end
end
end
context '#sourcegraph_experimental_message' do
let(:feature_conditional) { false }
let(:public_only) { false }
before do
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_public_only).and_return(public_only)
allow(Gitlab::Sourcegraph).to receive(:feature_conditional?).and_return(feature_conditional)
end
subject { helper.sourcegraph_experimental_message }
context 'when not limited by feature or public only' do
it { is_expected.to eq "This feature is experimental." }
end
context 'when limited by feature' do
let(:feature_conditional) { true }
it { is_expected.to eq "This feature is experimental and currently limited to certain projects." }
end
context 'when limited by public only' do
let(:public_only) { true }
it { is_expected.to eq "This feature is experimental and limited to public projects." }
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Sourcegraph do
let_it_be(:user) { create(:user) }
let(:feature_scope) { true }
before do
Feature.enable(:sourcegraph, feature_scope)
end
describe '.feature_conditional?' do
subject { described_class.feature_conditional? }
context 'when feature is enabled globally' do
it { is_expected.to be_falsey }
end
context 'when feature is enabled only to a resource' do
let(:feature_scope) { user }
it { is_expected.to be_truthy }
end
end
describe '.feature_available?' do
subject { described_class.feature_available? }
context 'when feature is enabled globally' do
it { is_expected.to be_truthy }
end
context 'when feature is enabled only to a resource' do
let(:feature_scope) { user }
it { is_expected.to be_truthy }
end
end
describe '.feature_enabled?' do
let(:current_user) { nil }
subject { described_class.feature_enabled?(current_user) }
context 'when feature is enabled globally' do
it { is_expected.to be_truthy }
end
context 'when feature is enabled only to a resource' do
let(:feature_scope) { user }
context 'for the same resource' do
let(:current_user) { user }
it { is_expected.to be_truthy }
end
context 'for a different resource' do
let(:current_user) { create(:user) }
it { is_expected.to be_falsey }
end
end
end
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
describe ApplicationSetting do
using RSpec::Parameterized::TableSyntax
subject(:setting) { described_class.create_from_defaults }
it { include(CacheableAttributes) }
......@@ -495,6 +497,15 @@ describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:static_objects_external_storage_auth_token) }
end
end
context 'sourcegraph settings' do
it 'is invalid if sourcegraph is enabled and no url is provided' do
allow(subject).to receive(:sourcegraph_enabled).and_return(true)
expect(subject.sourcegraph_url).to be_nil
is_expected.to be_invalid
end
end
end
context 'restrict creating duplicates' do
......@@ -583,5 +594,24 @@ describe ApplicationSetting do
end
end
describe '#sourcegraph_url_is_com?' do
where(:url, :is_com) do
'https://sourcegraph.com' | true
'https://sourcegraph.com/' | true
'https://www.sourcegraph.com' | true
'shttps://www.sourcegraph.com' | false
'https://sourcegraph.example.com/' | false
'https://sourcegraph.org/' | false
end
with_them do
it 'matches the url with sourcegraph.com' do
setting.sourcegraph_url = url
expect(setting.sourcegraph_url_is_com?).to eq(is_com)
end
end
end
it_behaves_like 'application settings examples'
end
......@@ -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
# frozen_string_literal: true
require 'spec_helper'
describe 'admin/application_settings/integrations.html.haml' do
let(:app_settings) { build(:application_setting) }
describe 'sourcegraph integration' do
let(:sourcegraph_flag) { true }
before do
assign(:application_setting, app_settings)
allow(Gitlab::Sourcegraph).to receive(:feature_available?).and_return(sourcegraph_flag)
end
context 'when sourcegraph feature is enabled' do
it 'show the form' do
render
expect(rendered).to have_field('application_setting_sourcegraph_enabled')
end
end
context 'when sourcegraph feature is disabled' do
let(:sourcegraph_flag) { false }
it 'show the form' do
render
expect(rendered).not_to have_field('application_setting_sourcegraph_enabled')
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'profiles/preferences/show' do
using RSpec::Parameterized::TableSyntax
let_it_be(:user) { build(:user) }
before do
assign(:user, user)
allow(controller).to receive(:current_user).and_return(user)
end
context 'sourcegraph' do
def have_sourcegraph_field(*args)
have_field('user_sourcegraph_enabled', *args)
end
def have_integrations_section
have_css('.profile-settings-sidebar', { text: 'Integrations' })
end
before do
# Can't use stub_feature_flags because we use Feature.get to check if conditinally applied
Feature.get(:sourcegraph).enable sourcegraph_feature
stub_application_setting(sourcegraph_enabled: sourcegraph_enabled)
end
context 'when not fully enabled' do
where(:feature, :admin_enabled) do
false | false
false | true
true | false
end
with_them do
let(:sourcegraph_feature) { feature }
let(:sourcegraph_enabled) { admin_enabled }
before do
render
end
it 'does not display sourcegraph field' do
expect(rendered).not_to have_sourcegraph_field
end
it 'does not display integrations settings' do
expect(rendered).not_to have_integrations_section
end
end
end
context 'when fully enabled' do
let(:sourcegraph_feature) { true }
let(:sourcegraph_enabled) { true }
before do
render
end
it 'displays the sourcegraph field' do
expect(rendered).to have_sourcegraph_field
end
it 'displays the integrations section' do
expect(rendered).to have_integrations_section
end
end
end
end
......@@ -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"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册