Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a071c2888d
commit
e0b023e388
|
@ -19,7 +19,7 @@
|
|||
- node --version
|
||||
- run_timed_command "retry yarn install --frozen-lockfile"
|
||||
- free -m
|
||||
- run_timed_command "bin/rake gitlab:assets:compile > assets-compile.log 2>&1"
|
||||
- run_timed_command "bin/rake gitlab:assets:compile"
|
||||
- run_timed_command "scripts/clean-old-cached-assets"
|
||||
|
||||
compile-production-assets:
|
||||
|
@ -34,7 +34,6 @@ compile-production-assets:
|
|||
name: webpack-report
|
||||
expire_in: 31d
|
||||
paths:
|
||||
- assets-compile.log
|
||||
# These assets are used in multiple locations:
|
||||
# - in `build-assets-image` job to create assets image for packaging systems
|
||||
# - GitLab UI for integration tests: https://gitlab.com/gitlab-org/gitlab-ui/-/blob/e88493b3c855aea30bf60baee692a64606b0eb1e/.storybook/preview-head.pug#L1
|
||||
|
@ -51,7 +50,6 @@ compile-test-assets:
|
|||
artifacts:
|
||||
expire_in: 7d
|
||||
paths:
|
||||
- assets-compile.log
|
||||
- public/assets/
|
||||
- node_modules/@gitlab/svgs/dist/icons.json # app/helpers/icons_helper.rb uses this file
|
||||
when: always
|
||||
|
|
|
@ -949,9 +949,6 @@ Rails/SaveBang:
|
|||
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
|
||||
- 'spec/lib/gitlab/git/object_pool_spec.rb'
|
||||
- 'spec/lib/gitlab/git/remote_mirror_spec.rb'
|
||||
- 'spec/lib/gitlab/git/repository_spec.rb'
|
||||
- 'spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -284,7 +284,6 @@ gem 'fast_blank'
|
|||
gem 'gitlab-chronic', '~> 0.10.5'
|
||||
gem 'gitlab_chronic_duration', '~> 0.10.6.2'
|
||||
|
||||
gem 'webpack-rails', '~> 0.9.10'
|
||||
gem 'rack-proxy', '~> 0.6.0'
|
||||
|
||||
gem 'sassc-rails', '~> 2.1.0'
|
||||
|
|
|
@ -1218,8 +1218,6 @@ GEM
|
|||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff
|
||||
webpack-rails (0.9.11)
|
||||
railties (>= 3.2.0)
|
||||
websocket-driver (0.7.1)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
|
@ -1499,7 +1497,6 @@ DEPENDENCIES
|
|||
vmstat (~> 2.3.0)
|
||||
webauthn (~> 2.3)
|
||||
webmock (~> 3.5.1)
|
||||
webpack-rails (~> 0.9.10)
|
||||
wikicloth (= 0.8.1)
|
||||
yajl-ruby (~> 1.4.1)
|
||||
|
||||
|
|
|
@ -201,7 +201,13 @@ export default {
|
|||
<section v-else>
|
||||
<ancestor-notice />
|
||||
|
||||
<gl-table :items="clusters" :fields="fields" stacked="md" class="qa-clusters-table">
|
||||
<gl-table
|
||||
:items="clusters"
|
||||
:fields="fields"
|
||||
stacked="md"
|
||||
class="qa-clusters-table"
|
||||
data-testid="cluster_list_table"
|
||||
>
|
||||
<template #cell(name)="{ item }">
|
||||
<div :class="[contentAlignClasses, 'js-status']">
|
||||
<img
|
||||
|
|
|
@ -474,7 +474,7 @@ export default {
|
|||
<div
|
||||
v-if="showTreeList"
|
||||
:style="{ width: `${treeWidth}px` }"
|
||||
class="diff-tree-list js-diff-tree-list mr-3"
|
||||
class="diff-tree-list js-diff-tree-list px-3 pr-md-0"
|
||||
>
|
||||
<panel-resizer
|
||||
:size.sync="treeWidth"
|
||||
|
@ -487,7 +487,7 @@ export default {
|
|||
<tree-list :hide-file-stats="hideFileStats" />
|
||||
</div>
|
||||
<div
|
||||
class="diff-files-holder"
|
||||
class="col-12 col-md-auto diff-files-holder"
|
||||
:class="{
|
||||
[CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
|
||||
}"
|
||||
|
|
|
@ -50,7 +50,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="!isDismissed" data-testid="root" :class="containerClasses">
|
||||
<div v-if="!isDismissed" data-testid="root" :class="containerClasses" class="col-12">
|
||||
<gl-alert
|
||||
:dismissible="true"
|
||||
:title="__('Some changes are not shown')"
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<script>
|
||||
import { GlIcon } from '@gitlab/ui';
|
||||
import { n__ } from '../../locale';
|
||||
import { MAX_CHILDREN_COUNT } from '../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlIcon,
|
||||
},
|
||||
props: {
|
||||
parentGroup: {
|
||||
type: Object,
|
||||
|
@ -45,7 +49,7 @@ export default {
|
|||
/>
|
||||
<li v-if="hasMoreChildren" class="group-row">
|
||||
<a :href="parentGroup.relativePath" class="group-row-contents has-more-items py-2">
|
||||
<i class="fa fa-external-link" aria-hidden="true"> </i> {{ moreChildrenStats }}
|
||||
<gl-icon name="external-link" aria-hidden="true" /> {{ moreChildrenStats }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
import $ from 'jquery';
|
||||
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
|
||||
import { initCommitBoxInfo } from '~/projects/commit_box/info';
|
||||
import initPipelines from '~/commit/pipelines/pipelines_bundle';
|
||||
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new MiniPipelineGraph({
|
||||
container: '.js-commit-pipeline-graph',
|
||||
}).bindEvents();
|
||||
// eslint-disable-next-line no-jquery/no-load
|
||||
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
|
||||
fetchCommitMergeRequests();
|
||||
initCommitBoxInfo();
|
||||
|
||||
initPipelines();
|
||||
});
|
||||
|
|
|
@ -4,10 +4,8 @@ import $ from 'jquery';
|
|||
import Diff from '~/diff';
|
||||
import ZenMode from '~/zen_mode';
|
||||
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
|
||||
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
|
||||
import initNotes from '~/init_notes';
|
||||
import initChangesDropdown from '~/init_changes_dropdown';
|
||||
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
|
||||
import '~/sourcegraph/load';
|
||||
import { handleLocationHash } from '~/lib/utils/common_utils';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
|
@ -15,6 +13,7 @@ import syntaxHighlight from '~/syntax_highlight';
|
|||
import flash from '~/flash';
|
||||
import { __ } from '~/locale';
|
||||
import loadAwardsHandler from '~/awards_handler';
|
||||
import { initCommitBoxInfo } from '~/projects/commit_box/info';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const hasPerfBar = document.querySelector('.with-performance-bar');
|
||||
|
@ -22,13 +21,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight);
|
||||
new ZenMode();
|
||||
new ShortcutsNavigation();
|
||||
new MiniPipelineGraph({
|
||||
container: '.js-commit-pipeline-graph',
|
||||
}).bindEvents();
|
||||
|
||||
initCommitBoxInfo();
|
||||
|
||||
initNotes();
|
||||
// eslint-disable-next-line no-jquery/no-load
|
||||
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
|
||||
fetchCommitMergeRequests();
|
||||
|
||||
const filesContainer = $('.js-diffs-batch');
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import $ from 'jquery';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { Rails } from '~/lib/utils/rails_ujs';
|
||||
import { deprecatedCreateFlash as flash } from '../flash';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import TimezoneDropdown, {
|
||||
|
@ -48,9 +49,13 @@ export default class Profile {
|
|||
}
|
||||
|
||||
submitForm() {
|
||||
return $(this)
|
||||
.parents('form')
|
||||
.submit();
|
||||
const $form = $(this).parents('form');
|
||||
|
||||
if ($form.data('remote')) {
|
||||
Rails.fire($form[0], 'submit');
|
||||
} else {
|
||||
$form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
onSubmitForm(e) {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { loadBranches } from './load_branches';
|
||||
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
|
||||
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
|
||||
|
||||
export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') => {
|
||||
const containerEl = document.querySelector(containerSelector);
|
||||
|
||||
// Display commit related branches
|
||||
loadBranches(containerEl);
|
||||
|
||||
// Related merge requests to this commit
|
||||
fetchCommitMergeRequests();
|
||||
|
||||
// Display pipeline info for this commit
|
||||
new MiniPipelineGraph({
|
||||
container: '.js-commit-pipeline-graph',
|
||||
}).bindEvents();
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
import axios from 'axios';
|
||||
import { sanitize } from '~/lib/dompurify';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
export const loadBranches = containerEl => {
|
||||
if (!containerEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { commitPath } = containerEl.dataset;
|
||||
const branchesEl = containerEl.querySelector('.commit-info.branches');
|
||||
axios
|
||||
.get(commitPath)
|
||||
.then(({ data }) => {
|
||||
branchesEl.innerHTML = sanitize(data);
|
||||
})
|
||||
.catch(() => {
|
||||
branchesEl.textContent = __('Failed to load branches. Please try again.');
|
||||
});
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { mapActions } from 'vuex';
|
||||
import { __ } from '~/locale';
|
||||
import { deprecatedCreateFlash as Flash } from '~/flash';
|
||||
|
@ -8,7 +8,7 @@ import eventHub from '../../event_hub';
|
|||
|
||||
export default {
|
||||
components: {
|
||||
GlLoadingIcon,
|
||||
GlButton,
|
||||
},
|
||||
props: {
|
||||
fullPath: {
|
||||
|
@ -64,18 +64,18 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="sidebar-item-warning-message-actions">
|
||||
<button type="button" class="btn btn-default gl-mr-3" @click="closeForm">
|
||||
<gl-button class="gl-mr-3" @click="closeForm">
|
||||
{{ __('Cancel') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-close"
|
||||
data-testid="confidential-toggle"
|
||||
</gl-button>
|
||||
<gl-button
|
||||
category="secondary"
|
||||
variant="warning"
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
data-testid="confidential-toggle"
|
||||
@click.prevent="submitForm"
|
||||
>
|
||||
<gl-loading-icon v-if="isLoading" inline />
|
||||
{{ toggleButtonText }}
|
||||
</button>
|
||||
</gl-button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
<script>
|
||||
/* eslint-disable vue/no-v-html */
|
||||
import { isEmpty } from 'lodash';
|
||||
import { GlIcon, GlButton, GlSprintf, GlLink } from '@gitlab/ui';
|
||||
import successSvg from 'icons/_icon_status_success.svg';
|
||||
import warningSvg from 'icons/_icon_status_warning.svg';
|
||||
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
|
||||
import simplePoll from '~/lib/utils/simple_poll';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import { __ } from '~/locale';
|
||||
import MergeRequest from '../../../merge_request';
|
||||
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
|
||||
import { deprecatedCreateFlash as Flash } from '../../../flash';
|
||||
|
@ -59,8 +56,6 @@ export default {
|
|||
commitMessage: this.mr.commitMessage,
|
||||
squashBeforeMerge: this.mr.squashIsSelected,
|
||||
isSquashReadOnly: this.mr.squashIsReadonly,
|
||||
successSvg,
|
||||
warningSvg,
|
||||
squashCommitMessage: this.mr.squashCommitMessage,
|
||||
};
|
||||
},
|
||||
|
@ -147,16 +142,7 @@ export default {
|
|||
return !this.mr.ffOnlyEnabled;
|
||||
},
|
||||
shaMismatchLink() {
|
||||
const href = this.mr.mergeRequestDiffsPath;
|
||||
|
||||
return sprintf(
|
||||
__('New changes were added. %{linkStart}Reload the page to review them%{linkEnd}'),
|
||||
{
|
||||
linkStart: `<a href="${href}">`,
|
||||
linkEnd: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
return this.mr.mergeRequestDiffsPath;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -331,7 +317,7 @@ export default {
|
|||
@click.prevent="handleMergeButtonClick(true)"
|
||||
>
|
||||
<span class="media">
|
||||
<span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span>
|
||||
<gl-icon name="status_success" class="merge-opt-icon" aria-hidden="true" />
|
||||
<span class="media-body merge-opt-title">{{ autoMergeText }}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
@ -349,7 +335,7 @@ export default {
|
|||
@click.prevent="handleMergeImmediatelyButtonClick"
|
||||
>
|
||||
<span class="media">
|
||||
<span class="merge-opt-icon" aria-hidden="true" v-html="warningSvg"></span>
|
||||
<gl-icon name="status_warning" class="merge-opt-icon" aria-hidden="true" />
|
||||
<span class="media-body merge-opt-title">{{ __('Merge immediately') }}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
@ -400,7 +386,17 @@ export default {
|
|||
</div>
|
||||
<div v-if="mr.isSHAMismatch" class="d-flex align-items-center mt-2 js-sha-mismatch">
|
||||
<gl-icon name="warning-solid" class="text-warning mr-1" />
|
||||
<span class="text-warning" v-html="shaMismatchLink"></span>
|
||||
<span class="text-warning">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
__('New changes were added. %{linkStart}Reload the page to review them%{linkEnd}')
|
||||
"
|
||||
>
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="mr.mergeRequestDiffsPath">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -257,6 +257,38 @@
|
|||
content: '\f127';
|
||||
}
|
||||
|
||||
.fa-file-pdf-o::before {
|
||||
content: '\f1c1';
|
||||
}
|
||||
|
||||
.fa-file-word-o::before {
|
||||
content: '\f1c2';
|
||||
}
|
||||
|
||||
.fa-file-excel-o::before {
|
||||
content: '\f1c3';
|
||||
}
|
||||
|
||||
.fa-file-powerpoint-o::before {
|
||||
content: '\f1c4';
|
||||
}
|
||||
|
||||
.fa-file-image-o::before {
|
||||
content: '\f1c5';
|
||||
}
|
||||
|
||||
.fa-file-archive-o::before {
|
||||
content: '\f1c6';
|
||||
}
|
||||
|
||||
.fa-file-audio-o::before {
|
||||
content: '\f1c7';
|
||||
}
|
||||
|
||||
.fa-file-video-o::before {
|
||||
content: '\f1c8';
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
|
|
|
@ -127,9 +127,4 @@
|
|||
@include gl-w-full;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Abstract to `@gitlab/ui` utility set: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/921
|
||||
.gl-fill-green-500 {
|
||||
fill: $green-500;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -770,8 +770,6 @@ $mr-widget-min-height: 69px;
|
|||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: $header-height + $mr-tabs-height;
|
||||
margin-left: -16px;
|
||||
width: calc(100% + 32px);
|
||||
|
||||
.mr-version-menus-container {
|
||||
flex-wrap: nowrap;
|
||||
|
@ -868,6 +866,13 @@ $mr-widget-min-height: 69px;
|
|||
}
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
// Negative margins for mobile/tablet screen
|
||||
.diffs.tab-pane {
|
||||
margin: 0 (-$gl-padding);
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap MR tabs/buttons so you don't have to scroll on desktop
|
||||
@include media-breakpoint-down(md) {
|
||||
.merge-request-tabs-container,
|
||||
|
|
|
@ -5,20 +5,11 @@ module Projects
|
|||
class PackagesController < Projects::ApplicationController
|
||||
include PackagesAccess
|
||||
|
||||
before_action :authorize_destroy_package!, only: [:destroy]
|
||||
|
||||
def show
|
||||
@package = project.packages.find(params[:id])
|
||||
@package_files = @package.package_files.recent
|
||||
@maven_metadatum = @package.maven_metadatum
|
||||
end
|
||||
|
||||
def destroy
|
||||
@package = project.packages.find(params[:id])
|
||||
@package.destroy
|
||||
|
||||
redirect_to project_packages_path(@project), status: :found, notice: _('Package was removed')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,7 +51,7 @@ module PackagesHelper
|
|||
{
|
||||
resource_id: resource.id,
|
||||
page_type: type,
|
||||
empty_list_help_url: help_page_path('administration/packages/index'),
|
||||
empty_list_help_url: help_page_path('user/packages/package_registry/index'),
|
||||
empty_list_illustration: image_path('illustrations/no-packages.svg'),
|
||||
coming_soon_json: packages_coming_soon_data(resource).to_json
|
||||
}
|
||||
|
|
|
@ -5,7 +5,13 @@ class AuditEvent < ApplicationRecord
|
|||
include IgnorableColumns
|
||||
include BulkInsertSafe
|
||||
|
||||
PARALLEL_PERSISTENCE_COLUMNS = [:author_name, :entity_path, :target_details, :target_type].freeze
|
||||
PARALLEL_PERSISTENCE_COLUMNS = [
|
||||
:author_name,
|
||||
:entity_path,
|
||||
:target_details,
|
||||
:target_type,
|
||||
:target_id
|
||||
].freeze
|
||||
|
||||
ignore_column :type, remove_with: '13.6', remove_after: '2020-11-22'
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
= s_('ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project')
|
||||
= render 'clusters/clusters/buttons'
|
||||
|
||||
- if Feature.enabled?(:clusters_list_redesign)
|
||||
- if Feature.enabled?(:clusters_list_redesign, default_enabled: true)
|
||||
#js-clusters-list-app{ data: js_clusters_list_data(clusterable.index_path(format: :json)) }
|
||||
- else
|
||||
- if @has_ancestor_clusters
|
||||
|
@ -20,7 +20,7 @@
|
|||
= s_('ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters.')
|
||||
%strong
|
||||
= link_to _('More information'), help_page_path('user/group/clusters/index', anchor: 'cluster-precedence')
|
||||
.clusters-table.js-clusters-list
|
||||
.clusters-table.js-clusters-list{ data: { testid: 'cluster_list_table' } }
|
||||
.gl-responsive-table-row.table-row-header{ role: "row" }
|
||||
.table-section.section-60{ role: "rowheader" }
|
||||
= s_("ClusterIntegration|Kubernetes cluster")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- can_collaborate = can_collaborate_with_project?(@project)
|
||||
|
||||
.page-content-header.js-commit-box{ 'data-commit-path' => branches_project_commit_path(@project, @commit.id) }
|
||||
.page-content-header
|
||||
.header-main-content
|
||||
= render partial: 'signature', object: @commit.signature
|
||||
%strong
|
||||
|
@ -58,7 +58,7 @@
|
|||
%pre.commit-description<
|
||||
= preserve(markdown_field(@commit, :description))
|
||||
|
||||
.info-well
|
||||
.info-well.js-commit-box-info{ 'data-commit-path' => branches_project_commit_path(@project, @commit.id) }
|
||||
.well-segment.branch-info
|
||||
.icon-container.commit-icon
|
||||
= custom_icon("icon_commit")
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
= form_for [@project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f|
|
||||
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
|
||||
|
||||
%span>= f.submit 'Save changes', class: 'btn btn-success gl-mr-3'
|
||||
= f.submit 'Save changes', class: 'btn gl-button btn-success gl-mr-3'
|
||||
= render 'shared/web_hooks/test_button', hook: @hook
|
||||
= link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: _('Are you sure?') }
|
||||
= link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn gl-button btn-danger float-right', data: { confirm: _('Are you sure?') }
|
||||
|
||||
%hr
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Display cluster list node information
|
||||
merge_request: 42396
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update confidential form buttons to gl-button
|
||||
merge_request: 40893
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Eliminate extra spacing on MR diffs from mobile/tablet screen
|
||||
merge_request: 42821
|
||||
author: Takuya Noguchi
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add missing fontawesome file icon classes
|
||||
merge_request: 43091
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Empty state Packages UI links to user docs
|
||||
merge_request: 43009
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Drop column instance_statistics_visibility_private
|
||||
merge_request: 42969
|
||||
author:
|
||||
type: deprecated
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Replace fa-external-link with GitLab SVG in group folder
|
||||
merge_request: 43128
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fixes Rails/SaveBang cop for spec files in spec/lib/gitlab/git/*
|
||||
merge_request: 43013
|
||||
author: Rajendra Kadam
|
||||
type: other
|
|
@ -152,12 +152,18 @@ module Gitlab
|
|||
config.active_record.schema_format = :sql
|
||||
|
||||
# Configure webpack
|
||||
config.webpack = ActiveSupport::OrderedOptions.new
|
||||
config.webpack.config_file = "config/webpack.config.js"
|
||||
config.webpack.output_dir = "public/assets/webpack"
|
||||
config.webpack.public_path = "assets/webpack"
|
||||
config.webpack.manifest_filename = "manifest.json"
|
||||
|
||||
# Webpack dev server configuration is handled in initializers/static_files.rb
|
||||
config.webpack.dev_server = ActiveSupport::OrderedOptions.new
|
||||
config.webpack.dev_server.enabled = false
|
||||
config.webpack.dev_server.host = 'localhost'
|
||||
config.webpack.dev_server.port = 3808
|
||||
config.webpack.dev_server.https = false
|
||||
|
||||
config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: clusters_list_redesign
|
||||
introduced_by_url:
|
||||
rollout_issue_url:
|
||||
group:
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/220182
|
||||
group: Configure
|
||||
type: development
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
@ -21,9 +21,7 @@ if app.config.public_file_server.enabled
|
|||
settings = {
|
||||
enabled: true,
|
||||
host: dev_server.host,
|
||||
port: dev_server.port,
|
||||
manifest_host: dev_server.host,
|
||||
manifest_port: dev_server.port
|
||||
port: dev_server.port
|
||||
}
|
||||
|
||||
if Rails.env.development?
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveInstanceStatisticsVisibilityPrivateFromApplicationSettings < ActiveRecord::Migration[6.0]
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
remove_column :application_settings, :instance_statistics_visibility_private
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :application_settings, :instance_statistics_visibility_private, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
c55f27f817afc60462e5dc43755a4ddd76f1399f5e461bab4b36bf5e5b26ce0a
|
|
@ -9146,7 +9146,6 @@ CREATE TABLE application_settings (
|
|||
snowplow_enabled boolean DEFAULT false NOT NULL,
|
||||
snowplow_collector_hostname character varying,
|
||||
snowplow_cookie_domain character varying,
|
||||
instance_statistics_visibility_private boolean DEFAULT false NOT NULL,
|
||||
web_ide_clientside_preview_enabled boolean DEFAULT false NOT NULL,
|
||||
user_show_add_ssh_key_message boolean DEFAULT true NOT NULL,
|
||||
custom_project_templates_group_id integer,
|
||||
|
|
|
@ -588,6 +588,52 @@ Refer to the documentation for your SAML Identity Provider for information on ho
|
|||
|
||||
The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML.
|
||||
|
||||
## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM ONLY)**
|
||||
|
||||
For information on the GitLab.com implementation, please see the [SAML SSO for GitLab.com groups page](../user/group/saml_sso).
|
||||
|
||||
Group SAML SSO helps if you need to allow access via multiple SAML identity providers, but as a multi-tenant solution is less suited to cases where you administer your own GitLab instance.
|
||||
|
||||
To proceed with configuring Group SAML SSO instead, you'll need to enable the `group_saml` OmniAuth provider. This can be done from:
|
||||
|
||||
- `gitlab.rb` for [Omnibus GitLab installations](#omnibus-installations).
|
||||
- `gitlab/config/gitlab.yml` for [source installations](#source-installations).
|
||||
|
||||
### Limitations
|
||||
|
||||
Group SAML on a self-managed instance is limited when compared to the recommended
|
||||
[instance-wide SAML](../user/group/saml_sso/index.md). The recommended solution allows you to take advantage of:
|
||||
|
||||
- [LDAP compatibility](../administration/auth/ldap/index.md).
|
||||
- [LDAP Group Sync](../user/group/index.md#manage-group-memberships-via-ldap).
|
||||
- [Required groups](#required-groups).
|
||||
- [Admin groups](#admin-groups).
|
||||
- [Auditor groups](#auditor-groups).
|
||||
|
||||
### Omnibus installations
|
||||
|
||||
1. Make sure GitLab is
|
||||
[configured with HTTPS](../install/installation.md#using-https).
|
||||
1. Enable OmniAuth and the `group_saml` provider in `gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['omniauth_enabled'] = true
|
||||
gitlab_rails['omniauth_providers'] = [{ name: 'group_saml' }]
|
||||
```
|
||||
|
||||
### Source installations
|
||||
|
||||
1. Make sure GitLab is
|
||||
[configured with HTTPS](../install/installation.md#using-https).
|
||||
1. Enable OmniAuth and the `group_saml` provider in `gitlab/config/gitlab.yml`:
|
||||
|
||||
```yaml
|
||||
omniauth:
|
||||
enabled: true
|
||||
providers:
|
||||
- { name: 'group_saml' }
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
You can find the base64-encoded SAML Response in the [`production_json.log`](../administration/logs.md#production_jsonlog).
|
||||
|
|
|
@ -14,6 +14,9 @@ Similar to [project-level](../../project/clusters/index.md) and
|
|||
group-level Kubernetes clusters allow you to connect a Kubernetes cluster to
|
||||
your group, enabling you to use the same cluster across multiple projects.
|
||||
|
||||
To view your group level Kubernetes clusters, navigate to your project and select
|
||||
**Kubernetes** from the left-hand menu.
|
||||
|
||||
## Installing applications
|
||||
|
||||
GitLab can install and manage some applications in your group-level
|
||||
|
|
|
@ -5,7 +5,7 @@ group: Access
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# SAML SSO for GitLab.com groups **(PREMIUM)**
|
||||
# SAML SSO for GitLab.com groups **(SILVER ONLY)**
|
||||
|
||||
> Introduced in GitLab 11.0.
|
||||
|
||||
|
@ -256,53 +256,6 @@ For example, to unlink the `MyOrg` account, the following **Disconnect** button
|
|||
| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
|
||||
| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. |
|
||||
|
||||
## Configuring on a self-managed GitLab instance **(PREMIUM ONLY)**
|
||||
|
||||
For self-managed GitLab instances we strongly recommend using the
|
||||
[instance-wide SAML OmniAuth Provider](../../../integration/saml.md) instead.
|
||||
|
||||
Group SAML SSO helps if you need to allow access via multiple SAML identity providers, but as a multi-tenant solution is less suited to cases where you administer your own GitLab instance.
|
||||
|
||||
To proceed with configuring Group SAML SSO instead, you'll need to enable the `group_saml` OmniAuth provider. This can be done from:
|
||||
|
||||
- `gitlab.rb` for [Omnibus GitLab installations](#omnibus-installations).
|
||||
- `gitlab/config/gitlab.yml` for [source installations](#source-installations).
|
||||
|
||||
### Limitations
|
||||
|
||||
Group SAML on a self-managed instance is limited when compared to the recommended
|
||||
[instance-wide SAML](../../../integration/saml.md). The recommended solution allows you to take advantage of:
|
||||
|
||||
- [LDAP compatibility](../../../administration/auth/ldap/index.md).
|
||||
- [LDAP Group Sync](../index.md#manage-group-memberships-via-ldap).
|
||||
- [Required groups](../../../integration/saml.md#required-groups).
|
||||
- [Admin groups](../../../integration/saml.md#admin-groups).
|
||||
- [Auditor groups](../../../integration/saml.md#auditor-groups).
|
||||
|
||||
### Omnibus installations
|
||||
|
||||
1. Make sure GitLab is
|
||||
[configured with HTTPS](../../../install/installation.md#using-https).
|
||||
1. Enable OmniAuth and the `group_saml` provider in `gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['omniauth_enabled'] = true
|
||||
gitlab_rails['omniauth_providers'] = [{ name: 'group_saml' }]
|
||||
```
|
||||
|
||||
### Source installations
|
||||
|
||||
1. Make sure GitLab is
|
||||
[configured with HTTPS](../../../install/installation.md#using-https).
|
||||
1. Enable OmniAuth and the `group_saml` provider in `gitlab/config/gitlab.yml`:
|
||||
|
||||
```yaml
|
||||
omniauth:
|
||||
enabled: true
|
||||
providers:
|
||||
- { name: 'group_saml' }
|
||||
```
|
||||
|
||||
## Passwords for users created via SAML SSO for Groups
|
||||
|
||||
The [Generated passwords for users created through integrated authentication](../../../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML SSO for Groups.
|
||||
|
|
|
@ -10,6 +10,8 @@ instance-level Kubernetes clusters allow you to connect a Kubernetes cluster to
|
|||
the GitLab instance, which enables you to use the same cluster across multiple
|
||||
projects.
|
||||
|
||||
The instance level Kubernetes clusters can be found in the top menu by navigating to your instance's **{admin}** **Admin Area > Kubernetes**.
|
||||
|
||||
## Cluster precedence
|
||||
|
||||
GitLab will try to match clusters in the following order:
|
||||
|
|
|
@ -31,6 +31,11 @@ Besides integration at the project level, Kubernetes clusters can also be
|
|||
integrated at the [group level](../../group/clusters/index.md) or
|
||||
[GitLab instance level](../../instance/clusters/index.md).
|
||||
|
||||
To view your project level Kubernetes clusters, navigate to **Operations > Kubernetes**
|
||||
from your project. On this page, you can [add a new cluster](#adding-and-removing-clusters)
|
||||
and view information about your existing clusters, such as nodes count and rough estimates
|
||||
of memory and CPU usage.
|
||||
|
||||
## Setting up
|
||||
|
||||
### Supported cluster versions
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'webpack/rails/manifest'
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
|
||||
module Gitlab
|
||||
module Webpack
|
||||
class Manifest < ::Webpack::Rails::Manifest
|
||||
# Raised if a supplied asset does not exist in the webpack manifest
|
||||
class Manifest
|
||||
# Raised if we can't read our webpack manifest for whatever reason
|
||||
class ManifestLoadError < StandardError
|
||||
def initialize(message, orig)
|
||||
super "#{message} (original error #{orig})"
|
||||
end
|
||||
end
|
||||
|
||||
# Raised if webpack couldn't build one of your entry points
|
||||
class WebpackError < StandardError
|
||||
def initialize(errors)
|
||||
super "Error in webpack compile, details follow below:\n#{errors.join("\n\n")}"
|
||||
end
|
||||
end
|
||||
|
||||
# Raised if a supplied entry point does not exist in the webpack manifest
|
||||
AssetMissingError = Class.new(StandardError)
|
||||
|
||||
class << self
|
||||
def entrypoint_paths(source)
|
||||
raise ::Webpack::Rails::Manifest::WebpackError, manifest["errors"] unless manifest_bundled?
|
||||
raise WebpackError, manifest["errors"] unless manifest_bundled?
|
||||
|
||||
dll_assets = manifest.fetch("dllAssets", [])
|
||||
entrypoint = manifest["entrypoints"][source]
|
||||
|
@ -20,10 +35,79 @@ module Gitlab
|
|||
[dll_assets, entrypoint["assets"]].flatten.reject { |p| p =~ /.*\.map$/ }.map do |p|
|
||||
"/#{::Rails.configuration.webpack.public_path}/#{p}"
|
||||
end
|
||||
else
|
||||
raise AssetMissingError, "Can't find asset '#{source}' in webpack manifest"
|
||||
end
|
||||
end
|
||||
|
||||
def asset_paths(source)
|
||||
raise WebpackError, manifest["errors"] unless manifest_bundled?
|
||||
|
||||
paths = manifest["assetsByChunkName"][source]
|
||||
if paths
|
||||
# Can be either a string or an array of strings.
|
||||
# Do not include source maps as they are not javascript
|
||||
[paths].flatten.reject { |p| p =~ /.*\.map$/ }.map do |p|
|
||||
"/#{::Rails.configuration.webpack.public_path}/#{p}"
|
||||
end
|
||||
else
|
||||
raise AssetMissingError, "Can't find entry point '#{source}' in webpack manifest"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def manifest_bundled?
|
||||
!manifest["errors"].any? { |error| error.include? "Module build failed" }
|
||||
end
|
||||
|
||||
def manifest
|
||||
if ::Rails.configuration.webpack.dev_server.enabled
|
||||
# Don't cache if we're in dev server mode, manifest may change ...
|
||||
load_manifest
|
||||
else
|
||||
# ... otherwise cache at class level, as JSON loading/parsing can be expensive
|
||||
@manifest ||= load_manifest
|
||||
end
|
||||
end
|
||||
|
||||
def load_manifest
|
||||
data = if ::Rails.configuration.webpack.dev_server.enabled
|
||||
load_dev_server_manifest
|
||||
else
|
||||
load_static_manifest
|
||||
end
|
||||
|
||||
Gitlab::Json.parse(data)
|
||||
end
|
||||
|
||||
def load_dev_server_manifest
|
||||
host = ::Rails.configuration.webpack.dev_server.host
|
||||
port = ::Rails.configuration.webpack.dev_server.port
|
||||
http = Net::HTTP.new(host, port)
|
||||
http.use_ssl = ::Rails.configuration.webpack.dev_server.https
|
||||
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
http.get(dev_server_path).body
|
||||
rescue => e
|
||||
raise ManifestLoadError.new("Could not load manifest from webpack-dev-server at http://#{host}:#{port}#{dev_server_path} - is it running, and is stats-webpack-plugin loaded?", e)
|
||||
end
|
||||
|
||||
def load_static_manifest
|
||||
File.read(static_manifest_path)
|
||||
rescue => e
|
||||
raise ManifestLoadError.new("Could not load compiled manifest from #{static_manifest_path} - have you run `rake webpack:compile`?", e)
|
||||
end
|
||||
|
||||
def static_manifest_path
|
||||
::Rails.root.join(
|
||||
::Rails.configuration.webpack.output_dir,
|
||||
::Rails.configuration.webpack.manifest_filename
|
||||
)
|
||||
end
|
||||
|
||||
def dev_server_path
|
||||
"/#{::Rails.configuration.webpack.public_path}/#{::Rails.configuration.webpack.manifest_filename}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace :gitlab do
|
|||
|
||||
if head_assets_md5 != master_assets_md5 || !public_assets_webpack_dir_exists
|
||||
FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) if public_assets_webpack_dir_exists
|
||||
Rake::Task['webpack:compile'].invoke
|
||||
system('yarn webpack')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -17999,9 +17999,6 @@ msgstr ""
|
|||
msgid "Package type must be PyPi"
|
||||
msgstr ""
|
||||
|
||||
msgid "Package was removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ RSpec.describe 'Issues > User sees live update', :js do
|
|||
expect(page).to have_css('.sidebar-item-warning-message')
|
||||
|
||||
within('.sidebar-item-warning-message') do
|
||||
find('.btn-close').click
|
||||
find('[data-testid="confidential-toggle"]').click
|
||||
end
|
||||
|
||||
wait_for_requests
|
||||
|
|
|
@ -11,6 +11,10 @@ RSpec.describe 'Clusters', :js do
|
|||
before do
|
||||
project.add_maintainer(user)
|
||||
gitlab_sign_in(user)
|
||||
end
|
||||
|
||||
context 'when clusters_list_redesign feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(clusters_list_redesign: false)
|
||||
end
|
||||
|
||||
|
@ -25,6 +29,31 @@ RSpec.describe 'Clusters', :js do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when user has a cluster and visits cluster index page' do
|
||||
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
|
||||
let(:project) { cluster.project }
|
||||
|
||||
before do
|
||||
visit project_clusters_path(project)
|
||||
end
|
||||
|
||||
it 'user sees a table with one cluster' do
|
||||
expect(page).to have_selector('[data-testid="cluster_list_table"] .card-body', count: 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user does not have a cluster and visits cluster index page' do
|
||||
before do
|
||||
visit project_clusters_path(project)
|
||||
end
|
||||
|
||||
it 'sees empty state' do
|
||||
expect(page).to have_link('Add Kubernetes cluster')
|
||||
expect(page).to have_selector('.empty-state')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user has a cluster' do
|
||||
before do
|
||||
allow_any_instance_of(Clusters::Cluster).to receive(:retrieve_connection_status).and_return(:connected)
|
||||
|
@ -196,8 +225,7 @@ RSpec.describe 'Clusters', :js do
|
|||
end
|
||||
|
||||
it 'user sees a table with one cluster' do
|
||||
# One is the header row, the other the cluster row
|
||||
expect(page).to have_selector('.gl-responsive-table-row', count: 2)
|
||||
expect(page).to have_selector('[data-testid="cluster_list_table"] tbody tr', count: 1)
|
||||
end
|
||||
|
||||
context 'when user clicks on a cluster' do
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('CollapsedFilesWarning', () => {
|
|||
({ limited, containerClasses }) => {
|
||||
createComponent({ limited });
|
||||
|
||||
expect(wrapper.classes()).toEqual(containerClasses);
|
||||
expect(wrapper.classes()).toEqual(['col-12'].concat(containerClasses));
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import axios from 'axios';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { loadBranches } from '~/projects/commit_box/info/load_branches';
|
||||
|
||||
const mockCommitPath = '/commit/abcd/branches';
|
||||
const mockBranchesRes =
|
||||
'<a href="/-/commits/master">master</a><span><a href="/-/commits/my-branch">my-branch</a></span>';
|
||||
|
||||
describe('~/projects/commit_box/info/load_branches', () => {
|
||||
let mock;
|
||||
let el;
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
mock.onGet(mockCommitPath).reply(200, mockBranchesRes);
|
||||
|
||||
el = document.createElement('div');
|
||||
el.dataset.commitPath = mockCommitPath;
|
||||
el.innerHTML = '<div class="commit-info branches"><span class="spinner"/></div>';
|
||||
});
|
||||
|
||||
it('loads and renders branches info', async () => {
|
||||
loadBranches(el);
|
||||
await waitForPromises();
|
||||
|
||||
expect(el.innerHTML).toBe(`<div class="commit-info branches">${mockBranchesRes}</div>`);
|
||||
});
|
||||
|
||||
it('does not load when no container is provided', async () => {
|
||||
loadBranches(null);
|
||||
await waitForPromises();
|
||||
|
||||
expect(mock.history.get).toHaveLength(0);
|
||||
});
|
||||
|
||||
describe('when braches request returns unsafe content', () => {
|
||||
beforeEach(() => {
|
||||
mock
|
||||
.onGet(mockCommitPath)
|
||||
.reply(200, '<a onload="alert(\'xss!\');" href="/-/commits/master">master</a>');
|
||||
});
|
||||
|
||||
it('displays sanitized html', async () => {
|
||||
loadBranches(el);
|
||||
await waitForPromises();
|
||||
|
||||
expect(el.innerHTML).toBe(
|
||||
'<div class="commit-info branches"><a href="/-/commits/master">master</a></div>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when braches request fails', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(mockCommitPath).reply(500, 'Error!');
|
||||
});
|
||||
|
||||
it('attempts to load and renders an error', async () => {
|
||||
loadBranches(el);
|
||||
await waitForPromises();
|
||||
|
||||
expect(el.innerHTML).toBe(
|
||||
'<div class="commit-info branches">Failed to load branches. Please try again.</div>',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,5 +1,4 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import EditFormButtons from '~/sidebar/components/confidential/edit_form_buttons.vue';
|
||||
import eventHub from '~/sidebar/event_hub';
|
||||
|
@ -56,11 +55,11 @@ describe('Edit Form Buttons', () => {
|
|||
});
|
||||
|
||||
it('disables the toggle button', () => {
|
||||
expect(findConfidentialToggle().attributes('disabled')).toBe('disabled');
|
||||
expect(findConfidentialToggle().props('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
it('finds the GlLoadingIcon', () => {
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
it('sets loading on the toggle button', () => {
|
||||
expect(findConfidentialToggle().props('loading')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -99,7 +98,7 @@ describe('Edit Form Buttons', () => {
|
|||
describe('when succeeds', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ data: { isLoading: false }, props: { confidential: true } });
|
||||
findConfidentialToggle().trigger('click');
|
||||
findConfidentialToggle().vm.$emit('click', new Event('click'));
|
||||
});
|
||||
|
||||
it('dispatches the correct action', () => {
|
||||
|
@ -109,9 +108,9 @@ describe('Edit Form Buttons', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('resets loading', () => {
|
||||
it('resets loading on the toggle button', () => {
|
||||
return waitForPromises().then(() => {
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
|
||||
expect(findConfidentialToggle().props('loading')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -135,7 +134,7 @@ describe('Edit Form Buttons', () => {
|
|||
props: { confidential: true },
|
||||
resolved: false,
|
||||
});
|
||||
findConfidentialToggle().trigger('click');
|
||||
findConfidentialToggle().vm.$emit('click', new Event('click'));
|
||||
});
|
||||
|
||||
it('calls flash with the correct message', () => {
|
||||
|
|
|
@ -101,8 +101,6 @@ describe('ReadyToMerge', () => {
|
|||
expect(vm.isMakingRequest).toBeFalsy();
|
||||
expect(vm.isMergingImmediately).toBeFalsy();
|
||||
expect(vm.commitMessage).toBe(vm.mr.commitMessage);
|
||||
expect(vm.successSvg).toBeDefined();
|
||||
expect(vm.warningSvg).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ RSpec.describe Gitlab::Git::ObjectPool do
|
|||
|
||||
describe '#create' do
|
||||
before do
|
||||
subject.create
|
||||
subject.create # rubocop:disable Rails/SaveBang
|
||||
end
|
||||
|
||||
context "when the pool doesn't exist yet" do
|
||||
|
@ -31,7 +31,7 @@ RSpec.describe Gitlab::Git::ObjectPool do
|
|||
context 'when the pool already exists' do
|
||||
it 'raises an FailedPrecondition' do
|
||||
expect do
|
||||
subject.create
|
||||
subject.create # rubocop:disable Rails/SaveBang
|
||||
end.to raise_error(GRPC::FailedPrecondition)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ RSpec.describe Gitlab::Git::RemoteMirror do
|
|||
.to receive(:update_remote_mirror)
|
||||
.with(ref_name, ['master'], ssh_key: 'KEY', known_hosts: 'KNOWN HOSTS', keep_divergent_refs: true)
|
||||
|
||||
remote_mirror.update
|
||||
remote_mirror.update # rubocop:disable Rails/SaveBang
|
||||
end
|
||||
|
||||
it 'wraps gitaly errors' do
|
||||
|
@ -24,7 +24,7 @@ RSpec.describe Gitlab::Git::RemoteMirror do
|
|||
.to receive(:update_remote_mirror)
|
||||
.and_raise(StandardError)
|
||||
|
||||
expect { remote_mirror.update }.to raise_error(StandardError)
|
||||
expect { remote_mirror.update }.to raise_error(StandardError) # rubocop:disable Rails/SaveBang
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2079,7 +2079,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
|
|||
let(:object_pool_rugged) { Rugged::Repository.new(object_pool_path) }
|
||||
|
||||
before do
|
||||
object_pool.create
|
||||
object_pool.create # rubocop:disable Rails/SaveBang
|
||||
end
|
||||
|
||||
it 'does not raise an error when disconnecting a non-linked repository' do
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require 'json'
|
||||
|
||||
RSpec.describe Gitlab::Webpack::Manifest do
|
||||
let(:manifest) do
|
||||
<<-EOF
|
||||
{
|
||||
"errors": [],
|
||||
"assetsByChunkName": {
|
||||
"entry1": [ "entry1.js", "entry1-a.js" ],
|
||||
"entry2": "entry2.js"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
end
|
||||
|
||||
shared_examples_for "a valid manifest" do
|
||||
it "returns single entry asset paths from the manifest" do
|
||||
expect(Gitlab::Webpack::Manifest.asset_paths("entry2")).to eq(["/public_path/entry2.js"])
|
||||
end
|
||||
|
||||
it "returns multiple entry asset paths from the manifest" do
|
||||
expect(Gitlab::Webpack::Manifest.asset_paths("entry1")).to eq(["/public_path/entry1.js", "/public_path/entry1-a.js"])
|
||||
end
|
||||
|
||||
it "errors on a missing entry point" do
|
||||
expect { Gitlab::Webpack::Manifest.asset_paths("herp") }.to raise_error(Gitlab::Webpack::Manifest::AssetMissingError)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
# Test that config variables work while we're here
|
||||
::Rails.configuration.webpack.dev_server.host = 'hostname'
|
||||
::Rails.configuration.webpack.dev_server.port = 2000
|
||||
::Rails.configuration.webpack.manifest_filename = "my_manifest.json"
|
||||
::Rails.configuration.webpack.public_path = "public_path"
|
||||
::Rails.configuration.webpack.output_dir = "manifest_output"
|
||||
end
|
||||
|
||||
context "with dev server enabled" do
|
||||
before do
|
||||
::Rails.configuration.webpack.dev_server.enabled = true
|
||||
|
||||
stub_request(:get, "http://hostname:2000/public_path/my_manifest.json").to_return(body: manifest, status: 200)
|
||||
end
|
||||
|
||||
describe ".asset_paths" do
|
||||
it_behaves_like "a valid manifest"
|
||||
|
||||
it "errors if we can't find the manifest" do
|
||||
::Rails.configuration.webpack.manifest_filename = "broken.json"
|
||||
stub_request(:get, "http://hostname:2000/public_path/broken.json").to_raise(SocketError)
|
||||
|
||||
expect { Gitlab::Webpack::Manifest.asset_paths("entry1") }.to raise_error(Gitlab::Webpack::Manifest::ManifestLoadError)
|
||||
end
|
||||
|
||||
describe "webpack errors" do
|
||||
context "when webpack has 'Module build failed' errors in its manifest" do
|
||||
it "errors" do
|
||||
error_manifest = Gitlab::Json.parse(manifest).merge("errors" => [
|
||||
"somethingModule build failed something",
|
||||
"I am an error"
|
||||
]).to_json
|
||||
stub_request(:get, "http://hostname:2000/public_path/my_manifest.json").to_return(body: error_manifest, status: 200)
|
||||
|
||||
expect { Gitlab::Webpack::Manifest.asset_paths("entry1") }.to raise_error(Gitlab::Webpack::Manifest::WebpackError)
|
||||
end
|
||||
end
|
||||
|
||||
context "when webpack does not have 'Module build failed' errors in its manifest" do
|
||||
it "does not error" do
|
||||
error_manifest = Gitlab::Json.parse(manifest).merge("errors" => ["something went wrong"]).to_json
|
||||
stub_request(:get, "http://hostname:2000/public_path/my_manifest.json").to_return(body: error_manifest, status: 200)
|
||||
|
||||
expect { Gitlab::Webpack::Manifest.asset_paths("entry1") }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
it "does not error if errors is present but empty" do
|
||||
error_manifest = Gitlab::Json.parse(manifest).merge("errors" => []).to_json
|
||||
stub_request(:get, "http://hostname:2000/public_path/my_manifest.json").to_return(body: error_manifest, status: 200)
|
||||
expect { Gitlab::Webpack::Manifest.asset_paths("entry1") }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with dev server disabled" do
|
||||
before do
|
||||
::Rails.configuration.webpack.dev_server.enabled = false
|
||||
allow(File).to receive(:read).with(::Rails.root.join("manifest_output/my_manifest.json")).and_return(manifest)
|
||||
end
|
||||
|
||||
describe ".asset_paths" do
|
||||
it_behaves_like "a valid manifest"
|
||||
|
||||
it "errors if we can't find the manifest" do
|
||||
::Rails.configuration.webpack.manifest_filename = "broken.json"
|
||||
allow(File).to receive(:read).with(::Rails.root.join("manifest_output/broken.json")).and_raise(Errno::ENOENT)
|
||||
expect { Gitlab::Webpack::Manifest.asset_paths("entry1") }.to raise_error(Gitlab::Webpack::Manifest::ManifestLoadError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -123,6 +123,10 @@ RSpec.configure do |config|
|
|||
port: session.server.port,
|
||||
protocol: 'http')
|
||||
|
||||
# CSRF protection is disabled by default. We only enable this for JS specs because some forms
|
||||
# require Javascript to set the CSRF token.
|
||||
allow_any_instance_of(ActionController::Base).to receive(:protect_against_forgery?).and_return(true)
|
||||
|
||||
# reset window size between tests
|
||||
unless session.current_window.size == CAPYBARA_WINDOW_SIZE
|
||||
begin
|
||||
|
|
Loading…
Reference in New Issue