Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
77ba8f96b5
commit
22a3da26ad
|
|
@ -66,9 +66,12 @@ _Consider adding links to check for Sentry errors, Production logs for 5xx, 302s
|
|||
|
||||
## Rollout Steps
|
||||
|
||||
Note: Please make sure to run the chatops commands in the slack channel that gets impacted by the command.
|
||||
|
||||
### Rollout on non-production environments
|
||||
|
||||
- Ensure that the feature MRs have been deployed to non-production environments.
|
||||
- [ ] Verify the MR with the feature flag is merged to master.
|
||||
- Verify that the feature MRs have been deployed to non-production environments with:
|
||||
- [ ] `/chatops run auto_deploy status <merge-commit-of-your-feature>`
|
||||
- [ ] Enable the feature globally on non-production environments.
|
||||
- [ ] `/chatops run feature set <feature-flag-name> true --dev --staging --staging-ref`
|
||||
|
|
@ -79,13 +82,16 @@ _Consider adding links to check for Sentry errors, Production logs for 5xx, 302s
|
|||
|
||||
### Specific rollout on production
|
||||
|
||||
For visibility, all `/chatops` commands that target production should be executed in the `#production` slack channel and cross-posted (with the command results) to the responsible team's slack channel (`#g_TEAM_NAME`).
|
||||
|
||||
- Ensure that the feature MRs have been deployed to both production and canary.
|
||||
- [ ] `/chatops run auto_deploy status <merge-commit-of-your-feature>`
|
||||
- If you're using [project-actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), you must enable the feature on these entries:
|
||||
- Depending on the [type of actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors) you are using, pick one of these options:
|
||||
- If you're using **project-actor**, you must enable the feature on these entries:
|
||||
- [ ] `/chatops run feature set --project=gitlab-org/gitlab,gitlab-org/gitlab-foss,gitlab-com/www-gitlab-com <feature-flag-name> true`
|
||||
- If you're using [group-actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), you must enable the feature on these entries:
|
||||
- If you're using **group-actor**, you must enable the feature on these entries:
|
||||
- [ ] `/chatops run feature set --group=gitlab-org,gitlab-com <feature-flag-name> true`
|
||||
- If you're using [user-actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), you must enable the feature on these entries:
|
||||
- If you're using **user-actor**, you must enable the feature on these entries:
|
||||
- [ ] `/chatops run feature set --user=<your-username> <feature-flag-name> true`
|
||||
- [ ] Verify that the feature works on the specific entries. Posting the QA result in this issue is preferable.
|
||||
|
||||
|
|
@ -124,7 +130,7 @@ To do so, follow these steps:
|
|||
|
||||
- [ ] Create a merge request with the following changes. Ask for review and merge it.
|
||||
- [ ] Set the `default_enabled` attribute in [the feature flag definition](https://docs.gitlab.com/ee/development/feature_flags/#feature-flag-definition-and-validation) to `true`.
|
||||
- [ ] Create [a changelog entry](https://docs.gitlab.com/ee/development/feature_flags/#changelog).
|
||||
- [ ] Review [what warrants a changelog entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry) and decide if [a changelog entry](https://docs.gitlab.com/ee/development/feature_flags/#changelog) is needed.
|
||||
- [ ] Ensure that the default-enabling MR has been included in the release package.
|
||||
If the merge request was deployed before [the monthly release was tagged](https://about.gitlab.com/handbook/engineering/releases/#self-managed-releases-1),
|
||||
the feature can be officially announced in a release blog post.
|
||||
|
|
@ -165,7 +171,7 @@ You can either [create a follow-up issue for Feature Flag Cleanup](https://gitla
|
|||
the feature can be officially announced in a release blog post.
|
||||
- [ ] `/chatops run release check <merge-request-url> <milestone>`
|
||||
- [ ] Close [the feature issue][main-issue] to indicate the feature will be released in the current milestone.
|
||||
- [ ] If not already done, clean up the feature flag from all environments by running these chatops command in `#production` channel:
|
||||
- [ ] Clean up the feature flag from all environments by running these chatops command in `#production` channel:
|
||||
- [ ] `/chatops run feature delete <feature-flag-name> --dev --staging --staging-ref --production`
|
||||
- [ ] Close this rollout issue.
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
15.7.0-rc1
|
||||
15.7.0
|
||||
|
|
|
|||
|
|
@ -59,21 +59,20 @@ export default {
|
|||
return [
|
||||
{
|
||||
title: I18N_ALL_TYPES,
|
||||
runnerType: null,
|
||||
},
|
||||
...tabs,
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onTabSelected({ runnerType }) {
|
||||
onTabSelected(runnerType) {
|
||||
this.$emit('input', {
|
||||
...this.value,
|
||||
runnerType,
|
||||
pagination: { page: 1 },
|
||||
});
|
||||
},
|
||||
isTabActive({ runnerType }) {
|
||||
isTabActive(runnerType = null) {
|
||||
return runnerType === this.value.runnerType;
|
||||
},
|
||||
tabBadgeCountVariables(runnerType) {
|
||||
|
|
@ -102,8 +101,8 @@ export default {
|
|||
<gl-tab
|
||||
v-for="tab in tabs"
|
||||
:key="`${tab.runnerType}`"
|
||||
:active="isTabActive(tab)"
|
||||
@click="onTabSelected(tab)"
|
||||
:active="isTabActive(tab.runnerType)"
|
||||
@click="onTabSelected(tab.runnerType)"
|
||||
>
|
||||
<template #title>
|
||||
{{ tab.title }}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ import { INSTANCE_TYPE, GROUP_TYPE } from '../../constants';
|
|||
* <strong/> tag.
|
||||
*
|
||||
* ```vue
|
||||
* <runner-count-stat
|
||||
* <runner-count
|
||||
* #default="{ count }"
|
||||
* :scope="INSTANCE_TYPE"
|
||||
* :variables="{ status: 'ONLINE' }"
|
||||
* >
|
||||
* <strong>{{ count }}</strong>
|
||||
* </runner-count-stat>
|
||||
* </runner-count>
|
||||
* ```
|
||||
*
|
||||
* Use `:skip="true"` to prevent data from being fetched and
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<script>
|
||||
import RunnerSingleStat from '~/ci/runner/components/stat/runner_single_stat.vue';
|
||||
import {
|
||||
I18N_STATUS_ONLINE,
|
||||
I18N_STATUS_OFFLINE,
|
||||
|
|
@ -8,9 +7,19 @@ import {
|
|||
STATUS_OFFLINE,
|
||||
STATUS_STALE,
|
||||
} from '../../constants';
|
||||
import RunnerSingleStat from './runner_single_stat.vue';
|
||||
import RunnerCount from './runner_count.vue';
|
||||
|
||||
/**
|
||||
* Shows general stats about the runners.
|
||||
*
|
||||
* First it checks if there are any runners in this context, and if so,
|
||||
* shows more details for different status.
|
||||
*/
|
||||
|
||||
export default {
|
||||
components: {
|
||||
RunnerCount,
|
||||
RunnerSingleStat,
|
||||
RunnerUpgradeStatusStats: () =>
|
||||
import('ee_component/ci/runner/components/stat/runner_upgrade_status_stats.vue'),
|
||||
|
|
@ -71,19 +80,21 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="gl-display-flex gl-flex-wrap gl-py-6">
|
||||
<runner-single-stat
|
||||
v-for="stat in stats"
|
||||
:key="stat.key"
|
||||
:scope="scope"
|
||||
v-bind="stat.props"
|
||||
class="gl-px-5"
|
||||
/>
|
||||
<runner-count #default="{ count }" :scope="scope" :variables="variables">
|
||||
<div v-if="count" class="gl-display-flex gl-flex-wrap gl-py-6">
|
||||
<runner-single-stat
|
||||
v-for="stat in stats"
|
||||
:key="stat.key"
|
||||
:scope="scope"
|
||||
v-bind="stat.props"
|
||||
class="gl-px-5"
|
||||
/>
|
||||
|
||||
<runner-upgrade-status-stats
|
||||
class="gl-display-contents"
|
||||
:scope="scope"
|
||||
:variables="variables"
|
||||
/>
|
||||
</div>
|
||||
<runner-upgrade-status-stats
|
||||
class="gl-display-contents"
|
||||
:scope="scope"
|
||||
:variables="variables"
|
||||
/>
|
||||
</div>
|
||||
</runner-count>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -20,13 +20,14 @@ export default {
|
|||
role="region"
|
||||
:aria-label="__('Merge request reports')"
|
||||
data-testid="mr-widget-app"
|
||||
class="mr-widget-section"
|
||||
>
|
||||
<component
|
||||
:is="widget"
|
||||
v-for="(widget, index) in widgets"
|
||||
:key="widget.name || index"
|
||||
:mr="mr"
|
||||
:class="{ 'mr-widget-border-top': index === 0 }"
|
||||
class="mr-widget-section"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -82,10 +82,8 @@ export default {
|
|||
v-if="data.children && data.children.length > 0 && level === 2"
|
||||
class="gl-m-0 gl-p-0 gl-list-style-none"
|
||||
>
|
||||
<li>
|
||||
<li v-for="(childData, index) in data.children" :key="childData.id || index">
|
||||
<dynamic-content
|
||||
v-for="(childData, index) in data.children"
|
||||
:key="childData.id || index"
|
||||
:data="childData"
|
||||
:widget-name="widgetName"
|
||||
:level="3"
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ export default {
|
|||
:class="{
|
||||
[iconClassNameText]: !isLoading,
|
||||
[`mr-widget-status-icon-level-${level}`]: !isLoading,
|
||||
'gl-mr-3': level === 1,
|
||||
'gl-w-6 gl-h-6 gl--flex-center': level === 1,
|
||||
}"
|
||||
class="gl-relative gl-w-6 gl-h-6 gl-rounded-full gl--flex-center"
|
||||
class="gl-relative gl-rounded-full gl-mr-3"
|
||||
>
|
||||
<gl-loading-icon v-if="isLoading" size="md" inline />
|
||||
<gl-icon
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import SafeHtml from '~/vue_shared/directives/safe_html';
|
|||
import { sprintf, __ } from '~/locale';
|
||||
import Poll from '~/lib/utils/poll';
|
||||
import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
||||
import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller';
|
||||
import { EXTENSION_ICONS } from '../../constants';
|
||||
import { createTelemetryHub } from '../extensions/telemetry';
|
||||
import ContentRow from './widget_content_row.vue';
|
||||
|
|
@ -26,6 +27,8 @@ export default {
|
|||
GlLoadingIcon,
|
||||
ContentRow,
|
||||
DynamicContent,
|
||||
DynamicScroller,
|
||||
DynamicScrollerItem,
|
||||
HelpPopover,
|
||||
},
|
||||
directives: {
|
||||
|
|
@ -305,7 +308,7 @@ export default {
|
|||
<div v-if="isLoadingExpandedContent" class="report-block-container gl-text-center">
|
||||
<gl-loading-icon size="sm" inline /> {{ loadingText }}
|
||||
</div>
|
||||
<div v-else class="gl-px-5 gl-display-flex">
|
||||
<div v-else class="gl-pl-5 gl-display-flex" :class="{ 'gl-pr-5': $scopedSlots.content }">
|
||||
<content-row
|
||||
v-if="contentError"
|
||||
:level="2"
|
||||
|
|
@ -318,12 +321,25 @@ export default {
|
|||
</content-row>
|
||||
<div v-else class="gl-w-full">
|
||||
<slot name="content">
|
||||
<dynamic-content
|
||||
v-for="(data, index) in content"
|
||||
:key="data.id || index"
|
||||
:data="data"
|
||||
:widget-name="widgetName"
|
||||
/>
|
||||
<dynamic-scroller
|
||||
v-if="content"
|
||||
:items="content"
|
||||
:min-item-size="32"
|
||||
:style="{ maxHeight: '170px' }"
|
||||
data-testid="dynamic-content-scroller"
|
||||
class="gl-pr-5"
|
||||
>
|
||||
<template #default="{ item, index, active }">
|
||||
<dynamic-scroller-item :item="item" :active="active">
|
||||
<dynamic-content
|
||||
:key="item.id || index"
|
||||
:data="item"
|
||||
:widget-name="widgetName"
|
||||
:level="2"
|
||||
/>
|
||||
</dynamic-scroller-item>
|
||||
</template>
|
||||
</dynamic-scroller>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -79,10 +79,15 @@ export default {
|
|||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="gl-w-full gl-display-flex mr-widget-content-row gl-align-items-baseline"
|
||||
class="gl-w-full gl-display-flex gl-align-items-baseline"
|
||||
:class="{ 'gl-border-t gl-py-3 gl-pl-7': level === 2 }"
|
||||
>
|
||||
<status-icon v-if="statusIconName" :level="2" :name="widgetName" :icon-name="statusIconName" />
|
||||
<status-icon
|
||||
v-if="statusIconName && !header"
|
||||
:level="2"
|
||||
:name="widgetName"
|
||||
:icon-name="statusIconName"
|
||||
/>
|
||||
<div class="gl-w-full">
|
||||
<div class="gl-display-flex">
|
||||
<slot name="header">
|
||||
|
|
@ -128,6 +133,12 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
<div class="gl-display-flex gl-align-items-baseline gl-w-full">
|
||||
<status-icon
|
||||
v-if="statusIconName && header"
|
||||
:level="2"
|
||||
:name="widgetName"
|
||||
:icon-name="statusIconName"
|
||||
/>
|
||||
<slot name="body"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1097,10 +1097,6 @@ $tabs-holder-z-index: 250;
|
|||
}
|
||||
}
|
||||
|
||||
.mr-widget-content-row:first-child {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.mr-widget-status-icon-level-1::before {
|
||||
@include gl-content-empty;
|
||||
@include gl-absolute;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Ci
|
|||
def show_secure_files_setting(project, user)
|
||||
return false if user.nil?
|
||||
|
||||
Feature.enabled?(:ci_secure_files, project) && user.can?(:read_secure_files, project)
|
||||
user.can?(:read_secure_files, project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -115,6 +115,15 @@ class GitlabUploader < CarrierWave::Uploader::Base
|
|||
end
|
||||
end
|
||||
|
||||
def multi_read(offsets)
|
||||
open do |stream|
|
||||
offsets.map do |start_offset, end_offset|
|
||||
stream.seek(start_offset)
|
||||
stream.read(end_offset - start_offset + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Used to replace an existing upload with another +file+ without modifying stored metadata
|
||||
# Use this method only to repair/replace an existing upload, or to upload to a Geo secondary node
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_secure_files
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78227
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350748
|
||||
milestone: '14.8'
|
||||
type: development
|
||||
group: group::incubation
|
||||
default_enabled: false
|
||||
|
|
@ -1,23 +1,23 @@
|
|||
- title: "`POST /api/v4/runners` method to register runners" # (required) The name of the feature to be deprecated
|
||||
- title: "Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint" # (required) The name of the feature to be deprecated
|
||||
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2022-11-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2024-04-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
|
||||
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/379743 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
The `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
|
||||
This endpoint and method [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
|
||||
with a GitLab instance at the instance, group, or project level through the API. We plan to remove this endpoint
|
||||
and method in GitLab 16.0.
|
||||
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
|
||||
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
|
||||
with a GitLab instance at the instance, group, or project level through the API. We plan to remove the support for
|
||||
registration tokens and certain configuration arguments in this endpoint in GitLab 17.0.
|
||||
|
||||
In GitLab 15.8, we plan to implement a new method to bind runners to a GitLab instance,
|
||||
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/).
|
||||
This new architecture introduces a new method for registering runners and will eliminate the legacy
|
||||
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
|
||||
From GitLab 16.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
|
||||
From GitLab 17.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
|
||||
end_of_support_milestone: "16.0" # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
end_of_support_date: "2023-05-22" # (optional) The date of the milestone release when support for this feature will end.
|
||||
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
- title: "`runnerRegistrationToken` parameter for GitLab Runner Helm Chart" # (required) The name of the feature to be deprecated
|
||||
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2022-11-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2024-04-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
|
||||
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
As part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/), in GitLab 15.8 we plan to introduce:
|
||||
|
||||
- A new method to bind runners to a GitLab instance.
|
||||
- A new method to bind runners to a GitLab instance leveraging `runnerToken`.
|
||||
- A unique system ID saved to the `config.toml`, which will ensure traceability between jobs and runners.
|
||||
From GitLab 16.0 and later, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
|
||||
From GitLab 17.0 and later, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
|
||||
end_of_support_milestone: "16.0" # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
end_of_support_date: "2023-05-22" # (optional) The date of the milestone release when support for this feature will end.
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
- title: "`gitlab-runner register` command" # (required) The name of the feature to be deprecated
|
||||
- title: "Registration tokens and server-side runner arguments in `gitlab-runner register` command" # (required) The name of the feature to be deprecated
|
||||
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2022-11-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2024-04-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
|
||||
reporter: pedropombeiro # (required) GitLab username of the person reporting the deprecation
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/380872 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
The command to [register](https://docs.gitlab.com/runner/register/) a runner, `gitlab-runner register` is deprecated.
|
||||
The support for registration tokens and certain configuration arguments in the command to [register](https://docs.gitlab.com/runner/register/) a runner, `gitlab-runner register` is deprecated.
|
||||
GitLab plans to introduce a new [GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/) in GitLab 15.8,
|
||||
which introduces a new method for registering runners and eliminates the legacy
|
||||
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
|
||||
The new method will involve passing a [runner authentication token](https://docs.gitlab.com/ee/security/token_overview.html#runner-authentication-tokens-also-called-runner-tokens)
|
||||
to a new `gitlab-runner deploy` command.
|
||||
The new method will involve creating the runner in the GitLab UI and passing the
|
||||
[runner authentication token](https://docs.gitlab.com/ee/security/token_overview.html#runner-authentication-tokens-also-called-runner-tokens)
|
||||
to the `gitlab-runner register` command.
|
||||
end_of_support_milestone: "16.0" # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
|
||||
end_of_support_date: "2023-05-22" # (optional) The date of the milestone release when support for this feature will end.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
- title: "GitLab Runner registration token in Runner Operator" # (required) The name of the feature to be deprecated
|
||||
announcement_milestone: "15.6" # (required) The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2022-11-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "17.0" # (required) The milestone when this feature is planned to be removed
|
||||
removal_date: "2024-04-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
|
||||
reporter: ratchade # (required) GitLab username of the person reporting the deprecation
|
||||
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
|
||||
|
|
|
|||
|
|
@ -1859,8 +1859,8 @@ Updates to example must be made at:
|
|||
# Set number of Sidekiq queue processes to the same number as available CPUs
|
||||
sidekiq['queue_groups'] = ['*'] * 4
|
||||
|
||||
# Set number of Sidekiq threads per queue process to the recommend number of 10
|
||||
sidekiq['max_concurrency'] = 10
|
||||
# Set number of Sidekiq threads per queue process to the recommend number of 20
|
||||
sidekiq['max_concurrency'] = 20
|
||||
|
||||
# Monitoring
|
||||
consul['enable'] = true
|
||||
|
|
|
|||
|
|
@ -1877,8 +1877,8 @@ Updates to example must be made at:
|
|||
# Set number of Sidekiq queue processes to the same number as available CPUs
|
||||
sidekiq['queue_groups'] = ['*'] * 4
|
||||
|
||||
# Set number of Sidekiq threads per queue process to the recommend number of 10
|
||||
sidekiq['max_concurrency'] = 10
|
||||
# Set number of Sidekiq threads per queue process to the recommend number of 20
|
||||
sidekiq['max_concurrency'] = 20
|
||||
|
||||
# Monitoring
|
||||
consul['enable'] = true
|
||||
|
|
|
|||
|
|
@ -700,8 +700,8 @@ On each node perform the following:
|
|||
puma['listen'] = '0.0.0.0'
|
||||
sidekiq['listen_address'] = "0.0.0.0"
|
||||
|
||||
# Configure Sidekiq with 2 workers and 10 max concurrency
|
||||
sidekiq['max_concurrency'] = 10
|
||||
# Configure Sidekiq with 2 workers and 20 max concurrency
|
||||
sidekiq['max_concurrency'] = 20
|
||||
sidekiq['queue_groups'] = ['*'] * 2
|
||||
|
||||
# Add the monitoring node's IP address to the monitoring whitelist and allow it to
|
||||
|
|
|
|||
|
|
@ -1794,8 +1794,8 @@ Updates to example must be made at:
|
|||
## Set number of Sidekiq queue processes to the same number as available CPUs
|
||||
sidekiq['queue_groups'] = ['*'] * 2
|
||||
|
||||
## Set number of Sidekiq threads per queue process to the recommend number of 10
|
||||
sidekiq['max_concurrency'] = 10
|
||||
## Set number of Sidekiq threads per queue process to the recommend number of 20
|
||||
sidekiq['max_concurrency'] = 20
|
||||
|
||||
# Monitoring
|
||||
consul['enable'] = true
|
||||
|
|
|
|||
|
|
@ -1872,8 +1872,8 @@ Updates to example must be made at:
|
|||
## Set number of Sidekiq queue processes to the same number as available CPUs
|
||||
sidekiq['queue_groups'] = ['*'] * 4
|
||||
|
||||
## Set number of Sidekiq threads per queue process to the recommend number of 10
|
||||
sidekiq['max_concurrency'] = 10
|
||||
## Set number of Sidekiq threads per queue process to the recommend number of 20
|
||||
sidekiq['max_concurrency'] = 20
|
||||
|
||||
# Monitoring
|
||||
consul['enable'] = true
|
||||
|
|
|
|||
|
|
@ -1790,8 +1790,8 @@ Updates to example must be made at:
|
|||
## Set number of Sidekiq queue processes to the same number as available CPUs
|
||||
sidekiq['queue_groups'] = ['*'] * 4
|
||||
|
||||
## Set number of Sidekiq threads per queue process to the recommend number of 10
|
||||
sidekiq['max_concurrency'] = 10
|
||||
## Set number of Sidekiq threads per queue process to the recommend number of 20
|
||||
sidekiq['max_concurrency'] = 20
|
||||
|
||||
# Monitoring
|
||||
consul['enable'] = true
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ There are two tokens to take into account when connecting a runner with GitLab.
|
|||
|
||||
| Token | Description |
|
||||
| ----- | ----------- |
|
||||
| Registration token | Token used to [register the runner](https://docs.gitlab.com/runner/register/). It can be [obtained through GitLab](../ci/runners/index.md). |
|
||||
| Authentication token | Token used to authenticate the runner with the GitLab instance. It is obtained automatically when you [register a runner](https://docs.gitlab.com/runner/register/) or by the Runner API when you manually [register a runner](#register-a-new-runner-deprecated) or [reset the authentication token](#reset-runners-authentication-token-by-using-the-runner-id). |
|
||||
| Registration token | Token used to [register the runner](https://docs.gitlab.com/runner/register/). It can be [obtained through GitLab](../ci/runners/index.md). |
|
||||
| Authentication token | Token used to authenticate the runner with the GitLab instance. It is obtained automatically when you [register a runner](https://docs.gitlab.com/runner/register/) or by the Runner API when you manually [register a runner](#register-a-new-runner) or [reset the authentication token](#reset-runners-authentication-token-by-using-the-runner-id). |
|
||||
|
||||
Here's an example of how the two tokens are used in runner registration:
|
||||
|
||||
|
|
@ -640,12 +640,7 @@ Example response:
|
|||
]
|
||||
```
|
||||
|
||||
## Register a new runner (deprecated)
|
||||
|
||||
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102579) in GitLab 15.6.
|
||||
|
||||
WARNING:
|
||||
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/102579) in GitLab 15.6 and is planned for removal in 16.0. This change is a breaking change.
|
||||
## Register a new runner
|
||||
|
||||
Register a new runner for the instance.
|
||||
|
||||
|
|
@ -655,18 +650,18 @@ POST /runners
|
|||
|
||||
| Attribute | Type | Required | Description |
|
||||
|--------------------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `token` | string | yes | [Registration token](#registration-and-authentication-tokens) |
|
||||
| `description` | string | no | Runner's description |
|
||||
| `token` | string | yes | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): [Registration token](#registration-and-authentication-tokens). The registration token will be replaced by an authentication token in GitLab 16.0 |
|
||||
| `description` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): Runner's description |
|
||||
| `info` | hash | no | Runner's metadata. You can include `name`, `version`, `revision`, `platform`, and `architecture`, but only `version`, `platform`, and `architecture` are displayed in the Admin Area of the UI |
|
||||
| `active` | boolean | no | Deprecated: Use `paused` instead. Specifies whether the runner is allowed to receive new jobs |
|
||||
| `paused` | boolean | no | Specifies whether the runner should ignore new jobs |
|
||||
| `locked` | boolean | no | Specifies whether the runner should be locked for the current project |
|
||||
| `run_untagged` | boolean | no | Specifies whether the runner should handle untagged jobs |
|
||||
| `tag_list` | string array | no | A list of runner tags |
|
||||
| `access_level` | string | no | The access level of the runner; `not_protected` or `ref_protected` |
|
||||
| `maximum_timeout` | integer | no | Maximum timeout that limits the amount of time (in seconds) that runners can run jobs |
|
||||
| `maintainer_note` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350730), see `maintenance_note` |
|
||||
| `maintenance_note` | string | no | Free-form maintenance notes for the runner (1024 characters) |
|
||||
| `active` | boolean | no | Deprecated: Use `paused` instead. Specifies whether the runner is allowed to receive new jobs |
|
||||
| `paused` | boolean | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): Specifies whether the runner should ignore new jobs |
|
||||
| `locked` | boolean | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): Specifies whether the runner should be locked for the current project |
|
||||
| `run_untagged` | boolean | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): Specifies whether the runner should handle untagged jobs |
|
||||
| `tag_list` | string array | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): A list of runner tags |
|
||||
| `access_level` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): The access level of the runner; `not_protected` or `ref_protected` |
|
||||
| `maximum_timeout` | integer | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): Maximum timeout that limits the amount of time (in seconds) that runners can run jobs |
|
||||
| `maintainer_note` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350730), see `maintenance_note` |
|
||||
| `maintenance_note` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/379743): Free-form maintenance notes for the runner (1024 characters) |
|
||||
|
||||
```shell
|
||||
curl --request POST "https://gitlab.example.com/api/v4/runners" \
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ CI/CD jobs in a reliable and concurrent environment. Ever since the beginnings
|
|||
of the service as a Ruby program, runners are registered in a GitLab instance with
|
||||
a registration token - a randomly generated string of text. The registration token is unique for its given scope
|
||||
(instance, group, or project). The registration token proves that the party that registers the runner has
|
||||
administrator access to the instance, group, or project to which the runner is registered.
|
||||
administrative access to the instance, group, or project to which the runner is registered.
|
||||
|
||||
This approach has worked well in the initial years, but some major known issues started to
|
||||
become apparent as the target audience grew:
|
||||
|
|
@ -37,49 +37,122 @@ We call this new mechanism the "next GitLab Runner Token architecture".
|
|||
|
||||
The proposal addresses the issues of a _single token per scope_ and _token storage_
|
||||
by eliminating the need for a registration token. Runner creation happens
|
||||
in the GitLab Runners settings page for the given scope, in the context of the logged-in user
|
||||
, which provides traceability. The page provides instructions to configure the newly-created
|
||||
runner in supported environments.
|
||||
in the GitLab Runners settings page for the given scope, in the context of the logged-in user,
|
||||
which provides traceability. The page provides instructions to configure the newly-created
|
||||
runner in supported environments using the existing `gitlab-runner register` command.
|
||||
|
||||
The runner configuration will be generated through a new `deploy` command, which will leverage
|
||||
the `/runners/verify` REST endpoint to ensure the validity of the authentication token.
|
||||
The remaining concerns become non-issues due to the elimination of the registration token.
|
||||
|
||||
The configuration can be applied across many machines by reusing the same instructions.
|
||||
A unique system identifier will be generated automatically if a value is missing from
|
||||
the runner entry in the `config.toml` file. This allows differentiating systems sharing the same
|
||||
runner token (for example, in auto-scaling scenarios), and is crucial for the proper functioning of our
|
||||
long-polling mechanism when the same authentication token is shared across two or more runner managers.
|
||||
### Using the authentication token in place of the registration token
|
||||
|
||||
Given that the creation of runners involves user interaction, it should be possible
|
||||
to eventually lower the per-plan limit of CI runners that can be registered per scope.
|
||||
<!-- vale gitlab.Spelling = NO -->
|
||||
In this proposal, runners created in the GitLab UI are assigned authentication tokens prefixed with
|
||||
`glrt-` (**G**it**L**ab **R**unner **T**oken).
|
||||
<!-- vale gitlab.Spelling = YES -->
|
||||
The prefix allows the existing `register` command to use the authentication token _in lieu_
|
||||
of the current registration token (`--registration-token`), requiring minimal adjustments in
|
||||
existing workflows.
|
||||
The authentication token is shown to the user only once - after completing the creation flow - to
|
||||
discourage unintended reuse.
|
||||
|
||||
### Auto-scaling scenarios (for example Helm chart)
|
||||
Given that the runner is pre-created through the GitLab UI, the `register` command fails if
|
||||
provided with arguments that are exposed in the runner creation form.
|
||||
Some examples are `--tag-list`, `--run-untagged`, `--locked`, or `--access-level` as these are
|
||||
sensitive parameters that should be decided at creation time by an administrator/owner.
|
||||
The runner configuration is generated through the existing `register` command, which can behave in
|
||||
two different ways depending on whether it is supplied a registration token or an authentication
|
||||
token in the `--registration-token` argument:
|
||||
|
||||
| Token type | Behavior |
|
||||
| ---------- | -------- |
|
||||
| Registration token | Leverages the `POST /api/v4/runners` REST endpoint to create a new runner, creating a new entry in `config.toml`. |
|
||||
| Authentication token | Leverages the `POST /api/v4/runners/verify` REST endpoint to ensure the validity of the authentication token. Creates an entry in `config.toml` file and a `system_id` value in a sidecar file if missing (`.runner_system_id`). |
|
||||
|
||||
### Transition period
|
||||
|
||||
During a transition period, legacy tokens ("registration tokens") continue to be shown on the
|
||||
GitLab Runners settings page and to be accepted by the `gitlab-runner register` command.
|
||||
The legacy workflow is nevertheless discouraged in the UI.
|
||||
Users are steered towards the new flow consisting of creating the runner in the UI and using the
|
||||
resulting authentication token with the `gitlab-runner register` command as they do today.
|
||||
This approach reduces disruption to users responsible for deploying runners.
|
||||
|
||||
### Reusing the runner authentication token across many machines
|
||||
|
||||
In the existing model, a new runner is created whenever a new worker is required. This
|
||||
has led to many situations where runners are left behind and become stale.
|
||||
|
||||
In the proposed model, a `ci_runners` table entry describes a configuration,
|
||||
which the runner could reuse across multiple machines. This allows differentiating the context in
|
||||
which the runner is being used. In situations where we must differentiate between runners
|
||||
that reuse the same configuration, we can use the unique system identifier to track all
|
||||
unique "runners" that are executed in context of a single `ci_runners` model. This unique
|
||||
system identifier would be present in the Runner's `config.toml` configuration file and
|
||||
initially set when generating the new `[[runners]]` configuration by means of the `deploy` command.
|
||||
Legacy files that miss values for unique system identifiers will get rewritten automatically with new values.
|
||||
In the proposed model, a `ci_runners` table entry describes a configuration that the user can reuse
|
||||
across multiple machines.
|
||||
A unique system identifier is [generated automatically](#generating-a-system_id-value) whenever the
|
||||
runner application starts up or the configuration is saved.
|
||||
This allows differentiating the context in which the runner is being used.
|
||||
|
||||
The `system_id` value complements the short runner token that is currently used to identify a
|
||||
runner in command line output, CI job logs, and GitLab UI.
|
||||
|
||||
Given that the creation of runners involves user interaction, it should be possible
|
||||
to eventually lower the per-plan limit of CI runners that can be registered per scope.
|
||||
|
||||
#### Generating a `system_id` value
|
||||
|
||||
We ensure that a unique system identifier is assigned at all times to a `gitlab-runner`
|
||||
installation.
|
||||
The ID is derived from an existing machine identifier such as `/etc/machine-id` (on Linux) and
|
||||
hashed for privacy, in which case it is prefixed with `s_`.
|
||||
If an ID is not available, a random string is used instead, in which case it is prefixed with `r_`.
|
||||
|
||||
This unique ID identifies the `gitlab-runner` process and is sent
|
||||
on `POST /api/v4/jobs` requests for all runners in the `config.toml` file.
|
||||
|
||||
The ID is generated and saved both at `gitlab-runner` startup and whenever the configuration is
|
||||
saved to disk.
|
||||
Instead of saving the ID at the root of `config.toml` though, we save it to a new file that lives
|
||||
next to it - `.runner_system_id`. The goal for this new file is to make it less likely that IDs
|
||||
get reused due to manual copying of the `config.toml` file
|
||||
|
||||
```plain
|
||||
s_cpwhDr7zFz4xBJujFeEM
|
||||
```
|
||||
|
||||
### Runner identification in CI jobs
|
||||
|
||||
For users to identify the machine where the job was executed, the unique identifier will need to be visible in CI job contexts.
|
||||
For users to identify the machine where the job was executed, the unique identifier needs to be
|
||||
visible in CI job contexts.
|
||||
As a first iteration, GitLab Runner will include the unique system identifier in the build logs,
|
||||
wherever it publishes the short token SHA.
|
||||
|
||||
Given that the runner will potentially be reused with different unique system identifiers,
|
||||
we can store the unique system ID. This ensures the unique system ID maps to a GitLab Runner's `config.toml` entry with
|
||||
the runner token. The `ci_runner_machines` would hold information about each unique runner machine,
|
||||
with information when runner last connected, and what type of runner it was. The relevant fields
|
||||
will be moved from the `ci_runners`.
|
||||
The `ci_builds_runner_session` (or `ci_builds` or `ci_builds_metadata`) will reference
|
||||
Given that the runner can potentially be reused with different unique system identifiers,
|
||||
we should store the unique system ID in the database.
|
||||
This ensures the unique system ID maps to a GitLab Runner's `system_id` value with the runner token.
|
||||
A new `ci_runner_machines` table holds information about each unique runner machine,
|
||||
with information regarding when the runner last connected, and what type of runner it was.
|
||||
|
||||
In the long term, the relevant fields are to be moved from the `ci_runners` into
|
||||
`ci_runner_machines`.
|
||||
Until the removal milestone though, they should be kept in the `ci_runners` as a fallback when a
|
||||
matching `ci_runner_machines` record does not exist.
|
||||
An expected scenario is the case when the table is created but the runner hasn't pinged the GitLab
|
||||
instance (for example if the runner is offline).
|
||||
|
||||
In addition, we should add the following columns to `ci_runners`:
|
||||
|
||||
- a `user_id` column to keep track of who created a runner;
|
||||
- a `registration_type` enum column to `ci_runners` to signal whether a runner has been created
|
||||
using the legacy `register` method, or the new UI-based method.
|
||||
Possible values are `:registration_token` and `:authenticated_user`.
|
||||
This allows the stale runner cleanup service to determine which runners to clean up, and allows
|
||||
future uses that may not be apparent.
|
||||
|
||||
```sql
|
||||
CREATE TABLE ci_runner (
|
||||
...
|
||||
user_id bigint
|
||||
registration_type int8
|
||||
)
|
||||
```
|
||||
|
||||
The `ci_builds_runner_session` (or `ci_builds` or `ci_builds_metadata`) shall reference
|
||||
`ci_runner_machines`.
|
||||
We might consider a more efficient way to store `contacted_at` than updating the existing record.
|
||||
|
||||
|
|
@ -110,7 +183,8 @@ CREATE TABLE ci_runner_machines (
|
|||
- Runners can always be traced back to the user who created it, using the audit log;
|
||||
- The claims of a CI runner are known at creation time, and cannot be changed from the runner
|
||||
(for example, changing the `access_level`/`protected` flag). Authenticated users
|
||||
may however still edit these settings through the GitLab UI.
|
||||
may however still edit these settings through the GitLab UI;
|
||||
- Easier cleanup of stale runners, which doesn't touch the `ci_runner` table.
|
||||
|
||||
## Details
|
||||
|
||||
|
|
@ -121,53 +195,95 @@ token to register new runners.
|
|||
|
||||
The new workflow looks as follows:
|
||||
|
||||
1. The user opens the Runners settings page;
|
||||
1. The user opens the Runners settings page (instance, group, or project level);
|
||||
1. The user fills in the details regarding the new desired runner, namely description,
|
||||
tags, protected, locked, etc.;
|
||||
1. The user clicks `Create`. That results in the following:
|
||||
|
||||
1. Creates a new runner in the `ci_runners` table (and corresponding authentication token);
|
||||
1. Creates a new runner in the `ci_runners` table (and corresponding `glrt-` prefixed authentication token);
|
||||
1. Presents the user with instructions on how to configure this new runner on a machine,
|
||||
with possibilities for different supported deployment scenarios (e.g. shell, `docker-compose`, Helm chart, etc.)
|
||||
This information contains a token which will only be available to the user once, and the UI
|
||||
will make it clear to the user that the value will not be shown again, as registering the same runner multiple times
|
||||
This information contains a token which is available to the user only once, and the UI
|
||||
makes it clear to the user that the value shall not be shown again, as registering the same runner multiple times
|
||||
is discouraged (though not impossible).
|
||||
|
||||
1. The user copies and pastes the instructions for the intended deployment scenario (a `deploy` command), leading to the following actions:
|
||||
1. The user copies and pastes the instructions for the intended deployment scenario (a `register` command), leading to the following actions:
|
||||
|
||||
1. Upon executing the new `gitlab-runner deploy` command in the instructions, `gitlab-runner` will perform
|
||||
a call to the `POST /runners/verify` with the given runner token;
|
||||
1. If the `POST /runners/verify` GitLab endpoint validates the token, the `config.toml` file will be populated with the configuration.
|
||||
1. Upon executing the new `gitlab-runner register` command in the instructions, `gitlab-runner` performs
|
||||
a call to the `POST /api/v4/runners/verify` with the given runner token;
|
||||
1. If the `POST /api/v4/runners/verify` GitLab endpoint validates the token, the `config.toml`
|
||||
file is populated with the configuration;
|
||||
1. Whenever a runner pings for a job, the respective `ci_runner_machines` record is
|
||||
["upserted"](https://en.wiktionary.org/wiki/upsert) with the latest information about the
|
||||
runner (with Redis cache in front of it like we do for Runner heartbeats).
|
||||
|
||||
The `gitlab-runner deploy` will also accept executor-specific arguments
|
||||
currently present in the `register` command.
|
||||
As part of the transition period, we provide admins and top-level group owners with an
|
||||
instance/group-level setting (`allow_runner_registration_token`) to disable the legacy registration
|
||||
token functionality and enforce using only the new workflow.
|
||||
Any attempt by a `gitlab-runner register` command to hit the `POST /api/v4/runners` endpoint
|
||||
to register a new runner with a registration token results in a `HTTP 410 Gone` status code.
|
||||
|
||||
As part of the transition period, we will provide admins and top-level group owners with a instance/group-level setting to disable
|
||||
the legacy registration token functionality and enforce using only the new workflow.
|
||||
Any attempt by a `gitlab-runner register` command to hit the `POST /runners` endpoint to register a new runner
|
||||
will result in a `HTTP 410 - Gone` status code. The instance setting is inherited by the groups
|
||||
, which means that if the legacy registration method is disabled at the instance method, the descendant groups/projects will also mandatorily
|
||||
prevent the legacy registration method.
|
||||
The instance setting is inherited by the groups. This means that if the legacy registration method
|
||||
is disabled at the instance method, the descendant groups/projects mandatorily prevents the legacy
|
||||
registration method.
|
||||
|
||||
The registration token workflow is to be deprecated (with a deprecation notice printed by the `gitlab-runner register` command)
|
||||
and removed at a future major release after the concept is proven stable and customers have migrated to the new workflow.
|
||||
|
||||
### Handling of legacy runners
|
||||
|
||||
Legacy versions of GitLab Runner will not send the unique system identifier in its requests, and we
|
||||
Legacy versions of GitLab Runner do not send the unique system identifier in its requests, and we
|
||||
will not change logic in Workhorse to handle unique system IDs. This can be improved upon in the
|
||||
future once the legacy registration system is removed, and runners have been upgraded to newer
|
||||
future after the legacy registration system is removed, and runners have been upgraded to newer
|
||||
versions.
|
||||
|
||||
Not using the unique system ID means that all connected runners with the same token will be
|
||||
Job pings from such legacy runners results in a `ci_runner_machines` record containing a
|
||||
`<legacy>` `machine_id` field value.
|
||||
|
||||
Not using the unique system ID means that all connected runners with the same token are
|
||||
notified, instead of just the runner matching the exact system identifier. While not ideal, this is
|
||||
not an issue per-se.
|
||||
|
||||
### Helm chart
|
||||
### `ci_runner_machines` record lifetime
|
||||
|
||||
The `runnerRegistrationToken` entry in the [`values.yaml` file](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/a70bc29a903b79d5675bb0c45d981adf8b7a8659/values.yaml#L52)
|
||||
will be retired. The `runnerRegistrationToken` entry will be replaced by the existing `runnerToken` value, which will be passed
|
||||
to the new `gitlab-runner deploy` command in [`configmap.yaml`](https://gitlab.com/gitlab-org/charts/gitlab-runner/-/blob/a70bc29a903b79d5675bb0c45d981adf8b7a8659/templates/configmap.yaml#L116).
|
||||
New records are created when the runner pings the GitLab instance for new jobs, if a record matching
|
||||
the `token`+`system_id` does not already exist.
|
||||
|
||||
Due to the time-decaying nature of the `ci_runner_machines` records, they are automatically
|
||||
cleaned after 7 days after the last contact from the respective runner.
|
||||
|
||||
### Required adaptations
|
||||
|
||||
#### Migration to `ci_runner_machines` table
|
||||
|
||||
When details from `ci_runner_machines` are needed, we need to fall back to the existing fields in
|
||||
`ci_runner` if a match is not found in `ci_runner_machines`.
|
||||
|
||||
#### REST API
|
||||
|
||||
API endpoints receiving runner tokens should be changed to also take an optional
|
||||
`system_id` parameter, sent alongside with the runner token (most often as a JSON parameter on the
|
||||
request body).
|
||||
|
||||
#### GraphQL `CiRunner` type
|
||||
|
||||
The [`CiRunner` type](../../../api/graphql/reference/index.md#cirunner) closely reflects the
|
||||
`ci_runners` model. This means that machine information such as `ipAddress`, `architectureName`,
|
||||
and `executorName` among others are no longer singular values in the proposed approach.
|
||||
We can live with that fact for the time being and start returning lists of unique values, separated
|
||||
by commas.
|
||||
The respective `CiRunner` fields must return the values for the `ci_runner_machines` entries
|
||||
(falling back to `ci_runner` record if non-existent).
|
||||
|
||||
#### Stale runner cleanup
|
||||
|
||||
The functionality to
|
||||
[clean up stale runners](../../../ci/runners/configure_runners.md#clean-up-stale-runners) needs
|
||||
to be adapted to clean up `ci_runner_machines` records instead of `ci_runners` records.
|
||||
|
||||
At some point after the removal of the registration token support, we'll want to create a background
|
||||
migration to clean up stale runners that have been created with a registration token (leveraging the
|
||||
enum column created in the `ci_runners` table.
|
||||
|
||||
### Runner creation through API
|
||||
|
||||
|
|
@ -176,21 +292,66 @@ using PAT tokens for example - such that every runner is associated with an owne
|
|||
|
||||
## Implementation plan
|
||||
|
||||
### Stage 1 - Deprecations
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|-----------|---------|
|
||||
| GitLab Rails app | `15.x` (latest at `15.6`) | Deprecate `POST /api/v4/runners` endpoint for `16.0`. This hinges on a [proposal](https://gitlab.com/gitlab-org/gitlab/-/issues/373774) to allow deprecating REST API endpoints for security reasons. |
|
||||
| GitLab Runner | `15.x` (latest at `15.8`) | Add deprecation notice for `register` command for `16.0`. |
|
||||
| GitLab Runner | `15.x` | Ensure all runner entries in `config.toml` have unique system identifier values assigned. Log new system ID values with `INFO` level as they get created. |
|
||||
| GitLab Runner | `15.x` | Start additionally logging unique system ID anywhere we log the runner short SHA. |
|
||||
| GitLab Rails app | `15.x` | Create database migrations to add settings from `application_settings` and `namaspace_settings` tables. |
|
||||
| GitLab Runner | `15.x` | Start sending `unique_id` value in `POST /jobs/request` request and other follow-up requests that require identifying the unique system. |
|
||||
| GitLab Runner | `15.x` | Implement new user-authenticated API (REST and GraphQL) to create a new runner. |
|
||||
| GitLab Rails app | `15.x` | Implement UI to create new runner. |
|
||||
| GitLab Runner | `16.0` | Remove `register` command and support for `POST /runners` endpoint. |
|
||||
| GitLab Rails app | `16.0` | Remove legacy UI showing registration with a registration token. |
|
||||
| GitLab Rails app | `16.0` | Create database migrations to remove settings from `application_settings` and `namaspace_settings` tables. |
|
||||
| GitLab Rails app | `16.0` | Make [`POST /api/v4/runners` endpoint](../../../api/runners.md#register-a-new-runner-deprecated) permanently return `410 Gone`. A future v5 version of the API would return `404 Not Found`. |
|
||||
| GitLab Rails app | `16.0` | Start refusing job requests that don't include a unique ID. |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Rails app | `15.6` | Deprecate `POST /api/v4/runners` endpoint for `17.0`. This hinges on a [proposal](https://gitlab.com/gitlab-org/gitlab/-/issues/373774) to allow deprecating REST API endpoints for security reasons. |
|
||||
| GitLab Runner | `15.6` | Add deprecation notice for `register` command for `17.0`. |
|
||||
| GitLab Runner Helm Chart | `15.6` | Add deprecation notice for `runnerRegistrationToken` command for `17.0`. |
|
||||
| GitLab Runner Operator | `15.6` | Add deprecation notice for `runner-registration-token` command for `17.0`. |
|
||||
| GitLab Runner / GitLab Rails app | `15.7` | Add deprecation notice for registration token reset for `17.0`. |
|
||||
|
||||
### Stage 2 - Prepare `gitlab-runner` for `system_id`
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Runner | `15.x` | Ensure a sidecar TOML file exists with a `system_id` value.<br/>Log new system ID values with `INFO` level as they get assigned. |
|
||||
| GitLab Runner | `15.x` | Log unique system ID in the build logs. |
|
||||
| GitLab Runner | `15.x` | Label Prometheus metrics with unique system ID. |
|
||||
| GitLab Runner | `15.x` | Prepare `register` command to fail if runner server-side configuration options are passed together with a new `glrt-` token. |
|
||||
|
||||
### Stage 3 - Database changes
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Rails app | | Create database migration to add columns to `ci_runners` table. |
|
||||
| GitLab Rails app | | Create database migration to add `ci_runner_machines` table. |
|
||||
| GitLab Rails app | | Create database migration to add `ci_runner_machines.machine_id` foreign key to `ci_builds_runner_session` table. |
|
||||
| GitLab Rails app | | Create database migrations to add `allow_runner_registration_token` setting to `application_settings` and `namespace_settings` tables (default: `true`). |
|
||||
| GitLab Runner | | Use runner token + `system_id` JSON parameters in `POST /jobs/request` request in the [heartbeat request](https://gitlab.com/gitlab-org/gitlab/blob/c73c96a8ffd515295842d72a3635a8ae873d688c/lib/api/ci/helpers/runner.rb#L14-20) to update the `ci_runner_machines` cache/table. |
|
||||
| GitLab Runner | | Start sending `system_id` value in `POST /jobs/request` request and other follow-up requests that require identifying the unique system. |
|
||||
| GitLab Rails app | | Create service similar to `StaleGroupRunnersPruneCronWorker` service to clean up `ci_runner_machines` records instead of `ci_runners` records.<br/>Existing service continues to exist but focuses only on legacy runners. |
|
||||
|
||||
### Stage 4 - New UI
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Runner | | Implement new GraphQL user-authenticated API to create a new runner. |
|
||||
| GitLab Runner | | [Add prefix to newly generated runner authentication tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/383198). |
|
||||
| GitLab Rails app | | Implement UI to create new runner. |
|
||||
| GitLab Rails app | | GraphQL changes to `CiRunner` type. |
|
||||
| GitLab Rails app | | UI changes to runner details view (listing of platform, architecture, IP address, etc.) (?) |
|
||||
|
||||
### Stage 5 - Optional disabling of registration token
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Rails app | | Add UI to allow disabling use of registration tokens at project or group level. |
|
||||
| GitLab Rails app | `16.0` | Introduce `:disable_runner_registration_tokens` feature flag (enabled by default) to control whether use of registration tokens is allowed. |
|
||||
| GitLab Rails app | | Make [`POST /api/v4/runners` endpoint](../../../api/runners.md#register-a-new-runner) permanently return `HTTP 410 Gone` if either `allow_runner_registration_token` setting or `:disable_runner_registration_tokens` feature flag disables registration tokens.<br/>A future v5 version of the API should return `HTTP 404 Not Found`. |
|
||||
| GitLab Rails app | | Start refusing job requests that don't include a unique ID, if either `allow_runner_registration_token` setting or `:disable_runner_registration_tokens` feature flag disables registration tokens. |
|
||||
| GitLab Rails app | | Hide legacy UI showing registration with a registration token, if `:disable_runner_registration_tokens` feature flag disables registration tokens. |
|
||||
|
||||
### Stage 6 - Removals
|
||||
|
||||
| Component | Milestone | Changes |
|
||||
|------------------|----------:|---------|
|
||||
| GitLab Rails app | `17.0` | Remove legacy UI showing registration with a registration token. |
|
||||
| GitLab Runner | `17.0` | Remove runner model arguments from `register` command (for example `--run-untagged`, `--tag-list`, etc.) |
|
||||
| GitLab Rails app | `17.0` | Create database migrations to drop `allow_runner_registration_token` setting columns from `application_settings` and `namespace_settings` tables. |
|
||||
| GitLab Rails app | `17.0` | Create database migrations to drop:<br/>- `runners_registration_token`/`runners_registration_token_encrypted` columns from `application_settings`;<br/>- `runners_token`/`runners_token_encrypted` from `namespaces` table;<br/>- `runners_token`/`runners_token_encrypted` from `projects` table. |
|
||||
| GitLab Rails app | `17.0` | Remove `:disable_runner_registration_tokens` feature flag. |
|
||||
|
||||
## Status
|
||||
|
||||
|
|
|
|||
|
|
@ -2340,12 +2340,12 @@ In this example:
|
|||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.7.
|
||||
|
||||
Use `needs:project` to download artifacts from up to five jobs in other pipelines.
|
||||
The artifacts are downloaded from the latest successful pipeline for the specified ref.
|
||||
The artifacts are downloaded from the latest successful specified job for the specified ref.
|
||||
To specify multiple jobs, add each as separate array items under the `needs` keyword.
|
||||
|
||||
If there is a pipeline running for the specified ref, a job with `needs:project`
|
||||
does not wait for the pipeline to complete. Instead, the job downloads the artifact
|
||||
from the latest pipeline that completed successfully.
|
||||
If there is a pipeline running for the ref, a job with `needs:project`
|
||||
does not wait for the pipeline to complete. Instead, the artifacts are downloaded
|
||||
from the latest successful run of the specified job.
|
||||
|
||||
`needs:project` must be used with `job`, `ref`, and `artifacts`.
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,34 @@ For non-200 HTTP responses, use the provided helpers in `lib/api/helpers.rb` to
|
|||
|
||||
For `DELETE` requests, you should also generally use the `destroy_conditionally!` helper which by default returns a `204 No Content` response on success, or a `412 Precondition Failed` response if the given `If-Unmodified-Since` header is out of range. This helper calls `#destroy` on the passed resource, but you can also implement a custom deletion method by passing a block.
|
||||
|
||||
## Choosing HTTP verbs
|
||||
|
||||
When defining a new [API route](https://github.com/ruby-grape/grape#routes), use
|
||||
the correct [HTTP request method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods).
|
||||
|
||||
### Deciding between `PATCH` and `PUT`
|
||||
|
||||
In a Rails application, both the `PATCH` and `PUT` request methods are routed to
|
||||
the `update` method in controllers. With Grape, the framework we use to write
|
||||
the GitLab API, you must explicitly set the `PATCH` or `PUT` HTTP verb for an
|
||||
endpoint that does updates.
|
||||
|
||||
If the endpoint updates *all* attributes of a given resource, use the
|
||||
[`PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) request
|
||||
method. If the endpoint updates *some* attributes of a given resource, use the
|
||||
[`PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH)
|
||||
request method.
|
||||
|
||||
Here is a good example for `PATCH`: [`PATCH /projects/:id/protected_branches/:name`](../api/protected_branches.md#update-a-protected-branch)
|
||||
Here is a good example for `PUT`: [`PUT /projects/:id/merge_requests/:merge_request_iid/approve`](../api/merge_request_approvals.md#approve-merge-request)
|
||||
|
||||
Often, a good `PUT` endpoint only has ids and a verb (in the example above, "approve").
|
||||
Or, they only have a single value and represent a key/value pair.
|
||||
|
||||
The [Rails blog](https://rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates)
|
||||
has a detailed explanation of why `PATCH` is usually the most apt verb for web
|
||||
API endpoints that perform an update.
|
||||
|
||||
## Using API path helpers in GitLab Rails codebase
|
||||
|
||||
Because we support [installing GitLab under a relative URL](../install/relative_url.md), one must take this
|
||||
|
|
|
|||
|
|
@ -289,10 +289,47 @@ To disable a feature flag that has been enabled for a specific project you can r
|
|||
/chatops run feature set --project=gitlab-org/gitlab some_feature false
|
||||
```
|
||||
|
||||
You cannot selectively disable feature flags for a specific project/group/user without applying a [specific method of implementing](index.md#selectively-disable-by-actor) the feature flags.
|
||||
You cannot selectively disable feature flags for a specific project/group/user without applying a [specific method of implementing](controls.md#selectively-disable-by-actor) the feature flags.
|
||||
|
||||
If a feature flag is disabled via ChatOps, that will take precedence over the `default_enabled` value in the YAML. In other words, you could have a feature enabled for on-premise installations but not for GitLab.com.
|
||||
|
||||
#### Selectively disable by actor
|
||||
|
||||
By default you cannot selectively disable a feature flag by actor.
|
||||
|
||||
```shell
|
||||
# This will not work how you would expect.
|
||||
/chatops run feature set some_feature true
|
||||
/chatops run feature set --project=gitlab-org/gitlab some_feature false
|
||||
```
|
||||
|
||||
However, if you add two feature flags, you can write your conditional statement in such a way that the equivalent selective disable is possible.
|
||||
|
||||
```ruby
|
||||
Feature.enabled?(:a_feature, project) && Feature.disabled?(:a_feature_override, project)
|
||||
```
|
||||
|
||||
```shell
|
||||
# This will enable a feature flag globally, except for gitlab-org/gitlab
|
||||
/chatops run feature set a_feature true
|
||||
/chatops run feature set --project=gitlab-org/gitlab a_feature_override true
|
||||
```
|
||||
|
||||
#### Percentage-based actor selection
|
||||
|
||||
When using the percentage rollout of actors on multiple feature flags, the actors for each feature flag are selected separately.
|
||||
|
||||
For example, the following feature flags are enabled for a certain percentage of actors:
|
||||
|
||||
```plaintext
|
||||
/chatops run feature set feature-set-1 25 --actors
|
||||
/chatops run feature set feature-set-2 25 --actors
|
||||
```
|
||||
|
||||
If a project A has `:feature-set-1` enabled, there is no guarantee that project A also has `:feature-set-2` enabled.
|
||||
|
||||
For more detail, see [This is how percentages work in Flipper](https://www.hackwithpassion.com/this-is-how-percentages-work-in-flipper/).
|
||||
|
||||
### Feature flag change logging
|
||||
|
||||
#### ChatOps level
|
||||
|
|
|
|||
|
|
@ -398,44 +398,8 @@ Feature.enabled?(:feature_flag, group)
|
|||
Feature.enabled?(:feature_flag, user)
|
||||
```
|
||||
|
||||
Please see [Feature flag controls](controls.md#process) for more details on working with feature flags.
|
||||
|
||||
#### Selectively disable by actor
|
||||
|
||||
By default you cannot selectively disable a feature flag by actor.
|
||||
|
||||
```shell
|
||||
# This will not work how you would expect.
|
||||
/chatops run feature set some_feature true
|
||||
/chatops run feature set --project=gitlab-org/gitlab some_feature false
|
||||
```
|
||||
|
||||
However, if you add two feature flags, you can write your conditional statement in such a way that the equivalent selective disable is possible.
|
||||
|
||||
```ruby
|
||||
Feature.enabled?(:a_feature, project) && Feature.disabled?(:a_feature_override, project)
|
||||
```
|
||||
|
||||
```shell
|
||||
# This will enable a feature flag globally, except for gitlab-org/gitlab
|
||||
/chatops run feature set a_feature true
|
||||
/chatops run feature set --project=gitlab-org/gitlab a_feature_override true
|
||||
```
|
||||
|
||||
#### Percentage-based actor selection
|
||||
|
||||
When using the percentage rollout of actors on multiple feature flags, the actors for each feature flag are selected separately.
|
||||
|
||||
For example, the following feature flags are enabled for a certain percentage of actors:
|
||||
|
||||
```plaintext
|
||||
/chatops run feature set feature-set-1 25 --actors
|
||||
/chatops run feature set feature-set-2 25 --actors
|
||||
```
|
||||
|
||||
If a project A has `:feature-set-1` enabled, there is no guarantee that project A also has `:feature-set-2` enabled.
|
||||
|
||||
For more detail, see [This is how percentages work in Flipper](https://www.hackwithpassion.com/this-is-how-percentages-work-in-flipper/).
|
||||
See [Feature flags in the development of GitLab](controls.md#process) for details on how to use ChatOps
|
||||
to selectively enable or disable feature flags in GitLab-provided environments, like staging and production.
|
||||
|
||||
#### Use actors for verifying in production
|
||||
|
||||
|
|
|
|||
|
|
@ -207,12 +207,12 @@ From GitLab 13.6, users can [specify any runner configuration in the GitLab Runn
|
|||
|
||||
</div>
|
||||
|
||||
<div class="deprecation removal-160 breaking-change">
|
||||
<div class="deprecation removal-170 breaking-change">
|
||||
|
||||
### GitLab Runner registration token in Runner Operator
|
||||
|
||||
End of Support: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)<br />
|
||||
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
|
||||
Planned removal: GitLab <span class="removal-milestone">17.0</span> (2024-04-22)
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
|
|
@ -222,56 +222,57 @@ The [`runner-registration-token`](https://docs.gitlab.com/runner/install/operato
|
|||
|
||||
</div>
|
||||
|
||||
<div class="deprecation removal-160 breaking-change">
|
||||
<div class="deprecation removal-170 breaking-change">
|
||||
|
||||
### `POST /api/v4/runners` method to register runners
|
||||
### Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint
|
||||
|
||||
End of Support: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)<br />
|
||||
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
|
||||
Planned removal: GitLab <span class="removal-milestone">17.0</span> (2024-04-22)
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
Review the details carefully before upgrading.
|
||||
|
||||
The `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
|
||||
This endpoint and method [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
|
||||
with a GitLab instance at the instance, group, or project level through the API. We plan to remove this endpoint
|
||||
and method in GitLab 16.0.
|
||||
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
|
||||
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
|
||||
with a GitLab instance at the instance, group, or project level through the API. We plan to remove the support for
|
||||
registration tokens and certain configuration arguments in this endpoint in GitLab 17.0.
|
||||
|
||||
In GitLab 15.8, we plan to implement a new method to bind runners to a GitLab instance,
|
||||
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/).
|
||||
This new architecture introduces a new method for registering runners and will eliminate the legacy
|
||||
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
|
||||
From GitLab 16.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
|
||||
From GitLab 17.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation removal-160 breaking-change">
|
||||
<div class="deprecation removal-170 breaking-change">
|
||||
|
||||
### `gitlab-runner register` command
|
||||
### Registration tokens and server-side runner arguments in `gitlab-runner register` command
|
||||
|
||||
End of Support: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)<br />
|
||||
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
|
||||
Planned removal: GitLab <span class="removal-milestone">17.0</span> (2024-04-22)
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
Review the details carefully before upgrading.
|
||||
|
||||
The command to [register](https://docs.gitlab.com/runner/register/) a runner, `gitlab-runner register` is deprecated.
|
||||
The support for registration tokens and certain configuration arguments in the command to [register](https://docs.gitlab.com/runner/register/) a runner, `gitlab-runner register` is deprecated.
|
||||
GitLab plans to introduce a new [GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/) in GitLab 15.8,
|
||||
which introduces a new method for registering runners and eliminates the legacy
|
||||
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
|
||||
The new method will involve passing a [runner authentication token](https://docs.gitlab.com/ee/security/token_overview.html#runner-authentication-tokens-also-called-runner-tokens)
|
||||
to a new `gitlab-runner deploy` command.
|
||||
The new method will involve creating the runner in the GitLab UI and passing the
|
||||
[runner authentication token](https://docs.gitlab.com/ee/security/token_overview.html#runner-authentication-tokens-also-called-runner-tokens)
|
||||
to the `gitlab-runner register` command.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation removal-160 breaking-change">
|
||||
<div class="deprecation removal-170 breaking-change">
|
||||
|
||||
### `runnerRegistrationToken` parameter for GitLab Runner Helm Chart
|
||||
|
||||
End of Support: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)<br />
|
||||
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
|
||||
Planned removal: GitLab <span class="removal-milestone">17.0</span> (2024-04-22)
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
|
|
@ -281,9 +282,9 @@ The [`runnerRegistrationToken`](https://docs.gitlab.com/runner/install/kubernete
|
|||
|
||||
As part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/architecture/blueprints/runner_tokens/), in GitLab 15.8 we plan to introduce:
|
||||
|
||||
- A new method to bind runners to a GitLab instance.
|
||||
- A new method to bind runners to a GitLab instance leveraging `runnerToken`.
|
||||
- A unique system ID saved to the `config.toml`, which will ensure traceability between jobs and runners.
|
||||
From GitLab 16.0 and later, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
|
||||
From GitLab 17.0 and later, the methods to register runners introduced by the new GitLab Runner token architecture will be the only supported methods.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ Otherwise, to add your license:
|
|||
1. Select **Add license**.
|
||||
|
||||
NOTE:
|
||||
In GitLab 14.1.x through 14.10.x, you can access the **Add License** page directly from the URL, `<YourGitLabURL>/admin/license/new`. In GitLab 15.0 and later, the path is `<YourGitLabURL>/admin/subscription`.
|
||||
In GitLab 14.7.x to 14.9.x, you can add the license file with the UI.
|
||||
In GitLab 14.1.x to 14.7, if you have already activated your subscription with an activation code, you cannot access **Add License** from the Admin Area. You must access **Add License** directly from the URL, `<YourGitLabURL>/admin/license/new`.
|
||||
|
||||
## Add your license file during installation
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ rule in the defined policy are met.
|
|||
| `site_profile` | `string` | Name of the selected [DAST site profile](../dast/proxy-based.md#site-profile). | The DAST site profile to execute the DAST scan. This field should only be set if `scan` type is `dast`. |
|
||||
| `scanner_profile` | `string` or `null` | Name of the selected [DAST scanner profile](../dast/proxy-based.md#scanner-profile). | The DAST scanner profile to execute the DAST scan. This field should only be set if `scan` type is `dast`.|
|
||||
| `variables` | `object` | | A set of CI variables, supplied as an array of `key: value` pairs, to apply and enforce for the selected scan. The `key` is the variable name, with its `value` provided as a string. This parameter supports any variable that the GitLab CI job supports for the specified scan. |
|
||||
| `tags` | `array` of `string` | | A list of runner tags for the policy. The policy jobs will be run by runner with the specified tags. |
|
||||
| `tags` | `array` of `string` | | A list of runner tags for the policy. The policy jobs will be run by runner with the specified tags. Tags are not supported for the `sast` and `dependency_scanning` scan types because they use the default template and run in a child pipeline. |
|
||||
|
||||
Note the following:
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ module API
|
|||
|
||||
before do
|
||||
authenticate!
|
||||
feature_flag_enabled?
|
||||
authorize! :read_secure_files, user_project
|
||||
end
|
||||
|
||||
|
|
@ -113,10 +112,6 @@ module API
|
|||
end
|
||||
|
||||
helpers do
|
||||
def feature_flag_enabled?
|
||||
service_unavailable! unless Feature.enabled?(:ci_secure_files, user_project)
|
||||
end
|
||||
|
||||
def read_only_feature_flag_enabled?
|
||||
service_unavailable! if Feature.enabled?(:ci_secure_files_read_only, user_project, type: :ops)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ module API
|
|||
]
|
||||
failure [
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 422, message: 'Validation failure' }
|
||||
{ code: 422, message: 'Validation failure' },
|
||||
{ code: 413, message: 'Request Entity Too Large' }
|
||||
]
|
||||
tags %w[terraform_state]
|
||||
end
|
||||
|
|
@ -101,6 +102,9 @@ module API
|
|||
data = request.body.read
|
||||
no_content! if data.empty?
|
||||
|
||||
max_state_size = Gitlab::CurrentSettings.max_terraform_state_size_bytes
|
||||
file_too_large! if max_state_size > 0 && data.size > max_state_size
|
||||
|
||||
remote_state_handler.handle_with_lock do |state|
|
||||
state.update_file!(CarrierWaveStringFile.new(data), version: params[:serial], build: current_authenticated_job)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module Gitlab
|
|||
|
||||
def initialize(logger: Gitlab::AppLogger)
|
||||
@logger = logger
|
||||
init_prometheus_metrics
|
||||
end
|
||||
|
||||
def started(labels = {})
|
||||
|
|
@ -21,13 +22,13 @@ module Gitlab
|
|||
end
|
||||
|
||||
def threshold_violated(monitor_name)
|
||||
counter_violations.increment(reason: monitor_name)
|
||||
@counter_violations.increment(reason: monitor_name)
|
||||
end
|
||||
|
||||
def strikes_exceeded(monitor_name, labels = {})
|
||||
logger.warn(log_labels(labels))
|
||||
|
||||
counter_violations_handled.increment(reason: monitor_name)
|
||||
@counter_violations_handled.increment(reason: monitor_name)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -48,24 +49,18 @@ module Gitlab
|
|||
::Prometheus::PidProvider.worker_id
|
||||
end
|
||||
|
||||
def counter_violations
|
||||
strong_memoize("counter_violations") do
|
||||
::Gitlab::Metrics.counter(
|
||||
:gitlab_memwd_violations_total,
|
||||
'Total number of times a Ruby process violated a memory threshold',
|
||||
{ pid: worker_id }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def counter_violations_handled
|
||||
strong_memoize("counter_violations_handled") do
|
||||
::Gitlab::Metrics.counter(
|
||||
:gitlab_memwd_violations_handled_total,
|
||||
'Total number of times Ruby process memory violations were handled',
|
||||
{ pid: worker_id }
|
||||
)
|
||||
end
|
||||
def init_prometheus_metrics
|
||||
default_labels = { pid: worker_id }
|
||||
@counter_violations = Gitlab::Metrics.counter(
|
||||
:gitlab_memwd_violations_total,
|
||||
'Total number of times a Ruby process violated a memory threshold',
|
||||
default_labels
|
||||
)
|
||||
@counter_violations_handled = Gitlab::Metrics.counter(
|
||||
:gitlab_memwd_violations_handled_total,
|
||||
'Total number of times Ruby process memory violations were handled',
|
||||
default_labels
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module Gitlab
|
|||
|
||||
def initialize(logger: ::Sidekiq.logger)
|
||||
@event_reporter = EventReporter.new(logger: logger)
|
||||
@sidekiq_daemon_monitor = Gitlab::SidekiqDaemon::Monitor.instance
|
||||
init_prometheus_metrics
|
||||
end
|
||||
|
||||
|
|
@ -26,16 +27,12 @@ module Gitlab
|
|||
attr_reader :event_reporter
|
||||
|
||||
def fetch_running_jobs
|
||||
running_jobs = []
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.with_running_jobs do |jobs|
|
||||
running_jobs = jobs.map do |jid, job|
|
||||
{
|
||||
jid: jid,
|
||||
worker_class: job[:worker_class].name
|
||||
}
|
||||
end
|
||||
@sidekiq_daemon_monitor.jobs.map do |jid, job|
|
||||
{
|
||||
jid: jid,
|
||||
worker_class: job[:worker_class].name
|
||||
}
|
||||
end
|
||||
running_jobs
|
||||
end
|
||||
|
||||
def increment_worker_counters(running_jobs)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ module Gitlab
|
|||
|
||||
@enabled = true
|
||||
@metrics = init_metrics
|
||||
@sidekiq_daemon_monitor = Gitlab::SidekiqDaemon::Monitor.instance
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -193,17 +194,12 @@ module Gitlab
|
|||
end
|
||||
|
||||
def fetch_running_jobs
|
||||
jobs = []
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.jobs_mutex.synchronize do
|
||||
jobs = Gitlab::SidekiqDaemon::Monitor.instance.jobs.map do |jid, job|
|
||||
{
|
||||
jid: jid,
|
||||
worker_class: job[:worker_class].name
|
||||
}
|
||||
end
|
||||
@sidekiq_daemon_monitor.jobs.map do |jid, job|
|
||||
{
|
||||
jid: jid,
|
||||
worker_class: job[:worker_class].name
|
||||
}
|
||||
end
|
||||
|
||||
jobs
|
||||
end
|
||||
|
||||
def out_of_range_description(rss, hard_limit, soft_limit, deadline_exceeded)
|
||||
|
|
@ -269,10 +265,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def rss_increase_by_jobs
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.jobs_mutex.synchronize do
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.jobs.sum do |job|
|
||||
rss_increase_by_job(job)
|
||||
end
|
||||
@sidekiq_daemon_monitor.jobs.sum do |_, job|
|
||||
rss_increase_by_job(job)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -297,7 +291,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def any_jobs?
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.jobs.any?
|
||||
@sidekiq_daemon_monitor.jobs.any?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ module Gitlab
|
|||
# that should not be caught by application
|
||||
CancelledError = Class.new(Exception) # rubocop:disable Lint/InheritException
|
||||
|
||||
attr_reader :jobs
|
||||
attr_reader :jobs_mutex
|
||||
|
||||
def initialize
|
||||
super
|
||||
|
||||
|
|
@ -31,8 +28,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def within_job(worker_class, jid, queue)
|
||||
jobs_mutex.synchronize do
|
||||
jobs[jid] = { worker_class: worker_class, thread: Thread.current, started_at: Gitlab::Metrics::System.monotonic_time }
|
||||
@jobs_mutex.synchronize do
|
||||
@jobs[jid] = { worker_class: worker_class, thread: Thread.current, started_at: Gitlab::Metrics::System.monotonic_time }
|
||||
end
|
||||
|
||||
if cancelled?(jid)
|
||||
|
|
@ -48,8 +45,8 @@ module Gitlab
|
|||
|
||||
yield
|
||||
ensure
|
||||
jobs_mutex.synchronize do
|
||||
jobs.delete(jid)
|
||||
@jobs_mutex.synchronize do
|
||||
@jobs.delete(jid)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -65,9 +62,9 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def with_running_jobs
|
||||
def jobs
|
||||
@jobs_mutex.synchronize do
|
||||
yield @jobs.dup
|
||||
@jobs.dup
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -172,14 +169,14 @@ module Gitlab
|
|||
# This is why it passes thread in block,
|
||||
# to ensure that we do process this thread
|
||||
def find_thread_unsafe(jid)
|
||||
jobs.dig(jid, :thread)
|
||||
@jobs.dig(jid, :thread)
|
||||
end
|
||||
|
||||
def find_thread_with_lock(jid)
|
||||
# don't try to lock if we cannot find the thread
|
||||
return unless find_thread_unsafe(jid)
|
||||
|
||||
jobs_mutex.synchronize do
|
||||
@jobs_mutex.synchronize do
|
||||
find_thread_unsafe(jid).tap do |thread|
|
||||
yield(thread) if thread
|
||||
end
|
||||
|
|
|
|||
|
|
@ -31420,6 +31420,9 @@ msgstr ""
|
|||
msgid "ProductAnalytics|An error occured while loading the %{widgetTitle} widget."
|
||||
msgstr ""
|
||||
|
||||
msgid "ProductAnalytics|An error occurred while fetching data. Refresh the page to try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "ProductAnalytics|Audience"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ module ReviewApps
|
|||
|
||||
private
|
||||
|
||||
attr_reader :api_endpoint, :dry_run, :environments_not_found_count, :gitlab_token, :project_path
|
||||
attr_reader :api_endpoint, :dry_run, :gitlab_token, :project_path
|
||||
|
||||
def fetch_environment(environment)
|
||||
gitlab.environment(project_path, environment.id)
|
||||
|
|
@ -190,9 +190,9 @@ module ReviewApps
|
|||
|
||||
rescue Gitlab::Error::NotFound
|
||||
puts "Review app '#{environment.name}' / '#{environment.slug}' (##{environment.id}) was not found: ignoring it"
|
||||
environments_not_found_count += 1
|
||||
@environments_not_found_count += 1
|
||||
|
||||
if environments_not_found_count >= ENVIRONMENTS_NOT_FOUND_THRESHOLD
|
||||
if @environments_not_found_count >= ENVIRONMENTS_NOT_FOUND_THRESHOLD
|
||||
raise "At least #{ENVIRONMENTS_NOT_FOUND_THRESHOLD} environments were missing when we tried to delete them. Please investigate"
|
||||
end
|
||||
rescue Gitlab::Error::Forbidden
|
||||
|
|
|
|||
|
|
@ -12,31 +12,10 @@ RSpec.describe 'Secure Files', :js, feature_category: :projects do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'when the :ci_secure_files feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: true)
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
it 'shows the secure files settings' do
|
||||
visit project_settings_ci_cd_path(project)
|
||||
end
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
it 'shows the secure files settings' do
|
||||
expect(page).to have_content('Secure Files')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :ci_secure_files feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: false)
|
||||
|
||||
visit project_settings_ci_cd_path(project)
|
||||
end
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
it 'does not shows the secure files settings' do
|
||||
expect(page).not_to have_content('Secure Files')
|
||||
end
|
||||
expect(page).to have_content('Secure Files')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,9 @@ jest.mock('~/lib/utils/url_utility', () => ({
|
|||
Vue.use(VueApollo);
|
||||
Vue.use(GlToast);
|
||||
|
||||
const COUNT_QUERIES = 7; // 4 tabs + 3 status queries
|
||||
const STATUS_COUNT_QUERIES = 3;
|
||||
const TAB_COUNT_QUERIES = 4;
|
||||
const COUNT_QUERIES = TAB_COUNT_QUERIES + STATUS_COUNT_QUERIES;
|
||||
|
||||
describe('AdminRunnersApp', () => {
|
||||
let wrapper;
|
||||
|
|
@ -170,6 +172,29 @@ describe('AdminRunnersApp', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('does not show total runner counts when total is 0', () => {
|
||||
beforeEach(async () => {
|
||||
mockRunnersCountHandler.mockResolvedValue({
|
||||
data: {
|
||||
runners: {
|
||||
count: 0,
|
||||
...runnersCountData.runners,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await createComponent({ mountFn: mountExtended });
|
||||
});
|
||||
|
||||
it('fetches only tab counts', () => {
|
||||
expect(mockRunnersCountHandler).toHaveBeenCalledTimes(TAB_COUNT_QUERIES);
|
||||
});
|
||||
|
||||
it('does not shows counters', () => {
|
||||
expect(findRunnerStats().text()).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the runners list', async () => {
|
||||
await createComponent();
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,23 @@ describe('RunnerStats', () => {
|
|||
|
||||
const findSingleStats = () => wrapper.findAllComponents(RunnerSingleStat);
|
||||
|
||||
const RunnerCountStub = {
|
||||
props: ['variables'],
|
||||
render() {
|
||||
// return a count for each status
|
||||
const mockCounts = {
|
||||
undefined: 6, // no status returns "all"
|
||||
[STATUS_ONLINE]: 3,
|
||||
[STATUS_OFFLINE]: 2,
|
||||
[STATUS_STALE]: 1,
|
||||
};
|
||||
|
||||
return this.$scopedSlots.default({
|
||||
count: mockCounts[this.variables.status],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const createComponent = ({ props = {}, mountFn = shallowMount, ...options } = {}) => {
|
||||
wrapper = mountFn(RunnerStats, {
|
||||
propsData: {
|
||||
|
|
@ -23,6 +40,9 @@ describe('RunnerStats', () => {
|
|||
variables: {},
|
||||
...props,
|
||||
},
|
||||
stubs: {
|
||||
RunnerCount: RunnerCountStub,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
|
@ -32,24 +52,8 @@ describe('RunnerStats', () => {
|
|||
});
|
||||
|
||||
it('Displays all the stats', () => {
|
||||
const mockCounts = {
|
||||
[STATUS_ONLINE]: 3,
|
||||
[STATUS_OFFLINE]: 2,
|
||||
[STATUS_STALE]: 1,
|
||||
};
|
||||
|
||||
createComponent({
|
||||
mountFn: mount,
|
||||
stubs: {
|
||||
RunnerCount: {
|
||||
props: ['variables'],
|
||||
render() {
|
||||
return this.$scopedSlots.default({
|
||||
count: mockCounts[this.variables.status],
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const text = wrapper.text();
|
||||
|
|
@ -78,4 +82,21 @@ describe('RunnerStats', () => {
|
|||
expect(stat.props('variables')).toMatchObject(mockVariables);
|
||||
});
|
||||
});
|
||||
|
||||
it('Does not display counts when total is 0', () => {
|
||||
createComponent({
|
||||
mountFn: mount,
|
||||
stubs: {
|
||||
RunnerCount: {
|
||||
render() {
|
||||
return this.$scopedSlots.default({
|
||||
count: 0,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toBe('');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ describe('~/vue_merge_request_widget/components/widget/widget.vue', () => {
|
|||
const findActionButtons = () => wrapper.findComponent(ActionButtons);
|
||||
const findToggleButton = () => wrapper.findByTestId('toggle-button');
|
||||
const findHelpPopover = () => wrapper.findComponent(HelpPopover);
|
||||
const findDynamicScroller = () => wrapper.findByTestId('dynamic-content-scroller');
|
||||
|
||||
const createComponent = ({ propsData, slots } = {}) => {
|
||||
wrapper = shallowMountExtended(Widget, {
|
||||
|
|
@ -411,4 +412,30 @@ describe('~/vue_merge_request_widget/components/widget/widget.vue', () => {
|
|||
expect(wrapper.vm.telemetryHub).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dynamic content', () => {
|
||||
const content = [
|
||||
{
|
||||
id: 'row-id',
|
||||
header: ['This is a header', 'This is a subheader'],
|
||||
text: 'Main text for the row',
|
||||
subtext: 'Optional: Smaller sub-text to be displayed below the main text',
|
||||
},
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
propsData: {
|
||||
isCollapsible: true,
|
||||
content,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('uses a dynamic scroller to show the items', async () => {
|
||||
findToggleButton().vm.$emit('click');
|
||||
await waitForPromises();
|
||||
expect(findDynamicScroller().props('items')).toEqual(content);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,58 +19,40 @@ RSpec.describe Ci::SecureFilesHelper do
|
|||
subject { helper.show_secure_files_setting(project, user) }
|
||||
|
||||
describe '#show_secure_files_setting' do
|
||||
context 'when the :ci_secure_files feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: true)
|
||||
end
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'authenticated user with read permissions' do
|
||||
let(:user) { developer }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'authenticated user with guest permissions' do
|
||||
let(:user) { guest }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'authenticated user with no permissions' do
|
||||
let(:user) { anonymous }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'unconfirmed user' do
|
||||
let(:user) { unconfirmed }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'unauthenticated user' do
|
||||
let(:user) { nil }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'when the :ci_secure_files feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: false)
|
||||
end
|
||||
context 'authenticated user with read permissions' do
|
||||
let(:user) { developer }
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
context 'authenticated user with guest permissions' do
|
||||
let(:user) { guest }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'authenticated user with no permissions' do
|
||||
let(:user) { anonymous }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'unconfirmed user' do
|
||||
let(:user) { unconfirmed }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'unauthenticated user' do
|
||||
let(:user) { nil }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ RSpec.describe Gitlab::Memory::Watchdog::SidekiqEventReporter, feature_category:
|
|||
let(:queue) { 'default' }
|
||||
let(:jid) { SecureRandom.hex }
|
||||
let(:running_jobs) { { jid => { worker_class: DummyWorker } } }
|
||||
let(:sidekiq_daemon_monitor) { instance_double(Gitlab::SidekiqDaemon::Monitor) }
|
||||
let(:worker) do
|
||||
Class.new do
|
||||
def self.name
|
||||
|
|
@ -33,14 +34,15 @@ RSpec.describe Gitlab::Memory::Watchdog::SidekiqEventReporter, feature_category:
|
|||
end
|
||||
|
||||
before do
|
||||
stub_const("DummyWorker", worker)
|
||||
stub_const('DummyWorker', worker)
|
||||
allow(Gitlab::SidekiqDaemon::Monitor).to receive(:instance).and_return(sidekiq_daemon_monitor)
|
||||
allow(::Gitlab::Metrics).to receive(:counter)
|
||||
.with(:sidekiq_watchdog_running_jobs_total, anything)
|
||||
.and_return(sidekiq_watchdog_running_jobs_counter)
|
||||
allow(sidekiq_watchdog_running_jobs_counter).to receive(:increment)
|
||||
allow(logger).to receive(:warn)
|
||||
|
||||
allow(Gitlab::SidekiqDaemon::Monitor.instance).to receive(:with_running_jobs).and_yield(running_jobs)
|
||||
allow(sidekiq_daemon_monitor).to receive(:jobs).and_return(running_jobs)
|
||||
end
|
||||
|
||||
it 'delegates #strikes_exceeded with correct arguments' do
|
||||
|
|
@ -49,7 +51,7 @@ RSpec.describe Gitlab::Memory::Watchdog::SidekiqEventReporter, feature_category:
|
|||
:monitor_name,
|
||||
{
|
||||
message: 'dummy_text',
|
||||
running_jobs: running_jobs
|
||||
running_jobs: [jid: jid, worker_class: 'DummyWorker']
|
||||
}
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,11 +4,23 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
||||
let(:memory_killer) { described_class.new }
|
||||
let(:sidekiq_daemon_monitor) { instance_double(Gitlab::SidekiqDaemon::Monitor) }
|
||||
let(:running_jobs) { {} }
|
||||
let(:pid) { 12345 }
|
||||
let(:worker) do
|
||||
Class.new do
|
||||
def self.name
|
||||
'DummyWorker'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
stub_const('DummyWorker', worker)
|
||||
allow(Sidekiq.logger).to receive(:info)
|
||||
allow(Sidekiq.logger).to receive(:warn)
|
||||
allow(Gitlab::SidekiqDaemon::Monitor).to receive(:instance).and_return(sidekiq_daemon_monitor)
|
||||
allow(sidekiq_daemon_monitor).to receive(:jobs).and_return(running_jobs)
|
||||
allow(memory_killer).to receive(:pid).and_return(pid)
|
||||
|
||||
# make sleep no-op
|
||||
|
|
@ -306,31 +318,37 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
stub_const("#{described_class}::CHECK_INTERVAL_SECONDS", check_interval_seconds)
|
||||
end
|
||||
|
||||
it 'send signal and return when all jobs finished' do
|
||||
expect(Process).to receive(:kill).with(signal, pid).ordered
|
||||
expect(Gitlab::Metrics::System).to receive(:monotonic_time).and_call_original
|
||||
context 'when all jobs are finished' do
|
||||
let(:running_jobs) { {} }
|
||||
|
||||
expect(memory_killer).to receive(:enabled?).and_return(true)
|
||||
expect(memory_killer).to receive(:any_jobs?).and_return(false)
|
||||
it 'send signal and return when all jobs finished' do
|
||||
expect(Process).to receive(:kill).with(signal, pid).ordered
|
||||
expect(Gitlab::Metrics::System).to receive(:monotonic_time).and_call_original
|
||||
|
||||
expect(memory_killer).not_to receive(:sleep)
|
||||
expect(memory_killer).to receive(:enabled?).and_return(true)
|
||||
|
||||
subject
|
||||
expect(memory_killer).not_to receive(:sleep)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it 'send signal and wait till deadline if any job not finished' do
|
||||
expect(Process).to receive(:kill)
|
||||
.with(signal, pid)
|
||||
.ordered
|
||||
context 'when there are still running jobs' do
|
||||
let(:running_jobs) { { 'jid1' => { worker_class: DummyWorker } } }
|
||||
|
||||
expect(Gitlab::Metrics::System).to receive(:monotonic_time)
|
||||
.and_call_original
|
||||
.at_least(:once)
|
||||
it 'send signal and wait till deadline if any job not finished' do
|
||||
expect(Process).to receive(:kill)
|
||||
.with(signal, pid)
|
||||
.ordered
|
||||
|
||||
expect(memory_killer).to receive(:enabled?).and_return(true).at_least(:once)
|
||||
expect(memory_killer).to receive(:any_jobs?).and_return(true).at_least(:once)
|
||||
expect(Gitlab::Metrics::System).to receive(:monotonic_time)
|
||||
.and_call_original
|
||||
.at_least(:once)
|
||||
|
||||
subject
|
||||
expect(memory_killer).to receive(:enabled?).and_return(true).at_least(:once)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -377,21 +395,11 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
let(:jid) { 1 }
|
||||
let(:reason) { 'rss out of range reason description' }
|
||||
let(:queue) { 'default' }
|
||||
let(:running_jobs) { [{ jid: jid, worker_class: 'DummyWorker' }] }
|
||||
let(:metrics) { memory_killer.instance_variable_get(:@metrics) }
|
||||
let(:worker) do
|
||||
Class.new do
|
||||
def self.name
|
||||
'DummyWorker'
|
||||
end
|
||||
|
||||
include ApplicationWorker
|
||||
end
|
||||
end
|
||||
let(:metrics) { memory_killer.instance_variable_get(:@metrics) }
|
||||
let(:running_jobs) { { jid => { worker_class: DummyWorker } } }
|
||||
|
||||
before do
|
||||
stub_const("DummyWorker", worker)
|
||||
|
||||
allow(memory_killer).to receive(:get_rss_kb).and_return(*current_rss)
|
||||
allow(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(soft_limit_rss)
|
||||
allow(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(hard_limit_rss)
|
||||
|
|
@ -413,15 +421,13 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
hard_limit_rss: hard_limit_rss,
|
||||
soft_limit_rss: soft_limit_rss,
|
||||
reason: reason,
|
||||
running_jobs: running_jobs,
|
||||
running_jobs: [jid: jid, worker_class: 'DummyWorker'],
|
||||
memory_total_kb: memory_total)
|
||||
|
||||
expect(metrics[:sidekiq_memory_killer_running_jobs]).to receive(:increment)
|
||||
.with({ worker_class: "DummyWorker", deadline_exceeded: true })
|
||||
|
||||
Gitlab::SidekiqDaemon::Monitor.instance.within_job(DummyWorker, jid, queue) do
|
||||
subject
|
||||
end
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -464,21 +470,24 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
end
|
||||
|
||||
describe '#rss_increase_by_jobs' do
|
||||
let(:running_jobs) { { id1: 'job1', id2: 'job2' } }
|
||||
let(:running_jobs) { { 'job1' => { worker_class: "Job1" }, 'job2' => { worker_class: "Job2" } } }
|
||||
|
||||
subject { memory_killer.send(:rss_increase_by_jobs) }
|
||||
|
||||
before do
|
||||
allow(memory_killer).to receive(:rss_increase_by_job).and_return(11, 22)
|
||||
end
|
||||
|
||||
it 'adds up individual rss_increase_by_job' do
|
||||
allow(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs_mutex, :synchronize).and_yield
|
||||
expect(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs).and_return(running_jobs)
|
||||
expect(memory_killer).to receive(:rss_increase_by_job).and_return(11, 22)
|
||||
expect(subject).to eq(33)
|
||||
end
|
||||
|
||||
it 'return 0 if no job' do
|
||||
allow(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs_mutex, :synchronize).and_yield
|
||||
expect(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs).and_return({})
|
||||
expect(subject).to eq(0)
|
||||
context 'when there is no running job' do
|
||||
let(:running_jobs) { {} }
|
||||
|
||||
it 'return 0 if no job' do
|
||||
expect(subject).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,15 @@ RSpec.describe Gitlab::SidekiqDaemon::Monitor do
|
|||
let(:monitor) { described_class.new }
|
||||
|
||||
describe '#within_job' do
|
||||
it 'tracks thread' do
|
||||
it 'tracks thread, jid and worker_class' do
|
||||
blk = proc do
|
||||
expect(monitor.jobs.dig('jid', :thread)).not_to be_nil
|
||||
monitor.jobs do |jobs|
|
||||
jobs.each do |jid, job|
|
||||
expect(job[:thread]).not_to be_nil
|
||||
expect(jid).to eq('jid')
|
||||
expect(job[:worker_class]).to eq('worker_class')
|
||||
end
|
||||
end
|
||||
|
||||
"OK"
|
||||
end
|
||||
|
|
@ -37,13 +43,13 @@ RSpec.describe Gitlab::SidekiqDaemon::Monitor do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#with_running_jobs' do
|
||||
it 'yields with correct jobs' do
|
||||
describe '#jobs' do
|
||||
it 'returns running jobs hash' do
|
||||
jid = SecureRandom.hex
|
||||
running_jobs = { jid => hash_including(worker_class: 'worker_class') }
|
||||
|
||||
monitor.within_job('worker_class', jid, 'queue') do
|
||||
expect { |b| monitor.with_running_jobs(&b) }.to yield_with_args(running_jobs)
|
||||
expect(monitor.jobs).to match(running_jobs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -231,7 +237,7 @@ RSpec.describe Gitlab::SidekiqDaemon::Monitor do
|
|||
let(:thread) { Thread.new { sleep 1000 } }
|
||||
|
||||
before do
|
||||
monitor.jobs[jid] = { worker_class: 'worker_class', thread: thread, started_at: Time.now.to_i }
|
||||
allow(monitor).to receive(:find_thread_unsafe).with(jid).and_return(thread)
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
|
|||
|
|
@ -2528,20 +2528,24 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration do
|
|||
end
|
||||
|
||||
describe '#ref_slug' do
|
||||
{
|
||||
'master' => 'master',
|
||||
'1-foo' => '1-foo',
|
||||
'fix/1-foo' => 'fix-1-foo',
|
||||
'fix-1-foo' => 'fix-1-foo',
|
||||
'a' * 63 => 'a' * 63,
|
||||
'a' * 64 => 'a' * 63,
|
||||
'FOO' => 'foo',
|
||||
'-' + 'a' * 61 + '-' => 'a' * 61,
|
||||
'-' + 'a' * 62 + '-' => 'a' * 62,
|
||||
'-' + 'a' * 63 + '-' => 'a' * 62,
|
||||
'a' * 62 + ' ' => 'a' * 62
|
||||
}.each do |ref, slug|
|
||||
it "transforms #{ref} to #{slug}" do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:ref, :slug) do
|
||||
'master' | 'master'
|
||||
'1-foo' | '1-foo'
|
||||
'fix/1-foo' | 'fix-1-foo'
|
||||
'fix-1-foo' | 'fix-1-foo'
|
||||
'a' * 63 | 'a' * 63
|
||||
'a' * 64 | 'a' * 63
|
||||
'FOO' | 'foo'
|
||||
'-' + 'a' * 61 + '-' | 'a' * 61
|
||||
'-' + 'a' * 62 + '-' | 'a' * 62
|
||||
'-' + 'a' * 63 + '-' | 'a' * 62
|
||||
'a' * 62 + ' ' | 'a' * 62
|
||||
end
|
||||
|
||||
with_them do
|
||||
it "transforms ref to slug" do
|
||||
build.ref = ref
|
||||
|
||||
expect(build.ref_slug).to eq(slug)
|
||||
|
|
|
|||
|
|
@ -31,23 +31,6 @@ RSpec.describe API::Ci::SecureFiles, feature_category: :pipeline_authoring do
|
|||
end
|
||||
|
||||
describe 'GET /projects/:id/secure_files' do
|
||||
context 'feature flag' do
|
||||
it 'returns a 503 when the feature flag is disabled' do
|
||||
stub_feature_flags(ci_secure_files: false)
|
||||
|
||||
get api("/projects/#{project.id}/secure_files", maintainer)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:service_unavailable)
|
||||
end
|
||||
|
||||
it 'returns a 200 when the feature flag is enabled' do
|
||||
get api("/projects/#{project.id}/secure_files", maintainer)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response).to be_a(Array)
|
||||
end
|
||||
end
|
||||
|
||||
context 'ci_secure_files_read_only feature flag' do
|
||||
context 'when the flag is enabled' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -74,39 +74,39 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
runner_data = graphql_data_at(:runner)
|
||||
expect(runner_data).not_to be_nil
|
||||
|
||||
expect(runner_data).to match a_hash_including(
|
||||
'id' => runner.to_global_id.to_s,
|
||||
'description' => runner.description,
|
||||
'createdAt' => runner.created_at&.iso8601,
|
||||
'contactedAt' => runner.contacted_at&.iso8601,
|
||||
'version' => runner.version,
|
||||
'shortSha' => runner.short_sha,
|
||||
'revision' => runner.revision,
|
||||
'locked' => false,
|
||||
'active' => runner.active,
|
||||
'paused' => !runner.active,
|
||||
'status' => runner.status('14.5').to_s.upcase,
|
||||
'jobExecutionStatus' => runner.builds.running.any? ? 'RUNNING' : 'IDLE',
|
||||
'maximumTimeout' => runner.maximum_timeout,
|
||||
'accessLevel' => runner.access_level.to_s.upcase,
|
||||
'runUntagged' => runner.run_untagged,
|
||||
'ipAddress' => runner.ip_address,
|
||||
'runnerType' => runner.instance_type? ? 'INSTANCE_TYPE' : 'PROJECT_TYPE',
|
||||
'executorName' => runner.executor_type&.dasherize,
|
||||
'architectureName' => runner.architecture,
|
||||
'platformName' => runner.platform,
|
||||
'maintenanceNote' => runner.maintenance_note,
|
||||
'maintenanceNoteHtml' =>
|
||||
expect(runner_data).to match a_graphql_entity_for(
|
||||
runner,
|
||||
description: runner.description,
|
||||
created_at: runner.created_at&.iso8601,
|
||||
contacted_at: runner.contacted_at&.iso8601,
|
||||
version: runner.version,
|
||||
short_sha: runner.short_sha,
|
||||
revision: runner.revision,
|
||||
locked: false,
|
||||
active: runner.active,
|
||||
paused: !runner.active,
|
||||
status: runner.status('14.5').to_s.upcase,
|
||||
job_execution_status: runner.builds.running.any? ? 'RUNNING' : 'IDLE',
|
||||
maximum_timeout: runner.maximum_timeout,
|
||||
access_level: runner.access_level.to_s.upcase,
|
||||
run_untagged: runner.run_untagged,
|
||||
ip_address: runner.ip_address,
|
||||
runner_type: runner.instance_type? ? 'INSTANCE_TYPE' : 'PROJECT_TYPE',
|
||||
executor_name: runner.executor_type&.dasherize,
|
||||
architecture_name: runner.architecture,
|
||||
platform_name: runner.platform,
|
||||
maintenance_note: runner.maintenance_note,
|
||||
maintenance_note_html:
|
||||
runner.maintainer_note.present? ? a_string_including('<strong>Test maintenance note</strong>') : '',
|
||||
'jobCount' => runner.builds.count,
|
||||
'jobs' => a_hash_including(
|
||||
job_count: runner.builds.count,
|
||||
jobs: a_hash_including(
|
||||
"count" => runner.builds.count,
|
||||
"nodes" => an_instance_of(Array),
|
||||
"pageInfo" => anything
|
||||
),
|
||||
'projectCount' => nil,
|
||||
'adminUrl' => "http://localhost/admin/runners/#{runner.id}",
|
||||
'userPermissions' => {
|
||||
project_count: nil,
|
||||
admin_url: "http://localhost/admin/runners/#{runner.id}",
|
||||
user_permissions: {
|
||||
'readRunner' => true,
|
||||
'updateRunner' => true,
|
||||
'deleteRunner' => true,
|
||||
|
|
@ -134,11 +134,7 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
runner_data = graphql_data_at(:runner)
|
||||
expect(runner_data).not_to be_nil
|
||||
|
||||
expect(runner_data).to match a_hash_including(
|
||||
'id' => runner.to_global_id.to_s,
|
||||
'adminUrl' => nil
|
||||
)
|
||||
expect(runner_data['tagList']).to match_array runner.tag_list
|
||||
expect(runner_data).to match a_graphql_entity_for(runner, :tag_list, admin_url: nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -231,10 +227,7 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
|
||||
runner_data = graphql_data_at(:runner)
|
||||
|
||||
expect(runner_data).to match a_hash_including(
|
||||
'id' => project_runner.to_global_id.to_s,
|
||||
'locked' => is_locked
|
||||
)
|
||||
expect(runner_data).to match a_graphql_entity_for(project_runner, locked: is_locked)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -258,18 +251,8 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
post_graphql(query, current_user: user)
|
||||
|
||||
expect(graphql_data).to match a_hash_including(
|
||||
'runner1' => {
|
||||
'id' => runner1.to_global_id.to_s,
|
||||
'ownerProject' => {
|
||||
'id' => project2.to_global_id.to_s
|
||||
}
|
||||
},
|
||||
'runner2' => {
|
||||
'id' => runner2.to_global_id.to_s,
|
||||
'ownerProject' => {
|
||||
'id' => project1.to_global_id.to_s
|
||||
}
|
||||
}
|
||||
'runner1' => a_graphql_entity_for(runner1, owner_project: a_graphql_entity_for(project2)),
|
||||
'runner2' => a_graphql_entity_for(runner2, owner_project: a_graphql_entity_for(project1))
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -299,8 +282,8 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
it 'retrieves groups field with expected value' do
|
||||
post_graphql(query, current_user: user)
|
||||
|
||||
runner_data = graphql_data_at(:runner, :groups)
|
||||
expect(runner_data).to eq 'nodes' => [{ 'id' => group.to_global_id.to_s }]
|
||||
runner_data = graphql_data_at(:runner, :groups, :nodes)
|
||||
expect(runner_data).to contain_exactly(a_graphql_entity_for(group))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -424,13 +407,13 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
'jobCount' => 1,
|
||||
'jobs' => a_hash_including(
|
||||
"count" => 1,
|
||||
"nodes" => [{ "id" => job.to_global_id.to_s, "status" => job.status.upcase }]
|
||||
"nodes" => [a_graphql_entity_for(job, status: job.status.upcase)]
|
||||
),
|
||||
'projectCount' => 2,
|
||||
'projects' => {
|
||||
'nodes' => [
|
||||
{ 'id' => project1.to_global_id.to_s },
|
||||
{ 'id' => project2.to_global_id.to_s }
|
||||
a_graphql_entity_for(project1),
|
||||
a_graphql_entity_for(project2)
|
||||
]
|
||||
})
|
||||
expect(runner2_data).to match a_hash_including(
|
||||
|
|
@ -557,27 +540,25 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner do
|
|||
expect(graphql_data.count).to eq 6
|
||||
expect(graphql_data).to match(
|
||||
a_hash_including(
|
||||
'instance_runner1' => a_hash_including('id' => active_instance_runner.to_global_id.to_s),
|
||||
'instance_runner2' => a_hash_including('id' => inactive_instance_runner.to_global_id.to_s),
|
||||
'group_runner1' => a_hash_including(
|
||||
'id' => active_group_runner.to_global_id.to_s,
|
||||
'groups' => { 'nodes' => [a_hash_including('id' => group.to_global_id.to_s)] }
|
||||
'instance_runner1' => a_graphql_entity_for(active_instance_runner),
|
||||
'instance_runner2' => a_graphql_entity_for(inactive_instance_runner),
|
||||
'group_runner1' => a_graphql_entity_for(
|
||||
active_group_runner,
|
||||
groups: { 'nodes' => contain_exactly(a_graphql_entity_for(group)) }
|
||||
),
|
||||
'group_runner2' => a_hash_including(
|
||||
'id' => active_group_runner2.to_global_id.to_s,
|
||||
'groups' => { 'nodes' => [a_hash_including('id' => active_group_runner2.groups[0].to_global_id.to_s)] }
|
||||
'group_runner2' => a_graphql_entity_for(
|
||||
active_group_runner2,
|
||||
groups: { 'nodes' => active_group_runner2.groups.map { |g| a_graphql_entity_for(g) } }
|
||||
),
|
||||
'project_runner1' => a_hash_including(
|
||||
'id' => active_project_runner.to_global_id.to_s,
|
||||
'projects' => { 'nodes' => [a_hash_including('id' => active_project_runner.projects[0].to_global_id.to_s)] },
|
||||
'ownerProject' => a_hash_including('id' => active_project_runner.projects[0].to_global_id.to_s)
|
||||
'project_runner1' => a_graphql_entity_for(
|
||||
active_project_runner,
|
||||
projects: { 'nodes' => active_project_runner.projects.map { |p| a_graphql_entity_for(p) } },
|
||||
owner_project: a_graphql_entity_for(active_project_runner.projects[0])
|
||||
),
|
||||
'project_runner2' => a_hash_including(
|
||||
'id' => active_project_runner2.to_global_id.to_s,
|
||||
'projects' => {
|
||||
'nodes' => [a_hash_including('id' => active_project_runner2.projects[0].to_global_id.to_s)]
|
||||
},
|
||||
'ownerProject' => a_hash_including('id' => active_project_runner2.projects[0].to_global_id.to_s)
|
||||
'project_runner2' => a_graphql_entity_for(
|
||||
active_project_runner2,
|
||||
projects: { 'nodes' => active_project_runner2.projects.map { |p| a_graphql_entity_for(p) } },
|
||||
owner_project: a_graphql_entity_for(active_project_runner2.projects[0])
|
||||
)
|
||||
))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ RSpec.describe 'Query.runners', feature_category: :runner do
|
|||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it 'returns expected runner' do
|
||||
expect(runners_graphql_data['nodes'].map { |n| n['id'] }).to contain_exactly(expected_runner.to_global_id.to_s)
|
||||
expect(runners_graphql_data['nodes']).to contain_exactly(a_graphql_entity_for(expected_runner))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -298,6 +298,48 @@ RSpec.describe API::Terraform::State, :snowplow, feature_category: :infrastructu
|
|||
expect(state.reload_latest_version.build).to eq(job)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'response depending on the max allowed state size' do
|
||||
let(:current_user) { maintainer }
|
||||
|
||||
before do
|
||||
stub_application_setting(max_terraform_state_size_bytes: max_allowed_state_size)
|
||||
|
||||
request
|
||||
end
|
||||
|
||||
context 'when the max allowed state size is unlimited (set as 0)' do
|
||||
let(:max_allowed_state_size) { 0 }
|
||||
|
||||
it 'returns a success response' do
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the max allowed state size is greater than the request state size' do
|
||||
let(:max_allowed_state_size) { params.to_json.size + 1 }
|
||||
|
||||
it 'returns a success response' do
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the max allowed state size is equal to the request state size' do
|
||||
let(:max_allowed_state_size) { params.to_json.size }
|
||||
|
||||
it 'returns a success response' do
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the max allowed state size is less than the request state size' do
|
||||
let(:max_allowed_state_size) { params.to_json.size - 1 }
|
||||
|
||||
it "returns a 'payload too large' response" do
|
||||
expect(response).to have_gitlab_http_status(:payload_too_large)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /projects/:id/terraform/state/:name' do
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module Spec
|
|||
submit_invites
|
||||
end
|
||||
|
||||
wait_for_all_requests
|
||||
wait_for_requests
|
||||
|
||||
page.refresh if refresh
|
||||
end
|
||||
|
|
@ -30,6 +30,8 @@ module Spec
|
|||
find('.dropdown-item', text: 'Invite "new_email@gitlab.com" by email').click
|
||||
|
||||
submit_invites
|
||||
|
||||
wait_for_requests
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -63,10 +63,13 @@ RSpec.shared_examples 'shows and resets runner registration token' do
|
|||
end
|
||||
|
||||
RSpec.shared_examples 'shows no runners registered' do
|
||||
it 'shows counts with 0' do
|
||||
expect(page).to have_text "#{s_('Runners|Online')} 0"
|
||||
expect(page).to have_text "#{s_('Runners|Offline')} 0"
|
||||
expect(page).to have_text "#{s_('Runners|Stale')} 0"
|
||||
it 'shows total count with 0' do
|
||||
expect(find('[data-testid="runner-type-tabs"]')).to have_text "#{s_('Runners|All')} 0"
|
||||
|
||||
# No stats are shown
|
||||
expect(page).not_to have_text s_('Runners|Online')
|
||||
expect(page).not_to have_text s_('Runners|Offline')
|
||||
expect(page).not_to have_text s_('Runners|Stale')
|
||||
end
|
||||
|
||||
it 'shows "no runners" message' do
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ require 'carrierwave/storage/fog'
|
|||
RSpec.describe GitlabUploader do
|
||||
let(:uploader_class) { Class.new(described_class) }
|
||||
|
||||
subject { uploader_class.new(double) }
|
||||
subject(:uploader) { uploader_class.new(double) }
|
||||
|
||||
describe '#file_storage?' do
|
||||
context 'when file storage is used' do
|
||||
|
|
@ -161,6 +161,19 @@ RSpec.describe GitlabUploader do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#multi_read' do
|
||||
let(:file) { fixture_file_upload('spec/fixtures/trace/sample_trace', 'text/plain') }
|
||||
let(:byte_offsets) { [[4, 10], [17, 29]] }
|
||||
|
||||
subject { uploader.multi_read(byte_offsets) }
|
||||
|
||||
before do
|
||||
uploader.store!(file)
|
||||
end
|
||||
|
||||
it { is_expected.to eq(%w[Running gitlab-runner]) }
|
||||
end
|
||||
|
||||
describe '.version' do
|
||||
subject { uploader_class.version }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue