diff options
Diffstat (limited to 'app')
7 files changed, 174 insertions, 14 deletions
diff --git a/app/assets/images/aws_logo.svg b/app/assets/images/aws_logo.svg new file mode 100644 index 00000000000..e028fd1b1c0 --- /dev/null +++ b/app/assets/images/aws_logo.svg @@ -0,0 +1,38 @@ +<?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>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue index e57da6c6d65..6531b945212 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue @@ -1,19 +1,29 @@ <script> import { + GlAlert, + GlButton, + GlCollapse, GlDeprecatedButton, - GlModal, - GlFormSelect, + GlFormCheckbox, GlFormGroup, GlFormInput, + GlFormSelect, GlFormTextarea, - GlFormCheckbox, - GlLink, GlIcon, + GlLink, + GlModal, + GlSprintf, } from '@gitlab/ui'; +import Cookies from 'js-cookie'; import { mapActions, mapState } from 'vuex'; import { __ } from '~/locale'; 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 CiKeyField from './ci_key_field.vue'; import CiEnvironmentsDropdown from './ci_environments_dropdown.vue'; @@ -23,19 +33,29 @@ export default { components: { CiEnvironmentsDropdown, CiKeyField, + GlAlert, + GlButton, + GlCollapse, GlDeprecatedButton, - GlModal, - GlFormSelect, + GlFormCheckbox, GlFormGroup, GlFormInput, + GlFormSelect, GlFormTextarea, - GlFormCheckbox, - GlLink, GlIcon, + GlLink, + GlModal, + GlSprintf, }, mixins: [glFeatureFlagsMixin()], tokens: awsTokens, tokenList: awsTokenList, + awsTipMessage: AWS_TIP_MESSAGE, + data() { + return { + isTipDismissed: Cookies.get(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true', + }; + }, computed: { ...mapState([ 'projectId', @@ -47,7 +67,16 @@ export default { 'maskableRegex', 'selectedEnvironment', 'isProtectedByDefault', + 'awsLogoSvgPath', + 'awsTipDeployLink', + 'awsTipCommandsLink', + 'awsTipLearnLink', + 'protectedEnvironmentVariablesLink', + 'maskedEnvironmentVariablesLink', ]), + isTipVisible() { + return !this.isTipDismissed && AWS_TOKEN_CONSTANTS.includes(this.variableData.key); + }, canSubmit() { return ( this.variableValidationState && @@ -126,6 +155,10 @@ export default { 'setSelectedEnvironment', 'setVariableProtected', ]), + dismissTip() { + Cookies.set(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 }); + this.isTipDismissed = true; + }, deleteVarAndClose() { this.deleteVariable(this.variableBeingEdited); this.hideModal(); @@ -232,7 +265,7 @@ export default { <gl-form-group :label="__('Flags')" label-for="ci-variable-flags"> <gl-form-checkbox v-model="variableData.protected" class="mb-0"> {{ __('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-link> <p class="gl-mt-2 text-secondary"> @@ -246,7 +279,7 @@ export default { data-qa-selector="ci_variable_masked_checkbox" > {{ __('Mask variable') }} - <gl-link href="/help/ci/variables/README#masked-variables"> + <gl-link target="_blank" :href="maskedEnvironmentVariablesLink"> <gl-icon name="question" :size="12" /> </gl-link> <p class="gl-mt-2 gl-mb-0 text-secondary"> @@ -258,13 +291,52 @@ export default { > {{ __('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') }}</gl-link> </p> </gl-form-checkbox> </gl-form-group> </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> <gl-deprecated-button @click="hideModal">{{ __('Cancel') }}</gl-deprecated-button> <gl-deprecated-button diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js index a4db6481720..ef304c7ccee 100644 --- a/app/assets/javascripts/ci_variable_list/constants.js +++ b/app/assets/javascripts/ci_variable_list/constants.js @@ -15,7 +15,13 @@ export const types = { 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 export const AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID'; export const AWS_DEFAULT_REGION = 'AWS_DEFAULT_REGION'; 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]; diff --git a/app/assets/javascripts/ci_variable_list/index.js b/app/assets/javascripts/ci_variable_list/index.js index 095c39d54b2..a28b52d6b57 100644 --- a/app/assets/javascripts/ci_variable_list/index.js +++ b/app/assets/javascripts/ci_variable_list/index.js @@ -5,7 +5,19 @@ import { parseBoolean } from '~/lib/utils/common_utils'; export default (containerId = 'js-ci-project-variables') => { 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 isProtectedByDefault = parseBoolean(protectedByDefault); @@ -15,6 +27,12 @@ export default (containerId = 'js-ci-project-variables') => { isGroup, maskableRegex, isProtectedByDefault, + awsLogoSvgPath, + awsTipDeployLink, + awsTipCommandsLink, + awsTipLearnLink, + protectedEnvironmentVariablesLink, + maskedEnvironmentVariablesLink, }); return new Vue({ diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml index 26051261715..fa5f2c514ae 100644 --- a/app/views/ci/variables/_index.html.haml +++ b/app/views/ci/variables/_index.html.haml @@ -8,7 +8,18 @@ - if Feature.enabled?(:new_variables_ui, @project || @group, default_enabled: true) - 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 .row diff --git a/app/workers/authorized_project_update/user_refresh_with_low_urgency_worker.rb b/app/workers/authorized_project_update/user_refresh_with_low_urgency_worker.rb index 19038cb8900..7ca59a72adf 100644 --- a/app/workers/authorized_project_update/user_refresh_with_low_urgency_worker.rb +++ b/app/workers/authorized_project_update/user_refresh_with_low_urgency_worker.rb @@ -5,6 +5,7 @@ module AuthorizedProjectUpdate feature_category :authentication_and_authorization urgency :low queue_namespace :authorized_project_update + deduplicate :until_executing, including_scheduled: true idempotent! end diff --git a/app/workers/concerns/worker_attributes.rb b/app/workers/concerns/worker_attributes.rb index 7fa56c25210..b19217b15de 100644 --- a/app/workers/concerns/worker_attributes.rb +++ b/app/workers/concerns/worker_attributes.rb @@ -119,6 +119,20 @@ module WorkerAttributes Array(worker_attributes[:tags]) end + def deduplicate(strategy, options = {}) + worker_attributes[:deduplication_strategy] = strategy + worker_attributes[:deduplication_options] = options + end + + def get_deduplicate_strategy + worker_attributes[:deduplication_strategy] || + Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DEFAULT_STRATEGY + end + + def get_deduplication_options + worker_attributes[:deduplication_options] || {} + end + protected # Returns a worker attribute declared on this class or its parent class. |