From 6c96746adc90fee22a04e7a5c5c91ad15d3ff62a Mon Sep 17 00:00:00 2001 From: Anna Vovchenko Date: Tue, 20 Jun 2023 13:30:36 +0300 Subject: [PATCH 1/4] Remove `environment_settings_to_graphql` FF The FF is enabled by default. This commit cleans up the code. The changes migrate the environments settings page from axios to graphql and introduce a new field to select the cluster agent. Changelog: changed --- .../components/edit_environment.vue | 69 ++--------- .../components/environment_form.vue | 11 +- .../components/new_environment.vue | 27 +--- app/assets/javascripts/environments/edit.js | 9 +- .../projects/environments_controller.rb | 4 - app/helpers/environments_helper.rb | 8 -- .../projects/environments/edit.html.haml | 2 +- .../environment_settings_to_graphql.yml | 8 -- doc/ci/environments/kubernetes_dashboard.md | 2 +- doc/user/clusters/agent/user_access.md | 2 +- .../environments/edit_environment_spec.js | 116 +++--------------- .../environments/environment_form_spec.js | 15 +-- .../environments/new_environment_spec.js | 108 +++------------- spec/helpers/environments_helper_spec.rb | 9 -- 14 files changed, 56 insertions(+), 334 deletions(-) delete mode 100644 config/feature_flags/development/environment_settings_to_graphql.yml diff --git a/app/assets/javascripts/environments/components/edit_environment.vue b/app/assets/javascripts/environments/components/edit_environment.vue index 7905c5cf572d43..fff68693fa2a6c 100644 --- a/app/assets/javascripts/environments/components/edit_environment.vue +++ b/app/assets/javascripts/environments/components/edit_environment.vue @@ -1,9 +1,7 @@ diff --git a/app/assets/javascripts/environments/components/environment_form.vue b/app/assets/javascripts/environments/components/environment_form.vue index 266b221b481374..fd8f9ef2bde1ba 100644 --- a/app/assets/javascripts/environments/components/environment_form.vue +++ b/app/assets/javascripts/environments/components/environment_form.vue @@ -15,7 +15,6 @@ import { ENVIRONMENT_NEW_HELP_TEXT, ENVIRONMENT_EDIT_HELP_TEXT, } from 'ee_else_ce/environments/constants'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import getUserAuthorizedAgents from '../graphql/queries/user_authorized_agents.query.graphql'; export default { @@ -28,7 +27,6 @@ export default { GlLink, GlSprintf, }, - mixins: [glFeatureFlagsMixin()], inject: { protectedEnvironmentSettingsPath: { default: '' }, projectPath: { default: '' }, @@ -120,9 +118,6 @@ export default { item.text.toLowerCase().includes(lowerCasedSearchTerm), ); }, - showAgentsSelect() { - return this.glFeatures?.environmentSettingsToGraphql; - }, }, watch: { environment(change) { @@ -223,11 +218,7 @@ export default { /> - + import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; import { visitUrl } from '~/lib/utils/url_utility'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import createEnvironment from '../graphql/mutations/create_environment.mutation.graphql'; import EnvironmentForm from './environment_form.vue'; @@ -10,13 +8,13 @@ export default { components: { EnvironmentForm, }, - mixins: [glFeatureFlagsMixin()], inject: ['projectEnvironmentsPath', 'projectPath'], data() { return { environment: { name: '', externalUrl: '', + clusterAgentId: null, }, loading: false, }; @@ -25,14 +23,7 @@ export default { onChange(env) { this.environment = env; }, - onSubmit() { - if (this.glFeatures?.environmentSettingsToGraphql) { - this.createWithGraphql(); - } else { - this.createWithAxios(); - } - }, - async createWithGraphql() { + async onSubmit() { this.loading = true; try { const { data } = await this.$apollo.mutate({ @@ -65,20 +56,6 @@ export default { this.loading = false; } }, - createWithAxios() { - this.loading = true; - axios - .post(this.projectEnvironmentsPath, { - name: this.environment.name, - external_url: this.environment.externalUrl, - }) - .then(({ data: { path } }) => visitUrl(path)) - .catch((error) => { - const message = error.response.data.message[0]; - createAlert({ message }); - this.loading = false; - }); - }, }, }; diff --git a/app/assets/javascripts/environments/edit.js b/app/assets/javascripts/environments/edit.js index b26d96e15bd902..69aecc1f44375f 100644 --- a/app/assets/javascripts/environments/edit.js +++ b/app/assets/javascripts/environments/edit.js @@ -15,7 +15,7 @@ export default (el) => { updateEnvironmentPath, protectedEnvironmentSettingsPath, projectPath, - environment, + environmentName, } = el.dataset; return new Vue({ @@ -26,13 +26,10 @@ export default (el) => { updateEnvironmentPath, protectedEnvironmentSettingsPath, projectPath, + environmentName, }, render(h) { - return h(EditEnvironment, { - props: { - environment: JSON.parse(environment), - }, - }); + return h(EditEnvironment); }, }); }; diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 10d0d03e56dbfe..c47e6bd33755c6 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -16,10 +16,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController push_frontend_feature_flag(:kas_user_access_project, @project) end - before_action only: [:edit, :new] do - push_frontend_feature_flag(:environment_settings_to_graphql, @project) - end - before_action :authorize_read_environment! before_action :authorize_create_environment!, only: [:new, :create] before_action :authorize_stop_environment!, only: [:stop] diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb index 525fdd3e9f6afe..9ae5170d9c8be3 100644 --- a/app/helpers/environments_helper.rb +++ b/app/helpers/environments_helper.rb @@ -46,14 +46,6 @@ def can_destroy_environment?(environment) can?(current_user, :destroy_environment, environment) end - def environment_data(environment) - Gitlab::Json.generate({ - id: environment.id, - name: environment.name, - external_url: environment.external_url - }) - end - private def project_metrics_data(project) diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml index c7752a45c63510..6b8af173097ddc 100644 --- a/app/views/projects/environments/edit.html.haml +++ b/app/views/projects/environments/edit.html.haml @@ -5,4 +5,4 @@ update_environment_path: project_environment_path(@project, @environment), protected_environment_settings_path: (project_settings_ci_cd_path(@project, anchor: 'js-protected-environments-settings') if @project.licensed_feature_available?(:protected_environments)), project_path: @project.full_path, - environment: environment_data(@environment) } } + environment_name: @environment.name } } diff --git a/config/feature_flags/development/environment_settings_to_graphql.yml b/config/feature_flags/development/environment_settings_to_graphql.yml deleted file mode 100644 index fc9d54eb3b3c47..00000000000000 --- a/config/feature_flags/development/environment_settings_to_graphql.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: environment_settings_to_graphql -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121091 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412332 -milestone: '16.1' -type: development -group: group::environments -default_enabled: true diff --git a/doc/ci/environments/kubernetes_dashboard.md b/doc/ci/environments/kubernetes_dashboard.md index 7da48bed5d78c0..03e4384d8c1d1b 100644 --- a/doc/ci/environments/kubernetes_dashboard.md +++ b/doc/ci/environments/kubernetes_dashboard.md @@ -7,7 +7,7 @@ type: reference # Dashboard for Kubernetes (Beta) **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../administration/feature_flags.md) named `environment_settings_to_graphql`, `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../policy/experiment-beta-support.md#beta). +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../policy/experiment-beta-support.md#beta). Use the Dashboard for Kubernetes to understand the status of your clusters with an intuitive visual interface. The dashboard works with every connected Kubernetes cluster, whether you deployed them diff --git a/doc/user/clusters/agent/user_access.md b/doc/user/clusters/agent/user_access.md index be3f88d072ee90..c0ad2b3494d37e 100644 --- a/doc/user/clusters/agent/user_access.md +++ b/doc/user/clusters/agent/user_access.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Grant users Kubernetes access (Beta) **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../../administration/feature_flags.md) named `environment_settings_to_graphql`, `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../../policy/experiment-beta-support.md#beta). +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../../policy/experiment-beta-support.md#beta). As an administrator of Kubernetes clusters in an organization, you can grant Kubernetes access to members of a specific project or group. diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js index f436c96f4a5ec4..7e2b833a4dc510 100644 --- a/spec/frontend/environments/edit_environment_spec.js +++ b/spec/frontend/environments/edit_environment_spec.js @@ -1,13 +1,10 @@ import { GlLoadingIcon } from '@gitlab/ui'; -import MockAdapter from 'axios-mock-adapter'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import EditEnvironment from '~/environments/components/edit_environment.vue'; import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { visitUrl } from '~/lib/utils/url_utility'; import getEnvironment from '~/environments/graphql/queries/environment.query.graphql'; import updateEnvironment from '~/environments/graphql/mutations/update_environment.mutation.graphql'; @@ -17,7 +14,6 @@ import createMockApollo from '../__helpers__/mock_apollo_helper'; jest.mock('~/lib/utils/url_utility'); jest.mock('~/alert'); -const newExternalUrl = 'https://google.ca'; const environment = { id: '1', name: 'foo', @@ -39,11 +35,11 @@ const provide = { updateEnvironmentPath: '/projects/environments/1', protectedEnvironmentSettingsPath: '/projects/1/settings/ci_cd', projectPath: '/path/to/project', + environmentName: 'foo', }; describe('~/environments/components/edit.vue', () => { let wrapper; - let mock; const createMockApolloProvider = (mutationResult) => { Vue.use(VueApollo); @@ -59,22 +55,10 @@ describe('~/environments/components/edit.vue', () => { return createMockApollo(mocks); }; - const createWrapper = () => { - wrapper = mountExtended(EditEnvironment, { - propsData: { environment: { id: '1', name: 'foo', external_url: 'https://foo.example.com' } }, - provide, - }); - }; - const createWrapperWithApollo = async ({ mutationResult = environmentUpdate } = {}) => { wrapper = mountExtended(EditEnvironment, { propsData: { environment: {} }, - provide: { - ...provide, - glFeatures: { - environmentSettingsToGraphql: true, - }, - }, + provide, apolloProvider: createMockApolloProvider(mutationResult), }); @@ -87,45 +71,36 @@ describe('~/environments/components/edit.vue', () => { const showsLoading = () => wrapper.findComponent(GlLoadingIcon).exists(); - const submitForm = async () => { - await findExternalUrlInput().setValue(newExternalUrl); - await findForm().trigger('submit'); - }; - describe('default', () => { - beforeEach(async () => { - await createWrapper(); + it('renders loading icon when environment query is loading', () => { + createWrapperWithApollo(); + expect(showsLoading()).toBe(true); }); - it('sets the title to Edit environment', () => { + it('sets the title to Edit environment', async () => { + await createWrapperWithApollo(); + const header = wrapper.findByRole('heading', { name: __('Edit environment') }); expect(header.exists()).toBe(true); }); - it('renders a disabled "Name" field', () => { - const nameInput = findNameInput(); + it('renders a disabled "Name" field', async () => { + await createWrapperWithApollo(); + const nameInput = findNameInput(); expect(nameInput.attributes().disabled).toBe('disabled'); expect(nameInput.element.value).toBe(environment.name); }); - it('renders an "External URL" field', () => { - const urlInput = findExternalUrlInput(); + it('renders an "External URL" field', async () => { + await createWrapperWithApollo(); + const urlInput = findExternalUrlInput(); expect(urlInput.element.value).toBe(environment.externalUrl); }); }); - describe('when environmentSettingsToGraphql feature is enabled', () => { - describe('when mounted', () => { - beforeEach(() => { - createWrapperWithApollo(); - }); - it('renders loading icon when environment query is loading', () => { - expect(showsLoading()).toBe(true); - }); - }); - + describe('on submit', () => { describe('when mutation successful', () => { beforeEach(async () => { await createWrapperWithApollo(); @@ -134,13 +109,13 @@ describe('~/environments/components/edit.vue', () => { it('shows loader after form is submitted', async () => { expect(showsLoading()).toBe(false); - await submitForm(); + await findForm().trigger('submit'); expect(showsLoading()).toBe(true); }); it('submits the updated environment on submit', async () => { - await submitForm(); + await findForm().trigger('submit'); await waitForPromises(); expect(visitUrl).toHaveBeenCalledWith(environmentUpdate.environment.path); @@ -155,7 +130,7 @@ describe('~/environments/components/edit.vue', () => { }); it('shows errors on error', async () => { - await submitForm(); + await findForm().trigger('submit'); await waitForPromises(); expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' }); @@ -163,59 +138,4 @@ describe('~/environments/components/edit.vue', () => { }); }); }); - - describe('when environmentSettingsToGraphql feature is disabled', () => { - beforeEach(() => { - mock = new MockAdapter(axios); - createWrapper(); - }); - - afterEach(() => { - mock.restore(); - }); - - it('shows loader after form is submitted', async () => { - expect(showsLoading()).toBe(false); - - mock - .onPut(provide.updateEnvironmentPath, { - external_url: newExternalUrl, - id: environment.id, - }) - .reply(...[HTTP_STATUS_OK, { path: '/test' }]); - - await submitForm(); - - expect(showsLoading()).toBe(true); - }); - - it('submits the updated environment on submit', async () => { - mock - .onPut(provide.updateEnvironmentPath, { - external_url: newExternalUrl, - id: environment.id, - }) - .reply(...[HTTP_STATUS_OK, { path: '/test' }]); - - await submitForm(); - await waitForPromises(); - - expect(visitUrl).toHaveBeenCalledWith('/test'); - }); - - it('shows errors on error', async () => { - mock - .onPut(provide.updateEnvironmentPath, { - external_url: newExternalUrl, - id: environment.id, - }) - .reply(...[HTTP_STATUS_BAD_REQUEST, { message: ['uh oh!'] }]); - - await submitForm(); - await waitForPromises(); - - expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' }); - expect(showsLoading()).toBe(false); - }); - }); }); diff --git a/spec/frontend/environments/environment_form_spec.js b/spec/frontend/environments/environment_form_spec.js index db81c490747762..1b60396359997b 100644 --- a/spec/frontend/environments/environment_form_spec.js +++ b/spec/frontend/environments/environment_form_spec.js @@ -40,9 +40,6 @@ describe('~/environments/components/form.vue', () => { return mountExtended(EnvironmentForm, { provide: { ...PROVIDE, - glFeatures: { - environmentSettingsToGraphql: true, - }, }, propsData: { ...DEFAULT_PROPS, @@ -207,12 +204,6 @@ describe('~/environments/components/form.vue', () => { expect(urlInput.element.value).toBe('https://example.com'); }); - }); - - describe('when `environmentSettingsToGraphql feature flag is enabled', () => { - beforeEach(() => { - wrapper = createWrapperWithApollo(); - }); it('renders an agent selector listbox', () => { expect(findAgentSelector().props()).toMatchObject({ @@ -224,6 +215,12 @@ describe('~/environments/components/form.vue', () => { items: [], }); }); + }); + + describe('agent selector', () => { + beforeEach(() => { + wrapper = createWrapperWithApollo(); + }); it('sets the items prop of the agent selector after fetching the list', async () => { findAgentSelector().vm.$emit('shown'); diff --git a/spec/frontend/environments/new_environment_spec.js b/spec/frontend/environments/new_environment_spec.js index 749e4e5caa4f28..23641a1416131f 100644 --- a/spec/frontend/environments/new_environment_spec.js +++ b/spec/frontend/environments/new_environment_spec.js @@ -1,5 +1,4 @@ import { GlLoadingIcon } from '@gitlab/ui'; -import MockAdapter from 'axios-mock-adapter'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import { mountExtended } from 'helpers/vue_test_utils_helper'; @@ -7,8 +6,6 @@ import waitForPromises from 'helpers/wait_for_promises'; import NewEnvironment from '~/environments/components/new_environment.vue'; import createEnvironment from '~/environments/graphql/mutations/create_environment.mutation.graphql'; import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { visitUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import createMockApollo from '../__helpers__/mock_apollo_helper'; @@ -16,9 +13,6 @@ import createMockApollo from '../__helpers__/mock_apollo_helper'; jest.mock('~/lib/utils/url_utility'); jest.mock('~/alert'); -const newName = 'test'; -const newExternalUrl = 'https://google.ca'; - const provide = { projectEnvironmentsPath: '/projects/environments', projectPath: '/path/to/project', @@ -32,7 +26,6 @@ const environmentCreateError = { describe('~/environments/components/new.vue', () => { let wrapper; - let mock; const createMockApolloProvider = (mutationResult) => { Vue.use(VueApollo); @@ -47,29 +40,13 @@ describe('~/environments/components/new.vue', () => { const createWrapperWithApollo = async (mutationResult = environmentCreate) => { wrapper = mountExtended(NewEnvironment, { - provide: { - ...provide, - glFeatures: { - environmentSettingsToGraphql: true, - }, - }, + provide, apolloProvider: createMockApolloProvider(mutationResult), }); await waitForPromises(); }; - const createWrapperWithAxios = () => { - wrapper = mountExtended(NewEnvironment, { - provide: { - ...provide, - glFeatures: { - environmentSettingsToGraphql: false, - }, - }, - }); - }; - const findNameInput = () => wrapper.findByLabelText(__('Name')); const findExternalUrlInput = () => wrapper.findByLabelText(__('External URL')); const findForm = () => wrapper.findByRole('form', { name: __('New environment') }); @@ -84,7 +61,7 @@ describe('~/environments/components/new.vue', () => { describe('default', () => { beforeEach(() => { - createWrapperWithAxios(); + createWrapperWithApollo(); }); it('sets the title to New environment', () => { @@ -103,93 +80,36 @@ describe('~/environments/components/new.vue', () => { }); }); - describe('when environmentSettingsToGraphql feature is enabled', () => { - describe('when mutation successful', () => { - beforeEach(() => { - createWrapperWithApollo(); - }); - - it('shows loader after form is submitted', async () => { - expect(showsLoading()).toBe(false); - - await submitForm(); - - expect(showsLoading()).toBe(true); - }); - - it('submits the new environment on submit', async () => { - submitForm(); - await waitForPromises(); - - expect(visitUrl).toHaveBeenCalledWith('path/to/environment'); - }); - }); - - describe('when failed', () => { - beforeEach(async () => { - createWrapperWithApollo(environmentCreateError); - submitForm(); - await waitForPromises(); - }); - - it('shows errors on error', () => { - expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' }); - expect(showsLoading()).toBe(false); - }); - }); - }); - - describe('when environmentSettingsToGraphql feature is disabled', () => { + describe('when mutation successful', () => { beforeEach(() => { - mock = new MockAdapter(axios); - createWrapperWithAxios(); - }); - - afterEach(() => { - mock.restore(); + createWrapperWithApollo(); }); it('shows loader after form is submitted', async () => { expect(showsLoading()).toBe(false); - mock - .onPost(provide.projectEnvironmentsPath, { - name: newName, - external_url: newExternalUrl, - }) - .reply(HTTP_STATUS_OK, { path: '/test' }); - await submitForm(); expect(showsLoading()).toBe(true); }); it('submits the new environment on submit', async () => { - mock - .onPost(provide.projectEnvironmentsPath, { - name: newName, - external_url: newExternalUrl, - }) - .reply(HTTP_STATUS_OK, { path: '/test' }); - - await submitForm(); + submitForm(); await waitForPromises(); - expect(visitUrl).toHaveBeenCalledWith('/test'); + expect(visitUrl).toHaveBeenCalledWith('path/to/environment'); }); + }); - it('shows errors on error', async () => { - mock - .onPost(provide.projectEnvironmentsPath, { - name: newName, - external_url: newExternalUrl, - }) - .reply(HTTP_STATUS_BAD_REQUEST, { message: ['name taken'] }); - - await submitForm(); + describe('when failed', () => { + beforeEach(async () => { + createWrapperWithApollo(environmentCreateError); + submitForm(); await waitForPromises(); + }); - expect(createAlert).toHaveBeenCalledWith({ message: 'name taken' }); + it('shows errors on error', () => { + expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' }); expect(showsLoading()).toBe(false); }); }); diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb index 0ebec3ed6d0a04..c0816f93a68b54 100644 --- a/spec/helpers/environments_helper_spec.rb +++ b/spec/helpers/environments_helper_spec.rb @@ -147,13 +147,4 @@ expect(helper.environment_logs_data(project, environment)).to eq(expected_data) end end - - describe '#environment_data' do - it 'returns the environment as JSON' do - expected_data = { id: environment.id, - name: environment.name, - external_url: environment.external_url }.to_json - expect(helper.environment_data(environment)).to eq(expected_data) - end - end end -- GitLab From 954c79830a494177cbdbed1b503d8eaa712e6fce Mon Sep 17 00:00:00 2001 From: Phillip Wells Date: Tue, 20 Jun 2023 19:55:32 +0000 Subject: [PATCH 2/4] Apply TW suggestions --- doc/ci/environments/kubernetes_dashboard.md | 3 ++- doc/user/clusters/agent/user_access.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/ci/environments/kubernetes_dashboard.md b/doc/ci/environments/kubernetes_dashboard.md index 03e4384d8c1d1b..178b6a8ed5a4c1 100644 --- a/doc/ci/environments/kubernetes_dashboard.md +++ b/doc/ci/environments/kubernetes_dashboard.md @@ -7,7 +7,8 @@ type: reference # Dashboard for Kubernetes (Beta) **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../policy/experiment-beta-support.md#beta). +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../policy/experiment-beta-support.md#beta). +> - Feature flag `environment_settings_to_graphql` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124177) in GitLab 16.2. Use the Dashboard for Kubernetes to understand the status of your clusters with an intuitive visual interface. The dashboard works with every connected Kubernetes cluster, whether you deployed them diff --git a/doc/user/clusters/agent/user_access.md b/doc/user/clusters/agent/user_access.md index c0ad2b3494d37e..bcd0afe181993a 100644 --- a/doc/user/clusters/agent/user_access.md +++ b/doc/user/clusters/agent/user_access.md @@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Grant users Kubernetes access (Beta) **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../../policy/experiment-beta-support.md#beta). +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../../policy/experiment-beta-support.md#beta). +> - Feature flag `environment_settings_to_graphql` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124177) in GitLab 16.2. As an administrator of Kubernetes clusters in an organization, you can grant Kubernetes access to members of a specific project or group. -- GitLab From b3513d6813018d8ebeddc9cf7f49e4b9bd88bdab Mon Sep 17 00:00:00 2001 From: Anna Vovchenko Date: Wed, 21 Jun 2023 15:10:52 +0300 Subject: [PATCH 3/4] Applied frontend reviewer's suggestions --- .../environments/components/edit_environment.vue | 2 +- .../environments/components/environment_form.vue | 6 ++++-- app/assets/javascripts/environments/edit.js | 2 -- app/views/projects/environments/edit.html.haml | 1 - spec/frontend/environments/edit_environment_spec.js | 1 - spec/frontend/environments/new_environment_spec.js | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/environments/components/edit_environment.vue b/app/assets/javascripts/environments/components/edit_environment.vue index fff68693fa2a6c..9e3f8d996e00de 100644 --- a/app/assets/javascripts/environments/components/edit_environment.vue +++ b/app/assets/javascripts/environments/components/edit_environment.vue @@ -11,7 +11,7 @@ export default { GlLoadingIcon, EnvironmentForm, }, - inject: ['projectEnvironmentsPath', 'updateEnvironmentPath', 'projectPath', 'environmentName'], + inject: ['projectEnvironmentsPath', 'projectPath', 'environmentName'], apollo: { environment: { query: getEnvironment, diff --git a/app/assets/javascripts/environments/components/environment_form.vue b/app/assets/javascripts/environments/components/environment_form.vue index fd8f9ef2bde1ba..727d86fbb55e58 100644 --- a/app/assets/javascripts/environments/components/environment_form.vue +++ b/app/assets/javascripts/environments/components/environment_form.vue @@ -66,7 +66,7 @@ export default { cancel: __('Cancel'), reset: __('Reset'), }, - helpPagePath: helpPagePath('ci/environments/index.md'), + environmentsHelpPagePath: helpPagePath('ci/environments/index.md'), renamingDisabledHelpPagePath: helpPagePath('ci/environments/index.md', { anchor: 'rename-an-environment', }), @@ -166,7 +166,9 @@ export default { > diff --git a/app/assets/javascripts/environments/edit.js b/app/assets/javascripts/environments/edit.js index 69aecc1f44375f..f936085af1566e 100644 --- a/app/assets/javascripts/environments/edit.js +++ b/app/assets/javascripts/environments/edit.js @@ -12,7 +12,6 @@ export default (el) => { const { projectEnvironmentsPath, - updateEnvironmentPath, protectedEnvironmentSettingsPath, projectPath, environmentName, @@ -23,7 +22,6 @@ export default (el) => { apolloProvider: apolloProvider(), provide: { projectEnvironmentsPath, - updateEnvironmentPath, protectedEnvironmentSettingsPath, projectPath, environmentName, diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml index 6b8af173097ddc..c637fee28f9103 100644 --- a/app/views/projects/environments/edit.html.haml +++ b/app/views/projects/environments/edit.html.haml @@ -2,7 +2,6 @@ - add_page_specific_style 'page_bundles/environments' #js-edit-environment{ data: { project_environments_path: project_environments_path(@project), - update_environment_path: project_environment_path(@project, @environment), protected_environment_settings_path: (project_settings_ci_cd_path(@project, anchor: 'js-protected-environments-settings') if @project.licensed_feature_available?(:protected_environments)), project_path: @project.full_path, environment_name: @environment.name } } diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js index 7e2b833a4dc510..3d92dd02f1c498 100644 --- a/spec/frontend/environments/edit_environment_spec.js +++ b/spec/frontend/environments/edit_environment_spec.js @@ -32,7 +32,6 @@ const environmentUpdateError = { const provide = { projectEnvironmentsPath: '/projects/environments', - updateEnvironmentPath: '/projects/environments/1', protectedEnvironmentSettingsPath: '/projects/1/settings/ci_cd', projectPath: '/path/to/project', environmentName: 'foo', diff --git a/spec/frontend/environments/new_environment_spec.js b/spec/frontend/environments/new_environment_spec.js index 23641a1416131f..30cd9265d0d4df 100644 --- a/spec/frontend/environments/new_environment_spec.js +++ b/spec/frontend/environments/new_environment_spec.js @@ -108,7 +108,7 @@ describe('~/environments/components/new.vue', () => { await waitForPromises(); }); - it('shows errors on error', () => { + it('display errors', () => { expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' }); expect(showsLoading()).toBe(false); }); -- GitLab From 67efcd1bb02effb83c7d6fed48624b23e0b51623 Mon Sep 17 00:00:00 2001 From: Anna Vovchenko Date: Thu, 22 Jun 2023 18:46:39 +0300 Subject: [PATCH 4/4] Implemented maintainer's suggestion --- .../environments/edit_environment_spec.js | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js index 3d92dd02f1c498..6f850f6e779e6e 100644 --- a/spec/frontend/environments/edit_environment_spec.js +++ b/spec/frontend/environments/edit_environment_spec.js @@ -21,7 +21,7 @@ const environment = { clusterAgent: null, }; const resolvedEnvironment = { project: { id: '1', environment } }; -const environmentUpdate = { +const environmentUpdateSuccess = { environment: { id: '1', path: 'path/to/environment', clusterAgentId: null }, errors: [], }; @@ -40,25 +40,30 @@ const provide = { describe('~/environments/components/edit.vue', () => { let wrapper; - const createMockApolloProvider = (mutationResult) => { + const getEnvironmentQuery = jest.fn().mockResolvedValue({ data: resolvedEnvironment }); + const updateEnvironmentSuccess = jest + .fn() + .mockResolvedValue({ data: { environmentUpdate: environmentUpdateSuccess } }); + const updateEnvironmentFail = jest + .fn() + .mockResolvedValue({ data: { environmentUpdate: environmentUpdateError } }); + + const createMockApolloProvider = (mutationHandler) => { Vue.use(VueApollo); const mocks = [ - [getEnvironment, jest.fn().mockResolvedValue({ data: resolvedEnvironment })], - [ - updateEnvironment, - jest.fn().mockResolvedValue({ data: { environmentUpdate: mutationResult } }), - ], + [getEnvironment, getEnvironmentQuery], + [updateEnvironment, mutationHandler], ]; return createMockApollo(mocks); }; - const createWrapperWithApollo = async ({ mutationResult = environmentUpdate } = {}) => { + const createWrapperWithApollo = async ({ mutationHandler = updateEnvironmentSuccess } = {}) => { wrapper = mountExtended(EditEnvironment, { propsData: { environment: {} }, provide, - apolloProvider: createMockApolloProvider(mutationResult), + apolloProvider: createMockApolloProvider(mutationHandler), }); await waitForPromises(); @@ -71,6 +76,11 @@ describe('~/environments/components/edit.vue', () => { const showsLoading = () => wrapper.findComponent(GlLoadingIcon).exists(); describe('default', () => { + it('performs the environment apollo query', () => { + createWrapperWithApollo(); + expect(getEnvironmentQuery).toHaveBeenCalled(); + }); + it('renders loading icon when environment query is loading', () => { createWrapperWithApollo(); expect(showsLoading()).toBe(true); @@ -100,6 +110,13 @@ describe('~/environments/components/edit.vue', () => { }); describe('on submit', () => { + it('performs the updateEnvironment apollo mutation', async () => { + await createWrapperWithApollo(); + await findForm().trigger('submit'); + + expect(updateEnvironmentSuccess).toHaveBeenCalled(); + }); + describe('when mutation successful', () => { beforeEach(async () => { await createWrapperWithApollo(); @@ -117,14 +134,14 @@ describe('~/environments/components/edit.vue', () => { await findForm().trigger('submit'); await waitForPromises(); - expect(visitUrl).toHaveBeenCalledWith(environmentUpdate.environment.path); + expect(visitUrl).toHaveBeenCalledWith(environmentUpdateSuccess.environment.path); }); }); describe('when mutation failed', () => { beforeEach(async () => { await createWrapperWithApollo({ - mutationResult: environmentUpdateError, + mutationHandler: updateEnvironmentFail, }); }); -- GitLab