Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-05-17 00:11:47 +00:00
parent 06076be6b8
commit 7233a3ac38
15 changed files with 77 additions and 107 deletions

View File

@ -16,7 +16,7 @@ import RunnerDetail from './runner_detail.vue';
import RunnerGroups from './runner_groups.vue';
import RunnerProjects from './runner_projects.vue';
import RunnerTags from './runner_tags.vue';
import RunnerManagersDetail from './runner_managers_detail.vue';
import RunnerManagers from './runner_managers.vue';
export default {
components: {
@ -29,7 +29,7 @@ export default {
RunnerGroups,
RunnerProjects,
RunnerTags,
RunnerManagersDetail,
RunnerManagers,
TimeAgo,
},
props: {
@ -143,7 +143,7 @@ export default {
</div>
<div class="gl-mt-3 gl-flex gl-flex-col gl-gap-5">
<runner-managers-detail :runner="runner" />
<runner-managers :runner="runner" />
<runner-groups v-if="isGroupRunner" :runner="runner" />
<runner-projects v-if="isProjectRunner" :runner="runner" />
</div>

View File

@ -1,17 +1,13 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__, formatNumber } from '~/locale';
import { createAlert } from '~/alert';
import CrudComponent from '~/vue_shared/components/crud_component.vue';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
import runnerManagersQuery from '../graphql/show/runner_managers.query.graphql';
import { I18N_FETCH_ERROR } from '../constants';
import { captureException } from '../sentry_utils';
import { tableField } from '../utils';
import RunnerManagersTable from './runner_managers_table.vue';
export default {
name: 'RunnerManagersDetail',
name: 'RunnerManagers',
components: {
GlLink,
GlSprintf,
@ -28,35 +24,15 @@ export default {
},
},
},
data() {
return {
managers: [],
};
},
apollo: {
managers: {
query: runnerManagersQuery,
variables() {
return { runnerId: this.runner.id };
},
update({ runner }) {
return runner?.managers?.nodes || [];
},
error(error) {
createAlert({ message: I18N_FETCH_ERROR });
captureException({ error, component: this.$options.name });
},
},
},
computed: {
runnerManagersCount() {
items() {
return this.runner?.managers?.nodes;
},
count() {
return this.runner?.managers?.count || 0;
},
runnerManagersCountFormatted() {
return formatNumber(this.runnerManagersCount);
},
loading() {
return this.$apollo?.queries.managers.loading;
formattedCount() {
return formatNumber(this.count);
},
},
fields: [
@ -73,11 +49,10 @@ export default {
<template>
<crud-component
v-if="runnerManagersCount > 0"
v-if="count > 0"
:title="s__('Runners|Runners')"
icon="container-image"
:count="runnerManagersCountFormatted"
:is-loading="loading"
:count="formattedCount"
anchor-id="runner-managers"
is-collapsible
collapsed
@ -103,6 +78,6 @@ export default {
</help-popover>
</template>
<runner-managers-table :items="managers" />
<runner-managers-table :items="items" />
</crud-component>
</template>

View File

@ -1,7 +1,16 @@
#import "ee_else_ce/ci/runner/graphql/show/runner_details.fragment.graphql"
#import "ee_else_ce/ci/runner/graphql/show/runner_manager.fragment.graphql"
query getRunner($id: CiRunnerID!) {
runner(id: $id) {
...RunnerDetails
# runner managers details
managers {
count
nodes {
...CiRunnerManager
}
}
}
}

View File

@ -1,13 +0,0 @@
#import "ee_else_ce/ci/runner/graphql/show/runner_manager.fragment.graphql"
query getRunnerManagers($runnerId: CiRunnerID!) {
runner(id: $runnerId) {
id
managers {
count
nodes {
...CiRunnerManager
}
}
}
}

View File

@ -1,15 +1,25 @@
import { __ } from '~/locale';
import groupsEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/empty-state/empty-groups-md.svg?url';
import { s__, __ } from '~/locale';
import {
SORT_LABEL_NAME,
SORT_LABEL_CREATED,
SORT_LABEL_UPDATED,
} from '~/groups_projects/constants';
import NestedGroupsProjectsList from '~/vue_shared/components/nested_groups_projects_list/nested_groups_projects_list.vue';
import ResourceListsEmptyState from '~/vue_shared/components/resource_lists/empty_state.vue';
import { formatGroups } from './utils';
import memberGroupsQuery from './graphql/queries/member_groups.query.graphql';
const baseTab = {
formatter: formatGroups,
emptyStateComponent: ResourceListsEmptyState,
emptyStateComponentProps: {
svgPath: groupsEmptyStateIllustration,
title: s__("Organization|You don't have any groups yet."),
description: s__(
'Organization|A group is a collection of several projects. If you organize your projects under a group, it works like a folder.',
),
},
};
export const MEMBER_TAB = {

View File

@ -288,6 +288,12 @@ export default {
}
},
async cancelEditing() {
// Don't cancel if autosuggest open in plain text editor
if (
this.$refs.markdownEditor.$el.querySelector('textarea')?.classList.contains('at-who-active')
) {
return;
}
if (this.commentText && this.commentText !== this.initialValue) {
const msg = s__('WorkItem|Are you sure you want to cancel editing?');

View File

@ -473,6 +473,16 @@ export default {
this.onInput();
}
},
handleEscape() {
// Don't cancel if autosuggest open in plain text editor
if (
!this.$refs.markdownEditor.$el
.querySelector('textarea')
?.classList.contains('at-who-active')
) {
this.cancelEditing();
}
},
},
};
</script>
@ -520,6 +530,7 @@ export default {
</template>
</gl-alert>
<markdown-editor
ref="markdownEditor"
:value="descriptionText"
:render-markdown-path="markdownPreviewPath"
:markdown-docs-path="$options.markdownDocsPath"
@ -535,6 +546,7 @@ export default {
@input="setDescriptionText"
@keydown.meta.enter="updateWorkItem"
@keydown.ctrl.enter="updateWorkItem"
@keydown.esc.stop="handleEscape"
/>
<div class="gl-flex">
<gl-alert

View File

@ -4,7 +4,7 @@ module QA
module Page
module Runners
class RunnerManagersDetail < Page::Base
view "app/assets/javascripts/ci/runner/components/runner_managers_detail.vue" do
view "app/assets/javascripts/ci/runner/components/runner_managers.vue" do
element "runner-managers"
end

View File

@ -10,7 +10,7 @@ import RunnerDetail from '~/ci/runner/components/runner_detail.vue';
import RunnerGroups from '~/ci/runner/components/runner_groups.vue';
import RunnerTags from '~/ci/runner/components/runner_tags.vue';
import RunnerTag from '~/ci/runner/components/runner_tag.vue';
import RunnerManagersDetail from '~/ci/runner/components/runner_managers_detail.vue';
import RunnerManagers from '~/ci/runner/components/runner_managers.vue';
import { runnerData, runnerWithGroupData } from '../mock_data';
@ -25,7 +25,7 @@ describe('RunnerDetails', () => {
useFakeDate(mockNow);
const findDetailGroups = () => wrapper.findComponent(RunnerGroups);
const findRunnerManagersDetail = () => wrapper.findComponent(RunnerManagersDetail);
const findRunnerManagers = () => wrapper.findComponent(RunnerManagers);
const findDdContent = (label) => findDd(label, wrapper).text().replace(/\s+/g, ' ');
@ -121,7 +121,7 @@ describe('RunnerDetails', () => {
},
});
expect(findRunnerManagersDetail().props('runner')).toEqual(mockRunner);
expect(findRunnerManagers().props('runner')).toEqual(mockRunner);
});
});

View File

@ -1,36 +1,28 @@
import { GlTableLite } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import RunnerManagersDetail from '~/ci/runner/components/runner_managers_detail.vue';
import RunnerManagers from '~/ci/runner/components/runner_managers.vue';
import RunnerManagersTable from '~/ci/runner/components/runner_managers_table.vue';
import CrudComponent from '~/vue_shared/components/crud_component.vue';
import runnerManagersQuery from '~/ci/runner/graphql/show/runner_managers.query.graphql';
import { runnerData, runnerManagersData } from '../mock_data';
import { runnerData } from '../mock_data';
jest.mock('~/alert');
jest.mock('~/ci/runner/sentry_utils');
const mockRunner = runnerData.data.runner;
const mockRunnerManagers = runnerManagersData.data.runner.managers.nodes;
Vue.use(VueApollo);
const mockRunnerManagers = runnerData.data.runner.managers.nodes;
describe('RunnerJobs', () => {
let wrapper;
let mockRunnerManagersHandler;
const findCrudComponent = () => wrapper.findComponent(CrudComponent);
const findCrudExpandToggle = () => wrapper.findByTestId('crud-collapse-toggle');
const findRunnerManagersTable = () => wrapper.findComponent(RunnerManagersTable);
const createComponent = ({ props, mountFn = shallowMountExtended } = {}) => {
wrapper = mountFn(RunnerManagersDetail, {
apolloProvider: createMockApollo([[runnerManagersQuery, mockRunnerManagersHandler]]),
wrapper = mountFn(RunnerManagers, {
propsData: {
runner: mockRunner,
...props,
@ -42,18 +34,11 @@ describe('RunnerJobs', () => {
});
};
beforeEach(() => {
mockRunnerManagersHandler = jest.fn();
});
afterEach(() => {
mockRunnerManagersHandler.mockReset();
});
it('hides if no runners', () => {
createComponent({
props: {
runner: {
...mockRunner,
managers: {
count: 0,
},
@ -88,19 +73,10 @@ describe('RunnerJobs', () => {
describe('Shows data', () => {
beforeEach(async () => {
mockRunnerManagersHandler.mockResolvedValue(runnerManagersData);
createComponent({ mountFn: mountExtended });
await waitForPromises();
});
it('fetches data', () => {
expect(mockRunnerManagersHandler).toHaveBeenCalledTimes(1);
expect(mockRunnerManagersHandler).toHaveBeenCalledWith({
runnerId: mockRunner.id,
});
});
it('shows rows', async () => {
await findCrudExpandToggle().vm.$emit('click');

View File

@ -5,12 +5,12 @@ import RunnerManagersTable from '~/ci/runner/components/runner_managers_table.vu
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { I18N_STATUS_NEVER_CONTACTED } from '~/ci/runner/constants';
import { runnerManagersData } from '../mock_data';
import { runnerData } from '../mock_data';
jest.mock('~/alert');
jest.mock('~/ci/runner/sentry_utils');
const mockItems = runnerManagersData.data.runner.managers.nodes;
const mockItems = runnerData.data.runner.managers.nodes;
describe('RunnerJobs', () => {
let wrapper;

View File

@ -19,7 +19,6 @@ import runnerData from 'test_fixtures/graphql/ci/runner/show/runner.query.graphq
import runnerWithGroupData from 'test_fixtures/graphql/ci/runner/show/runner.query.graphql.with_group.json';
import runnerProjectsData from 'test_fixtures/graphql/ci/runner/show/runner_projects.query.graphql.json';
import runnerJobsData from 'test_fixtures/graphql/ci/runner/show/runner_jobs.query.graphql.json';
import runnerManagersData from 'test_fixtures/graphql/ci/runner/show/runner_managers.query.graphql.json';
// Edit runner queries
import runnerFormData from 'test_fixtures/graphql/ci/runner/edit/runner_form.query.graphql.json';
@ -479,7 +478,6 @@ export {
runnerWithGroupData,
runnerProjectsData,
runnerJobsData,
runnerManagersData,
runnerFormData,
runnerCreateResult,
runnerForRegistration,

View File

@ -143,22 +143,6 @@ RSpec.describe 'Runner (JavaScript fixtures)', feature_category: :fleet_visibili
end
end
describe 'runner_managers.query.graphql', type: :request do
runner_managers_query = 'show/runner_managers.query.graphql'
let_it_be(:query) do
get_graphql_query_as_string("#{query_path}#{runner_managers_query}")
end
it "#{fixtures_path}#{runner_managers_query}.json" do
post_graphql(query, current_user: admin, variables: {
runner_id: runner.to_global_id.to_s
})
expect_graphql_errors_to_be_empty
end
end
describe 'runner_form.query.graphql', type: :request do
runner_jobs_query = 'edit/runner_form.query.graphql'

View File

@ -1,4 +1,4 @@
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { shallowMount } from '@vue/test-utils';
import YourWorkGroupsApp from '~/groups/your_work/components/app.vue';
import {
GROUP_DASHBOARD_TABS,
@ -24,7 +24,7 @@ describe('YourWorkGroupsApp', () => {
};
const createComponent = () => {
wrapper = shallowMountExtended(YourWorkGroupsApp, { propsData: defaultPropsData });
wrapper = shallowMount(YourWorkGroupsApp, { propsData: defaultPropsData });
};
beforeEach(() => {

View File

@ -878,6 +878,19 @@ RSpec.describe GroupsHelper, feature_category: :groups_and_projects do
end
end
describe '#groups_list_with_filtered_search_app_data' do
let_it_be(:endpoint) { '/groups' }
it 'returns expected json' do
expect(Gitlab::Json.parse(helper.groups_list_with_filtered_search_app_data(endpoint))).to eq(
{
'endpoint' => endpoint,
'initial_sort' => 'created_desc'
}
)
end
end
describe '#group_merge_requests' do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }