Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-05-21 03:11:43 +00:00
parent e67a224437
commit 65edff9059
12 changed files with 81 additions and 44 deletions

View File

@ -89,6 +89,7 @@ export default {
v-gl-tooltip.hover v-gl-tooltip.hover
category="secondary" category="secondary"
data-testid="subscribe-button" data-testid="subscribe-button"
:data-subscribed="subscribedToNotifications ? 'true' : 'false'"
:title="notificationTooltip" :title="notificationTooltip"
class="btn-icon" class="btn-icon"
@click="toggleNotifications(!subscribedToNotifications)" @click="toggleNotifications(!subscribedToNotifications)"

View File

@ -10,6 +10,7 @@ import {
BASE_ALLOWED_CREATE_TYPES, BASE_ALLOWED_CREATE_TYPES,
WORK_ITEM_TYPE_NAME_ISSUE, WORK_ITEM_TYPE_NAME_ISSUE,
WORK_ITEM_TYPE_NAME_INCIDENT, WORK_ITEM_TYPE_NAME_INCIDENT,
WORK_ITEM_TYPE_NAME_TASK,
} from '../constants'; } from '../constants';
import workItemRelatedItemQuery from '../graphql/work_item_related_item.query.graphql'; import workItemRelatedItemQuery from '../graphql/work_item_related_item.query.graphql';
import { convertTypeEnumToName } from '../utils'; import { convertTypeEnumToName } from '../utils';
@ -69,14 +70,17 @@ export default {
}, },
}, },
computed: { computed: {
isIssue() {
return this.workItemType === WORK_ITEM_TYPE_NAME_ISSUE;
},
isIncident() { isIncident() {
return this.workItemType === WORK_ITEM_TYPE_NAME_INCIDENT; return this.workItemType === WORK_ITEM_TYPE_NAME_INCIDENT;
}, },
allowedWorkItemTypes() { allowedWorkItemTypes() {
if (this.isIssue || this.isIncident) { if (
[
WORK_ITEM_TYPE_NAME_ISSUE,
WORK_ITEM_TYPE_NAME_INCIDENT,
WORK_ITEM_TYPE_NAME_TASK,
].includes(this.workItemType)
) {
return BASE_ALLOWED_CREATE_TYPES; return BASE_ALLOWED_CREATE_TYPES;
} }
@ -150,7 +154,7 @@ export default {
:is-group="isGroup" :is-group="isGroup"
:related-item="relatedItem" :related-item="relatedItem"
:should-discard-draft="shouldDiscardDraft" :should-discard-draft="shouldDiscardDraft"
:always-show-work-item-type-select="isIncident || isIssue" :always-show-work-item-type-select="!isGroup"
:allowed-work-item-types="allowedWorkItemTypes" :allowed-work-item-types="allowedWorkItemTypes"
@updateType="updateWorkItemType($event)" @updateType="updateWorkItemType($event)"
@confirmCancel="handleConfirmCancellation" @confirmCancel="handleConfirmCancellation"

View File

@ -9,6 +9,10 @@ class Groups::BoardsController < Groups::ApplicationController
push_frontend_feature_flag(:board_multi_select, group) push_frontend_feature_flag(:board_multi_select, group)
push_frontend_feature_flag(:issues_list_drawer, group) push_frontend_feature_flag(:issues_list_drawer, group)
push_force_frontend_feature_flag(:work_items_beta, !!group&.work_items_beta_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_beta, !!group&.work_items_beta_feature_flag_enabled?)
push_frontend_feature_flag(:notifications_todos_buttons)
push_force_frontend_feature_flag(:glql_integration, !!group&.glql_integration_feature_flag_enabled?)
push_force_frontend_feature_flag(:continue_indented_text, !!group&.continue_indented_text_feature_flag_enabled?)
push_frontend_feature_flag(:work_item_status_feature_flag, group&.root_ancestor)
end end
feature_category :team_planning feature_category :team_planning

View File

@ -9,6 +9,10 @@ class Projects::BoardsController < Projects::ApplicationController
push_frontend_feature_flag(:board_multi_select, project) push_frontend_feature_flag(:board_multi_select, project)
push_frontend_feature_flag(:issues_list_drawer, project) push_frontend_feature_flag(:issues_list_drawer, project)
push_force_frontend_feature_flag(:work_items_beta, !!project&.work_items_beta_feature_flag_enabled?) push_force_frontend_feature_flag(:work_items_beta, !!project&.work_items_beta_feature_flag_enabled?)
push_frontend_feature_flag(:notifications_todos_buttons)
push_force_frontend_feature_flag(:glql_integration, !!project&.glql_integration_feature_flag_enabled?)
push_force_frontend_feature_flag(:continue_indented_text, !!project&.continue_indented_text_feature_flag_enabled?)
push_frontend_feature_flag(:work_item_status_feature_flag, project&.root_ancestor)
end end
feature_category :team_planning feature_category :team_planning

View File

@ -74,18 +74,32 @@ validates :new_setting,
## Migrate a database column to a JSONB column ## Migrate a database column to a JSONB column
To migrate a column to JSONB, add the new setting under the JSONB accessor. To migrate a column to JSONB, add the new setting under the JSONB accessor.
Follow the [process to add a new application setting](#add-a-new-application-setting).
You can use the same name as the existing column to maintain consistency. During the ### Adding the JSONB setting
transition period, Rails writes the same information to both the existing database
- Follow the [process to add a new application setting](#add-a-new-application-setting).
- Use the same name as the existing column to maintain consistency.
- During transition, Rails writes the same information to both the existing database
column and the field under the new JSONB column. This ensures data consistency and column and the field under the new JSONB column. This ensures data consistency and
prevents downtime. prevents downtime.
You must follow the [process for dropping columns](database/avoiding_downtime_in_migrations.md#dropping-columns) to remove the original column. ### Required cleanup steps
This a required multi-milestone process that involves:
You must follow the [process for dropping columns](database/avoiding_downtime_in_migrations.md#dropping-columns)
to remove the original column. This a required multi-milestone process that involves:
1. Ignoring the column. 1. Ignoring the column.
1. Dropping the column. 1. Dropping the column.
1. Removing the ignore rule. 1. Removing the ignore rule.
{{< alert type="warning" >}}
Dropping the original column before ignoring it in the model can cause problems with zero-downtime migrations. Dropping the original column before ignoring it in the model can cause problems with zero-downtime migrations.
{{< /alert >}}
### Default values
When migrating settings to JSONB columns with `jsonb_accessor` defaults,
remove them from `ApplicationSettingImplementation.defaults` because
JSONB accessors take precedence over the `defaults` method.

View File

@ -259,7 +259,6 @@ to the table's database dictionary file. This can be used for:
- JiHu specific tables, since they do not have any data on the .com database. [!145905](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/145905) - JiHu specific tables, since they do not have any data on the .com database. [!145905](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/145905)
- tables that are marked to be dropped soon, like `operations_feature_flag_scopes`. [!147541](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147541) - tables that are marked to be dropped soon, like `operations_feature_flag_scopes`. [!147541](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147541)
- tables that mandatorily need to be present per cell to support a cell's operations, have unique data per cell, but cannot have a sharding key defined. For example, `zoekt_nodes`.
When tables are exempted from sharding key requirements, they also do not show up in our When tables are exempted from sharding key requirements, they also do not show up in our
[progress dashboard](https://cells-progress-tracker-gitlab-org-tenant-scale-g-f4ad96bf01d25f.gitlab.io/sharding_keys). [progress dashboard](https://cells-progress-tracker-gitlab-org-tenant-scale-g-f4ad96bf01d25f.gitlab.io/sharding_keys).

View File

@ -322,6 +322,10 @@ The `GITLAB_TOKEN` for the [@gl-service-dev-secure-analyzers-automation](https:/
The `ci-templates` project requires the `GITLAB_TOKEN` to allow certain scripts to execute API calls. This step can be removed after [allow JOB-TOKEN access to CI/lint endpoint](https://gitlab.com/gitlab-org/gitlab/-/issues/438781) has been completed. The `ci-templates` project requires the `GITLAB_TOKEN` to allow certain scripts to execute API calls. This step can be removed after [allow JOB-TOKEN access to CI/lint endpoint](https://gitlab.com/gitlab-org/gitlab/-/issues/438781) has been completed.
1. `GITLAB_TOKEN` CI/CD variable for the [`gitlab-org/secure/tools/security-triage-automation`](https://gitlab.com/gitlab-org/secure/tools/security-triage-automation) project.
This must be explicitly configured because the `security-triage-automation` project is not nested under the `gitlab-org/security-products/analyzers` namespace, and therefore _does not inherit_ the `GITLAB_TOKEN` value.
1. `SEC_REGISTRY_PASSWORD` CI/CD variable for [`gitlab-advanced-sast`](https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-advanced-sast/-/settings/ci_cd#js-cicd-variables-settings). 1. `SEC_REGISTRY_PASSWORD` CI/CD variable for [`gitlab-advanced-sast`](https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-advanced-sast/-/settings/ci_cd#js-cicd-variables-settings).
This allows our [tagging script](https://gitlab.com/gitlab-org/security-products/ci-templates/blob/cfe285a/scripts/tag_image.sh) to pull from the private container registry in the development project `registry.gitlab.com/gitlab-org/security-products/analyzers/<analyzer-name>/tmp`, and push to the publicly accessible container registry `registry.gitlab.com/security-products/<analyzer-name>`. This allows our [tagging script](https://gitlab.com/gitlab-org/security-products/ci-templates/blob/cfe285a/scripts/tag_image.sh) to pull from the private container registry in the development project `registry.gitlab.com/gitlab-org/security-products/analyzers/<analyzer-name>/tmp`, and push to the publicly accessible container registry `registry.gitlab.com/security-products/<analyzer-name>`.

View File

@ -21,6 +21,7 @@ RSpec.describe 'Project issue boards sidebar', :js, feature_category: :portfolio
context 'when issues drawer is disabled' do context 'when issues drawer is disabled' do
before do before do
stub_feature_flags(issues_list_drawer: false) stub_feature_flags(issues_list_drawer: false)
stub_feature_flags(notifications_todos_buttons: false)
sign_in(user) sign_in(user)
visit project_board_path(project, board) visit project_board_path(project, board)

View File

@ -131,6 +131,18 @@ describe('WorkItemActions component', () => {
expect(findNotificationsButton().findComponent(GlIcon).props('name')).toBe(icon); expect(findNotificationsButton().findComponent(GlIcon).props('name')).toBe(icon);
}); });
it.each`
scenario | subscribedToNotifications | dataSubscribed
${'notifications are off'} | ${false} | ${'false'}
${'notifications are on'} | ${true} | ${'true'}
`(
'has the correct data-subscribed attribute when $scenario',
({ subscribedToNotifications, dataSubscribed }) => {
createComponent({ subscribedToNotifications });
expect(findNotificationsButton().attributes('data-subscribed')).toBe(dataSubscribed);
},
);
it('emits error when the update notification mutation fails', async () => { it('emits error when the update notification mutation fails', async () => {
createComponent({ createComponent({
notificationsMutationHandler: toggleNotificationsFailureHandler, notificationsMutationHandler: toggleNotificationsFailureHandler,

View File

@ -81,6 +81,16 @@ describe('Create work item page component', () => {
}); });
}); });
it('passes alwaysShowWorkItemTypeSelect prop as `true` to the CreateWorkItem component when isGroup is false', () => {
const pushMock = jest.fn();
createComponent({ push: pushMock }, false);
expect(findCreateWorkItem().props()).toMatchObject({
alwaysShowWorkItemTypeSelect: true,
allowedWorkItemTypes: ['Incident', 'Issue', 'Task'],
});
});
it('visits work item detail page after create if router is not present', () => { it('visits work item detail page after create if router is not present', () => {
createComponent(); createComponent();

View File

@ -111,6 +111,7 @@ module InvokeRopSteps
context_passed_along_steps: context_passed_along_steps:
) )
expected_rop_steps = [] expected_rop_steps = []
skip_unless_inspect = false
rop_steps.each do |rop_step| rop_steps.each do |rop_step|
step_class = rop_step[0] step_class = rop_step[0]
@ -121,13 +122,11 @@ module InvokeRopSteps
step_action: step_action step_action: step_action
} }
next if skip_unless_inspect && [:inspect_ok, :inspect_err].freeze.exclude?(step_action)
if err_results_for_steps.key?(step_class) if err_results_for_steps.key?(step_class)
expected_rop_step[:returned_object] = err_results_for_steps[step_class] expected_rop_step[:returned_object] = err_results_for_steps[step_class]
skip_unless_inspect = true
# Currently, only a single error step is supported, so we assign expected_rop_step as the last entry
# in expected_rop_steps, break out of the loop early, and do not add any more steps
expected_rop_steps << expected_rop_step
break
elsif ok_results_for_steps.key?(step_class) elsif ok_results_for_steps.key?(step_class)
expected_rop_step[:returned_object] = ok_results_for_steps[step_class] expected_rop_step[:returned_object] = ok_results_for_steps[step_class]
elsif step_action == :and_then elsif step_action == :and_then
@ -169,7 +168,9 @@ module InvokeRopSteps
context_passed_along_steps:, context_passed_along_steps:,
returned_object: returned_object:
) )
expect(step_class).to receive(step_class_method).with(context_passed_along_steps).ordered do expectation = expect(step_class).to receive(step_class_method)
expectation = expectation.with(context_passed_along_steps) if step_class_method != :observe
expectation.ordered do
returned_object returned_object
end end
end end

View File

@ -64,38 +64,21 @@ RSpec.shared_examples 'work item drawer' do
end end
context 'when in notifications subscription' do context 'when in notifications subscription' do
before do
within_testid('work-item-drawer') do
find_by_testid('work-item-actions-dropdown').click
end
end
it 'displays notifications toggle', :aggregate_failures do
within_testid('work-item-drawer') do
expect(page).to have_selector('[data-testid="notifications-toggle-form"]')
expect(page).to have_content('Notifications')
expect(page).not_to have_content('Disabled by project owner')
end
end
it 'shows toggle as on then as off as user toggles to subscribe and unsubscribe', :aggregate_failures do it 'shows toggle as on then as off as user toggles to subscribe and unsubscribe', :aggregate_failures do
within_testid('notifications-toggle-form') do subscribe_button = find_by_testid('subscribe-button')
subscription_button = find('[data-testid="notifications-toggle"] button') expect(page).to have_selector("button[data-testid='subscribe-button'][data-subscribed='false']")
expect(page).not_to have_css("button.is-checked") subscribe_button.click
wait_for_requests
subscription_button.click expect(page).to have_content("Notifications turned on.")
expect(page).to have_selector("button[data-testid='subscribe-button'][data-subscribed='true']")
wait_for_requests subscribe_button.click
wait_for_requests
expect(page).to have_css("button.is-checked") expect(page).to have_content("Notifications turned off.")
expect(page).to have_selector("button[data-testid='subscribe-button'][data-subscribed='false']")
subscription_button.click
wait_for_requests
expect(page).not_to have_css("button.is-checked")
end
end end
end end