Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
889bf7a0ee
commit
7ea46a9866
|
@ -79,6 +79,7 @@ const Api = {
|
|||
issuePath: '/api/:version/projects/:id/issues/:issue_iid',
|
||||
tagsPath: '/api/:version/projects/:id/repository/tags',
|
||||
freezePeriodsPath: '/api/:version/projects/:id/freeze_periods',
|
||||
freezePeriodPath: '/api/:version/projects/:id/freeze_periods/:freeze_period_id',
|
||||
usageDataIncrementCounterPath: '/api/:version/usage_data/increment_counter',
|
||||
usageDataIncrementUniqueUsersPath: '/api/:version/usage_data/increment_unique_users',
|
||||
featureFlagUserLists: '/api/:version/projects/:id/feature_flags_user_lists',
|
||||
|
@ -832,6 +833,14 @@ const Api = {
|
|||
return axios.post(url, freezePeriod);
|
||||
},
|
||||
|
||||
updateFreezePeriod(id, freezePeriod = {}) {
|
||||
const url = Api.buildUrl(this.freezePeriodPath)
|
||||
.replace(':id', encodeURIComponent(id))
|
||||
.replace(':freeze_period_id', encodeURIComponent(freezePeriod.id));
|
||||
|
||||
return axios.put(url, freezePeriod);
|
||||
},
|
||||
|
||||
trackRedisCounterEvent(event) {
|
||||
if (!gon.features?.usageDataApi) {
|
||||
return null;
|
||||
|
|
|
@ -3,8 +3,7 @@ import { parseBoolean } from '~/lib/utils/common_utils';
|
|||
import CiVariableSettings from './components/ci_variable_settings.vue';
|
||||
import createStore from './store';
|
||||
|
||||
export default (containerId = 'js-ci-project-variables') => {
|
||||
const containerEl = document.getElementById(containerId);
|
||||
const mountCiVariableListApp = (containerEl) => {
|
||||
const {
|
||||
endpoint,
|
||||
projectId,
|
||||
|
@ -43,3 +42,8 @@ export default (containerId = 'js-ci-project-variables') => {
|
|||
},
|
||||
});
|
||||
};
|
||||
|
||||
export default () => {
|
||||
const el = document.querySelector('#js-ci-project-variables');
|
||||
return !el ? {} : mountCiVariableListApp(el);
|
||||
};
|
||||
|
|
|
@ -18,7 +18,6 @@ export default {
|
|||
modalOptions: {
|
||||
ref: 'modal',
|
||||
modalId: 'deploy-freeze-modal',
|
||||
title: __('Add deploy freeze'),
|
||||
actionCancel: {
|
||||
text: __('Cancel'),
|
||||
},
|
||||
|
@ -30,10 +29,13 @@ export default {
|
|||
cronSyntaxInstructions: __(
|
||||
'Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}',
|
||||
),
|
||||
addTitle: __('Add deploy freeze'),
|
||||
editTitle: __('Edit deploy freeze'),
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'projectId',
|
||||
'selectedId',
|
||||
'selectedTimezone',
|
||||
'timezoneData',
|
||||
'freezeStartCron',
|
||||
|
@ -45,9 +47,9 @@ export default {
|
|||
]),
|
||||
addDeployFreezeButton() {
|
||||
return {
|
||||
text: __('Add deploy freeze'),
|
||||
text: this.isEditing ? __('Save deploy freeze') : __('Add deploy freeze'),
|
||||
attributes: [
|
||||
{ variant: 'success' },
|
||||
{ variant: 'confirm' },
|
||||
{
|
||||
disabled:
|
||||
!isValidCron(this.freezeStartCron) ||
|
||||
|
@ -77,9 +79,17 @@ export default {
|
|||
this.setSelectedTimezone(selectedTimezone);
|
||||
},
|
||||
},
|
||||
isEditing() {
|
||||
return Boolean(this.selectedId);
|
||||
},
|
||||
modalTitle() {
|
||||
return this.isEditing
|
||||
? this.$options.translations.editTitle
|
||||
: this.$options.translations.addTitle;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['addFreezePeriod', 'setSelectedTimezone', 'resetModal']),
|
||||
...mapActions(['addFreezePeriod', 'updateFreezePeriod', 'setSelectedTimezone', 'resetModal']),
|
||||
resetModalHandler() {
|
||||
this.resetModal();
|
||||
},
|
||||
|
@ -89,6 +99,13 @@ export default {
|
|||
}
|
||||
return '';
|
||||
},
|
||||
submit() {
|
||||
if (this.isEditing) {
|
||||
this.updateFreezePeriod();
|
||||
} else {
|
||||
this.addFreezePeriod();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -96,8 +113,9 @@ export default {
|
|||
<template>
|
||||
<gl-modal
|
||||
v-bind="$options.modalOptions"
|
||||
:title="modalTitle"
|
||||
:action-primary="addDeployFreezeButton"
|
||||
@primary="addFreezePeriod"
|
||||
@primary="submit"
|
||||
@canceled="resetModalHandler"
|
||||
>
|
||||
<p>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { GlTable, GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui';
|
||||
import { mapState, mapActions } from 'vuex';
|
||||
import { s__, __ } from '~/locale';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
|
@ -17,9 +17,16 @@ export default {
|
|||
key: 'cronTimezone',
|
||||
label: s__('DeployFreeze|Time zone'),
|
||||
},
|
||||
{
|
||||
key: 'edit',
|
||||
label: s__('DeployFreeze|Edit'),
|
||||
},
|
||||
],
|
||||
translations: {
|
||||
addDeployFreeze: __('Add deploy freeze'),
|
||||
addDeployFreeze: s__('DeployFreeze|Add deploy freeze'),
|
||||
emptyStateText: s__(
|
||||
'DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}',
|
||||
),
|
||||
},
|
||||
components: {
|
||||
GlTable,
|
||||
|
@ -39,7 +46,7 @@ export default {
|
|||
this.fetchFreezePeriods();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchFreezePeriods']),
|
||||
...mapActions(['fetchFreezePeriods', 'setFreezePeriod']),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -53,15 +60,20 @@ export default {
|
|||
show-empty
|
||||
stacked="lg"
|
||||
>
|
||||
<template #cell(cronTimezone)="{ item }">
|
||||
{{ item.cronTimezone.formattedTimezone }}
|
||||
</template>
|
||||
<template #cell(edit)="{ item }">
|
||||
<gl-button
|
||||
v-gl-modal.deploy-freeze-modal
|
||||
icon="pencil"
|
||||
data-testid="edit-deploy-freeze"
|
||||
@click="setFreezePeriod(item)"
|
||||
/>
|
||||
</template>
|
||||
<template #empty>
|
||||
<p data-testid="empty-freeze-periods" class="gl-text-center text-plain">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__(
|
||||
'DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}',
|
||||
)
|
||||
"
|
||||
>
|
||||
<gl-sprintf :message="$options.translations.emptyStateText">
|
||||
<template #strong="{ content }">
|
||||
<strong>{{ content }}</strong>
|
||||
</template>
|
||||
|
@ -73,7 +85,7 @@ export default {
|
|||
v-gl-modal.deploy-freeze-modal
|
||||
data-testid="add-deploy-freeze"
|
||||
category="primary"
|
||||
variant="success"
|
||||
variant="confirm"
|
||||
>
|
||||
{{ $options.translations.addDeployFreeze }}
|
||||
</gl-button>
|
||||
|
|
|
@ -3,37 +3,53 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
|
|||
import { __ } from '~/locale';
|
||||
import * as types from './mutation_types';
|
||||
|
||||
export const requestAddFreezePeriod = ({ commit }) => {
|
||||
export const requestFreezePeriod = ({ commit }) => {
|
||||
commit(types.REQUEST_ADD_FREEZE_PERIOD);
|
||||
};
|
||||
|
||||
export const receiveAddFreezePeriodSuccess = ({ commit }) => {
|
||||
export const receiveFreezePeriodSuccess = ({ commit }) => {
|
||||
commit(types.RECEIVE_ADD_FREEZE_PERIOD_SUCCESS);
|
||||
};
|
||||
|
||||
export const receiveAddFreezePeriodError = ({ commit }, error) => {
|
||||
export const receiveFreezePeriodError = ({ commit }, error) => {
|
||||
commit(types.RECEIVE_ADD_FREEZE_PERIOD_ERROR, error);
|
||||
};
|
||||
|
||||
export const addFreezePeriod = ({ state, dispatch, commit }) => {
|
||||
dispatch('requestAddFreezePeriod');
|
||||
const receiveFreezePeriod = (store, request) => {
|
||||
const { dispatch, commit } = store;
|
||||
dispatch('requestFreezePeriod');
|
||||
|
||||
return Api.createFreezePeriod(state.projectId, {
|
||||
freeze_start: state.freezeStartCron,
|
||||
freeze_end: state.freezeEndCron,
|
||||
cron_timezone: state.selectedTimezoneIdentifier,
|
||||
})
|
||||
request(store)
|
||||
.then(() => {
|
||||
dispatch('receiveAddFreezePeriodSuccess');
|
||||
dispatch('receiveFreezePeriodSuccess');
|
||||
commit(types.RESET_MODAL);
|
||||
dispatch('fetchFreezePeriods');
|
||||
})
|
||||
.catch((error) => {
|
||||
createFlash(__('Error: Unable to create deploy freeze'));
|
||||
dispatch('receiveAddFreezePeriodError', error);
|
||||
dispatch('receiveFreezePeriodError', error);
|
||||
});
|
||||
};
|
||||
|
||||
export const addFreezePeriod = (store) =>
|
||||
receiveFreezePeriod(store, ({ state }) =>
|
||||
Api.createFreezePeriod(state.projectId, {
|
||||
freeze_start: state.freezeStartCron,
|
||||
freeze_end: state.freezeEndCron,
|
||||
cron_timezone: state.selectedTimezoneIdentifier,
|
||||
}),
|
||||
);
|
||||
|
||||
export const updateFreezePeriod = (store) =>
|
||||
receiveFreezePeriod(store, ({ state }) =>
|
||||
Api.updateFreezePeriod(state.projectId, {
|
||||
id: state.selectedId,
|
||||
freeze_start: state.freezeStartCron,
|
||||
freeze_end: state.freezeEndCron,
|
||||
cron_timezone: state.selectedTimezoneIdentifier,
|
||||
}),
|
||||
);
|
||||
|
||||
export const fetchFreezePeriods = ({ commit, state }) => {
|
||||
commit(types.REQUEST_FREEZE_PERIODS);
|
||||
|
||||
|
@ -46,6 +62,13 @@ export const fetchFreezePeriods = ({ commit, state }) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const setFreezePeriod = ({ commit }, freezePeriod) => {
|
||||
commit(types.SET_SELECTED_ID, freezePeriod.id);
|
||||
commit(types.SET_SELECTED_TIMEZONE, freezePeriod.cronTimezone);
|
||||
commit(types.SET_FREEZE_START_CRON, freezePeriod.freezeStart);
|
||||
commit(types.SET_FREEZE_END_CRON, freezePeriod.freezeEnd);
|
||||
};
|
||||
|
||||
export const setSelectedTimezone = ({ commit }, timezone) => {
|
||||
commit(types.SET_SELECTED_TIMEZONE, timezone);
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@ export const RECEIVE_ADD_FREEZE_PERIOD_SUCCESS = 'RECEIVE_ADD_FREEZE_PERIOD_SUCC
|
|||
export const RECEIVE_ADD_FREEZE_PERIOD_ERROR = 'RECEIVE_ADD_FREEZE_PERIOD_ERROR';
|
||||
|
||||
export const SET_SELECTED_TIMEZONE = 'SET_SELECTED_TIMEZONE';
|
||||
export const SET_SELECTED_ID = 'SET_SELECTED_ID';
|
||||
export const SET_FREEZE_START_CRON = 'SET_FREEZE_START_CRON';
|
||||
export const SET_FREEZE_END_CRON = 'SET_FREEZE_END_CRON';
|
||||
|
||||
|
|
|
@ -4,7 +4,11 @@ import * as types from './mutation_types';
|
|||
const formatTimezoneName = (freezePeriod, timezoneList) =>
|
||||
convertObjectPropsToCamelCase({
|
||||
...freezePeriod,
|
||||
cron_timezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)?.name,
|
||||
cron_timezone: {
|
||||
formattedTimezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)
|
||||
?.name,
|
||||
identifier: freezePeriod.cronTimezone,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
|
@ -45,10 +49,15 @@ export default {
|
|||
state.freezeEndCron = freezeEndCron;
|
||||
},
|
||||
|
||||
[types.SET_SELECTED_ID](state, id) {
|
||||
state.selectedId = id;
|
||||
},
|
||||
|
||||
[types.RESET_MODAL](state) {
|
||||
state.freezeStartCron = '';
|
||||
state.freezeEndCron = '';
|
||||
state.selectedTimezone = '';
|
||||
state.selectedTimezoneIdentifier = '';
|
||||
state.selectedId = '';
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@ export default ({
|
|||
selectedTimezoneIdentifier = '',
|
||||
freezeStartCron = '',
|
||||
freezeEndCron = '',
|
||||
selectedId = '',
|
||||
}) => ({
|
||||
projectId,
|
||||
freezePeriods,
|
||||
|
@ -14,4 +15,5 @@ export default ({
|
|||
selectedTimezoneIdentifier,
|
||||
freezeStartCron,
|
||||
freezeEndCron,
|
||||
selectedId,
|
||||
});
|
||||
|
|
|
@ -26,7 +26,10 @@ export default {
|
|||
class="settings no-animate qa-incident-management-settings"
|
||||
>
|
||||
<div class="settings-header">
|
||||
<h4 ref="sectionHeader">
|
||||
<h4
|
||||
ref="sectionHeader"
|
||||
class="settings-title js-settings-toggle js-settings-toggle-trigger-only"
|
||||
>
|
||||
{{ $options.i18n.headerText }}
|
||||
</h4>
|
||||
<gl-button ref="toggleBtn" class="js-settings-toggle">{{
|
||||
|
|
|
@ -4,9 +4,7 @@ import initSearchSettings from '~/search_settings';
|
|||
import selfMonitor from '~/self_monitor';
|
||||
import initSettingsPanels from '~/settings_panels';
|
||||
|
||||
if (gon.features?.ciInstanceVariablesUi) {
|
||||
initVariableList('js-instance-variables');
|
||||
}
|
||||
selfMonitor();
|
||||
// Initialize expandable settings panels
|
||||
initSettingsPanels();
|
||||
|
|
|
@ -13,10 +13,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
|
||||
before_action :disable_query_limiting, only: [:usage_data]
|
||||
|
||||
before_action only: [:ci_cd] do
|
||||
push_frontend_feature_flag(:ci_instance_variables_ui, default_enabled: true)
|
||||
end
|
||||
|
||||
feature_category :not_owned, [
|
||||
:general, :reporting, :metrics_and_profiling, :network,
|
||||
:preferences, :update, :reset_health_check_token
|
||||
|
|
|
@ -462,7 +462,7 @@ class ApplicationController < ActionController::Base
|
|||
feature_category: feature_category) do
|
||||
yield
|
||||
ensure
|
||||
@current_context = Labkit::Context.current.to_h
|
||||
@current_context = Gitlab::ApplicationContext.current
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ module Mutations
|
|||
|
||||
ADMIN_MESSAGE = 'You must be an admin to use this mutation'
|
||||
|
||||
Labkit::Context::KNOWN_KEYS.each do |key|
|
||||
Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
|
||||
argument key,
|
||||
GraphQL::STRING_TYPE,
|
||||
required: false,
|
||||
|
|
|
@ -21,11 +21,17 @@ class BuildArtifactEntity < Grape::Entity
|
|||
)
|
||||
end
|
||||
|
||||
expose :keep_path, if: -> (*) { artifact.expiring? } do |artifact|
|
||||
expose :keep_path, if: -> (*) { artifact.expiring? && show_duplicated_paths?(artifact.project) } do |artifact|
|
||||
fast_keep_project_job_artifacts_path(artifact.project, artifact.job)
|
||||
end
|
||||
|
||||
expose :browse_path do |artifact|
|
||||
expose :browse_path, if: -> (*) { show_duplicated_paths?(artifact.project) } do |artifact|
|
||||
fast_browse_project_job_artifacts_path(artifact.project, artifact.job)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def show_duplicated_paths?(project)
|
||||
!Gitlab::Ci::Features.remove_duplicate_artifact_exposure_paths?(project)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
- page_title _("CI/CD")
|
||||
- @content_class = "limit-container-width" unless fluid_layout
|
||||
|
||||
- if ::Gitlab::Ci::Features.instance_variables_ui_enabled?
|
||||
%section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
|
||||
.settings-header
|
||||
= render 'admin/application_settings/ci/header', expanded: expanded_by_default?
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%section.settings.js-service-desk-setting-wrapper.no-animate#js-service-desk{ class: ('expanded' if expanded), data: { qa_selector: 'service_desk_settings_content' } }
|
||||
.settings-header
|
||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Service Desk')
|
||||
%button.btn.gl-button.js-settings-toggle
|
||||
%button.btn.gl-button.btn-default.js-settings-toggle
|
||||
= expanded ? _('Collapse') : _('Expand')
|
||||
- link_start = "<a href='#{help_page_path('user/project/service_desk')}' target='_blank' rel='noopener noreferrer'>".html_safe
|
||||
%p= _('Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
|
||||
|
|
|
@ -18,7 +18,7 @@ module ApplicationWorker
|
|||
set_queue
|
||||
|
||||
def structured_payload(payload = {})
|
||||
context = Labkit::Context.current.to_h.merge(
|
||||
context = Gitlab::ApplicationContext.current.merge(
|
||||
'class' => self.class.name,
|
||||
'job_status' => 'running',
|
||||
'queue' => self.class.queue,
|
||||
|
|
|
@ -15,7 +15,7 @@ module CronjobQueue
|
|||
# Cronjobs never get scheduled with arguments, so this is safe to
|
||||
# override
|
||||
def context_for_arguments(_args)
|
||||
return if Gitlab::ApplicationContext.current_context_include?('meta.caller_id')
|
||||
return if Gitlab::ApplicationContext.current_context_include?(:caller_id)
|
||||
|
||||
Gitlab::ApplicationContext.new(caller_id: "Cronjob")
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Project Settings Operations header Incidents expand/collapse on-click/on-tap
|
||||
merge_request: 56273
|
||||
author: Daniel Schömer
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add Ability to Edit Freeze Periods
|
||||
merge_request: 56407
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add btn-default class for Service Desk toggle in settings
|
||||
merge_request: 56195
|
||||
author: Yogi (@yo)
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Enable the instance variables UI
|
||||
merge_request: 56255
|
||||
author:
|
||||
type: other
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_instance_variables_ui
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33510
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299879
|
||||
milestone: '13.1'
|
||||
type: development
|
||||
group: group::continuous integration
|
||||
default_enabled: true
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: remove_duplicate_artifact_exposure_paths
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54611
|
||||
rollout_issue_url:
|
||||
milestone: '13.10'
|
||||
type: development
|
||||
group: group::testing
|
||||
default_enabled: false
|
|
@ -268,7 +268,13 @@ To install a package:
|
|||
Without the `gitlab-domains` definition in `composer.json`, Composer uses the GitLab token
|
||||
as basic-auth, with the token as a username and a blank password. This results in a 401 error.
|
||||
|
||||
Output indicates that the package has been successfully installed.
|
||||
1. With the `composer.json` and `auth.json` files configured, you can install the package by running:
|
||||
|
||||
```shell
|
||||
composer update
|
||||
```
|
||||
|
||||
If successful, you should see output indicating that the package installed successfully.
|
||||
|
||||
WARNING:
|
||||
Never commit the `auth.json` file to your repository. To install packages from a CI/CD job,
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
|
@ -340,6 +340,31 @@ As in other list types, click the trash icon to remove a list.
|
|||
|
||||
![Milestone lists](img/issue_board_milestone_lists_v13_6.png)
|
||||
|
||||
### Iteration lists **(PREMIUM)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250479) in GitLab 13.10.
|
||||
> - It's [deployed behind the `board_new_lists` feature flag](../feature_flags.md), disabled by default.
|
||||
> - It's disabled on GitLab.com.
|
||||
> - It's recommended for production use.
|
||||
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-new-add-list-form).
|
||||
|
||||
WARNING:
|
||||
This feature might not be available to you. Check the **version history** note above for details.
|
||||
|
||||
You're also able to create lists of an iteration.
|
||||
These are lists that filter issues by the assigned
|
||||
iteration. To add an iteration list:
|
||||
|
||||
1. Select **Create list**.
|
||||
1. Select the **Iteration**.
|
||||
1. In the dropdown, select an iteration.
|
||||
1. Select **Add to board**.
|
||||
|
||||
Like the milestone lists, you're able to [drag issues](#drag-issues-between-lists)
|
||||
to and from a iteration list to manipulate the iteration of the dragged issues.
|
||||
|
||||
![Iteration lists](img/issue_board_iteration_lists_v13_10.png)
|
||||
|
||||
### Group issues in swimlanes **(PREMIUM)**
|
||||
|
||||
> - Grouping by epic [introduced](https://gitlab.com/groups/gitlab-org/-/epics/3352) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6.
|
||||
|
@ -649,3 +674,22 @@ To disable it:
|
|||
```ruby
|
||||
Feature.disable(:add_issues_button)
|
||||
```
|
||||
|
||||
### Enable or disable new add list form **(FREE SELF)**
|
||||
|
||||
The new form for adding lists is under development and not ready for production use. It is
|
||||
deployed behind a feature flag that is **disabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
|
||||
can enable it.
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:board_new_list)
|
||||
```
|
||||
|
||||
To disable it:
|
||||
|
||||
```ruby
|
||||
Feature.disable(:board_new_list)
|
||||
```
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
|
@ -217,11 +217,11 @@ To set a deploy freeze window in the UI, complete these steps:
|
|||
1. Click **Add deploy freeze** to open the deploy freeze modal.
|
||||
1. Enter the start time, end time, and timezone of the desired deploy freeze period.
|
||||
1. Click **Add deploy freeze** in the modal.
|
||||
|
||||
![Deploy freeze modal for setting a deploy freeze period](img/deploy_freeze_v13_2.png)
|
||||
1. After the deploy freeze is saved, you can edit it by selecting the edit button (**{pencil}**).
|
||||
![Deploy freeze modal for setting a deploy freeze period](img/deploy_freeze_v13_10.png)
|
||||
|
||||
WARNING:
|
||||
To edit or delete a deploy freeze, use the [Freeze Periods API](../../../api/freeze_periods.md).
|
||||
To delete a deploy freeze, use the [Freeze Periods API](../../../api/freeze_periods.md).
|
||||
|
||||
If a project contains multiple freeze periods, all periods apply. If they overlap, the freeze covers the
|
||||
complete overlapping period.
|
||||
|
|
|
@ -45,7 +45,8 @@ module.exports = (path) => {
|
|||
'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
|
||||
'^spec/test_constants$': '<rootDir>/spec/frontend/__helpers__/test_constants',
|
||||
'^jest/(.*)$': '<rootDir>/spec/frontend/$1',
|
||||
'test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
|
||||
'^test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
|
||||
'^ee_else_ce_test_helpers(/.*)$': '<rootDir>/spec/frontend_integration/test_helpers$1',
|
||||
};
|
||||
|
||||
const collectCoverageFrom = ['<rootDir>/app/assets/javascripts/**/*.{js,vue}'];
|
||||
|
@ -56,6 +57,7 @@ module.exports = (path) => {
|
|||
'^ee(/.*)$': rootDirEE,
|
||||
'^ee_component(/.*)$': rootDirEE,
|
||||
'^ee_else_ce(/.*)$': rootDirEE,
|
||||
'^ee_else_ce_test_helpers(/.*)$': '<rootDir>/ee/spec/frontend_integration/test_helpers$1',
|
||||
'^ee_jest/(.*)$': '<rootDir>/ee/spec/frontend/$1',
|
||||
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures-ee$1',
|
||||
});
|
||||
|
|
|
@ -12,11 +12,11 @@ module API
|
|||
namespace 'queues' do
|
||||
desc 'Drop jobs matching the given metadata from the Sidekiq queue'
|
||||
params do
|
||||
Labkit::Context::KNOWN_KEYS.each do |key|
|
||||
Gitlab::ApplicationContext::KNOWN_KEYS.each do |key|
|
||||
optional key, type: String, allow_blank: false
|
||||
end
|
||||
|
||||
at_least_one_of(*Labkit::Context::KNOWN_KEYS)
|
||||
at_least_one_of(*Gitlab::ApplicationContext::KNOWN_KEYS)
|
||||
end
|
||||
delete ':queue_name' do
|
||||
result =
|
||||
|
|
|
@ -8,6 +8,9 @@ module Gitlab
|
|||
|
||||
Attribute = Struct.new(:name, :type)
|
||||
|
||||
LOG_KEY = Labkit::Context::LOG_KEY
|
||||
KNOWN_KEYS = Labkit::Context::KNOWN_KEYS
|
||||
|
||||
APPLICATION_ATTRIBUTES = [
|
||||
Attribute.new(:project, Project),
|
||||
Attribute.new(:namespace, Namespace),
|
||||
|
@ -24,6 +27,10 @@ module Gitlab
|
|||
application_context.use(&block)
|
||||
end
|
||||
|
||||
def self.with_raw_context(attributes = {}, &block)
|
||||
Labkit::Context.with_context(attributes, &block)
|
||||
end
|
||||
|
||||
def self.push(args)
|
||||
application_context = new(**args)
|
||||
Labkit::Context.push(application_context.to_lazy_hash)
|
||||
|
|
|
@ -10,10 +10,6 @@ module Gitlab
|
|||
::Feature.enabled?(:ci_artifacts_exclude, default_enabled: true)
|
||||
end
|
||||
|
||||
def self.instance_variables_ui_enabled?
|
||||
::Feature.enabled?(:ci_instance_variables_ui, default_enabled: true)
|
||||
end
|
||||
|
||||
def self.pipeline_latest?
|
||||
::Feature.enabled?(:ci_pipeline_latest, default_enabled: true)
|
||||
end
|
||||
|
@ -71,6 +67,10 @@ module Gitlab
|
|||
def self.ci_commit_pipeline_mini_graph_vue_enabled?(project)
|
||||
::Feature.enabled?(:ci_commit_pipeline_mini_graph_vue, project, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
def self.remove_duplicate_artifact_exposure_paths?(project)
|
||||
::Feature.enabled?(:remove_duplicate_artifact_exposure_paths, project, default_enabled: :yaml)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -215,7 +215,7 @@ module Gitlab
|
|||
'client_name' => CLIENT_NAME
|
||||
}
|
||||
|
||||
context_data = Labkit::Context.current&.to_h
|
||||
context_data = Gitlab::ApplicationContext.current
|
||||
|
||||
feature_stack = Thread.current[:gitaly_feature_stack]
|
||||
feature = feature_stack && feature_stack[0]
|
||||
|
|
|
@ -6,7 +6,7 @@ module Gitlab
|
|||
module Loggers
|
||||
class ContextLogger < ::GrapeLogging::Loggers::Base
|
||||
def parameters(_, _)
|
||||
Labkit::Context.current.to_h
|
||||
Gitlab::ApplicationContext.current
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ module Gitlab
|
|||
job_search_metadata =
|
||||
search_metadata
|
||||
.stringify_keys
|
||||
.slice(*Labkit::Context::KNOWN_KEYS)
|
||||
.slice(*Gitlab::ApplicationContext::KNOWN_KEYS)
|
||||
.transform_keys { |key| "meta.#{key}" }
|
||||
.compact
|
||||
|
||||
|
|
|
@ -10245,13 +10245,19 @@ msgstr ""
|
|||
msgid "DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeployFreeze|Add deploy freeze"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeployFreeze|Edit"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeployFreeze|Freeze end"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeployFreeze|Freeze start"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
|
||||
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
|
||||
|
@ -11191,6 +11197,9 @@ msgstr ""
|
|||
msgid "Edit comment"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit deploy freeze"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit description"
|
||||
msgstr ""
|
||||
|
||||
|
@ -26436,6 +26445,9 @@ msgstr ""
|
|||
msgid "Save comment"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save deploy freeze"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save password"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -898,7 +898,7 @@ RSpec.describe ApplicationController do
|
|||
feature_category :issue_tracking
|
||||
|
||||
def index
|
||||
Labkit::Context.with_context do |context|
|
||||
Gitlab::ApplicationContext.with_raw_context do |context|
|
||||
render json: context.to_h
|
||||
end
|
||||
end
|
||||
|
|
|
@ -524,7 +524,7 @@ RSpec.describe SessionsController do
|
|||
|
||||
it 'sets the username and caller_id in the context' do
|
||||
expect(controller).to receive(:destroy).and_wrap_original do |m, *args|
|
||||
expect(Labkit::Context.current.to_h)
|
||||
expect(Gitlab::ApplicationContext.current)
|
||||
.to include('meta.user' => user.username,
|
||||
'meta.caller_id' => 'SessionsController#destroy')
|
||||
|
||||
|
@ -538,9 +538,9 @@ RSpec.describe SessionsController do
|
|||
context 'when not signed in' do
|
||||
it 'sets the caller_id in the context' do
|
||||
expect(controller).to receive(:new).and_wrap_original do |m, *args|
|
||||
expect(Labkit::Context.current.to_h)
|
||||
expect(Gitlab::ApplicationContext.current)
|
||||
.to include('meta.caller_id' => 'SessionsController#new')
|
||||
expect(Labkit::Context.current.to_h)
|
||||
expect(Gitlab::ApplicationContext.current)
|
||||
.not_to include('meta.user')
|
||||
|
||||
m.call(*args)
|
||||
|
@ -557,9 +557,9 @@ RSpec.describe SessionsController do
|
|||
|
||||
it 'sets the caller_id in the context' do
|
||||
allow_any_instance_of(User).to receive(:lock_access!).and_wrap_original do |m, *args|
|
||||
expect(Labkit::Context.current.to_h)
|
||||
expect(Gitlab::ApplicationContext.current)
|
||||
.to include('meta.caller_id' => 'SessionsController#create')
|
||||
expect(Labkit::Context.current.to_h)
|
||||
expect(Gitlab::ApplicationContext.current)
|
||||
.not_to include('meta.user')
|
||||
|
||||
m.call(*args)
|
||||
|
|
|
@ -1382,6 +1382,38 @@ describe('Api', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('updateFreezePeriod', () => {
|
||||
const options = {
|
||||
id: 10,
|
||||
freeze_start: '* * * * *',
|
||||
freeze_end: '* * * * *',
|
||||
cron_timezone: 'America/Juneau',
|
||||
created_at: '2020-07-11T07:04:50.153Z',
|
||||
updated_at: '2020-07-11T07:04:50.153Z',
|
||||
};
|
||||
const projectId = 8;
|
||||
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectId}/freeze_periods/${options.id}`;
|
||||
|
||||
const expectedResult = {
|
||||
id: 10,
|
||||
freeze_start: '* * * * *',
|
||||
freeze_end: '* * * * *',
|
||||
cron_timezone: 'America/Juneau',
|
||||
created_at: '2020-07-11T07:04:50.153Z',
|
||||
updated_at: '2020-07-11T07:04:50.153Z',
|
||||
};
|
||||
|
||||
describe('when the freeze period is successfully updated', () => {
|
||||
it('resolves the Promise', () => {
|
||||
mock.onPut(expectedUrl, options).replyOnce(httpStatus.OK, expectedResult);
|
||||
|
||||
return Api.updateFreezePeriod(projectId, options).then(({ data }) => {
|
||||
expect(data).toStrictEqual(expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createPipeline', () => {
|
||||
it('creates new pipeline', () => {
|
||||
const redirectUrl = 'ci-project/-/pipelines/95';
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import { GlButton, GlModal } from '@gitlab/ui';
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import Api from '~/api';
|
||||
import DeployFreezeModal from '~/deploy_freeze/components/deploy_freeze_modal.vue';
|
||||
import createStore from '~/deploy_freeze/store';
|
||||
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
|
||||
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
jest.mock('~/api');
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
describe('Deploy freeze modal', () => {
|
||||
let wrapper;
|
||||
|
@ -23,18 +26,19 @@ describe('Deploy freeze modal', () => {
|
|||
stubs: {
|
||||
GlModal,
|
||||
},
|
||||
localVue,
|
||||
store,
|
||||
});
|
||||
});
|
||||
|
||||
const findModal = () => wrapper.find(GlModal);
|
||||
const addDeployFreezeButton = () => findModal().findAll(GlButton).at(1);
|
||||
const findModal = () => wrapper.findComponent(GlModal);
|
||||
const submitDeployFreezeButton = () => findModal().findAllComponents(GlButton).at(1);
|
||||
|
||||
const setInput = (freezeStartCron, freezeEndCron, selectedTimezone) => {
|
||||
const setInput = (freezeStartCron, freezeEndCron, selectedTimezone, id = '') => {
|
||||
store.state.freezeStartCron = freezeStartCron;
|
||||
store.state.freezeEndCron = freezeEndCron;
|
||||
store.state.selectedTimezone = selectedTimezone;
|
||||
store.state.selectedTimezoneIdentifier = selectedTimezone;
|
||||
store.state.selectedId = id;
|
||||
|
||||
wrapper.find('#deploy-freeze-start').trigger('input');
|
||||
wrapper.find('#deploy-freeze-end').trigger('input');
|
||||
|
@ -48,18 +52,36 @@ describe('Deploy freeze modal', () => {
|
|||
|
||||
describe('Basic interactions', () => {
|
||||
it('button is disabled when freeze period is invalid', () => {
|
||||
expect(addDeployFreezeButton().attributes('disabled')).toBeTruthy();
|
||||
expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Adding a new deploy freeze', () => {
|
||||
beforeEach(() => {
|
||||
const { freeze_start, freeze_end, cron_timezone } = freezePeriodsFixture[0];
|
||||
|
||||
beforeEach(() => {
|
||||
setInput(freeze_start, freeze_end, cron_timezone);
|
||||
});
|
||||
|
||||
it('button is enabled when valid freeze period settings are present', () => {
|
||||
expect(addDeployFreezeButton().attributes('disabled')).toBeUndefined();
|
||||
expect(submitDeployFreezeButton().attributes('disabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should display Add deploy freeze', () => {
|
||||
expect(findModal().props('title')).toBe('Add deploy freeze');
|
||||
expect(submitDeployFreezeButton().text()).toBe('Add deploy freeze');
|
||||
});
|
||||
|
||||
it('should call the add deploy freze API', () => {
|
||||
Api.createFreezePeriod.mockResolvedValue();
|
||||
findModal().vm.$emit('primary');
|
||||
|
||||
expect(Api.createFreezePeriod).toHaveBeenCalledTimes(1);
|
||||
expect(Api.createFreezePeriod).toHaveBeenCalledWith(store.state.projectId, {
|
||||
freeze_start,
|
||||
freeze_end,
|
||||
cron_timezone,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -70,7 +92,7 @@ describe('Deploy freeze modal', () => {
|
|||
});
|
||||
|
||||
it('disables the add deploy freeze button', () => {
|
||||
expect(addDeployFreezeButton().attributes('disabled')).toBeTruthy();
|
||||
expect(submitDeployFreezeButton().attributes('disabled')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -81,7 +103,32 @@ describe('Deploy freeze modal', () => {
|
|||
});
|
||||
|
||||
it('does not disable the submit button', () => {
|
||||
expect(addDeployFreezeButton().attributes('disabled')).toBeFalsy();
|
||||
expect(submitDeployFreezeButton().attributes('disabled')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Editing an existing deploy freeze', () => {
|
||||
const { freeze_start, freeze_end, cron_timezone, id } = freezePeriodsFixture[0];
|
||||
beforeEach(() => {
|
||||
setInput(freeze_start, freeze_end, cron_timezone, id);
|
||||
});
|
||||
|
||||
it('should display Edit deploy freeze', () => {
|
||||
expect(findModal().props('title')).toBe('Edit deploy freeze');
|
||||
expect(submitDeployFreezeButton().text()).toBe('Save deploy freeze');
|
||||
});
|
||||
|
||||
it('should call the update deploy freze API', () => {
|
||||
Api.updateFreezePeriod.mockResolvedValue();
|
||||
findModal().vm.$emit('primary');
|
||||
|
||||
expect(Api.updateFreezePeriod).toHaveBeenCalledTimes(1);
|
||||
expect(Api.updateFreezePeriod).toHaveBeenCalledWith(store.state.projectId, {
|
||||
id,
|
||||
freeze_start,
|
||||
freeze_end,
|
||||
cron_timezone,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import { createLocalVue, mount } from '@vue/test-utils';
|
|||
import Vuex from 'vuex';
|
||||
import DeployFreezeTable from '~/deploy_freeze/components/deploy_freeze_table.vue';
|
||||
import createStore from '~/deploy_freeze/store';
|
||||
import { RECEIVE_FREEZE_PERIODS_SUCCESS } from '~/deploy_freeze/store/mutation_types';
|
||||
import { freezePeriodsFixture, timezoneDataFixture } from '../helpers';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
|
@ -26,6 +27,7 @@ describe('Deploy freeze table', () => {
|
|||
|
||||
const findEmptyFreezePeriods = () => wrapper.find('[data-testid="empty-freeze-periods"]');
|
||||
const findAddDeployFreezeButton = () => wrapper.find('[data-testid="add-deploy-freeze"]');
|
||||
const findEditDeployFreezeButton = () => wrapper.find('[data-testid="edit-deploy-freeze"]');
|
||||
const findDeployFreezeTable = () => wrapper.find('[data-testid="deploy-freeze-table"]');
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -45,17 +47,31 @@ describe('Deploy freeze table', () => {
|
|||
it('displays empty', () => {
|
||||
expect(findEmptyFreezePeriods().exists()).toBe(true);
|
||||
expect(findEmptyFreezePeriods().text()).toBe(
|
||||
'No deploy freezes exist for this project. To add one, click Add deploy freeze',
|
||||
'No deploy freezes exist for this project. To add one, select Add deploy freeze',
|
||||
);
|
||||
});
|
||||
|
||||
it('displays data', () => {
|
||||
store.state.freezePeriods = freezePeriodsFixture;
|
||||
describe('with data', () => {
|
||||
beforeEach(async () => {
|
||||
store.commit(RECEIVE_FREEZE_PERIODS_SUCCESS, freezePeriodsFixture);
|
||||
await wrapper.vm.$nextTick();
|
||||
});
|
||||
|
||||
return wrapper.vm.$nextTick(() => {
|
||||
it('displays data', () => {
|
||||
const tableRows = findDeployFreezeTable().findAll('tbody tr');
|
||||
expect(tableRows.length).toBe(freezePeriodsFixture.length);
|
||||
expect(findEmptyFreezePeriods().exists()).toBe(false);
|
||||
expect(findEditDeployFreezeButton().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('allows user to edit deploy freeze', async () => {
|
||||
findEditDeployFreezeButton().trigger('click');
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith(
|
||||
'setFreezePeriod',
|
||||
store.state.freezePeriods[0],
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,12 +23,46 @@ describe('deploy freeze store actions', () => {
|
|||
});
|
||||
Api.freezePeriods.mockResolvedValue({ data: freezePeriodsFixture });
|
||||
Api.createFreezePeriod.mockResolvedValue();
|
||||
Api.updateFreezePeriod.mockResolvedValue();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
describe('setSelectedFreezePeriod', () => {
|
||||
it('commits SET_SELECTED_TIMEZONE mutation', () => {
|
||||
testAction(
|
||||
actions.setFreezePeriod,
|
||||
{
|
||||
id: 3,
|
||||
cronTimezone: 'UTC',
|
||||
freezeStart: 'start',
|
||||
freezeEnd: 'end',
|
||||
},
|
||||
{},
|
||||
[
|
||||
{
|
||||
payload: 3,
|
||||
type: types.SET_SELECTED_ID,
|
||||
},
|
||||
{
|
||||
payload: 'UTC',
|
||||
type: types.SET_SELECTED_TIMEZONE,
|
||||
},
|
||||
{
|
||||
payload: 'start',
|
||||
type: types.SET_FREEZE_START_CRON,
|
||||
},
|
||||
{
|
||||
payload: 'end',
|
||||
type: types.SET_FREEZE_END_CRON,
|
||||
},
|
||||
],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSelectedTimezone', () => {
|
||||
it('commits SET_SELECTED_TIMEZONE mutation', () => {
|
||||
testAction(actions.setSelectedTimezone, {}, {}, [
|
||||
|
@ -68,10 +102,16 @@ describe('deploy freeze store actions', () => {
|
|||
state,
|
||||
[{ type: 'RESET_MODAL' }],
|
||||
[
|
||||
{ type: 'requestAddFreezePeriod' },
|
||||
{ type: 'receiveAddFreezePeriodSuccess' },
|
||||
{ type: 'requestFreezePeriod' },
|
||||
{ type: 'receiveFreezePeriodSuccess' },
|
||||
{ type: 'fetchFreezePeriods' },
|
||||
],
|
||||
() =>
|
||||
expect(Api.createFreezePeriod).toHaveBeenCalledWith(state.projectId, {
|
||||
freeze_start: state.freezeStartCron,
|
||||
freeze_end: state.freezeEndCron,
|
||||
cron_timezone: state.selectedTimezoneIdentifier,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -83,7 +123,43 @@ describe('deploy freeze store actions', () => {
|
|||
{},
|
||||
state,
|
||||
[],
|
||||
[{ type: 'requestAddFreezePeriod' }, { type: 'receiveAddFreezePeriodError' }],
|
||||
[{ type: 'requestFreezePeriod' }, { type: 'receiveFreezePeriodError' }],
|
||||
() => expect(createFlash).toHaveBeenCalled(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateFreezePeriod', () => {
|
||||
it('dispatch correct actions on updating a freeze period', () => {
|
||||
testAction(
|
||||
actions.updateFreezePeriod,
|
||||
{},
|
||||
state,
|
||||
[{ type: 'RESET_MODAL' }],
|
||||
[
|
||||
{ type: 'requestFreezePeriod' },
|
||||
{ type: 'receiveFreezePeriodSuccess' },
|
||||
{ type: 'fetchFreezePeriods' },
|
||||
],
|
||||
() =>
|
||||
expect(Api.updateFreezePeriod).toHaveBeenCalledWith(state.projectId, {
|
||||
id: state.selectedId,
|
||||
freeze_start: state.freezeStartCron,
|
||||
freeze_end: state.freezeEndCron,
|
||||
cron_timezone: state.selectedTimezoneIdentifier,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should show flash error and set error in state on add failure', () => {
|
||||
Api.updateFreezePeriod.mockRejectedValue();
|
||||
|
||||
testAction(
|
||||
actions.updateFreezePeriod,
|
||||
{},
|
||||
state,
|
||||
[],
|
||||
[{ type: 'requestFreezePeriod' }, { type: 'receiveFreezePeriodError' }],
|
||||
() => expect(createFlash).toHaveBeenCalled(),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -33,7 +33,10 @@ describe('Deploy freeze mutations', () => {
|
|||
|
||||
const expectedFreezePeriods = freezePeriodsFixture.map((freezePeriod, index) => ({
|
||||
...convertObjectPropsToCamelCase(freezePeriod),
|
||||
cronTimezone: timezoneNames[index],
|
||||
cronTimezone: {
|
||||
formattedTimezone: timezoneNames[index],
|
||||
identifier: freezePeriod.cronTimezone,
|
||||
},
|
||||
}));
|
||||
|
||||
expect(stateCopy.freezePeriods).toMatchObject(expectedFreezePeriods);
|
||||
|
@ -62,11 +65,19 @@ describe('Deploy freeze mutations', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('SET_FREEZE_ENDT_CRON', () => {
|
||||
describe('SET_FREEZE_END_CRON', () => {
|
||||
it('should set freezeEndCron', () => {
|
||||
mutations[types.SET_FREEZE_END_CRON](stateCopy, '5 0 * 8 *');
|
||||
|
||||
expect(stateCopy.freezeEndCron).toBe('5 0 * 8 *');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_SELECTED_ID', () => {
|
||||
it('should set selectedId', () => {
|
||||
mutations[types.SET_SELECTED_ID](stateCopy, 5);
|
||||
|
||||
expect(stateCopy.selectedId).toBe(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,7 +9,9 @@ exports[`IncidentsSettingTabs should render the component 1`] = `
|
|||
<div
|
||||
class="settings-header"
|
||||
>
|
||||
<h4>
|
||||
<h4
|
||||
class="settings-title js-settings-toggle js-settings-toggle-trigger-only"
|
||||
>
|
||||
|
||||
Incidents
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Server, Model, RestSerializer } from 'miragejs';
|
||||
import setupRoutes from 'ee_else_ce_test_helpers/mock_server/routes';
|
||||
import {
|
||||
getProject,
|
||||
getEmptyProject,
|
||||
|
@ -11,7 +12,6 @@ import {
|
|||
getBlobImage,
|
||||
getBlobZip,
|
||||
} from 'test_helpers/fixtures';
|
||||
import setupRoutes from './routes';
|
||||
|
||||
export const createMockServerOptions = () => ({
|
||||
models: {
|
||||
|
|
|
@ -27,6 +27,20 @@ RSpec.describe Gitlab::ApplicationContext do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.with_raw_context' do
|
||||
it 'yields the block' do
|
||||
expect { |b| described_class.with_raw_context({}, &b) }.to yield_control
|
||||
end
|
||||
|
||||
it 'passes the attributes unaltered on to labkit' do
|
||||
attrs = { foo: :bar }
|
||||
|
||||
expect(Labkit::Context).to receive(:with_context).with(attrs)
|
||||
|
||||
described_class.with_raw_context(attrs) {}
|
||||
end
|
||||
end
|
||||
|
||||
describe '.push' do
|
||||
it 'passes the expected context on to labkit' do
|
||||
fake_proc = duck_type(:call)
|
||||
|
@ -138,7 +152,7 @@ RSpec.describe Gitlab::ApplicationContext do
|
|||
it 'does not cause queries' do
|
||||
context = described_class.new(project: create(:project), namespace: create(:group, :nested), user: create(:user))
|
||||
|
||||
expect { context.use { Labkit::Context.current.to_h } }.not_to exceed_query_limit(0)
|
||||
expect { context.use { Gitlab::ApplicationContext.current } }.not_to exceed_query_limit(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,7 +30,7 @@ RSpec.describe Gitlab::Metrics::BackgroundTransaction do
|
|||
|
||||
describe '#labels' do
|
||||
it 'provides labels with endpoint_id and feature_category' do
|
||||
Labkit::Context.with_context(feature_category: 'projects', caller_id: 'TestWorker') do
|
||||
Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: 'TestWorker') do
|
||||
expect(transaction.labels).to eq({ endpoint_id: 'TestWorker', feature_category: 'projects' })
|
||||
end
|
||||
end
|
||||
|
@ -41,7 +41,7 @@ RSpec.describe Gitlab::Metrics::BackgroundTransaction do
|
|||
value = 1
|
||||
expect(prometheus_metric).to receive(metric_method).with({ endpoint_id: 'TestWorker', feature_category: 'projects' }, value)
|
||||
|
||||
Labkit::Context.with_context(feature_category: 'projects', caller_id: 'TestWorker') do
|
||||
Gitlab::ApplicationContext.with_raw_context(feature_category: 'projects', caller_id: 'TestWorker') do
|
||||
transaction.send(metric_method, :test_metric, value)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::WorkerContext::Server do
|
|||
worker_context user: nil
|
||||
|
||||
def perform(identifier, *args)
|
||||
self.class.contexts.merge!(identifier => Labkit::Context.current.to_h)
|
||||
self.class.contexts.merge!(identifier => Gitlab::ApplicationContext.current)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,7 +105,7 @@ RSpec.describe API::API do
|
|||
|
||||
it 'logs all application context fields' do
|
||||
allow_any_instance_of(Gitlab::GrapeLogging::Loggers::ContextLogger).to receive(:parameters) do
|
||||
Labkit::Context.current.to_h.tap do |log_context|
|
||||
Gitlab::ApplicationContext.current.tap do |log_context|
|
||||
expect(log_context).to match('correlation_id' => an_instance_of(String),
|
||||
'meta.caller_id' => '/api/:version/projects/:id/issues',
|
||||
'meta.remote_ip' => an_instance_of(String),
|
||||
|
@ -122,7 +122,7 @@ RSpec.describe API::API do
|
|||
|
||||
it 'skips fields that do not apply' do
|
||||
allow_any_instance_of(Gitlab::GrapeLogging::Loggers::ContextLogger).to receive(:parameters) do
|
||||
Labkit::Context.current.to_h.tap do |log_context|
|
||||
Gitlab::ApplicationContext.current.tap do |log_context|
|
||||
expect(log_context).to match('correlation_id' => an_instance_of(String),
|
||||
'meta.caller_id' => '/api/:version/users',
|
||||
'meta.remote_ip' => an_instance_of(String),
|
||||
|
|
|
@ -21,15 +21,30 @@ RSpec.describe BuildArtifactEntity do
|
|||
expect(subject).to include(:expired, :expire_at)
|
||||
end
|
||||
|
||||
it 'contains paths to the artifacts' do
|
||||
expect(subject[:path])
|
||||
.to include "jobs/#{job.id}/artifacts/download?file_type=codequality"
|
||||
it 'exposes the artifact download path' do
|
||||
expect(subject[:path]).to include "jobs/#{job.id}/artifacts/download?file_type=codequality"
|
||||
end
|
||||
|
||||
expect(subject[:keep_path])
|
||||
.to include "jobs/#{job.id}/artifacts/keep"
|
||||
context 'with remove_duplicate_artifact_exposure_paths enabled' do
|
||||
before do
|
||||
stub_feature_flags(remove_duplicate_artifact_exposure_paths: true)
|
||||
end
|
||||
|
||||
expect(subject[:browse_path])
|
||||
.to include "jobs/#{job.id}/artifacts/browse"
|
||||
it 'has no keep or browse path' do
|
||||
expect(subject).not_to include(:keep_path)
|
||||
expect(subject).not_to include(:browse_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with remove_duplicate_artifact_exposure_paths disabled' do
|
||||
before do
|
||||
stub_feature_flags(remove_duplicate_artifact_exposure_paths: false)
|
||||
end
|
||||
|
||||
it 'has keep and browse paths' do
|
||||
expect(subject[:keep_path]).to be_present
|
||||
expect(subject[:browse_path]).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -333,10 +333,20 @@ RSpec.configure do |config|
|
|||
RequestStore.clear!
|
||||
end
|
||||
|
||||
config.around do |example|
|
||||
if ENV['SKIP_RSPEC_CONTEXT_WRAPPING']
|
||||
config.around(:example, :context_aware) do |example|
|
||||
# Wrap each example in it's own context to make sure the contexts don't
|
||||
# leak
|
||||
Labkit::Context.with_context { example.run }
|
||||
Gitlab::ApplicationContext.with_raw_context { example.run }
|
||||
end
|
||||
else
|
||||
config.around do |example|
|
||||
if [:controller, :request, :feature].include?(example.metadata[:type]) || example.metadata[:context_aware]
|
||||
Gitlab::ApplicationContext.with_raw_context { example.run }
|
||||
else
|
||||
example.run
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
config.around do |example|
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'API::CI::Runner application context metadata' do |api_route|
|
||||
it 'contains correct context metadata' do
|
||||
it 'contains correct context metadata', :context_aware do
|
||||
# Avoids popping the context from the thread so we can
|
||||
# check its content after the request.
|
||||
allow(Labkit::Context).to receive(:pop)
|
||||
|
||||
send_request
|
||||
|
||||
Labkit::Context.with_context do |context|
|
||||
Gitlab::ApplicationContext.with_raw_context do |context|
|
||||
expected_context = {
|
||||
'meta.caller_id' => api_route,
|
||||
'meta.user' => job.user.username,
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'storing arguments in the application context' do
|
||||
around do |example|
|
||||
Labkit::Context.with_context { example.run }
|
||||
end
|
||||
|
||||
it 'places the expected params in the application context' do
|
||||
it 'places the expected params in the application context', :context_aware do
|
||||
# Stub the clearing of the context so we can validate it later
|
||||
# The `around` block above makes sure we do clean it up later
|
||||
allow(Labkit::Context).to receive(:pop)
|
||||
|
||||
subject
|
||||
|
||||
Labkit::Context.with_context do |context|
|
||||
expect(context.to_h)
|
||||
.to include(log_hash(expected_params))
|
||||
end
|
||||
expect(Gitlab::ApplicationContext.current).to include(log_hash(expected_params))
|
||||
end
|
||||
|
||||
def log_hash(hash)
|
||||
|
|
|
@ -101,7 +101,7 @@ RSpec.describe BackgroundMigrationWorker, :clean_gitlab_redis_shared_state do
|
|||
|
||||
it 'sets the class that will be executed as the caller_id' do
|
||||
expect(Gitlab::BackgroundMigration).to receive(:perform) do
|
||||
expect(Labkit::Context.current.to_h).to include('meta.caller_id' => 'Foo')
|
||||
expect(Gitlab::ApplicationContext.current).to include('meta.caller_id' => 'Foo')
|
||||
end
|
||||
|
||||
worker.perform('Foo', [10, 20])
|
||||
|
|
|
@ -103,7 +103,7 @@ RSpec.describe WorkerContext do
|
|||
describe '#with_context' do
|
||||
it 'allows modifying context when the job is running' do
|
||||
worker.new.with_context(user: build_stubbed(:user, username: 'jane-doe')) do
|
||||
expect(Labkit::Context.current.to_h).to include('meta.user' => 'jane-doe')
|
||||
expect(Gitlab::ApplicationContext.current).to include('meta.user' => 'jane-doe')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue