summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-12 21:09:45 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-12 21:09:45 +0000
commitdd4bee69b7d55620f7dc9db8c36b478bd4959755 (patch)
tree78ba4c486ad8aa2d5effaccf23241ffb6c6dde26
parentce8a0b90849ac5d1895e741c023432930f24d724 (diff)
downloadgitlab-ce-dd4bee69b7d55620f7dc9db8c36b478bd4959755.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/CODEOWNERS27
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue17
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js1
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue23
-rw-r--r--app/assets/javascripts/ide/index.js1
-rw-r--r--app/assets/javascripts/ide/stores/state.js1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue4
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js4
-rw-r--r--app/controllers/concerns/clientside_preview_csp.rb17
-rw-r--r--app/controllers/ide_controller.rb1
-rw-r--r--app/helpers/blob_helper.rb4
-rw-r--r--app/helpers/ide_helper.rb5
-rw-r--r--app/models/application_setting_implementation.rb6
-rw-r--r--app/models/wiki_page.rb2
-rw-r--r--app/views/projects/blob/_editor.html.haml3
-rw-r--r--app/views/projects/blob/new.html.haml3
-rw-r--r--changelogs/unreleased/10526-smartcard_support_different_hostname.yml5
-rw-r--r--changelogs/unreleased/207623-fix-code-search-pagination.yml5
-rw-r--r--changelogs/unreleased/209761-fix-wiki-directories-with-hyphens.yml5
-rw-r--r--changelogs/unreleased/27144-gitlab-hosted-codesandbox.yml5
-rw-r--r--config/gitlab.yml.example4
-rw-r--r--config/initializers/1_settings.rb1
-rw-r--r--package.json4
-rwxr-xr-xscripts/lint-doc.sh29
-rwxr-xr-xscripts/security-harness6
-rw-r--r--spec/features/ide/clientside_preview_csp_spec.rb35
-rw-r--r--spec/features/ide/static_object_external_storage_csp_spec.rb2
-rw-r--r--spec/features/projects/sourcegraph_csp_spec.rb2
-rw-r--r--spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js36
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js55
-rw-r--r--spec/models/wiki_page_spec.rb50
-rw-r--r--spec/support/shared_examples/csp.rb32
-rw-r--r--yarn.lock18
33 files changed, 318 insertions, 95 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index fa87b981f5d..21a376c4885 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -10,17 +10,24 @@
*.md @gl-docsteam
# Frontend maintainers should see everything in `app/assets/`
-app/assets/ @gitlab-org/maintainers/frontend
*.scss @annabeldunstone @gitlab-org/maintainers/frontend
-/scripts/frontend/ @gitlab-org/maintainers/frontend
+*.js @gitlab-org/maintainers/frontend
+/app/assets/ @gitlab-org/maintainers/frontend
+/ee/app/assets/ @gitlab-org/maintainers/frontend
+/spec/javascripts/ @gitlab-org/maintainers/frontend
+/ee/spec/javascripts/ @gitlab-org/maintainers/frontend
+/spec/frontend/ @gitlab-org/maintainers/frontend
+/ee/spec/frontend/ @gitlab-org/maintainers/frontend
# Database maintainers should review changes in `db/`
-db/ @gitlab-org/maintainers/database
-lib/gitlab/background_migration/ @gitlab-org/maintainers/database
-lib/gitlab/database/ @gitlab-org/maintainers/database
-lib/gitlab/sql/ @gitlab-org/maintainers/database
-lib/gitlab/github_import/ @gitlab-org/maintainers/database
+/db/ @gitlab-org/maintainers/database
/ee/db/ @gitlab-org/maintainers/database
+/lib/gitlab/background_migration/ @gitlab-org/maintainers/database
+/ee/lib/ee/gitlab/background_migration/ @gitlab-org/maintainers/database
+/lib/gitlab/database/ @gitlab-org/maintainers/database
+/ee/lib/gitlab/database/ @gitlab-org/maintainers/database
+/lib/gitlab/sql/ @gitlab-org/maintainers/database
+/lib/gitlab/github_import/ @gitlab-org/maintainers/database
/app/finders/ @gitlab-org/maintainers/database
/ee/app/finders/ @gitlab-org/maintainers/database
@@ -40,14 +47,14 @@ lib/gitlab/github_import/ @gitlab-org/maintainers/database
# Engineering Productivity owned files
/.gitlab-ci.yml @gl-quality/eng-prod
/.gitlab/ci/ @gl-quality/eng-prod
+/.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam
+/.gitlab/ci/releases.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/delivery
/.gitlab/CODEOWNERS @gl-quality/eng-prod
Dangerfile @gl-quality/eng-prod
/danger/ @gl-quality/eng-prod
/lib/gitlab/danger/ @gl-quality/eng-prod
/scripts/ @gl-quality/eng-prod
-
-# Delivery owner files
-/.gitlab/ci/releases.gitlab-ci.yml @gitlab-org/delivery
+/scripts/frontend/ @gl-quality/eng-prod @gitlab-org/maintainers/frontend
# Telemetry owner files
/ee/lib/gitlab/usage_data_counters/ @gitlab-org/growth/telemetry
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
index d304ae7dbf6..7f0c232eea8 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
@@ -4,6 +4,9 @@ import Cookies from 'js-cookie';
import { parseBoolean, scrollToElement } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { glEmojiTag } from '~/emoji';
+import Tracking from '~/tracking';
+
+const trackingMixin = Tracking.mixin();
const popoverStates = {
suggest_gitlab_ci_yml: {
@@ -27,6 +30,7 @@ export default {
GlIcon,
GlButton,
},
+ mixins: [trackingMixin],
props: {
target: {
type: String,
@@ -40,10 +44,18 @@ export default {
type: String,
required: true,
},
+ humanAccess: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
popoverDismissed: parseBoolean(Cookies.get(this.dismissKey)),
+ tracking: {
+ label: this.trackLabel,
+ property: this.humanAccess,
+ },
};
},
computed: {
@@ -60,12 +72,17 @@ export default {
mounted() {
if (this.trackLabel === 'suggest_commit_first_project_gitlab_ci_yml' && !this.popoverDismissed)
scrollToElement(document.querySelector(this.target));
+
+ this.trackOnShow();
},
methods: {
onDismiss() {
this.popoverDismissed = true;
Cookies.set(this.dismissKey, this.popoverDismissed, { expires: 365 });
},
+ trackOnShow() {
+ if (!this.popoverDismissed) this.track();
+ },
},
};
</script>
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
index 2cc342fb381..3b67b3dd259 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
@@ -10,6 +10,7 @@ export default el =>
target: el.dataset.target,
trackLabel: el.dataset.trackLabel,
dismissKey: el.dataset.dismissKey,
+ humanAccess: el.dataset.humanAccess,
},
});
},
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index beb179d0411..aa8d932da6e 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -21,7 +21,7 @@ export default {
};
},
computed: {
- ...mapState(['entries', 'promotionSvgPath', 'links']),
+ ...mapState(['entries', 'promotionSvgPath', 'links', 'codesandboxBundlerUrl']),
...mapGetters(['packageJson', 'currentProject']),
normalizedEntries() {
return Object.keys(this.entries).reduce((acc, path) => {
@@ -106,12 +106,7 @@ export default {
return this.loadFileContent(this.mainEntry)
.then(() => this.$nextTick())
.then(() => {
- this.initManager('#ide-preview', this.sandboxOpts, {
- fileResolver: {
- isFile: p => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
- readFile: p => this.loadFileContent(createPathWithExt(p)).then(content => content),
- },
- });
+ this.initManager();
this.listener = listen(e => {
switch (e.type) {
@@ -139,8 +134,18 @@ export default {
this.manager.updatePreview(this.sandboxOpts);
}, 250);
},
- initManager(el, opts, resolver) {
- this.manager = new Manager(el, opts, resolver);
+ initManager() {
+ const { codesandboxBundlerUrl: bundlerURL } = this;
+
+ const settings = {
+ fileResolver: {
+ isFile: p => Promise.resolve(Boolean(this.entries[createPathWithExt(p)])),
+ readFile: p => this.loadFileContent(createPathWithExt(p)).then(content => content),
+ },
+ ...(bundlerURL ? { bundlerURL } : {}),
+ };
+
+ this.manager = new Manager('#ide-preview', this.sandboxOpts, settings);
},
},
};
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index a3450522697..9e9d9df8f82 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -53,6 +53,7 @@ export function initIde(el, options = {}) {
clientsidePreviewEnabled: parseBoolean(el.dataset.clientsidePreviewEnabled),
renderWhitespaceInCode: parseBoolean(el.dataset.renderWhitespaceInCode),
editorTheme: window.gon?.user_color_scheme || DEFAULT_THEME,
+ codesandboxBundlerUrl: el.dataset.codesandboxBundlerUrl,
});
},
methods: {
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index a714562c5b2..0fd6a448283 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -34,4 +34,5 @@ export default () => ({
clientsidePreviewEnabled: false,
renderWhitespaceInCode: false,
editorTheme: DEFAULT_THEME,
+ codesandboxBundlerUrl: null,
});
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index 018b30d2a67..05ad7b4ea3e 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import _ from 'underscore';
+import { intersection } from 'lodash';
import '~/smart_interval';
@@ -38,7 +38,7 @@ export default {
} else {
changedCommands = [];
}
- if (changedCommands && _.intersection(subscribedCommands, changedCommands).length) {
+ if (changedCommands && intersection(subscribedCommands, changedCommands).length) {
this.mediator.fetch();
}
},
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index 66d1fed7d31..2a61f7b5c05 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import '~/gl_dropdown';
-import _ from 'underscore';
+import { escape as esc } from 'lodash';
import { __ } from '~/locale';
function isValidProjectId(id) {
@@ -49,7 +49,7 @@ class SidebarMoveIssue {
renderRow: project => `
<li>
<a href="#" class="js-move-issue-dropdown-item">
- ${_.escape(project.name_with_namespace)}
+ ${esc(project.name_with_namespace)}
</a>
</li>
`,
diff --git a/app/controllers/concerns/clientside_preview_csp.rb b/app/controllers/concerns/clientside_preview_csp.rb
new file mode 100644
index 00000000000..6892c441b67
--- /dev/null
+++ b/app/controllers/concerns/clientside_preview_csp.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module ClientsidePreviewCSP
+ extend ActiveSupport::Concern
+
+ included do
+ content_security_policy do |p|
+ next if p.directives.blank?
+ next unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
+
+ default_frame_src = p.directives['frame-src'] || p.directives['default-src']
+ frame_src_values = Array.wrap(default_frame_src) | [Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url].compact
+
+ p.frame_src(*frame_src_values)
+ end
+ end
+end
diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb
index d94f18beb5d..8a838db04f9 100644
--- a/app/controllers/ide_controller.rb
+++ b/app/controllers/ide_controller.rb
@@ -3,6 +3,7 @@
class IdeController < ApplicationController
layout 'fullscreen'
+ include ClientsidePreviewCSP
include StaticObjectExternalStorageCSP
def index
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 9c09ddafbf1..cc5ae32856a 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -353,4 +353,8 @@ module BlobHelper
def suggest_pipeline_commit_cookie_name
"suggest_gitlab_ci_yml_commit_#{@project.id}"
end
+
+ def human_access
+ @project.team.human_max_access(current_user&.id).try(:downcase)
+ end
end
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index e4d0e605254..d6145493ba6 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -10,8 +10,9 @@ module IdeHelper
"promotion-svg-path": image_path('illustrations/web-ide_promotion.svg'),
"ci-help-page-path" => help_page_path('ci/quick_start/README'),
"web-ide-help-page-path" => help_page_path('user/project/web_ide/index.html'),
- "clientside-preview-enabled": Gitlab::CurrentSettings.current_application_settings.web_ide_clientside_preview_enabled.to_s,
- "render-whitespace-in-code": current_user.render_whitespace_in_code.to_s
+ "clientside-preview-enabled": Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?.to_s,
+ "render-whitespace-in-code": current_user.render_whitespace_in_code.to_s,
+ "codesandbox-bundler-url": Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url
}
end
end
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 3f2106c80bf..d1a919fc01a 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -351,6 +351,12 @@ module ApplicationSettingImplementation
static_objects_external_storage_url.present?
end
+ # This will eventually be configurable
+ # https://gitlab.com/gitlab-org/gitlab/issues/208161
+ def web_ide_clientside_preview_bundler_url
+ 'https://sandbox-prod.gitlab-static.net'
+ end
+
private
def separate_whitelists(string_array)
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index c6481bdbb6c..5436f034657 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -257,7 +257,7 @@ class WikiPage
def title_changed?
if persisted?
old_title, old_dir = wiki.page_title_and_dir(self.class.unhyphenize(@page.url_path))
- new_title, new_dir = wiki.page_title_and_dir(title)
+ new_title, new_dir = wiki.page_title_and_dir(self.class.unhyphenize(title))
new_title != old_title || (title.include?('/') && new_dir != old_dir)
else
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index cd8407608a3..51b0b2722d1 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -23,7 +23,8 @@
.js-suggest-gitlab-ci-yml{ data: { toggle: 'popover',
target: '#gitlab-ci-yml-selector',
track_label: 'suggest_gitlab_ci_yml',
- dismiss_key: "suggest_gitlab_ci_yml_#{@project.id}" } }
+ dismiss_key: "suggest_gitlab_ci_yml_#{@project.id}",
+ human_access: human_access } }
.file-buttons
- if is_markdown
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index bf7900018c3..1afbe1fe24e 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -17,4 +17,5 @@
.js-suggest-gitlab-ci-yml-commit-changes{ data: { toggle: 'popover',
target: '#commit-changes',
track_label: 'suggest_commit_first_project_gitlab_ci_yml',
- dismiss_key: "suggest_commit_first_project_gitlab_ci_yml_#{@project.id}" } }
+ dismiss_key: "suggest_commit_first_project_gitlab_ci_yml_#{@project.id}",
+ human_access: human_access } }
diff --git a/changelogs/unreleased/10526-smartcard_support_different_hostname.yml b/changelogs/unreleased/10526-smartcard_support_different_hostname.yml
new file mode 100644
index 00000000000..6990449d171
--- /dev/null
+++ b/changelogs/unreleased/10526-smartcard_support_different_hostname.yml
@@ -0,0 +1,5 @@
+---
+title: Make hostname configurable for smartcard authentication
+merge_request: 26411
+author:
+type: added
diff --git a/changelogs/unreleased/207623-fix-code-search-pagination.yml b/changelogs/unreleased/207623-fix-code-search-pagination.yml
new file mode 100644
index 00000000000..7cb90f0bef4
--- /dev/null
+++ b/changelogs/unreleased/207623-fix-code-search-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Fix code search pagination on a custom branch
+merge_request: 25984
+author:
+type: fixed
diff --git a/changelogs/unreleased/209761-fix-wiki-directories-with-hyphens.yml b/changelogs/unreleased/209761-fix-wiki-directories-with-hyphens.yml
new file mode 100644
index 00000000000..3a18143ba7a
--- /dev/null
+++ b/changelogs/unreleased/209761-fix-wiki-directories-with-hyphens.yml
@@ -0,0 +1,5 @@
+---
+title: Fix WikiPage#title_changed for paths with spaces
+merge_request: 27087
+author:
+type: fixed
diff --git a/changelogs/unreleased/27144-gitlab-hosted-codesandbox.yml b/changelogs/unreleased/27144-gitlab-hosted-codesandbox.yml
new file mode 100644
index 00000000000..bb7e011f94c
--- /dev/null
+++ b/changelogs/unreleased/27144-gitlab-hosted-codesandbox.yml
@@ -0,0 +1,5 @@
+---
+title: Update Web IDE clientside preview bundler to use GitLab managed server
+merge_request: 21520
+author:
+type: changed
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 760688d8088..81085d4641e 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -752,7 +752,9 @@ production: &base
# Path to a file containing a CA certificate
ca_file: '/etc/ssl/certs/CA.pem'
- # Port where the client side certificate is requested by the webserver (NGINX/Apache)
+ # Host and port where the client side certificate is requested by the
+ # webserver (NGINX/Apache)
+ # client_certificate_required_host: smartcard.gitlab.example.com
# client_certificate_required_port: 3444
# Browser session with smartcard sign-in is required for Git access
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index f22ddc7f081..1b368346cfa 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -77,6 +77,7 @@ end
Gitlab.ee do
Settings['smartcard'] ||= Settingslogic.new({})
Settings.smartcard['enabled'] = false if Settings.smartcard['enabled'].nil?
+ Settings.smartcard['client_certificate_required_host'] = Settings.gitlab['host'] if Settings.smartcard['client_certificate_required_host'].nil?
Settings.smartcard['client_certificate_required_port'] = 3444 if Settings.smartcard['client_certificate_required_port'].nil?
Settings.smartcard['required_for_git_access'] = false if Settings.smartcard['required_for_git_access'].nil?
Settings.smartcard['san_extensions'] = false if Settings.smartcard['san_extensions'].nil?
diff --git a/package.json b/package.json
index f8f00b67f6b..fa359867ea2 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
"chart.js": "2.7.2",
"classlist-polyfill": "^1.2.0",
"clipboard": "^1.7.1",
- "codesandbox-api": "^0.0.20",
+ "codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^3.0.1",
"copy-webpack-plugin": "^5.0.5",
"core-js": "^3.6.4",
@@ -110,7 +110,7 @@
"raw-loader": "^4.0.0",
"sanitize-html": "^1.22.0",
"select2": "3.5.2-browserify",
- "smooshpack": "^0.0.54",
+ "smooshpack": "^0.0.62",
"sortablejs": "^1.10.2",
"sql.js": "^0.4.0",
"stickyfilljs": "^2.1.0",
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index d9440a5f052..d9de48fd0c0 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -2,36 +2,41 @@
cd "$(dirname "$0")/.."
echo "=> Linting documents at path $(pwd) as $(whoami)..."
+echo
+ERRORCODE=0
# Use long options (e.g. --header instead of -H) for curl examples in documentation.
echo '=> Checking for cURL short options...'
+echo
grep --extended-regexp --recursive --color=auto 'curl (.+ )?-[^- ].*' doc/ >/dev/null 2>&1
if [ $? -eq 0 ]
then
echo '✖ ERROR: Short options for curl should not be used in documentation!
Use long options (e.g., --header instead of -H):' >&2
grep --extended-regexp --recursive --color=auto 'curl (.+ )?-[^- ].*' doc/
- exit 1
+ ((ERRORCODE++))
fi
# Ensure that the CHANGELOG.md does not contain duplicate versions
DUPLICATE_CHANGELOG_VERSIONS=$(grep --extended-regexp '^## .+' CHANGELOG.md | sed -E 's| \(.+\)||' | sort -r | uniq -d)
echo '=> Checking for CHANGELOG.md duplicate entries...'
+echo
if [ "${DUPLICATE_CHANGELOG_VERSIONS}" != "" ]
then
echo '✖ ERROR: Duplicate versions in CHANGELOG.md:' >&2
echo "${DUPLICATE_CHANGELOG_VERSIONS}" >&2
- exit 1
+ ((ERRORCODE++))
fi
# Make sure no files in doc/ are executable
EXEC_PERM_COUNT=$(find doc/ -type f -perm 755 | wc -l)
echo "=> Checking $(pwd)/doc for executable permissions..."
+echo
if [ "${EXEC_PERM_COUNT}" -ne 0 ]
then
echo '✖ ERROR: Executable permissions should not be used in documentation! Use `chmod 644` to the files in question:' >&2
find doc/ -type f -perm 755
- exit 1
+ ((ERRORCODE++))
fi
# Do not use 'README.md', instead use 'index.md'
@@ -39,13 +44,14 @@ fi
NUMBER_READMES=46
FIND_READMES=$(find doc/ -name "README.md" | wc -l)
echo '=> Checking for new README.md files...'
+echo
if [ ${FIND_READMES} -ne $NUMBER_READMES ]
then
echo
echo ' ✖ ERROR: New README.md file(s) detected, prefer index.md over README.md.' >&2
echo ' https://docs.gitlab.com/ee/development/documentation/styleguide.html#work-with-directories-and-files'
echo
- exit 1
+ ((ERRORCODE++))
fi
MD_DOC_PATH=${MD_DOC_PATH:-doc}
@@ -64,7 +70,7 @@ function run_locally_or_in_docker() {
echo
echo " ✖ ERROR: '${cmd}' not found. Install '${cmd}' or Docker to proceed." >&2
echo
- exit 1
+ ((ERRORCODE++))
fi
if [ $? -ne 0 ]
@@ -72,15 +78,22 @@ function run_locally_or_in_docker() {
echo
echo " ✖ ERROR: '${cmd}' failed with errors." >&2
echo
- exit 1
+ ((ERRORCODE++))
fi
}
echo '=> Linting markdown style...'
+echo
run_locally_or_in_docker 'markdownlint' "--config .markdownlint.json ${MD_DOC_PATH}"
echo '=> Linting prose...'
run_locally_or_in_docker 'vale' "--minAlertLevel error ${MD_DOC_PATH}"
-echo "✔ Linting passed"
-exit 0
+if [ $ERRORCODE -ne 0 ]
+then
+ echo "✖ ${ERRORCODE} lint test(s) failed. Review the log carefully to see full listing."
+ exit 1
+else
+ echo "✔ Linting passed"
+ exit 0
+fi
diff --git a/scripts/security-harness b/scripts/security-harness
index a1642489fe2..a0fa57ef042 100755
--- a/scripts/security-harness
+++ b/scripts/security-harness
@@ -28,9 +28,9 @@ HOOK_DATA = <<~HOOK
if [ -e "$harness" ]
then
- if [[ ("$url" != *"dev.gitlab.org"*) && ("$url" != *"gitlab-org/security/"*) ]]
+ if [["$url" != *"gitlab-org/security/"*]]
then
- echo "Pushing to remotes other than dev.gitlab.org and gitlab.com/gitlab-org/security has been disabled!"
+ echo "Pushing to remotes other than gitlab.com/gitlab-org/security has been disabled!"
echo "Run scripts/security-harness to disable this check."
echo
@@ -58,7 +58,7 @@ def toggle
else
FileUtils.touch(harness_path)
- puts "#{SHELL_GREEN}Security harness installed -- you will only be able to push to dev.gitlab.org or gitlab.com/gitlab-org/security!#{SHELL_CLEAR}"
+ puts "#{SHELL_GREEN}Security harness installed -- you will only be able to push to gitlab.com/gitlab-org/security!#{SHELL_CLEAR}"
end
end
diff --git a/spec/features/ide/clientside_preview_csp_spec.rb b/spec/features/ide/clientside_preview_csp_spec.rb
new file mode 100644
index 00000000000..e097513def3
--- /dev/null
+++ b/spec/features/ide/clientside_preview_csp_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'IDE Clientside Preview CSP' do
+ let_it_be(:user) { create(:user) }
+
+ shared_context 'disable feature' do
+ before do
+ allow_next_instance_of(ApplicationSetting) do |instance|
+ allow(instance).to receive(:web_ide_clientside_preview_enabled?).and_return(false)
+ end
+ end
+ end
+
+ it_behaves_like 'setting CSP', 'frame-src' do
+ let(:whitelisted_url) { 'https://sandbox.gitlab-static.test' }
+ let(:extended_controller_class) { IdeController }
+
+ subject do
+ visit ide_path
+
+ response_headers['Content-Security-Policy']
+ end
+
+ before do
+ allow_next_instance_of(ApplicationSetting) do |instance|
+ allow(instance).to receive(:web_ide_clientside_preview_enabled?).and_return(true)
+ allow(instance).to receive(:web_ide_clientside_preview_bundler_url).and_return(whitelisted_url)
+ end
+
+ sign_in(user)
+ end
+ end
+end
diff --git a/spec/features/ide/static_object_external_storage_csp_spec.rb b/spec/features/ide/static_object_external_storage_csp_spec.rb
index 93c22b35786..739b3fe2471 100644
--- a/spec/features/ide/static_object_external_storage_csp_spec.rb
+++ b/spec/features/ide/static_object_external_storage_csp_spec.rb
@@ -11,7 +11,7 @@ describe 'Static Object External Storage Content Security Policy' do
end
end
- it_behaves_like 'setting CSP connect-src' do
+ it_behaves_like 'setting CSP', 'connect-src' do
let_it_be(:whitelisted_url) { 'https://static-objects.test' }
let_it_be(:extended_controller_class) { IdeController }
diff --git a/spec/features/projects/sourcegraph_csp_spec.rb b/spec/features/projects/sourcegraph_csp_spec.rb
index 385a797368c..f252d3cd027 100644
--- a/spec/features/projects/sourcegraph_csp_spec.rb
+++ b/spec/features/projects/sourcegraph_csp_spec.rb
@@ -12,7 +12,7 @@ describe 'Sourcegraph Content Security Policy' do
end
end
- it_behaves_like 'setting CSP connect-src' do
+ it_behaves_like 'setting CSP', 'connect-src' do
let_it_be(:whitelisted_url) { 'https://sourcegraph.test' }
let_it_be(:extended_controller_class) { Projects::BlobController }
diff --git a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
index 2c7891e4b1a..43e92bdca5f 100644
--- a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
+++ b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import Popover from '~/blob/suggest_gitlab_ci_yml/components/popover.vue';
import Cookies from 'js-cookie';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import * as utils from '~/lib/utils/common_utils';
jest.mock('~/lib/utils/common_utils', () => ({
@@ -11,6 +12,8 @@ jest.mock('~/lib/utils/common_utils', () => ({
const target = 'gitlab-ci-yml-selector';
const dismissKey = 'suggest_gitlab_ci_yml_99';
const defaultTrackLabel = 'suggest_gitlab_ci_yml';
+const commitTrackLabel = 'suggest_commit_first_project_gitlab_ci_yml';
+const humanAccess = 'owner';
describe('Suggest gitlab-ci.yml Popover', () => {
let wrapper;
@@ -21,6 +24,7 @@ describe('Suggest gitlab-ci.yml Popover', () => {
target,
trackLabel,
dismissKey,
+ humanAccess,
},
});
}
@@ -50,15 +54,43 @@ describe('Suggest gitlab-ci.yml Popover', () => {
expect(wrapper.vm.popoverDismissed).toEqual(true);
});
- beforeEach(() => {
+ afterEach(() => {
Cookies.remove(dismissKey);
});
});
+ describe('tracking', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ createWrapper(commitTrackLabel);
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('sends a tracking event with the expected properties for the popover being viewed', () => {
+ const expectedCategory = undefined;
+ const expectedAction = undefined;
+ const expectedLabel = 'suggest_commit_first_project_gitlab_ci_yml';
+ const expectedProperty = 'owner';
+
+ document.body.dataset.page = 'projects:blob:new';
+
+ wrapper.vm.trackOnShow();
+
+ expect(trackingSpy).toHaveBeenCalledWith(expectedCategory, expectedAction, {
+ label: expectedLabel,
+ property: expectedProperty,
+ });
+ });
+ });
+
describe('when the popover is mounted with the trackLabel of the Confirm button popover at the bottom of the page', () => {
it('calls scrollToElement so that the Confirm button and popover will be in sight', () => {
const scrollToElementSpy = jest.spyOn(utils, 'scrollToElement');
- const commitTrackLabel = 'suggest_commit_first_project_gitlab_ci_yml';
createWrapper(commitTrackLabel);
diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js
index c7d5ea9c513..0cde6fb6060 100644
--- a/spec/frontend/ide/components/preview/clientside_spec.js
+++ b/spec/frontend/ide/components/preview/clientside_spec.js
@@ -16,6 +16,17 @@ const dummyPackageJson = () => ({
main: 'index.js',
}),
});
+const expectedSandpackOptions = () => ({
+ files: {},
+ entry: '/index.js',
+ showOpenInCodeSandbox: true,
+});
+const expectedSandpackSettings = () => ({
+ fileResolver: {
+ isFile: expect.any(Function),
+ readFile: expect.any(Function),
+ },
+});
describe('IDE clientside preview', () => {
let wrapper;
@@ -87,6 +98,46 @@ describe('IDE clientside preview', () => {
it('creates sandpack manager', () => {
expect(smooshpack.Manager).toHaveBeenCalledWith(
'#ide-preview',
+ expectedSandpackOptions(),
+ expectedSandpackSettings(),
+ );
+ });
+
+ it('pings usage', () => {
+ expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('with codesandboxBundlerUrl', () => {
+ const TEST_BUNDLER_URL = 'https://test.gitlab-static.test';
+
+ beforeEach(() => {
+ createComponent({
+ getters: { packageJson: dummyPackageJson },
+ state: { codesandboxBundlerUrl: TEST_BUNDLER_URL },
+ });
+
+ return waitForCalls();
+ });
+
+ it('creates sandpack manager with bundlerURL', () => {
+ expect(smooshpack.Manager).toHaveBeenCalledWith('#ide-preview', expectedSandpackOptions(), {
+ ...expectedSandpackSettings(),
+ bundlerURL: TEST_BUNDLER_URL,
+ });
+ });
+ });
+
+ describe('with codesandboxBundlerURL', () => {
+ beforeEach(() => {
+ createComponent({ getters: { packageJson: dummyPackageJson } });
+
+ return waitForCalls();
+ });
+
+ it('creates sandpack manager', () => {
+ expect(smooshpack.Manager).toHaveBeenCalledWith(
+ '#ide-preview',
{
files: {},
entry: '/index.js',
@@ -100,10 +151,6 @@ describe('IDE clientside preview', () => {
},
);
});
-
- it('pings usage', () => {
- expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(1);
- });
});
describe('computed', () => {
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index dd6690b4d1e..42a7d567613 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -480,29 +480,39 @@ describe WikiPage do
let(:untitled_page) { described_class.new(wiki) }
let(:directory_page) do
- create_page('parent/child', 'test content')
- wiki.find_page('parent/child')
+ create_page('parent directory/child page', 'test content')
+ wiki.find_page('parent directory/child page')
end
where(:page, :title, :changed) do
- :untitled_page | nil | false
- :untitled_page | 'new title' | true
-
- :new_page | nil | true
- :new_page | 'test page' | true
- :new_page | 'new title' | true
-
- :existing_page | nil | false
- :existing_page | 'test page' | false
- :existing_page | '/test page' | false
- :existing_page | 'new title' | true
-
- :directory_page | nil | false
- :directory_page | 'parent/child' | false
- :directory_page | 'child' | false
- :directory_page | '/child' | true
- :directory_page | 'parent/other' | true
- :directory_page | 'other/child' | true
+ :untitled_page | nil | false
+ :untitled_page | 'new title' | true
+
+ :new_page | nil | true
+ :new_page | 'test page' | true
+ :new_page | 'new title' | true
+
+ :existing_page | nil | false
+ :existing_page | 'test page' | false
+ :existing_page | 'test-page' | false
+ :existing_page | '/test page' | false
+ :existing_page | '/test-page' | false
+ :existing_page | ' test page ' | true
+ :existing_page | 'new title' | true
+ :existing_page | 'new-title' | true
+
+ :directory_page | nil | false
+ :directory_page | 'parent directory/child page' | false
+ :directory_page | 'parent-directory/child page' | false
+ :directory_page | 'parent-directory/child-page' | false
+ :directory_page | 'child page' | false
+ :directory_page | 'child-page' | false
+ :directory_page | '/child page' | true
+ :directory_page | 'parent directory/other' | true
+ :directory_page | 'parent-directory/other' | true
+ :directory_page | 'parent-directory / child-page' | true
+ :directory_page | 'other directory/child page' | true
+ :directory_page | 'other-directory/child page' | true
end
with_them do
diff --git a/spec/support/shared_examples/csp.rb b/spec/support/shared_examples/csp.rb
index 10c4158522f..c4a8c7df898 100644
--- a/spec/support/shared_examples/csp.rb
+++ b/spec/support/shared_examples/csp.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'setting CSP connect-src' do
+RSpec.shared_examples 'setting CSP' do |rule_name|
let_it_be(:default_csp_values) { "'self' https://some-cdn.test" }
shared_context 'csp config' do |csp_rule|
@@ -10,7 +10,7 @@ RSpec.shared_examples 'setting CSP connect-src' do
end
expect_next_instance_of(extended_controller_class) do |controller|
- expect(controller).to receive(:current_content_security_policy).and_return(csp)
+ expect(controller).to receive(:current_content_security_policy).at_least(:once).and_return(csp)
end
end
end
@@ -23,55 +23,55 @@ RSpec.shared_examples 'setting CSP connect-src' do
end
end
- describe 'when a CSP config exists for connect-src' do
- include_context 'csp config', :connect_src
+ describe "when a CSP config exists for #{rule_name}" do
+ include_context 'csp config', rule_name.parameterize.underscore.to_sym
context 'when feature is enabled' do
- it 'appends to connect-src' do
- is_expected.to eql("connect-src #{default_csp_values} #{whitelisted_url}")
+ it "appends to #{rule_name}" do
+ is_expected.to eql("#{rule_name} #{default_csp_values} #{whitelisted_url}")
end
end
context 'when feature is disabled' do
include_context 'disable feature'
- it 'keeps original connect-src' do
- is_expected.to eql("connect-src #{default_csp_values}")
+ it "keeps original #{rule_name}" do
+ is_expected.to eql("#{rule_name} #{default_csp_values}")
end
end
end
- describe 'when a CSP config exists for default-src but not connect-src' do
+ describe "when a CSP config exists for default-src but not #{rule_name}" do
include_context 'csp config', :default_src
context 'when feature is enabled' do
- it 'uses default-src values in connect-src' do
- is_expected.to eql("default-src #{default_csp_values}; connect-src #{default_csp_values} #{whitelisted_url}")
+ it "uses default-src values in #{rule_name}" do
+ is_expected.to eql("default-src #{default_csp_values}; #{rule_name} #{default_csp_values} #{whitelisted_url}")
end
end
context 'when feature is disabled' do
include_context 'disable feature'
- it 'does not add connect-src' do
+ it "does not add #{rule_name}" do
is_expected.to eql("default-src #{default_csp_values}")
end
end
end
- describe 'when a CSP config exists for font-src but not connect-src' do
+ describe "when a CSP config exists for font-src but not #{rule_name}" do
include_context 'csp config', :font_src
context 'when feature is enabled' do
- it 'uses default-src values in connect-src' do
- is_expected.to eql("font-src #{default_csp_values}; connect-src #{whitelisted_url}")
+ it "uses default-src values in #{rule_name}" do
+ is_expected.to eql("font-src #{default_csp_values}; #{rule_name} #{whitelisted_url}")
end
end
context 'when feature is disabled' do
include_context 'disable feature'
- it 'does not add connect-src' do
+ it "does not add #{rule_name}" do
is_expected.to eql("font-src #{default_csp_values}")
end
end
diff --git a/yarn.lock b/yarn.lock
index b93a588c992..a6348615309 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2779,10 +2779,10 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-codesandbox-api@^0.0.20:
- version "0.0.20"
- resolved "https://registry.yarnpkg.com/codesandbox-api/-/codesandbox-api-0.0.20.tgz#174bcd76c9f31521175c6bceabc37da6b1fbc30b"
- integrity sha512-jhxZzAmjCKBZad8QWMeueiQVFE87igK6F2DBOEVFFJO6jgTXT8qjuzGYepr+B8bjgo/icN7bc/2xmEMBA63s2w==
+codesandbox-api@0.0.23:
+ version "0.0.23"
+ resolved "https://registry.yarnpkg.com/codesandbox-api/-/codesandbox-api-0.0.23.tgz#bf650a21b5f3c2369e03f0c19d10b4e2ba255b4f"
+ integrity sha512-fFGBkIghDkQILh7iHYlpZU5sfWncCDb92FQSFE4rR3VBcTfUsD5VZgpQi+JjZQuwWIdfl4cOhcIFrUYwshUezA==
codesandbox-import-util-types@^1.2.11:
version "1.2.11"
@@ -10334,12 +10334,12 @@ slugify@^1.3.1:
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.1.tgz#f572127e8535329fbc6c1edb74ab856b61ad7de2"
integrity sha512-6BwyhjF5tG5P8s+0DPNyJmBSBePG6iMyhjvIW5zGdA3tFik9PtK+yNkZgTeiroCRGZYgkHftFA62tGVK1EI9Kw==
-smooshpack@^0.0.54:
- version "0.0.54"
- resolved "https://registry.yarnpkg.com/smooshpack/-/smooshpack-0.0.54.tgz#9044358b85052d348b801f385678c8a0c76f2bb6"
- integrity sha512-yIwEWb17hqoW5IaWyzO6O6nxY89I5UdRoGIZy5hihoqXP9OYcoMbBTxKwS57MeXSKdNA2rtk86rlCcOgAYIgrA==
+smooshpack@^0.0.62:
+ version "0.0.62"
+ resolved "https://registry.yarnpkg.com/smooshpack/-/smooshpack-0.0.62.tgz#cb31b9f808f73de3146b050f84d044eb353b5503"
+ integrity sha512-lFuJV2f504/U78sifWy0V2FyoE/8mTgOXM4DL918ncNxAxbtu236XSCLAH3SQwXZWn0JdmRnWs/XU4+sIUVVmQ==
dependencies:
- codesandbox-api "^0.0.20"
+ codesandbox-api "0.0.23"
codesandbox-import-utils "^1.2.3"
lodash.isequal "^4.5.0"