summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-01 15:14:27 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-01 15:14:27 +0000
commitafbaf78b0d819326741a01b093bdbc4702570417 (patch)
treea16a6f2a8fcc18e60f25ac72df6ab22cfe0eae79
parent38b3003b67db3f2eadfa81fd28b13d168f665766 (diff)
downloadgitlab-ce-afbaf78b0d819326741a01b093bdbc4702570417.tar.gz
Add latest changes from gitlab-org/gitlab@13-10-stable-ee
-rw-r--r--app/assets/javascripts/emoji/components/category.vue7
-rw-r--r--app/assets/javascripts/emoji/components/picker.vue38
-rw-r--r--app/assets/javascripts/emoji/components/utils.js69
-rw-r--r--app/assets/javascripts/emoji/constants.js4
-rw-r--r--app/assets/javascripts/emoji/index.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue4
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/presenters/packages/composer/packages_presenter.rb22
-rw-r--r--changelogs/unreleased/290288-disable-composer-shas-for-v2.yml5
-rw-r--r--changelogs/unreleased/325864-fix-image-blob-rendering.yml5
-rw-r--r--data/whats_new/202102180001_13_09.yml6
-rw-r--r--data/whats_new/202103220001_13_10.yml91
-rw-r--r--doc/user/application_security/sast/index.md3
-rw-r--r--doc/user/clusters/agent/index.md46
-rw-r--r--doc/user/group/epics/epic_boards.md68
-rw-r--r--doc/user/group/epics/img/epic_board_v13_10.pngbin0 -> 147584 bytes
-rw-r--r--lib/api/composer_packages.rb22
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/composer/index_v2.json14
-rw-r--r--spec/frontend/__helpers__/test_constants.js3
-rw-r--r--spec/frontend/emoji/components/utils_spec.js56
-rw-r--r--spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js18
-rw-r--r--spec/helpers/commits_helper_spec.rb10
-rw-r--r--spec/presenters/packages/composer/packages_presenter_spec.rb17
-rw-r--r--spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb24
-rwxr-xr-x[-rw-r--r--]vendor/gitignore/C++.gitignore0
-rwxr-xr-x[-rw-r--r--]vendor/gitignore/Java.gitignore0
-rw-r--r--workhorse/config_test.go2
-rw-r--r--workhorse/main.go2
28 files changed, 457 insertions, 86 deletions
diff --git a/app/assets/javascripts/emoji/components/category.vue b/app/assets/javascripts/emoji/components/category.vue
index a11122d5403..db6ead3ff69 100644
--- a/app/assets/javascripts/emoji/components/category.vue
+++ b/app/assets/javascripts/emoji/components/category.vue
@@ -1,6 +1,6 @@
<script>
import { GlIntersectionObserver } from '@gitlab/ui';
-import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { humanize } from '~/lib/utils/text_utility';
import EmojiGroup from './emoji_group.vue';
export default {
@@ -25,7 +25,7 @@ export default {
},
computed: {
categoryTitle() {
- return capitalizeFirstCharacter(this.category);
+ return humanize(this.category);
},
},
methods: {
@@ -33,9 +33,6 @@ export default {
this.renderGroup = true;
this.$emit('appear', this.category);
},
- categoryDissappeared() {
- this.renderGroup = false;
- },
},
};
</script>
diff --git a/app/assets/javascripts/emoji/components/picker.vue b/app/assets/javascripts/emoji/components/picker.vue
index 7cd20d82329..37f3433b781 100644
--- a/app/assets/javascripts/emoji/components/picker.vue
+++ b/app/assets/javascripts/emoji/components/picker.vue
@@ -1,11 +1,12 @@
<script>
import { GlIcon, GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
+import { findLastIndex } from 'lodash';
import VirtualList from 'vue-virtual-scroll-list';
import { CATEGORY_NAMES } from '~/emoji';
-import { CATEGORY_ICON_MAP } from '../constants';
+import { CATEGORY_ICON_MAP, FREQUENTLY_USED_KEY } from '../constants';
import Category from './category.vue';
import EmojiList from './emoji_list.vue';
-import { getEmojiCategories } from './utils';
+import { addToFrequentlyUsed, getEmojiCategories, hasFrequentlyUsedEmojis } from './utils';
export default {
components: {
@@ -25,13 +26,16 @@ export default {
},
data() {
return {
- currentCategory: null,
+ currentCategory: 0,
searchValue: '',
};
},
computed: {
categoryNames() {
- return CATEGORY_NAMES.map((category) => ({
+ return CATEGORY_NAMES.filter((c) => {
+ if (c === FREQUENTLY_USED_KEY) return hasFrequentlyUsedEmojis();
+ return true;
+ }).map((category) => ({
name: category,
icon: CATEGORY_ICON_MAP[category],
}));
@@ -50,6 +54,7 @@ export default {
selectEmoji(name) {
this.$emit('click', name);
this.$refs.dropdown.hide();
+ addToFrequentlyUsed(name);
},
getBoundaryElement() {
return document.querySelector('.content-wrapper') || 'scrollParent';
@@ -58,6 +63,11 @@ export default {
this.$refs.virtualScoller.setScrollTop(0);
this.$refs.virtualScoller.forceRender();
},
+ async onScroll(event, { offset }) {
+ const categories = await getEmojiCategories();
+
+ this.currentCategory = findLastIndex(Object.values(categories), ({ top }) => offset >= top);
+ },
},
};
</script>
@@ -86,10 +96,10 @@ export default {
class="gl-display-flex gl-mx-5 gl-border-b-solid gl-border-gray-100 gl-border-b-1"
>
<button
- v-for="category in categoryNames"
+ v-for="(category, index) in categoryNames"
:key="category.name"
:class="{
- 'gl-text-black-normal! emoji-picker-category-active': category.name === currentCategory,
+ 'gl-text-black-normal! emoji-picker-category-active': index === currentCategory,
}"
type="button"
class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-fill-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab"
@@ -100,18 +110,20 @@ export default {
</div>
<emoji-list :search-value="searchValue">
<template #default="{ filteredCategories }">
- <virtual-list ref="virtualScoller" :size="258" :remain="1" :bench="2" variable>
+ <virtual-list
+ ref="virtualScoller"
+ :size="258"
+ :remain="1"
+ :bench="2"
+ variable
+ :onscroll="onScroll"
+ >
<div
v-for="(category, categoryKey) in filteredCategories"
:key="categoryKey"
:style="{ height: category.height + 'px' }"
>
- <category
- :category="categoryKey"
- :emojis="category.emojis"
- @appear="categoryAppeared"
- @click="selectEmoji"
- />
+ <category :category="categoryKey" :emojis="category.emojis" @click="selectEmoji" />
</div>
</virtual-list>
</template>
diff --git a/app/assets/javascripts/emoji/components/utils.js b/app/assets/javascripts/emoji/components/utils.js
index b95b56a1d6f..3465a8ae7e6 100644
--- a/app/assets/javascripts/emoji/components/utils.js
+++ b/app/assets/javascripts/emoji/components/utils.js
@@ -1,27 +1,68 @@
-import { chunk, memoize } from 'lodash';
+import Cookies from 'js-cookie';
+import { chunk, memoize, uniq } from 'lodash';
import { initEmojiMap, getEmojiCategoryMap } from '~/emoji';
-import { EMOJIS_PER_ROW, EMOJI_ROW_HEIGHT, CATEGORY_ROW_HEIGHT } from '../constants';
+import {
+ EMOJIS_PER_ROW,
+ EMOJI_ROW_HEIGHT,
+ CATEGORY_ROW_HEIGHT,
+ FREQUENTLY_USED_KEY,
+ FREQUENTLY_USED_COOKIE_KEY,
+} from '../constants';
export const generateCategoryHeight = (emojisLength) =>
emojisLength * EMOJI_ROW_HEIGHT + CATEGORY_ROW_HEIGHT;
+export const getFrequentlyUsedEmojis = () => {
+ const savedEmojis = Cookies.get(FREQUENTLY_USED_COOKIE_KEY);
+
+ if (!savedEmojis) return null;
+
+ const emojis = chunk(uniq(savedEmojis.split(',')), 9);
+
+ return {
+ frequently_used: {
+ emojis,
+ top: 0,
+ height: generateCategoryHeight(emojis.length),
+ },
+ };
+};
+
+export const addToFrequentlyUsed = (emoji) => {
+ const frequentlyUsedEmojis = uniq(
+ (Cookies.get(FREQUENTLY_USED_COOKIE_KEY) || '')
+ .split(',')
+ .filter((e) => e)
+ .concat(emoji),
+ );
+
+ Cookies.set(FREQUENTLY_USED_COOKIE_KEY, frequentlyUsedEmojis.join(','), { expires: 365 });
+};
+
+export const hasFrequentlyUsedEmojis = () => getFrequentlyUsedEmojis() !== null;
+
export const getEmojiCategories = memoize(async () => {
await initEmojiMap();
const categories = await getEmojiCategoryMap();
- let top = 0;
+ const frequentlyUsedEmojis = getFrequentlyUsedEmojis();
+ let top = frequentlyUsedEmojis
+ ? frequentlyUsedEmojis.frequently_used.top + frequentlyUsedEmojis.frequently_used.height
+ : 0;
return Object.freeze(
- Object.keys(categories).reduce((acc, category) => {
- const emojis = chunk(categories[category], EMOJIS_PER_ROW);
- const height = generateCategoryHeight(emojis.length);
- const newAcc = {
- ...acc,
- [category]: { emojis, height, top },
- };
- top += height;
-
- return newAcc;
- }, {}),
+ Object.keys(categories)
+ .filter((c) => c !== FREQUENTLY_USED_KEY)
+ .reduce((acc, category) => {
+ const emojis = chunk(categories[category], EMOJIS_PER_ROW);
+ const height = generateCategoryHeight(emojis.length);
+ const newAcc = {
+ ...acc,
+ [category]: { emojis, height, top },
+ };
+ top += height;
+
+ return newAcc;
+ }, frequentlyUsedEmojis || {}),
);
});
diff --git a/app/assets/javascripts/emoji/constants.js b/app/assets/javascripts/emoji/constants.js
index bf73d1ca5a9..e9f2272e759 100644
--- a/app/assets/javascripts/emoji/constants.js
+++ b/app/assets/javascripts/emoji/constants.js
@@ -1,4 +1,8 @@
+export const FREQUENTLY_USED_KEY = 'frequently_used';
+export const FREQUENTLY_USED_COOKIE_KEY = 'frequently_used_emojis';
+
export const CATEGORY_ICON_MAP = {
+ [FREQUENTLY_USED_KEY]: 'history',
activity: 'dumbbell',
people: 'smiley',
nature: 'nature',
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index d3b658a4020..7faf0fe5f08 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -2,7 +2,7 @@ import { escape, minBy } from 'lodash';
import emojiAliases from 'emojis/aliases.json';
import AccessorUtilities from '../lib/utils/accessor';
import axios from '../lib/utils/axios_utils';
-import { CATEGORY_ICON_MAP } from './constants';
+import { CATEGORY_ICON_MAP, FREQUENTLY_USED_KEY } from './constants';
let emojiMap = null;
let validEmojiNames = null;
@@ -162,6 +162,9 @@ let emojiCategoryMap;
export function getEmojiCategoryMap() {
if (!emojiCategoryMap) {
emojiCategoryMap = CATEGORY_NAMES.reduce((acc, category) => {
+ if (category === FREQUENTLY_USED_KEY) {
+ return acc;
+ }
return { ...acc, [category]: [] };
}, {});
Object.keys(emojiMap).forEach((name) => {
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
index a49eb7fd611..04ab0fd00aa 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
@@ -3,6 +3,8 @@ import { throttle } from 'lodash';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { encodeSaferUrl } from '~/lib/utils/url_utility';
+const BLOB_PREFIX = 'blob:';
+
export default {
props: {
path: {
@@ -45,7 +47,7 @@ export default {
return this.width && this.height;
},
safePath() {
- return encodeSaferUrl(this.path);
+ return this.path.startsWith(BLOB_PREFIX) ? this.path : encodeSaferUrl(this.path);
},
},
beforeDestroy() {
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 93776503dd6..42e4844cc8d 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -135,6 +135,8 @@ module CommitsHelper
end
def cherry_pick_projects_data(project)
+ return [] unless Feature.enabled?(:pick_into_project, project, default_enabled: :yaml)
+
target_projects(project).map do |project|
{
id: project.id.to_s,
diff --git a/app/presenters/packages/composer/packages_presenter.rb b/app/presenters/packages/composer/packages_presenter.rb
index 8e3f482126d..2eb9b8910a3 100644
--- a/app/presenters/packages/composer/packages_presenter.rb
+++ b/app/presenters/packages/composer/packages_presenter.rb
@@ -5,25 +5,35 @@ module Packages
class PackagesPresenter
include API::Helpers::RelatedResourcesHelpers
- def initialize(group, packages)
+ def initialize(group, packages, is_v2 = false)
@group = group
@packages = packages
+ @is_v2 = is_v2
end
def root
- v1_path = expose_path(api_v4_group___packages_composer_package_name_path({ id: @group.id, package_name: '%package%$%hash%', format: '.json' }, true))
v2_path = expose_path(api_v4_group___packages_composer_p2_package_name_path({ id: @group.id, package_name: '%package%', format: '.json' }, true))
- {
+ index = {
'packages' => [],
+ 'metadata-url' => v2_path
+ }
+
+ # if the client is composer v2 then we don't want to
+ # include the provider_sha since it is computationally expensive
+ # to compute.
+ return index if @is_v2
+
+ v1_path = expose_path(api_v4_group___packages_composer_package_name_path({ id: @group.id, package_name: '%package%$%hash%', format: '.json' }, true))
+
+ index.merge!(
'provider-includes' => {
'p/%hash%.json' => {
'sha256' => provider_sha
}
},
- 'providers-url' => v1_path,
- 'metadata-url' => v2_path
- }
+ 'providers-url' => v1_path
+ )
end
def provider
diff --git a/changelogs/unreleased/290288-disable-composer-shas-for-v2.yml b/changelogs/unreleased/290288-disable-composer-shas-for-v2.yml
new file mode 100644
index 00000000000..45838d30160
--- /dev/null
+++ b/changelogs/unreleased/290288-disable-composer-shas-for-v2.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance for composer v2 clients
+merge_request: 55169
+author:
+type: added
diff --git a/changelogs/unreleased/325864-fix-image-blob-rendering.yml b/changelogs/unreleased/325864-fix-image-blob-rendering.yml
new file mode 100644
index 00000000000..fa07c4abfc0
--- /dev/null
+++ b/changelogs/unreleased/325864-fix-image-blob-rendering.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed rendering of the image blobs
+merge_request: 57479
+author:
+type: fixed
diff --git a/data/whats_new/202102180001_13_09.yml b/data/whats_new/202102180001_13_09.yml
index 314ffc8dba3..48c8b547a0e 100644
--- a/data/whats_new/202102180001_13_09.yml
+++ b/data/whats_new/202102180001_13_09.yml
@@ -109,8 +109,10 @@
release: 13.9
- title: "Allow Deploy Keys to push to protected branches"
body: |
- When viewing a roadmap, there used to be no way to hide confidential epics from the main view. This could be frustrating if you wanted to share your roadmap with a public audience. We've updated the search bar filter to include confidentiality so you now have another layer in which you can refine your roadmap.
- stage: Plan
+ Prior to GitLab 12.0, deploy keys with write access could push commits to protected branches. Support for this was removed due to security concerns, but many users still requested it, as they used deploy keys to ensure that only users with deploy keys could push to their repositories. Removing deploy keys also eliminates the need to use a service user or machine user, which ties up a license for any team that wants to allow deploy keys to push to protected branches just for this use case.
+
+ We are excited to announce that we resolved this issue and now deploy keys can push to protected branches once more while abiding by security best practices. By moving towards an isolated permission model for deploy keys, users can now select deploy keys to link to protected branches directly from the **Settings** page on protected branches.
+ stage: Release
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
diff --git a/data/whats_new/202103220001_13_10.yml b/data/whats_new/202103220001_13_10.yml
new file mode 100644
index 00000000000..6de61ecdb06
--- /dev/null
+++ b/data/whats_new/202103220001_13_10.yml
@@ -0,0 +1,91 @@
+- title: "GitLab Runner for Red Hat OpenShift GA"
+ body: |
+ The GitLab Runner Operator is generally available in the [Red Hat OpenShift Container Platform](https://www.openshift.com/products/container-platform). To install GitLab Runner on OpenShift, you can use the [GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator), which is available from the stable channel in the OperatorHub. The Container Platform is a web console for OpenShift cluster administrators to discover and select Operators to install on their cluster. We are also developing an [Operator](https://gitlab.com/groups/gitlab-org/-/epics/3444) for GitLab, so stay tuned to future release posts for those announcements.
+ stage: Verify
+ self-managed: true
+ gitlab-com: true
+ packages: [Free, Premium, Ultimate]
+ url: https://docs.gitlab.com/runner/install/openshift.html
+ image_url: https://img.youtube.com/vi/ZNBc_QnDUu4/hqdefault.jpg
+ published_at: 2021-03-22
+ release: 13.10
+- title: "View epics on a board (MVC)"
+ body: |
+ If you work on epics in GitLab, it can be tough to visualize your epics' workflow status. Often, when drafting or writing epics, you might want to use labels (like `Open`, `Doing`, or `Done`) to keep tabs on the next steps when creating your project plan.
+
+ In this release, we took our awesome [Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html) feature and optimized it for viewing epics. You can now visualize the workflow status of your epics on an epic board by applying [labels](https://docs.gitlab.com/ee/user/project/labels.html#label-management) or [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to them.
+
+ We are releasing this early version of Epic Boards in 13.10, so we can start [gathering customer feedback](https://gitlab.com/gitlab-org/gitlab/-/issues/324677). We will follow it up with [MVC 2](https://gitlab.com/groups/gitlab-org/-/epics/5069) and [MVC 3](https://gitlab.com/groups/gitlab-org/-/epics/5079), which will achieve parity with Issue Boards. Please leave feedback about your experience in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324677).
+ stage: Plan
+ self-managed: true
+ gitlab-com: true
+ packages: [Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/user/group/epics/epic_boards.html
+ image_url: https://about.gitlab.com/images/13_10/view-epics-on-a-board-mvc-1.png
+ published_at: 2021-03-22
+ release: 13.10
+- title: "View Jira issue details in GitLab"
+ body: |
+ Users of our Jira issue list feature can now view the details of an issue directly inside of GitLab! This MVC enables developers to see the details, labels, and comments on an issue, giving them the ability to stay in GitLab while working on Jira issues.
+
+ Our goal is to empower developers to _stay inside of GitLab_ during the majority of their day, and this is now one less trip to Jira you'll have to make.
+
+ In GitLab 13.10, this feature is available if you [enable a feature flag](https://docs.gitlab.com/ee/user/project/integrations/jira.html#enable-or-disable-jira-issue-detail-view). This feature will be [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/299832) in GitLab 13.11.
+ stage: Create
+ self-managed: true
+ gitlab-com: true
+ packages: [Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/user/project/integrations/jira.html#view-a-jira-issue
+ image_url: https://about.gitlab.com/images/13_10/jira-detail-view.png
+ published_at: 2021-03-22
+ release: 13.10
+- title: "DORA4-based lead time for changes"
+ body: |
+ Measuring the efficiency of your software development lifecycle is an important step to grow DevOps adoption for any organization. In the previous milestone, we added support for [DORA4-based Deployment Frequency](https://docs.gitlab.com/ee/api/dora4_project_analytics.html). In this release, we are excited to announce the support of a new API for lead time for changes (via merge requests) on the project level. The lead time for changes gives you an indication of how long it takes for code to be committed and deployed to your production environment. Understanding and tracking this data is a great starting point in your journey to continuous improvement in your DevOps process.
+ stage: Release
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-merge-request-lead-times
+ image_url: https://about.gitlab.com/images/13_10/api.png
+ published_at: 2021-03-22
+ release: 13.10
+- title: "Create a release from an existing tag"
+ body: |
+ Previously, creating a release was supported only for new tags. In GitLab 13.10, you can now create a release by selecting an existing tag, something that will give you more flexibility when planning releases.
+ stage: Release
+ self-managed: true
+ gitlab-com: true
+ packages: [Free, Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/user/project/releases/#create-a-release
+ image_url: https://about.gitlab.com/images/13_10/exiting_tags.png
+ published_at: 2021-03-22
+ release: 13.10
+- title: "Integrate any IT alerting tool with GitLab"
+ body: |
+ Alert integrations are a critical part of your Incident Management workflows. It's difficult to manage integrations between tools, especially when several monitoring tools like Nagios, Solarwinds, etc. alert on your services. These integrations notify you and your team of incidents, so it's critical for them to be easy to set up and maintain.
+
+ In this version of GitLab, you can create multiple HTTP endpoints with unique auth tokens for each integrated monitoring tool. When you set up an HTTP endpoint with a unique auth token for each monitoring tool, your team can manage each tool separately without affecting alerts from other tools nor take down all of your alerting by resetting a single auth token!
+ stage: Monitor
+ self-managed: true
+ gitlab-com: true
+ packages: [Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/operations/incident_management/integrations.html#http-endpoints
+ image_url: https://about.gitlab.com/images/13_10/integrate_alerts.png
+ published_at: 2021-03-22
+ release: 13.10
+- title: "Merge Request test summary usability improvements"
+ body: |
+ Increasing the number of tests or custom metrics in a pipeline gives you additional confidence and information. However, increasing these to a large number has also come with a degraded visual experience of the Merge Request page. The Merge Request test summary widget has been improved so you can better differentiate between the different test jobs in the widget, making it easier to identify which job contains failed tests.
+
+ It has also been challenging to understand why a `junit.xml` file was not parsed without errors being presented. Now you can see parsing errors in the Test Summary widget, as well as the Unit Test report, to identify and resolve structural issues and see test results in GitLab.
+
+ The [Metrics Reports](https://docs.gitlab.com/ee/ci/metrics_reports.html) widget [(Premium and Ultimate)](https://about.gitlab.com/pricing/) is now sorted so new, changed, and unchanged metrics are all together, making the experience of finding metrics that have changed as part of the Merge Request more intuitive.
+ stage: Verify
+ self-managed: true
+ gitlab-com: true
+ packages: [Free, Premium, Ultimate]
+ url: https://docs.gitlab.com/ee/ci/unit_test_reports.html
+ image_url: https://about.gitlab.com/images/13_10/test_summary_ux_improvements.png
+ published_at: 2021-03-22
+ release: 13.10
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index b71cefbc7fe..fffff4efba6 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -100,8 +100,7 @@ and the [Maven wrapper](https://github.com/takari/maven-wrapper).
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4895) in GitLab 13.7.
-GitLab SAST can scan repositories that contain multiple projects. All projects must be in the same
-language.
+GitLab SAST can scan repositories that contain multiple projects.
The following analyzers have multi-project support:
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 9af339b20c6..77b9dbb1c7e 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Kubernetes Agent **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
-> - It's disabled on GitLab.com. Rolling this feature out to GitLab.com is [planned](https://gitlab.com/groups/gitlab-org/-/epics/3834).
+> - [In GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/300960), KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@@ -85,7 +85,7 @@ component, `agentk`.
Upgrade your agent installations together with GitLab upgrades. To decide which version of `agentk`to install follow:
-1. Open the [GITLAB_KAS_VERSION](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_KAS_VERSION) file from the GitLab Repository, which contains the latest `agentk` version associated with the `master` branch.
+1. Open the [`GITLAB_KAS_VERSION`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_KAS_VERSION) file from the GitLab Repository, which contains the latest `agentk` version associated with the `master` branch.
1. Change the `master` branch and select the Git tag associated with your version. For instance, you could change it to GitLab [v13.5.3-ee release](https://gitlab.com/gitlab-org/gitlab/-/blob/v13.5.3-ee/GITLAB_KAS_VERSION)
The available `agentk` and `kas` versions can be found in
@@ -96,20 +96,21 @@ The available `agentk` and `kas` versions can be found in
[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.10,
the GitLab Kubernetes Agent Server (KAS) is available on GitLab.com under `wss://kas.gitlab.com`.
If you are a GitLab.com user, skip this step and directly
-[set up the configuration repository](#define-a-configuration-repository)
+[set up the configuration repository](#define-a-configuration-repository)
for your agent.
-The GitLab Kubernetes Agent Server (KAS) can be deployed using [Omnibus
-GitLab](https://docs.gitlab.com/omnibus/) or the [GitLab
-chart](https://gitlab.com/gitlab-org/charts/gitlab). If you don't already have
+The GitLab Kubernetes Agent Server (KAS) can be installed through Omnibus GitLab or
+through the GitLab Helm Chart. If you don't already have
GitLab installed, please refer to our [installation
documentation](https://docs.gitlab.com/ee/install/README.html).
+You can install the KAS within GitLab as explained below according to your GitLab installation method.
+You can also opt to use an [external KAS](#use-an-external-kas-installation).
-#### Install with Omnibus
+#### Install KAS with Omnibus
-When using the [Omnibus GitLab](https://docs.gitlab.com/omnibus/) package:
+For [Omnibus](https://docs.gitlab.com/omnibus/) package installations:
-1. Edit `/etc/gitlab/gitlab.rb`:
+1. Edit `/etc/gitlab/gitlab.rb` to enable the Kubernetes Agent Server:
```plaintext
gitlab_kas['enable'] = true
@@ -121,9 +122,9 @@ To configure any additional options related to GitLab Kubernetes Agent Server,
refer to the **Enable GitLab KAS** section of the
[`gitlab.rb.template`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/files/gitlab-config-template/gitlab.rb.template).
-#### Install with the Helm chart
+#### Install KAS with GitLab Helm Chart
-When installing or upgrading the GitLab Helm chart, consider the following Helm v3 example.
+For GitLab [Helm Chart](https://gitlab.com/gitlab-org/charts/gitlab) installations, consider the following Helm v3 example.
If you're using Helm v2, you must modify this example. See our [notes regarding deploy with Helm](https://docs.gitlab.com/charts/installation/deployment.html#deploy-using-helm).
You must set `global.kas.enabled=true` for the KAS to be properly installed and configured:
@@ -150,6 +151,29 @@ gitlab:
For details, read [Using the GitLab-KAS chart](https://docs.gitlab.com/charts/charts/gitlab/kas/).
+#### Use an external KAS installation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299850) in GitLab 13.10.
+
+Besides installing KAS with GitLab, you can opt to configure GitLab to use an external KAS.
+
+For GitLab instances installed through the GitLab Helm Chart, see [how to configure your external KAS](https://docs.gitlab.com/charts/charts/globals.html#external-kas).
+
+For GitLab instances installed through Omnibus packages:
+
+1. Edit `/etc/gitlab/gitlab.rb` adding the paths to your external KAS:
+
+ ```ruby
+ gitlab_kas['enable'] = false
+ gitlab_kas['api_secret_key'] = 'Your shared secret between GitLab and KAS'
+
+ gitlab_rails['gitlab_kas_enabled'] = true
+ gitlab_rails['gitlab_kas_external_url'] = 'wss://kas.gitlab.example.com' # User-facing URL for the in-cluster agentk
+ gitlab_rails['gitlab_kas_internal_url'] = 'grpc://kas.internal.gitlab.example.com' # Internal URL for the GitLab backend
+ ```
+
+1. [Reconfigure GitLab](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+
### Define a configuration repository
Next, you need a GitLab repository to contain your Agent configuration. The minimal
diff --git a/doc/user/group/epics/epic_boards.md b/doc/user/group/epics/epic_boards.md
new file mode 100644
index 00000000000..343f7c496b1
--- /dev/null
+++ b/doc/user/group/epics/epic_boards.md
@@ -0,0 +1,68 @@
+---
+stage: Plan
+group: Product Planning
+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/#assignments
+---
+
+# Epic Boards **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2864) in GitLab 13.10.
+> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
+> - It's disabled on GitLab.com.
+> - It's not recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](../../../administration/feature_flags.md).
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+The GitLab Epic Board is a software project management tool used to plan,
+organize, and visualize a workflow for a feature or product release.
+
+Epic boards build on the existing [epic tracking functionality](index.md) and
+[labels](../../project/labels.md). Your epics appear as cards in vertical lists, organized by their assigned
+labels.
+
+To view an epic board, in a group, select **Epics > Boards**.
+
+![GitLab epic board - Premium](img/epic_board_v13_10.png)
+
+## Create an epic board
+
+To create a new epic board:
+
+1. Select the dropdown with the current board name in the upper left corner of the Epic Boards page.
+1. Select **Create new board**.
+1. Enter the new board's name and select **Create**.
+
+## Limitations of epic boards
+
+As of GitLab 13.10, these limitations apply:
+
+- Epic Boards need to be enabled by an administrator.
+- Epic Boards can be created but not deleted.
+- Lists can be added to the board but not deleted.
+- There is no sidebar on the board. To edit an epic, go to the epic's page.
+- There is no drag and drop support yet. To move an epic between lists, edit epic labels on the epic's page.
+- Epics cannot be re-ordered within the list.
+
+To learn more about the future iterations of this feature, visit
+[epic 5067](https://gitlab.com/groups/gitlab-org/-/epics/5067).
+
+## Enable or disable Epic Boards
+
+Epic Boards are under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:epic_boards)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:epic_boards)
+```
diff --git a/doc/user/group/epics/img/epic_board_v13_10.png b/doc/user/group/epics/img/epic_board_v13_10.png
new file mode 100644
index 00000000000..5148e6dd4ec
--- /dev/null
+++ b/doc/user/group/epics/img/epic_board_v13_10.png
Binary files differ
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index ec7585363e2..bd8d9b68858 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -47,8 +47,12 @@ module API
end
end
+ def composer_v2?
+ headers['User-Agent'].to_s.include?('Composer/2')
+ end
+
def presenter
- @presenter ||= ::Packages::Composer::PackagesPresenter.new(user_group, packages)
+ @presenter ||= ::Packages::Composer::PackagesPresenter.new(user_group, packages, composer_v2?)
end
end
@@ -66,33 +70,25 @@ module API
end
desc 'Composer packages endpoint at group level'
-
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
get ':id/-/packages/composer/packages' do
presenter.root
end
desc 'Composer packages endpoint at group level for packages list'
-
params do
requires :sha, type: String, desc: 'Shasum of current json'
end
-
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
get ':id/-/packages/composer/p/:sha' do
presenter.provider
end
- desc 'Composer packages endpoint at group level for package versions metadata'
-
+ desc 'Composer v2 packages p2 endpoint at group level for package versions metadata'
params do
requires :package_name, type: String, file_path: true, desc: 'The Composer package name'
end
-
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
get ':id/-/packages/composer/p2/*package_name', requirements: COMPOSER_ENDPOINT_REQUIREMENTS, file_path: true do
not_found! if packages.empty?
@@ -100,13 +96,10 @@ module API
end
desc 'Composer packages endpoint at group level for package versions metadata'
-
params do
requires :package_name, type: String, file_path: true, desc: 'The Composer package name'
end
-
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
get ':id/-/packages/composer/*package_name', requirements: COMPOSER_ENDPOINT_REQUIREMENTS, file_path: true do
not_found! if packages.empty?
not_found! if params[:sha].blank?
@@ -125,7 +118,6 @@ module API
end
desc 'Composer packages endpoint for registering packages'
-
namespace ':id/packages/composer' do
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
@@ -134,7 +126,6 @@ module API
optional :tag, type: String, desc: 'The name of the tag'
exactly_one_of :tag, :branch
end
-
post do
authorize_create_package!(authorized_user_project)
@@ -159,7 +150,6 @@ module API
requires :sha, type: String, desc: 'Shasum of current json'
requires :package_name, type: String, file_path: true, desc: 'The Composer package name'
end
-
get 'archives/*package_name' do
metadata = unauthorized_user_project
.packages
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/composer/index_v2.json b/spec/fixtures/api/schemas/public_api/v4/packages/composer/index_v2.json
new file mode 100644
index 00000000000..6b77b758bfd
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/composer/index_v2.json
@@ -0,0 +1,14 @@
+{
+ "type": "object",
+ "required": ["packages", "metadata-url"],
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": { "type": "integer" }
+ },
+ "metadata-url": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/frontend/__helpers__/test_constants.js b/spec/frontend/__helpers__/test_constants.js
index 69b78f556aa..628b9b054d3 100644
--- a/spec/frontend/__helpers__/test_constants.js
+++ b/spec/frontend/__helpers__/test_constants.js
@@ -6,6 +6,8 @@ const DUMMY_IMAGE_URL = `${FIXTURES_PATH}/static/images/one_white_pixel.png`;
const GREEN_BOX_IMAGE_URL = `${FIXTURES_PATH}/static/images/green_box.png`;
const RED_BOX_IMAGE_URL = `${FIXTURES_PATH}/static/images/red_box.png`;
+const DUMMY_IMAGE_BLOB_PATH = 'SpongeBlob.png';
+
// NOTE: module.exports is needed so that this file can be used
// by environment.js
//
@@ -16,4 +18,5 @@ module.exports = {
DUMMY_IMAGE_URL,
GREEN_BOX_IMAGE_URL,
RED_BOX_IMAGE_URL,
+ DUMMY_IMAGE_BLOB_PATH,
};
diff --git a/spec/frontend/emoji/components/utils_spec.js b/spec/frontend/emoji/components/utils_spec.js
new file mode 100644
index 00000000000..36521eb1051
--- /dev/null
+++ b/spec/frontend/emoji/components/utils_spec.js
@@ -0,0 +1,56 @@
+import Cookies from 'js-cookie';
+import { getFrequentlyUsedEmojis, addToFrequentlyUsed } from '~/emoji/components/utils';
+
+jest.mock('js-cookie');
+
+describe('getFrequentlyUsedEmojis', () => {
+ it('it returns null when no saved emojis set', () => {
+ jest.spyOn(Cookies, 'get').mockReturnValue(null);
+
+ expect(getFrequentlyUsedEmojis()).toBe(null);
+ });
+
+ it('it returns frequently used emojis object', () => {
+ jest.spyOn(Cookies, 'get').mockReturnValue('thumbsup,thumbsdown');
+
+ expect(getFrequentlyUsedEmojis()).toEqual({
+ frequently_used: {
+ emojis: [['thumbsup', 'thumbsdown']],
+ top: 0,
+ height: 71,
+ },
+ });
+ });
+});
+
+describe('addToFrequentlyUsed', () => {
+ it('sets cookie value', () => {
+ jest.spyOn(Cookies, 'get').mockReturnValue(null);
+
+ addToFrequentlyUsed('thumbsup');
+
+ expect(Cookies.set).toHaveBeenCalledWith('frequently_used_emojis', 'thumbsup', {
+ expires: 365,
+ });
+ });
+
+ it('sets cookie value to include previously set cookie value', () => {
+ jest.spyOn(Cookies, 'get').mockReturnValue('thumbsdown');
+
+ addToFrequentlyUsed('thumbsup');
+
+ expect(Cookies.set).toHaveBeenCalledWith('frequently_used_emojis', 'thumbsdown,thumbsup', {
+ expires: 365,
+ });
+ });
+
+ it('sets cookie value with uniq values', () => {
+ jest.spyOn(Cookies, 'get').mockReturnValue('thumbsup');
+
+ addToFrequentlyUsed('thumbsup');
+
+ expect(Cookies.set).toHaveBeenCalledWith('frequently_used_emojis', 'thumbsup', {
+ expires: 365,
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js b/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js
index af3b63ad7e5..974d06a6ed4 100644
--- a/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/content_viewer/viewers/image_viewer_spec.js
@@ -1,12 +1,12 @@
-import { mount } from '@vue/test-utils';
-import { GREEN_BOX_IMAGE_URL } from 'spec/test_constants';
+import { shallowMount } from '@vue/test-utils';
+import { GREEN_BOX_IMAGE_URL, DUMMY_IMAGE_BLOB_PATH } from 'spec/test_constants';
import ImageViewer from '~/vue_shared/components/content_viewer/viewers/image_viewer.vue';
describe('Image Viewer', () => {
let wrapper;
it('renders image preview', () => {
- wrapper = mount(ImageViewer, {
+ wrapper = shallowMount(ImageViewer, {
propsData: { path: GREEN_BOX_IMAGE_URL, fileSize: 1024 },
});
@@ -22,7 +22,7 @@ describe('Image Viewer', () => {
`(
'shows file size as "$humanizedFileSize", if fileSize=$fileSize and renderInfo=$renderInfo',
({ fileSize, renderInfo, elementExists, humanizedFileSize }) => {
- wrapper = mount(ImageViewer, {
+ wrapper = shallowMount(ImageViewer, {
propsData: { path: GREEN_BOX_IMAGE_URL, fileSize, renderInfo },
});
@@ -36,11 +36,19 @@ describe('Image Viewer', () => {
describe('file path', () => {
it('should output a valid URL path for the image', () => {
- wrapper = mount(ImageViewer, {
+ wrapper = shallowMount(ImageViewer, {
propsData: { path: '/url/hello#1.jpg' },
});
expect(wrapper.find('img').attributes('src')).toBe('/url/hello%231.jpg');
});
+ it('outputs path without transformations when outputting a Blob', () => {
+ const file = new File([], DUMMY_IMAGE_BLOB_PATH);
+ const path = window.URL.createObjectURL(file);
+ wrapper = shallowMount(ImageViewer, {
+ propsData: { path },
+ });
+ expect(wrapper.find('img').attributes('src')).toBe(path);
+ });
});
});
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 397751b07af..2a8e2e04947 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -257,5 +257,15 @@ RSpec.describe CommitsHelper do
{ id: forked_project.id.to_s, name: forked_project.full_path, refsUrl: refs_project_path(forked_project) }
])
end
+
+ context 'pick_into_project is disabled' do
+ before do
+ stub_feature_flags(pick_into_project: false)
+ end
+
+ it 'does not calculate target projects' do
+ expect(helper.cherry_pick_projects_data(project)).to eq([])
+ end
+ end
end
end
diff --git a/spec/presenters/packages/composer/packages_presenter_spec.rb b/spec/presenters/packages/composer/packages_presenter_spec.rb
index c4217b6e37c..d0e3b68fc9f 100644
--- a/spec/presenters/packages/composer/packages_presenter_spec.rb
+++ b/spec/presenters/packages/composer/packages_presenter_spec.rb
@@ -15,7 +15,8 @@ RSpec.describe ::Packages::Composer::PackagesPresenter do
let(:branch) { project.repository.find_branch('master') }
let(:packages) { [package1, package2] }
- let(:presenter) { described_class.new(group, packages) }
+ let(:is_v2) { false }
+ let(:presenter) { described_class.new(group, packages, is_v2) }
describe '#package_versions' do
subject { presenter.package_versions }
@@ -79,5 +80,19 @@ RSpec.describe ::Packages::Composer::PackagesPresenter do
it 'returns the provider json' do
expect(subject).to match(expected_json)
end
+
+ context 'with a client version 2' do
+ let(:is_v2) { true }
+ let(:expected_json) do
+ {
+ 'packages' => [],
+ 'metadata-url' => "prefix/api/v4/group/#{group.id}/-/packages/composer/p2/%package%.json"
+ }
+ end
+
+ it 'returns the provider json' do
+ expect(subject).to match(expected_json)
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
index 4b5299cebec..b86c0529338 100644
--- a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
@@ -7,20 +7,30 @@ RSpec.shared_context 'Composer user type' do |user_type, add_member|
end
end
+RSpec.shared_examples 'Composer package index with version' do |schema_path|
+ it 'returns the package index' do
+ subject
+
+ expect(response).to have_gitlab_http_status(status)
+
+ if status == :success
+ expect(response).to match_response_schema(schema_path)
+ expect(json_response).to eq presenter.root
+ end
+ end
+end
+
RSpec.shared_examples 'Composer package index' do |user_type, status, add_member, include_package|
include_context 'Composer user type', user_type, add_member do
let(:expected_packages) { include_package == :include_package ? [package] : [] }
let(:presenter) { ::Packages::Composer::PackagesPresenter.new(group, expected_packages ) }
- it 'returns the package index' do
- subject
+ it_behaves_like 'Composer package index with version', 'public_api/v4/packages/composer/index'
- expect(response).to have_gitlab_http_status(status)
+ context 'with version 2' do
+ let(:headers) { super().merge('User-Agent' => 'Composer/2.0.9 (Darwin; 19.6.0; PHP 7.4.8; cURL 7.71.1)') }
- if status == :success
- expect(response).to match_response_schema('public_api/v4/packages/composer/index')
- expect(json_response).to eq presenter.root
- end
+ it_behaves_like 'Composer package index with version', 'public_api/v4/packages/composer/index_v2'
end
end
end
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 259148fa18f..259148fa18f 100644..100755
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
diff --git a/vendor/gitignore/Java.gitignore b/vendor/gitignore/Java.gitignore
index a1c2a238a96..a1c2a238a96 100644..100755
--- a/vendor/gitignore/Java.gitignore
+++ b/vendor/gitignore/Java.gitignore
diff --git a/workhorse/config_test.go b/workhorse/config_test.go
index cf33e5bb7ca..f9d12bd5e2b 100644
--- a/workhorse/config_test.go
+++ b/workhorse/config_test.go
@@ -85,7 +85,7 @@ func TestConfigDefaults(t *testing.T) {
DocumentRoot: "public",
ProxyHeadersTimeout: 5 * time.Minute,
APIQueueTimeout: queueing.DefaultTimeout,
- APICILongPollingDuration: 50 * time.Second,
+ APICILongPollingDuration: 50 * time.Nanosecond, // TODO this is meant to be 50*time.Second but it has been wrong for ages
ImageResizerConfig: config.DefaultImageResizerConfig,
}
diff --git a/workhorse/main.go b/workhorse/main.go
index 28162a00fae..47ab63a875a 100644
--- a/workhorse/main.go
+++ b/workhorse/main.go
@@ -102,7 +102,7 @@ func buildConfig(arg0 string, args []string) (*bootConfig, *config.Config, error
fset.UintVar(&cfg.APILimit, "apiLimit", 0, "Number of API requests allowed at single time")
fset.UintVar(&cfg.APIQueueLimit, "apiQueueLimit", 0, "Number of API requests allowed to be queued")
fset.DurationVar(&cfg.APIQueueTimeout, "apiQueueDuration", queueing.DefaultTimeout, "Maximum queueing duration of requests")
- fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50*time.Second, "Long polling duration for job requesting for runners (default 50s - enabled)")
+ fset.DurationVar(&cfg.APICILongPollingDuration, "apiCiLongPollingDuration", 50, "Long polling duration for job requesting for runners (default 50s - enabled)")
fset.BoolVar(&cfg.PropagateCorrelationID, "propagateCorrelationID", false, "Reuse existing Correlation-ID from the incoming request header `X-Request-ID` if present")
if err := fset.Parse(args); err != nil {