Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-06-26 06:11:26 +00:00
parent 7db49154e7
commit 0a362b6da1
21 changed files with 105 additions and 45 deletions

View File

@ -44,6 +44,7 @@ export default {
getFormDataAsObject() {
const assigneeIds = this.form.find('input[name="update[assignee_ids][]"]').val();
const statusId = this.form.find('input[name="update[status]"]')?.val();
const formData = {
update: {
state_event: this.form.find('input[name="update[state_event]"]').val(),
@ -58,6 +59,12 @@ export default {
confidential: this.form.find('input[name="update[confidentiality]"]').val(),
},
};
if (statusId) {
// when the FF is disabled or license check fails the status dropdown is not visible
formData.update.status = statusId;
}
if (assigneeIds) {
formData.update.assignee_ids = [assigneeIds];
}

View File

@ -73,11 +73,19 @@ export default class IssuableBulkUpdateSidebar {
// runtime this block won't execute.
if (IS_EE) {
import('ee_else_ce/sidebar/mount_sidebar')
.then(({ mountEpicDropdown, mountHealthStatusDropdown, mountIterationDropdown }) => {
mountEpicDropdown();
mountHealthStatusDropdown();
mountIterationDropdown();
})
.then(
({
mountEpicDropdown,
mountHealthStatusDropdown,
mountIterationDropdown,
mountSidebarCustomStatusWidget,
}) => {
mountEpicDropdown();
mountHealthStatusDropdown();
mountIterationDropdown();
mountSidebarCustomStatusWidget();
},
)
.catch(() => {});
}
}

View File

@ -18,6 +18,9 @@ export class DiffFile extends HTMLElement {
trigger;
/** @type {Object} Storage for intermediate state used by adapters */
sink = {};
_hookTeardowns = {
[events.MOUNTED]: new Set(),
};
static findByFileHash(hash) {
return document.querySelector(`diff-file[id="${hash}"]`);
@ -37,11 +40,19 @@ export class DiffFile extends HTMLElement {
this.observeVisibility();
// eslint-disable-next-line no-underscore-dangle
this.trigger = this._trigger.bind(this);
this.trigger(events.MOUNTED);
this.trigger(events.MOUNTED, this.registerMountedTeardowns.bind(this));
this.dispatchEvent(new CustomEvent(DIFF_FILE_MOUNTED, { bubbles: true }));
}
disconnectedCallback() {
// eslint-disable-next-line no-underscore-dangle
const mountedTeardowns = this._hookTeardowns[events.MOUNTED];
mountedTeardowns.forEach((cb) => {
cb();
});
mountedTeardowns.clear();
// eslint-disable-next-line no-underscore-dangle
this._hookTeardowns = undefined;
// app might be missing if the file was destroyed before mounting
// for example: changing view settings in the middle of the streaming
if (this.app) this.unobserveVisibility();
@ -60,6 +71,11 @@ export class DiffFile extends HTMLElement {
this.adapters.forEach((adapter) => adapter[event]?.call?.(this.adapterContext, ...args));
}
registerMountedTeardowns(callback) {
// eslint-disable-next-line no-underscore-dangle
this._hookTeardowns[events.MOUNTED].add(callback);
}
observeVisibility() {
if (!this.adapters.some((adapter) => adapter[events.VISIBLE] || adapter[events.INVISIBLE]))
return;

View File

@ -1,4 +1,8 @@
import { COLLAPSE_FILE, EXPAND_FILE } from '~/rapid_diffs/events';
import { COLLAPSE_FILE, EXPAND_FILE, MOUNTED } from '~/rapid_diffs/events';
function getDetails(root) {
return root.querySelector('[data-file-body]');
}
function getOppositeToggleButton(clicked) {
const isOpened = clicked.dataset.opened;
@ -12,15 +16,13 @@ function getOppositeToggleButton(clicked) {
function collapse(root = this.diffElement) {
// eslint-disable-next-line no-param-reassign
root.dataset.collapsed = true;
// eslint-disable-next-line no-param-reassign
root.querySelector('[data-file-body]').hidden = true;
getDetails(root).removeAttribute('open');
}
function expand(root = this.diffElement) {
// eslint-disable-next-line no-param-reassign
delete root.dataset.collapsed;
// eslint-disable-next-line no-param-reassign
root.querySelector('[data-file-body]').hidden = false;
getDetails(root).open = true;
}
function stopTransition(element) {
@ -51,4 +53,18 @@ export const ToggleFileAdapter = {
[COLLAPSE_FILE]() {
collapse.call(this);
},
[MOUNTED](onUnmounted) {
const details = getDetails(this.diffElement);
const handleToggle = () => {
if (details.open) {
expand.call(this);
} else {
collapse.call(this);
}
};
details.addEventListener('toggle', handleToggle);
onUnmounted(() => {
details.removeEventListener('toggle', handleToggle);
});
},
};

View File

@ -27,8 +27,8 @@ export default {
},
},
i18n: {
dropdownTitle: __('Change status'),
defaultDropdownText: __('Select status'),
dropdownTitle: __('Change state'),
defaultDropdownText: __('Select state'),
resetText: __('Reset'),
},
statusDropdownOptions,

View File

@ -14,6 +14,10 @@
--rd-diff-file-border-radius: #{$gl-border-radius-base};
}
.rd-diff-file-details > summary {
display: none;
}
.rd-diff-file[data-virtual]:not([data-collapsed]) {
// header top/bottom borders + body border
$total-borders: constants.$diff-file-border-width * 3;

View File

@ -3,8 +3,9 @@
%diff-file.rd-diff-file-component{ id: id, data: { testid: 'rd-diff-file', file_data: file_data.to_json } }
%article.rd-diff-file{ data: { virtual: virtual? }, style: ("--total-rows: #{total_rows}" if virtual?), aria: { labelledby: heading_id } }
= header || default_header
-# extra wrapper needed so content-visibility: hidden doesn't require removing border or other styles
%div{ data: { file_body: '' } }
-# extra wrapper needed so hidden state doesn't require removing border or other styles
%details.rd-diff-file-details{ open: true, data: { file_body: '' } }
%summary>
.rd-diff-file-body
= render viewer_component.new(diff_file: @diff_file)
%diff-file-mounted

View File

@ -11,9 +11,11 @@
= _('Update selected')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-bulk-update-menu-hide gl-float-right' }) do
= _('Cancel')
- if is_issue
= render_if_exists 'shared/issuable/status_dropdown', parent: @project.group
.block.js-status-dropdown-container
.title
= _('Status')
= _('State')
.js-status-dropdown
.block
.title

View File

@ -206,7 +206,7 @@ not be replicated.
{{< /alert >}}
These instructions help set up a single PostgreSQL database, which creates a single point of failure. To avoid this, you can configure your own clustered
PostgreSQL. Support for PostgreSQL replication and failover using the Linux package is proposed in [epic 7814](https://gitlab.com/groups/gitlab-org/-/epics/7814).
PostgreSQL.
Clustered database support for other databases (for example, Praefect and Geo databases) is proposed in
[issue 7292](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7292).

View File

@ -45,12 +45,12 @@ For more information, see [GitLab CI/CD variables](../variables/_index.md).
```yaml
variables:
# Configure mysql environment variables (https://hub.docker.com/_/mysql/)
MYSQL_DATABASE: $MYSQL_DATABASE
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
MYSQL_DATABASE: $MYSQL_DB
MYSQL_ROOT_PASSWORD: $MYSQL_PASS
```
The MySQL container uses `MYSQL_DATABASE` and `MYSQL_ROOT_PASSWORD` to connect to the database.
Pass these values by using variables (`$MYSQL_DB` and `$MYSQL_PASS`),
Pass these values by using [GitLab CI/CD variables](../variables/_index.md) (`$MYSQL_DB` and `$MYSQL_PASS` in the example above),
[rather than calling them directly](https://gitlab.com/gitlab-org/gitlab/-/issues/30178).
1. Configure your application to use the database, for example:

View File

@ -8,12 +8,6 @@ title: Dependency Proxy
The Dependency Proxy is a pull-through-cache for public registry images from DockerHub. This document describes how this
feature is constructed in GitLab.
{{< alert type="note" >}}
Support for private registry images is proposed in [issue 331741](https://gitlab.com/gitlab-org/gitlab/-/issues/331741).
{{< /alert >}}
## Container registry
The Dependency Proxy for the container registry acts a stand-in for a remote container registry. In our case,

View File

@ -809,8 +809,6 @@ To ensure that both pipeline execution policies and scan execution policies are
- Consider using a different strategy for pipeline execution policies, such as `inject_policy`.
- If you must use `override_project_ci`, include the scanner templates that you require in your pipeline execution policy to maintain the desired security scans.
Support for improvements in the integration between these policy types is proposed in [issue 504434](https://gitlab.com/gitlab-org/gitlab/-/issues/504434).
## Examples
These examples demonstrate what you can achieve with pipeline execution policies.

View File

@ -683,7 +683,7 @@ Audit event types belong to the following product categories.
| Type name | Event triggered when | Saved to database | Introduced in | Scope |
|:----------|:---------------------|:------------------|:--------------|:------|
| [`email_confirmation_sent`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/129261) | Users add or change an email address and it must be confirmed | {{< icon name="dotted-circle" >}} No | GitLab [16.3](https://gitlab.com/gitlab-org/gitlab/-/issues/377625) | User |
| [`remove_ssh_key`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65615) | A SSH key is removed | {{< icon name="check-circle" >}} Yes | GitLab [14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/220127) | User |
| [`remove_ssh_key`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65615) | An SSH key is removed from a user's profile. Group scope was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195390) for enterprise users in GitLab 18.2. | {{< icon name="check-circle" >}} Yes | GitLab [14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/220127) | User, Group |
| [`user_admin_status_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65168) | A user is either made an administrator or removed as an administrator | {{< icon name="check-circle" >}} Yes | GitLab [14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/323905) | User |
| [`user_auditor_status_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136456) | A user is either made an auditor or removed as an auditor | {{< icon name="check-circle" >}} Yes | GitLab [16.6](https://gitlab.com/gitlab-org/gitlab/-/issues/430235) | User |
| [`user_email_address_updated`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2103) | A user updates their email address | {{< icon name="check-circle" >}} Yes | GitLab [10.1](https://gitlab.com/gitlab-org/gitlab-ee/issues/1370) | User |

View File

@ -605,7 +605,7 @@ Support for creating a retention policy for job logs is proposed in [issue 37471
### Delete old pipelines
Pipelines do not add to the overall storage usage, but if required you can automate their deletion.
Pipelines do not add to the overall storage usage, but if required you can [automate their deletion](../ci/pipelines/settings.md#automatic-pipeline-cleanup).
To delete pipelines based on a specific date, specify the `created_at` key.
You can use the date to calculate the difference between the current date and
@ -802,8 +802,6 @@ the `created_at` attribute to implement a similar algorithm that compares the jo
{{< /tabs >}}
Automatic deletion of old pipelines is proposed in [issue 338480](https://gitlab.com/gitlab-org/gitlab/-/issues/338480).
### List expiry settings for job artifacts
To manage artifact storage, you can update or configure when an artifact expires.

View File

@ -12501,7 +12501,7 @@ msgstr ""
msgid "Change severity"
msgstr ""
msgid "Change status"
msgid "Change state"
msgstr ""
msgid "Change subscription"

View File

@ -24,6 +24,7 @@ RSpec.shared_context "with diff file component tests" do
render_component
expect(page).to have_selector(web_component_selector)
expect(page).to have_selector("#{web_component_selector}-mounted")
expect(page).to have_selector("details[data-file-body]")
end
it "renders server data" do

View File

@ -19,13 +19,13 @@ RSpec.describe 'Multiple issue updating from issues#index', :js, feature_categor
sign_in(user)
end
context 'status' do
context 'state' do
it 'sets to closed', :js do
visit project_issues_path(project)
click_button 'Bulk edit'
check 'Select all'
select_from_listbox('Closed', from: 'Select status')
select_from_listbox('Closed', from: 'Select state')
click_update_issues_button
expect(page).to have_selector('.issue', count: 0)
@ -37,7 +37,7 @@ RSpec.describe 'Multiple issue updating from issues#index', :js, feature_categor
click_button 'Bulk edit'
check 'Select all'
select_from_listbox('Open', from: 'Select status')
select_from_listbox('Open', from: 'Select state')
click_update_issues_button
expect(page).to have_selector('.issue', count: 0)

View File

@ -51,7 +51,7 @@ RSpec.describe 'Merge requests > User mass updates', :js, feature_category: :cod
click_button 'Bulk edit'
expect(page).not_to have_button 'Select status'
expect(page).not_to have_button 'Select state'
end
end
@ -115,7 +115,7 @@ RSpec.describe 'Merge requests > User mass updates', :js, feature_category: :cod
def change_status(text)
click_button 'Bulk edit'
check 'Select all'
select_from_listbox(text, from: 'Select status')
select_from_listbox(text, from: 'Select state')
click_update_merge_requests_button
end

View File

@ -12,6 +12,7 @@ describe('DiffFile Web Component', () => {
`;
let app;
let adapter;
let adapterMountedCleanup;
const getDiffElement = () => document.querySelector('[id=foo]');
const getWebComponentElement = () => document.querySelector('diff-file');
@ -29,7 +30,10 @@ describe('DiffFile Web Component', () => {
},
visible: jest.fn(),
invisible: jest.fn(),
mounted: jest.fn(),
mounted: jest.fn((onUnmounted) => {
adapterMountedCleanup = jest.fn();
onUnmounted(adapterMountedCleanup);
}),
});
const initRapidDiffsApp = (currentAdapter = createDefaultAdapter(), appData = {}) => {
@ -77,6 +81,10 @@ describe('DiffFile Web Component', () => {
customElements.define('diff-file', DiffFile);
});
beforeEach(() => {
adapterMountedCleanup = undefined;
});
it('observes diff element', () => {
mount();
expect(app.observe).toHaveBeenCalledWith(getWebComponentElement());
@ -98,6 +106,7 @@ describe('DiffFile Web Component', () => {
const element = getWebComponentElement();
document.body.innerHTML = '';
expect(app.unobserve).toHaveBeenCalledWith(element);
expect(adapterMountedCleanup).toHaveBeenCalled();
});
it('can self replace', () => {

View File

@ -37,7 +37,7 @@ describe('Diff File Toggle Behavior', () => {
<button data-opened="" data-click="toggleFile" aria-label="Hide file contents" type="button"></button>
<button data-closed="" data-click="toggleFile" aria-label="Show file contents" type="button"></button>
</div>
<div data-file-body=""><!-- body content --></div>
<details open data-file-body=""><summary></summary><div><!-- body content --></div></details>
</div>
</diff-file>
`;
@ -67,19 +67,19 @@ describe('Diff File Toggle Behavior', () => {
delegatedClick(hide);
expect(body.hidden).toEqual(true);
expect(body.open).toEqual(false);
expect(document.activeElement).toEqual(show);
});
it('collapses file', () => {
get('file').trigger(COLLAPSE_FILE);
expect(get('body').hidden).toEqual(true);
expect(get('body').open).toEqual(false);
expect(get('file').diffElement.dataset.collapsed).toEqual('true');
});
it('expands file', () => {
get('file').trigger(EXPAND_FILE);
expect(get('body').hidden).toEqual(false);
expect(get('body').open).toEqual(true);
expect(get('file').diffElement.dataset.collapsed).not.toEqual('true');
});
@ -99,4 +99,10 @@ describe('Diff File Toggle Behavior', () => {
tick();
expect(get('hide').style.transition).toBe('');
});
it('removes events listeners from body', () => {
const spy = jest.spyOn(get('body'), 'removeEventListener');
get('file').remove();
expect(spy).toHaveBeenCalledWith('toggle', expect.any(Function));
});
});

View File

@ -26,7 +26,7 @@ describe('SubscriptionsDropdown component', () => {
});
it('renders default text', () => {
expect(findDropdown().props('toggleText')).toBe('Select status');
expect(findDropdown().props('toggleText')).toBe('Select state');
});
it('renders dropdown items with `isSelected` prop set to `false`', () => {
@ -74,7 +74,7 @@ describe('SubscriptionsDropdown component', () => {
expect(dropdownItems.at(0).props('isSelected')).toBe(false);
expect(dropdownItems.at(1).props('isSelected')).toBe(false);
expect(findDropdown().props('toggleText')).toBe('Select status');
expect(findDropdown().props('toggleText')).toBe('Select state');
});
});
});