Commit 964cf7e0 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'aws-guidance' into 'master'

Adds aws tip to cicd add variable modal

See merge request gitlab-org/gitlab!34009
parents 242ef90d 2c5c5ff8
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 304 182" style="enable-background:new 0 0 304 182;" xml:space="preserve">
<style type="text/css">
.st0{fill:#252F3E;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FF9900;}
</style>
<g>
<path class="st0" d="M86.4,66.4c0,3.7,0.4,6.7,1.1,8.9c0.8,2.2,1.8,4.6,3.2,7.2c0.5,0.8,0.7,1.6,0.7,2.3c0,1-0.6,2-1.9,3l-6.3,4.2
c-0.9,0.6-1.8,0.9-2.6,0.9c-1,0-2-0.5-3-1.4C76.2,90,75,88.4,74,86.8c-1-1.7-2-3.6-3.1-5.9c-7.8,9.2-17.6,13.8-29.4,13.8
c-8.4,0-15.1-2.4-20-7.2c-4.9-4.8-7.4-11.2-7.4-19.2c0-8.5,3-15.4,9.1-20.6c6.1-5.2,14.2-7.8,24.5-7.8c3.4,0,6.9,0.3,10.6,0.8
c3.7,0.5,7.5,1.3,11.5,2.2v-7.3c0-7.6-1.6-12.9-4.7-16c-3.2-3.1-8.6-4.6-16.3-4.6c-3.5,0-7.1,0.4-10.8,1.3c-3.7,0.9-7.3,2-10.8,3.4
c-1.6,0.7-2.8,1.1-3.5,1.3c-0.7,0.2-1.2,0.3-1.6,0.3c-1.4,0-2.1-1-2.1-3.1v-4.9c0-1.6,0.2-2.8,0.7-3.5c0.5-0.7,1.4-1.4,2.8-2.1
c3.5-1.8,7.7-3.3,12.6-4.5c4.9-1.3,10.1-1.9,15.6-1.9c11.9,0,20.6,2.7,26.2,8.1c5.5,5.4,8.3,13.6,8.3,24.6V66.4z M45.8,81.6
c3.3,0,6.7-0.6,10.3-1.8c3.6-1.2,6.8-3.4,9.5-6.4c1.6-1.9,2.8-4,3.4-6.4c0.6-2.4,1-5.3,1-8.7v-4.2c-2.9-0.7-6-1.3-9.2-1.7
c-3.2-0.4-6.3-0.6-9.4-0.6c-6.7,0-11.6,1.3-14.9,4c-3.3,2.7-4.9,6.5-4.9,11.5c0,4.7,1.2,8.2,3.7,10.6
C37.7,80.4,41.2,81.6,45.8,81.6z M126.1,92.4c-1.8,0-3-0.3-3.8-1c-0.8-0.6-1.5-2-2.1-3.9L96.7,10.2c-0.6-2-0.9-3.3-0.9-4
c0-1.6,0.8-2.5,2.4-2.5h9.8c1.9,0,3.2,0.3,3.9,1c0.8,0.6,1.4,2,2,3.9l16.8,66.2l15.6-66.2c0.5-2,1.1-3.3,1.9-3.9c0.8-0.6,2.2-1,4-1
h8c1.9,0,3.2,0.3,4,1c0.8,0.6,1.5,2,1.9,3.9l15.8,67l17.3-67c0.6-2,1.3-3.3,2-3.9c0.8-0.6,2.1-1,3.9-1h9.3c1.6,0,2.5,0.8,2.5,2.5
c0,0.5-0.1,1-0.2,1.6c-0.1,0.6-0.3,1.4-0.7,2.5l-24.1,77.3c-0.6,2-1.3,3.3-2.1,3.9c-0.8,0.6-2.1,1-3.8,1h-8.6c-1.9,0-3.2-0.3-4-1
c-0.8-0.7-1.5-2-1.9-4L156,23l-15.4,64.4c-0.5,2-1.1,3.3-1.9,4c-0.8,0.7-2.2,1-4,1H126.1z M254.6,95.1c-5.2,0-10.4-0.6-15.4-1.8
c-5-1.2-8.9-2.5-11.5-4c-1.6-0.9-2.7-1.9-3.1-2.8c-0.4-0.9-0.6-1.9-0.6-2.8v-5.1c0-2.1,0.8-3.1,2.3-3.1c0.6,0,1.2,0.1,1.8,0.3
c0.6,0.2,1.5,0.6,2.5,1c3.4,1.5,7.1,2.7,11,3.5c4,0.8,7.9,1.2,11.9,1.2c6.3,0,11.2-1.1,14.6-3.3c3.4-2.2,5.2-5.4,5.2-9.5
c0-2.8-0.9-5.1-2.7-7c-1.8-1.9-5.2-3.6-10.1-5.2L246,52c-7.3-2.3-12.7-5.7-16-10.2c-3.3-4.4-5-9.3-5-14.5c0-4.2,0.9-7.9,2.7-11.1
c1.8-3.2,4.2-6,7.2-8.2c3-2.3,6.4-4,10.4-5.2c4-1.2,8.2-1.7,12.6-1.7c2.2,0,4.5,0.1,6.7,0.4c2.3,0.3,4.4,0.7,6.5,1.1
c2,0.5,3.9,1,5.7,1.6c1.8,0.6,3.2,1.2,4.2,1.8c1.4,0.8,2.4,1.6,3,2.5c0.6,0.8,0.9,1.9,0.9,3.3v4.7c0,2.1-0.8,3.2-2.3,3.2
c-0.8,0-2.1-0.4-3.8-1.2c-5.7-2.6-12.1-3.9-19.2-3.9c-5.7,0-10.2,0.9-13.3,2.8c-3.1,1.9-4.7,4.8-4.7,8.9c0,2.8,1,5.2,3,7.1
c2,1.9,5.7,3.8,11,5.5l14.2,4.5c7.2,2.3,12.4,5.5,15.5,9.6c3.1,4.1,4.6,8.8,4.6,14c0,4.3-0.9,8.2-2.6,11.6
c-1.8,3.4-4.2,6.4-7.3,8.8c-3.1,2.5-6.8,4.3-11.1,5.6C264.4,94.4,259.7,95.1,254.6,95.1z"/>
<g>
<path class="st1" d="M273.5,143.7c-32.9,24.3-80.7,37.2-121.8,37.2c-57.6,0-109.5-21.3-148.7-56.7c-3.1-2.8-0.3-6.6,3.4-4.4
c42.4,24.6,94.7,39.5,148.8,39.5c36.5,0,76.6-7.6,113.5-23.2C274.2,133.6,278.9,139.7,273.5,143.7z"/>
<path class="st1" d="M287.2,128.1c-4.2-5.4-27.8-2.6-38.5-1.3c-3.2,0.4-3.7-2.4-0.8-4.5c18.8-13.2,49.7-9.4,53.3-5
c3.6,4.5-1,35.4-18.6,50.2c-2.7,2.3-5.3,1.1-4.1-1.9C282.5,155.7,291.4,133.4,287.2,128.1z"/>
</g>
</g>
</svg>
<script> <script>
import { import {
GlAlert,
GlButton,
GlCollapse,
GlDeprecatedButton, GlDeprecatedButton,
GlModal, GlFormCheckbox,
GlFormSelect,
GlFormGroup, GlFormGroup,
GlFormInput, GlFormInput,
GlFormSelect,
GlFormTextarea, GlFormTextarea,
GlFormCheckbox,
GlLink,
GlIcon, GlIcon,
GlLink,
GlModal,
GlSprintf,
} from '@gitlab/ui'; } from '@gitlab/ui';
import Cookies from 'js-cookie';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale'; import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ADD_CI_VARIABLE_MODAL_ID } from '../constants'; import {
AWS_TOKEN_CONSTANTS,
ADD_CI_VARIABLE_MODAL_ID,
AWS_TIP_DISMISSED_COOKIE_NAME,
AWS_TIP_MESSAGE,
} from '../constants';
import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens'; import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
import CiKeyField from './ci_key_field.vue'; import CiKeyField from './ci_key_field.vue';
import CiEnvironmentsDropdown from './ci_environments_dropdown.vue'; import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
...@@ -23,19 +33,29 @@ export default { ...@@ -23,19 +33,29 @@ export default {
components: { components: {
CiEnvironmentsDropdown, CiEnvironmentsDropdown,
CiKeyField, CiKeyField,
GlAlert,
GlButton,
GlCollapse,
GlDeprecatedButton, GlDeprecatedButton,
GlModal, GlFormCheckbox,
GlFormSelect,
GlFormGroup, GlFormGroup,
GlFormInput, GlFormInput,
GlFormSelect,
GlFormTextarea, GlFormTextarea,
GlFormCheckbox,
GlLink,
GlIcon, GlIcon,
GlLink,
GlModal,
GlSprintf,
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
tokens: awsTokens, tokens: awsTokens,
tokenList: awsTokenList, tokenList: awsTokenList,
awsTipMessage: AWS_TIP_MESSAGE,
data() {
return {
isTipDismissed: Cookies.get(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
};
},
computed: { computed: {
...mapState([ ...mapState([
'projectId', 'projectId',
...@@ -47,7 +67,16 @@ export default { ...@@ -47,7 +67,16 @@ export default {
'maskableRegex', 'maskableRegex',
'selectedEnvironment', 'selectedEnvironment',
'isProtectedByDefault', 'isProtectedByDefault',
'awsLogoSvgPath',
'awsTipDeployLink',
'awsTipCommandsLink',
'awsTipLearnLink',
'protectedEnvironmentVariablesLink',
'maskedEnvironmentVariablesLink',
]), ]),
isTipVisible() {
return !this.isTipDismissed && AWS_TOKEN_CONSTANTS.includes(this.variableData.key);
},
canSubmit() { canSubmit() {
return ( return (
this.variableValidationState && this.variableValidationState &&
...@@ -126,6 +155,10 @@ export default { ...@@ -126,6 +155,10 @@ export default {
'setSelectedEnvironment', 'setSelectedEnvironment',
'setVariableProtected', 'setVariableProtected',
]), ]),
dismissTip() {
Cookies.set(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 });
this.isTipDismissed = true;
},
deleteVarAndClose() { deleteVarAndClose() {
this.deleteVariable(this.variableBeingEdited); this.deleteVariable(this.variableBeingEdited);
this.hideModal(); this.hideModal();
...@@ -232,7 +265,7 @@ export default { ...@@ -232,7 +265,7 @@ export default {
<gl-form-group :label="__('Flags')" label-for="ci-variable-flags"> <gl-form-group :label="__('Flags')" label-for="ci-variable-flags">
<gl-form-checkbox v-model="variableData.protected" class="mb-0"> <gl-form-checkbox v-model="variableData.protected" class="mb-0">
{{ __('Protect variable') }} {{ __('Protect variable') }}
<gl-link href="/help/ci/variables/README#protected-environment-variables"> <gl-link target="_blank" :href="protectedEnvironmentVariablesLink">
<gl-icon name="question" :size="12" /> <gl-icon name="question" :size="12" />
</gl-link> </gl-link>
<p class="gl-mt-2 text-secondary"> <p class="gl-mt-2 text-secondary">
...@@ -246,7 +279,7 @@ export default { ...@@ -246,7 +279,7 @@ export default {
data-qa-selector="ci_variable_masked_checkbox" data-qa-selector="ci_variable_masked_checkbox"
> >
{{ __('Mask variable') }} {{ __('Mask variable') }}
<gl-link href="/help/ci/variables/README#masked-variables"> <gl-link target="_blank" :href="maskedEnvironmentVariablesLink">
<gl-icon name="question" :size="12" /> <gl-icon name="question" :size="12" />
</gl-link> </gl-link>
<p class="gl-mt-2 gl-mb-0 text-secondary"> <p class="gl-mt-2 gl-mb-0 text-secondary">
...@@ -258,13 +291,52 @@ export default { ...@@ -258,13 +291,52 @@ export default {
> >
{{ __('Requires values to meet regular expression requirements.') }}</span {{ __('Requires values to meet regular expression requirements.') }}</span
> >
<gl-link href="/help/ci/variables/README#masked-variables">{{ <gl-link target="_blank" :href="maskedEnvironmentVariablesLink">{{
__('More information') __('More information')
}}</gl-link> }}</gl-link>
</p> </p>
</gl-form-checkbox> </gl-form-checkbox>
</gl-form-group> </gl-form-group>
</form> </form>
<gl-collapse :visible="isTipVisible">
<gl-alert
:title="__('Deploying to AWS is easy with GitLab')"
variant="tip"
data-testid="aws-guidance-tip"
@dismiss="dismissTip"
>
<div class="gl-display-flex gl-flex-direction-row">
<div>
<p>
<gl-sprintf :message="$options.awsTipMessage">
<template #deployLink="{ content }">
<gl-link :href="awsTipDeployLink" target="_blank">{{ content }}</gl-link>
</template>
<template #commandsLink="{ content }">
<gl-link :href="awsTipCommandsLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
<p>
<gl-button
:href="awsTipLearnLink"
target="_blank"
category="secondary"
variant="info"
class="gl-overflow-wrap-break"
>{{ __('Learn more about deploying to AWS') }}</gl-button
>
</p>
</div>
<img
class="gl-mt-3"
:alt="__('Amazon Web Services Logo')"
:src="awsLogoSvgPath"
height="32"
/>
</div>
</gl-alert>
</gl-collapse>
<template #modal-footer> <template #modal-footer>
<gl-deprecated-button @click="hideModal">{{ __('Cancel') }}</gl-deprecated-button> <gl-deprecated-button @click="hideModal">{{ __('Cancel') }}</gl-deprecated-button>
<gl-deprecated-button <gl-deprecated-button
......
...@@ -15,7 +15,13 @@ export const types = { ...@@ -15,7 +15,13 @@ export const types = {
allEnvironmentsType: '*', allEnvironmentsType: '*',
}; };
export const AWS_TIP_DISMISSED_COOKIE_NAME = 'ci_variable_list_constants_aws_tip_dismissed';
export const AWS_TIP_MESSAGE = __(
'%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}.',
);
// AWS TOKEN CONSTANTS // AWS TOKEN CONSTANTS
export const AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID'; export const AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID';
export const AWS_DEFAULT_REGION = 'AWS_DEFAULT_REGION'; export const AWS_DEFAULT_REGION = 'AWS_DEFAULT_REGION';
export const AWS_SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY'; export const AWS_SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY';
export const AWS_TOKEN_CONSTANTS = [AWS_ACCESS_KEY_ID, AWS_DEFAULT_REGION, AWS_SECRET_ACCESS_KEY];
...@@ -5,7 +5,19 @@ import { parseBoolean } from '~/lib/utils/common_utils'; ...@@ -5,7 +5,19 @@ import { parseBoolean } from '~/lib/utils/common_utils';
export default (containerId = 'js-ci-project-variables') => { export default (containerId = 'js-ci-project-variables') => {
const containerEl = document.getElementById(containerId); const containerEl = document.getElementById(containerId);
const { endpoint, projectId, group, maskableRegex, protectedByDefault } = containerEl.dataset; const {
endpoint,
projectId,
group,
maskableRegex,
protectedByDefault,
awsLogoSvgPath,
awsTipDeployLink,
awsTipCommandsLink,
awsTipLearnLink,
protectedEnvironmentVariablesLink,
maskedEnvironmentVariablesLink,
} = containerEl.dataset;
const isGroup = parseBoolean(group); const isGroup = parseBoolean(group);
const isProtectedByDefault = parseBoolean(protectedByDefault); const isProtectedByDefault = parseBoolean(protectedByDefault);
...@@ -15,6 +27,12 @@ export default (containerId = 'js-ci-project-variables') => { ...@@ -15,6 +27,12 @@ export default (containerId = 'js-ci-project-variables') => {
isGroup, isGroup,
maskableRegex, maskableRegex,
isProtectedByDefault, isProtectedByDefault,
awsLogoSvgPath,
awsTipDeployLink,
awsTipCommandsLink,
awsTipLearnLink,
protectedEnvironmentVariablesLink,
maskedEnvironmentVariablesLink,
}); });
return new Vue({ return new Vue({
......
...@@ -8,7 +8,18 @@ ...@@ -8,7 +8,18 @@
- if Feature.enabled?(:new_variables_ui, @project || @group, default_enabled: true) - if Feature.enabled?(:new_variables_ui, @project || @group, default_enabled: true)
- is_group = !@group.nil? - is_group = !@group.nil?
#js-ci-project-variables{ data: { endpoint: save_endpoint, project_id: @project&.id || '', group: is_group.to_s, maskable_regex: ci_variable_maskable_regex, protected_by_default: ci_variable_protected_by_default?.to_s} } #js-ci-project-variables{ data: { endpoint: save_endpoint,
project_id: @project&.id || '',
group: is_group.to_s,
maskable_regex: ci_variable_maskable_regex,
protected_by_default: ci_variable_protected_by_default?.to_s,
aws_logo_svg_path: image_path('aws_logo.svg'),
aws_tip_deploy_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'deploy-your-application-to-the-aws-elastic-container-service-ecs'),
aws_tip_commands_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'run-aws-commands-from-gitlab-cicd'),
aws_tip_learn_link: help_page_path('ci/cloud_deployment/index.md', anchor: 'aws'),
protected_environment_variables_link: help_page_path('ci/variables/README', anchor: 'protect-a-custom-variable'),
masked_environment_variables_link: help_page_path('ci/variables/README', anchor: 'mask-a-custom-variable'),
} }
- else - else
.row .row
......
---
title: Adds AWS guidance to CI/CD > Add Variable modal
merge_request: 34009
author:
type: added
...@@ -329,6 +329,9 @@ msgstr "" ...@@ -329,6 +329,9 @@ msgstr ""
msgid "%{days} days until tags are automatically removed" msgid "%{days} days until tags are automatically removed"
msgstr "" msgstr ""
msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}" msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "" msgstr ""
...@@ -2176,6 +2179,9 @@ msgstr "" ...@@ -2176,6 +2179,9 @@ msgstr ""
msgid "Amazon Web Services" msgid "Amazon Web Services"
msgstr "" msgstr ""
msgid "Amazon Web Services Logo"
msgstr ""
msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service." msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr "" msgstr ""
...@@ -7572,6 +7578,9 @@ msgstr "" ...@@ -7572,6 +7578,9 @@ msgstr ""
msgid "Deploying to" msgid "Deploying to"
msgstr "" msgstr ""
msgid "Deploying to AWS is easy with GitLab"
msgstr ""
msgid "Deployment Frequency" msgid "Deployment Frequency"
msgstr "" msgstr ""
...@@ -13039,6 +13048,9 @@ msgstr "" ...@@ -13039,6 +13048,9 @@ msgstr ""
msgid "Learn more about custom project templates" msgid "Learn more about custom project templates"
msgstr "" msgstr ""
msgid "Learn more about deploying to AWS"
msgstr ""
msgid "Learn more about deploying to a cluster" msgid "Learn more about deploying to a cluster"
msgstr "" msgstr ""
......
...@@ -105,6 +105,46 @@ describe('Ci variable modal', () => { ...@@ -105,6 +105,46 @@ describe('Ci variable modal', () => {
}); });
}); });
describe('Adding a new non-AWS variable', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidKeyVariable = {
...variable,
key: 'key',
value: 'value',
secret_value: 'secret_value',
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
});
it('does not show AWS guidance tip', () => {
const tip = wrapper.find(`div[data-testid='aws-guidance-tip']`);
expect(tip.exists()).toBe(true);
expect(tip.isVisible()).toBe(false);
});
});
describe('Adding a new AWS variable', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidKeyVariable = {
...variable,
key: AWS_ACCESS_KEY_ID,
value: 'AKIAIOSFODNN7EXAMPLEjdhy',
secret_value: 'AKIAIOSFODNN7EXAMPLEjdhy',
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
});
it('shows AWS guidance tip', () => {
const tip = wrapper.find(`[data-testid='aws-guidance-tip']`);
expect(tip.exists()).toBe(true);
expect(tip.isVisible()).toBe(true);
});
});
describe('Editing a variable', () => { describe('Editing a variable', () => {
beforeEach(() => { beforeEach(() => {
const [variable] = mockData.mockVariables; const [variable] = mockData.mockVariables;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment