diff options
146 files changed, 879 insertions, 350 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0354a2b650b..591c83f0cff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,6 +35,8 @@ default: .default-branch-incident-variables: &default-branch-incident-variables CREATE_INCIDENT_FOR_PIPELINE_FAILURE: "true" NOTIFY_PIPELINE_FAILURE_CHANNEL: "master-broken" + BROKEN_BRANCH_INCIDENTS_PROJECT: "gitlab-org/quality/engineering-productivity/master-broken-incidents" + BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN: "${BROKEN_MASTER_INCIDENTS_PROJECT_TOKEN}" workflow: name: '$PIPELINE_NAME' @@ -107,6 +109,9 @@ workflow: <<: *ruby2-variables NOTIFY_PIPELINE_FAILURE_CHANNEL: "releases" PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline' + CREATE_INCIDENT_FOR_PIPELINE_FAILURE: "true" + BROKEN_BRANCH_INCIDENTS_PROJECT: "gitlab-org/release/tasks" + BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN: "${BROKEN_STABLE_INCIDENTS_PROJECT_TOKEN}" - if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/' variables: <<: *ruby2-variables diff --git a/.gitlab/ci/notify.gitlab-ci.yml b/.gitlab/ci/notify.gitlab-ci.yml index 84fb5a55ed1..bdd7979126f 100644 --- a/.gitlab/ci/notify.gitlab-ci.yml +++ b/.gitlab/ci/notify.gitlab-ci.yml @@ -43,8 +43,9 @@ notify-pipeline-failure: - .notify:rules:notify-pipeline-failure image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION} variables: - BROKEN_MASTER_INCIDENTS_PROJECT: "gitlab-org/quality/engineering-productivity/master-broken-incidents" - BROKEN_MASTER_INCIDENT_JSON: "${CI_PROJECT_DIR}/incident.json" + INCIDENT_PROJECT: "#{BROKEN_BRANCH_INCIDENTS_PROJECT}" + BROKEN_BRANCH_PROJECT_TOKEN: "${BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN}" + INCIDENT_JSON: "${CI_PROJECT_DIR}/incident.json" SLACK_CHANNEL: "${NOTIFY_PIPELINE_FAILURE_CHANNEL}" FAILED_PIPELINE_SLACK_MESSAGE_FILE: "${CI_PROJECT_DIR}/failed_pipeline_slack_message.json" before_script: @@ -54,17 +55,17 @@ notify-pipeline-failure: script: - | if [[ "${CREATE_INCIDENT_FOR_PIPELINE_FAILURE}" == "true" ]]; then - scripts/create-pipeline-failure-incident.rb -p ${BROKEN_MASTER_INCIDENTS_PROJECT} -f ${BROKEN_MASTER_INCIDENT_JSON} -t ${BROKEN_MASTER_INCIDENTS_PROJECT_TOKEN}; - echosuccess "Created incident $(jq '.web_url' ${BROKEN_MASTER_INCIDENT_JSON})"; + scripts/create-pipeline-failure-incident.rb -p ${INCIDENT_PROJECT} -f ${INCIDENT_JSON} -t ${BROKEN_BRANCH_PROJECT_TOKEN}; + echosuccess "Created incident $(jq '.web_url' ${INCIDENT_JSON})"; fi - | - scripts/generate-failed-pipeline-slack-message.rb -i ${BROKEN_MASTER_INCIDENT_JSON} -f ${FAILED_PIPELINE_SLACK_MESSAGE_FILE}; + scripts/generate-failed-pipeline-slack-message.rb -i ${INCIDENT_JSON} -f ${FAILED_PIPELINE_SLACK_MESSAGE_FILE}; curl -X POST -H 'Content-Type: application/json' --data @${FAILED_PIPELINE_SLACK_MESSAGE_FILE} "$CI_SLACK_WEBHOOK_URL" || scripts/slack ${SLACK_CHANNEL} "☠️ Broken pipeline notification failed! ☠️ See ${CI_JOB_URL}" ci_failing "Failed pipeline reporter" artifacts: paths: - - ${BROKEN_MASTER_INCIDENT_JSON} + - ${INCIDENT_JSON} - ${FAILED_PIPELINE_SLACK_MESSAGE_FILE} when: always expire_in: 2 days diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 718b4e67f4e..c26dd45ae93 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -2096,7 +2096,7 @@ changes: *code-patterns when: manual allow_failure: true - - <<: *if-dot-com-gitlab-org-schedule + - <<: *if-dot-com-ee-schedule-default-branch-maintenance allow_failure: true .review:rules:review-k8s-resources-count-checks: diff --git a/.rubocop_todo/performance/string_include.yml b/.rubocop_todo/performance/string_include.yml deleted file mode 100644 index 2a2d0559397..00000000000 --- a/.rubocop_todo/performance/string_include.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -# Cop supports --autocorrect. -Performance/StringInclude: - Exclude: - - 'app/models/snippet_repository.rb' - - 'config/initializers/macos.rb' - - 'config/spring.rb' - - 'ee/app/models/ee/container_registry/event.rb' - - 'ee/lib/gitlab/auth/smartcard/certificate.rb' - - 'lib/kramdown/parser/atlassian_document_format.rb' - - 'lib/prometheus/pid_provider.rb' - - 'spec/features/projects/jobs_spec.rb' - - 'spec/spec_helper.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 2dd600c5f52..3a65378f961 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -4e200026c03189abe2c60b071204340c4af5cf35 +6eb7389db0d54ef9ba3622eb7d1412f71e9deb2f diff --git a/app/assets/javascripts/graphql_shared/issuable_client.js b/app/assets/javascripts/graphql_shared/issuable_client.js index 745a03f411a..316bc746051 100644 --- a/app/assets/javascripts/graphql_shared/issuable_client.js +++ b/app/assets/javascripts/graphql_shared/issuable_client.js @@ -6,6 +6,8 @@ import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.grap import createDefaultClient from '~/lib/graphql'; import typeDefs from '~/work_items/graphql/typedefs.graphql'; import { WIDGET_TYPE_NOTES } from '~/work_items/constants'; +import getWorkItemLinksQuery from '~/work_items/graphql/work_item_links.query.graphql'; +import { findHierarchyWidgetChildren } from '~/work_items/utils'; export const config = { typeDefs, @@ -143,6 +145,28 @@ export const config = { export const resolvers = { Mutation: { + addHierarchyChild: (_, { id, workItem }, { cache }) => { + const queryArgs = { query: getWorkItemLinksQuery, variables: { id } }; + const sourceData = cache.readQuery(queryArgs); + + const data = produce(sourceData, (draftState) => { + findHierarchyWidgetChildren(draftState.workItem).push(workItem); + }); + + cache.writeQuery({ ...queryArgs, data }); + }, + removeHierarchyChild: (_, { id, workItem }, { cache }) => { + const queryArgs = { query: getWorkItemLinksQuery, variables: { id } }; + const sourceData = cache.readQuery(queryArgs); + + const data = produce(sourceData, (draftState) => { + const hierarchyChildren = findHierarchyWidgetChildren(draftState.workItem); + const index = hierarchyChildren.findIndex((child) => child.id === workItem.id); + hierarchyChildren.splice(index, 1); + }); + + cache.writeQuery({ ...queryArgs, data }); + }, updateIssueState: (_, { issueType = undefined, isDirty = false }, { cache }) => { const sourceData = cache.readQuery({ query: getIssueStateQuery }); const data = produce(sourceData, (draftData) => { diff --git a/app/assets/javascripts/issues/show/graphql.js b/app/assets/javascripts/issues/show/graphql.js deleted file mode 100644 index deee034f9d1..00000000000 --- a/app/assets/javascripts/issues/show/graphql.js +++ /dev/null @@ -1,9 +0,0 @@ -import Vue from 'vue'; -import VueApollo from 'vue-apollo'; -import { defaultClient } from '~/graphql_shared/issuable_client'; - -Vue.use(VueApollo); - -export default new VueApollo({ - defaultClient, -}); diff --git a/app/assets/javascripts/issues/show/index.js b/app/assets/javascripts/issues/show/index.js index 8b8c710c641..489b65b8704 100644 --- a/app/assets/javascripts/issues/show/index.js +++ b/app/assets/javascripts/issues/show/index.js @@ -1,6 +1,7 @@ import Vue from 'vue'; import { mapGetters } from 'vuex'; import errorTrackingStore from '~/error_tracking/store'; +import { apolloProvider } from '~/graphql_shared/issuable_client'; import { parseBoolean } from '~/lib/utils/common_utils'; import { scrollToTargetOnResize } from '~/lib/utils/resize_observer'; import IssueApp from './components/app.vue'; @@ -8,7 +9,6 @@ import HeaderActions from './components/header_actions.vue'; import IncidentTabs from './components/incidents/incident_tabs.vue'; import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue'; import { INCIDENT_TYPE, issueState } from './constants'; -import apolloProvider from './graphql'; import getIssueStateQuery from './queries/get_issue_state.query.graphql'; const bootstrapApollo = (state = {}) => { diff --git a/app/assets/javascripts/related_issues/index.js b/app/assets/javascripts/related_issues/index.js index c77a67c4287..c42ee27fbdf 100644 --- a/app/assets/javascripts/related_issues/index.js +++ b/app/assets/javascripts/related_issues/index.js @@ -1,5 +1,5 @@ import Vue from 'vue'; -import apolloProvider from '~/issues/show/graphql'; +import { apolloProvider } from '~/graphql_shared/issuable_client'; import { parseBoolean } from '~/lib/utils/common_utils'; import RelatedIssuesRoot from './components/related_issues_root.vue'; diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue index 62680195984..3c3d5f0b42f 100644 --- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue +++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue @@ -1,6 +1,5 @@ <script> import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; -import { produce } from 'immer'; import { isEmpty } from 'lodash'; import { s__ } from '~/locale'; import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils'; @@ -18,6 +17,8 @@ import { WORK_ITEM_STATUS_TEXT, } from '../../constants'; import getWorkItemLinksQuery from '../../graphql/work_item_links.query.graphql'; +import addHierarchyChildMutation from '../../graphql/add_hierarchy_child.mutation.graphql'; +import removeHierarchyChildMutation from '../../graphql/remove_hierarchy_child.mutation.graphql'; import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql'; import workItemQuery from '../../graphql/work_item.query.graphql'; import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql'; @@ -177,10 +178,6 @@ export default { hideAddForm() { this.isShownAddForm = false; }, - addChild(child) { - const { defaultClient: client } = this.$apollo.provider.clients; - this.toggleChildFromCache(child, child.id, client); - }, openChild(child, e) { if (isMetaKey(e)) { return; @@ -194,9 +191,8 @@ export default { this.activeChild = {}; this.updateWorkItemIdUrlQuery(); }, - handleWorkItemDeleted(childId) { - const { defaultClient: client } = this.$apollo.provider.clients; - this.toggleChildFromCache(null, childId, client); + handleWorkItemDeleted(child) { + this.removeHierarchyChild(child); this.activeToast = this.$toast.show(s__('WorkItem|Task deleted')); }, updateWorkItemIdUrlQuery({ id, iid } = {}) { @@ -205,38 +201,31 @@ export default { : { work_item_id: getIdFromGraphQLId(id) }; updateHistory({ url: setUrlParams(params), replace: true }); }, - toggleChildFromCache(workItem, childId, store) { - const sourceData = store.readQuery({ - query: getWorkItemLinksQuery, - variables: { id: this.issuableGid }, - }); - - const newData = produce(sourceData, (draftState) => { - const widgetHierarchy = draftState.workItem.widgets.find( - (widget) => widget.type === WIDGET_TYPE_HIERARCHY, - ); - - const index = widgetHierarchy.children.nodes.findIndex((child) => child.id === childId); - - if (index >= 0) { - widgetHierarchy.children.nodes.splice(index, 1); - } else { - widgetHierarchy.children.nodes.push(workItem); - } + async addHierarchyChild(workItem) { + return this.$apollo.mutate({ + mutation: addHierarchyChildMutation, + variables: { id: this.issuableGid, workItem }, }); - - store.writeQuery({ - query: getWorkItemLinksQuery, - variables: { id: this.issuableGid }, - data: newData, + }, + async removeHierarchyChild(workItem) { + return this.$apollo.mutate({ + mutation: removeHierarchyChildMutation, + variables: { id: this.issuableGid, workItem }, }); }, async updateWorkItem(workItem, childId, parentId) { - return this.$apollo.mutate({ + const response = await this.$apollo.mutate({ mutation: updateWorkItemMutation, variables: { input: { id: childId, hierarchyWidget: { parentId } } }, - update: (store) => this.toggleChildFromCache(workItem, childId, store), }); + + if (parentId === null) { + await this.removeHierarchyChild(workItem); + } else { + await this.addHierarchyChild(workItem); + } + + return response; }, async undoChildRemoval(workItem, childId) { const { data } = await this.updateWorkItem(workItem, childId, this.issuableGid); @@ -246,7 +235,7 @@ export default { } }, async removeChild(childId) { - const { data } = await this.updateWorkItem(null, childId, null); + const { data } = await this.updateWorkItem({ id: childId }, childId, null); if (data.workItemUpdate.errors.length === 0) { this.activeToast = this.$toast.show(s__('WorkItem|Child removed'), { @@ -365,7 +354,7 @@ export default { :form-type="formType" :parent-work-item-type="workItem.workItemType.name" @cancel="hideAddForm" - @addWorkItemChild="addChild" + @addWorkItemChild="addHierarchyChild" /> <work-item-link-child v-for="child in children" @@ -384,7 +373,7 @@ export default { :work-item-id="activeChild.id" :work-item-iid="activeChild.iid" @close="closeModal" - @workItemDeleted="handleWorkItemDeleted(activeChild.id)" + @workItemDeleted="handleWorkItemDeleted(activeChild)" /> </template> </template> diff --git a/app/assets/javascripts/work_items/graphql/add_hierarchy_child.mutation.graphql b/app/assets/javascripts/work_items/graphql/add_hierarchy_child.mutation.graphql new file mode 100644 index 00000000000..30a5d2388b1 --- /dev/null +++ b/app/assets/javascripts/work_items/graphql/add_hierarchy_child.mutation.graphql @@ -0,0 +1,3 @@ +mutation addHierarchyChild($id: WorkItemID!, $workItem: WorkItem!) { + addHierarchyChild(id: $id, workItem: $workItem) @client +} diff --git a/app/assets/javascripts/work_items/graphql/remove_hierarchy_child.mutation.graphql b/app/assets/javascripts/work_items/graphql/remove_hierarchy_child.mutation.graphql new file mode 100644 index 00000000000..3fece06eefa --- /dev/null +++ b/app/assets/javascripts/work_items/graphql/remove_hierarchy_child.mutation.graphql @@ -0,0 +1,3 @@ +mutation removeHierarchyChild($id: WorkItemID!, $workItem: WorkItem!) { + removeHierarchyChild(id: $id, workItem: $workItem) @client +} diff --git a/app/assets/javascripts/work_items/utils.js b/app/assets/javascripts/work_items/utils.js index e58fd19ea31..93d9c48ba27 100644 --- a/app/assets/javascripts/work_items/utils.js +++ b/app/assets/javascripts/work_items/utils.js @@ -1,3 +1,4 @@ +import { WIDGET_TYPE_HIERARCHY } from '~/work_items/constants'; import workItemQuery from './graphql/work_item.query.graphql'; import workItemByIidQuery from './graphql/work_item_by_iid.query.graphql'; import workItemNotesIdQuery from './graphql/work_item_notes.query.graphql'; @@ -10,3 +11,6 @@ export function getWorkItemQuery(isFetchedByIid) { export function getWorkItemNotesQuery(isFetchedByIid) { return isFetchedByIid ? workItemNotesByIidQuery : workItemNotesIdQuery; } + +export const findHierarchyWidgetChildren = (workItem) => + workItem.widgets.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY).children.nodes; diff --git a/app/models/concerns/sensitive_serializable_hash.rb b/app/models/concerns/sensitive_serializable_hash.rb index 794748483e4..5a9b75d4db8 100644 --- a/app/models/concerns/sensitive_serializable_hash.rb +++ b/app/models/concerns/sensitive_serializable_hash.rb @@ -24,12 +24,12 @@ module SensitiveSerializableHash options[:except].concat self.class.attributes_exempt_from_serializable_hash - if self.class.respond_to?(:encrypted_attributes) - options[:except].concat self.class.encrypted_attributes.keys + if self.class.respond_to?(:attr_encrypted_attributes) + options[:except].concat self.class.attr_encrypted_attributes.keys # Per https://github.com/attr-encrypted/attr_encrypted/blob/a96693e9a2a25f4f910bf915e29b0f364f277032/lib/attr_encrypted.rb#L413 - options[:except].concat self.class.encrypted_attributes.values.map { |v| v[:attribute] } - options[:except].concat self.class.encrypted_attributes.values.map { |v| "#{v[:attribute]}_iv" } + options[:except].concat self.class.attr_encrypted_attributes.values.map { |v| v[:attribute] } + options[:except].concat self.class.attr_encrypted_attributes.values.map { |v| "#{v[:attribute]}_iv" } end super(options) diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index 47829a07495..ef31bedc3a8 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -12,6 +12,7 @@ class DeployKey < Key has_many :deploy_keys_projects_with_write_access, -> { with_write_access }, class_name: "DeployKeysProject", inverse_of: :deploy_key has_many :projects_with_write_access, -> { includes(:route) }, class_name: 'Project', through: :deploy_keys_projects_with_write_access, source: :project has_many :protected_branch_push_access_levels, class_name: '::ProtectedBranch::PushAccessLevel', inverse_of: :deploy_key + has_many :protected_tag_create_access_levels, class_name: '::ProtectedTag::CreateAccessLevel', inverse_of: :deploy_key scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where(deploy_keys_projects: { project_id: projects }) } scope :with_write_access, -> { joins(:deploy_keys_projects).merge(DeployKeysProject.with_write_access) } diff --git a/app/models/grafana_integration.rb b/app/models/grafana_integration.rb index 5cd5aa1b085..71abfd3f6da 100644 --- a/app/models/grafana_integration.rb +++ b/app/models/grafana_integration.rb @@ -45,7 +45,7 @@ class GrafanaIntegration < ApplicationRecord end def token - decrypt(:token, encrypted_token) + attr_decrypt(:token, encrypted_token) end def check_token_changes diff --git a/app/models/integration.rb b/app/models/integration.rb index 54eeab10360..8bef8b08c19 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -493,9 +493,9 @@ class Integration < ApplicationRecord def reencrypt_properties unless properties.nil? || properties.empty? - alg = self.class.encrypted_attributes[:properties][:algorithm] + alg = self.class.attr_encrypted_attributes[:properties][:algorithm] iv = generate_iv(alg) - ep = self.class.encrypt(:properties, properties, { iv: iv }) + ep = self.class.attr_encrypt(:properties, properties, { iv: iv }) end { 'encrypted_properties' => ep, 'encrypted_properties_iv' => iv } diff --git a/app/models/protected_tag/create_access_level.rb b/app/models/protected_tag/create_access_level.rb index 5d8b1fb4f71..abb233d3800 100644 --- a/app/models/protected_tag/create_access_level.rb +++ b/app/models/protected_tag/create_access_level.rb @@ -4,9 +4,43 @@ class ProtectedTag::CreateAccessLevel < ApplicationRecord include Importable include ProtectedTagAccess + belongs_to :deploy_key + + validates :access_level, uniqueness: { scope: :protected_tag_id, if: :role?, + conditions: -> { where(user_id: nil, group_id: nil, deploy_key_id: nil) } } + validates :deploy_key_id, uniqueness: { scope: :protected_tag_id, allow_nil: true } + validate :validate_deploy_key_membership + + def type + if deploy_key.present? + :deploy_key + else + super + end + end + def check_access(user) return false if access_level == Gitlab::Access::NO_ACCESS + if user && deploy_key.present? + return user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user) + end + super end + + private + + def validate_deploy_key_membership + return unless deploy_key + + return if project.deploy_keys_projects.where(deploy_key: deploy_key).exists? + + errors.add(:deploy_key, 'is not enabled for this project') + end + + def enabled_deploy_key_for_user?(deploy_key, user) + deploy_key.user_id == user.id && + DeployKey.with_write_access_for_project(protected_tag.project, deploy_key: deploy_key).any? + end end diff --git a/app/models/snippet_repository.rb b/app/models/snippet_repository.rb index a959ad4d548..9139dc22a94 100644 --- a/app/models/snippet_repository.rb +++ b/app/models/snippet_repository.rb @@ -121,7 +121,7 @@ class SnippetRepository < ApplicationRecord def invalid_signature_error?(err) err.is_a?(ArgumentError) && - err.message.downcase.match?(/failed to parse signature/) + err.message.downcase.include?('failed to parse signature') end def only_rename_action?(action) diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index ea768b20990..266c5ecca10 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -775,7 +775,7 @@ Gitlab.ee do Settings.cron_jobs['elastic_migration_worker']['cron'] ||= '*/30 * * * *' Settings.cron_jobs['elastic_migration_worker']['job_class'] ||= 'Elastic::MigrationWorker' Settings.cron_jobs['search_index_curation_worker'] ||= Settingslogic.new({}) - Settings.cron_jobs['search_index_curation_worker']['cron'] ||= '*/30 * * * *' + Settings.cron_jobs['search_index_curation_worker']['cron'] ||= '*/1 * * * *' Settings.cron_jobs['search_index_curation_worker']['job_class'] ||= 'Search::IndexCurationWorker' Settings.cron_jobs['sync_seat_link_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} #{rand(3..4)} * * * UTC" diff --git a/config/initializers/macos.rb b/config/initializers/macos.rb index 1edd6c0a730..3b669a73f49 100644 --- a/config/initializers/macos.rb +++ b/config/initializers/macos.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -if /darwin/ =~ RUBY_PLATFORM +if RUBY_PLATFORM.include?('darwin') Gitlab::Cluster::LifecycleEvents.on_before_fork do require 'fiddle' diff --git a/config/spring.rb b/config/spring.rb index 3f00e6ab23f..f06a707111c 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -10,7 +10,7 @@ Spring.after_fork do if ENV['DEBUGGER_STORED_RUBYLIB'] ENV['DEBUGGER_STORED_RUBYLIB'].split(File::PATH_SEPARATOR).each do |path| - next unless path =~ /ruby-debug-ide/ + next unless path.include?('ruby-debug-ide') load path + '/ruby-debug-ide/multiprocess/starter.rb' end diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md index aefc00fba82..a73595c731b 100644 --- a/doc/administration/auth/cognito.md +++ b/doc/administration/auth/cognito.md @@ -17,7 +17,7 @@ To enable AWS Cognito as an authentication provider, complete the following step 1. Sign in to the [AWS console](https://console.aws.amazon.com/console/home). 1. From the **Services** menu, select **Cognito**. -1. Select **Manage User Pools** and then select **Create a user pool** in the top right corner. +1. Select **Manage User Pools** and then in the upper-right corner, select **Create a user pool**. 1. Enter the user pool name and then select **Step through settings**. 1. Under **How do you want your end users to sign in?**, select **Email address or phone number** and **Allow email addresses**. 1. Under **Which standard attributes do you want to require?**, select **email**. diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md index 95064b296af..7e21d3c6655 100644 --- a/doc/administration/auth/ldap/ldap-troubleshooting.md +++ b/doc/administration/auth/ldap/ldap-troubleshooting.md @@ -170,13 +170,12 @@ We have a workaround, based on toggling the access level of affected users: 1. As an administrator, on the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Overview > Users**. 1. Select the name of the affected user. -1. In the user's administrative page, press **Edit** on the top right of the page. -1. Change the user's access level from `Regular` to `Admin` (or vice versa), - and press **Save changes** at the bottom of the page. -1. Press **Edit** on the top right of the user's profile page - again. -1. Restore the user's original access level (`Regular` or `Admin`) - and press **Save changes** again. +1. In the upper right, select **Edit**. +1. Change the user's access level from `Regular` to `Administrator` (or vice versa). +1. At the bottom of the page, select **Save changes**. +1. In the upper right, select **Edit** again. +1. Restore the user's original access level (`Regular` or `Administrator`) + and select **Save changes** again. The user should now be able to sign in. diff --git a/doc/administration/instance_review.md b/doc/administration/instance_review.md index 5516a47637d..277595190b3 100644 --- a/doc/administration/instance_review.md +++ b/doc/administration/instance_review.md @@ -20,7 +20,7 @@ details and contact you with suggestions to improve your use of GitLab. To request an instance review: 1. Sign in as an administrator. -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Get a free instance review**. ![Instance review](img/instance_review_v14_7.png) diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md index cb7e46d20ab..b53355f8297 100644 --- a/doc/administration/reference_architectures/index.md +++ b/doc/administration/reference_architectures/index.md @@ -49,7 +49,7 @@ The Reference Architectures are designed to strike a balance between two importa While they are designed to make it easier to set up GitLab at scale, it can still be a challenge to know which one meets your requirements. -As a general guide, **the more performant and/or resilient you want your environment to be, the more involved it is**. +As a general guide, **the more performant and/or resilient you want your environment to be, the more complex it is**. This section explains the designs you can choose from. It begins with the least complexity, goes to the most, and ends with a decision tree. @@ -57,11 +57,13 @@ This section explains the designs you can choose from. It begins with the least For environments serving 2,000 or fewer users we generally recommend that an [automated backup](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups) strategy is used instead of HA. +Depending on your setup and requirements, this can include configuring backups on any external services you may be using, such as Object Storage (AWS S3 / Google Cloud Storage) or Postgres (AWS RDS / Google Cloud SQL) backups for further resilience. + Backups can provide a good level of RPO / RTO while avoiding the complexities that come with HA. ### High Availability (HA) -High Availability ensures every component in the GitLab setup can handle failures through various mechanisms. To achieve this however is involved, and the environments required can be sizable. +High Availability ensures every component in the GitLab setup can handle failures through various mechanisms. To achieve this however is complex, and the environments required can be sizable. For environments serving 3,000 or more users we generally recommend that a HA strategy is used as at this level outages have a bigger impact against more users. All the architectures in this range have HA built in by design for this reason. @@ -80,7 +82,7 @@ In general then, we'd only recommend you employ HA in the following scenarios: #### Zero Downtime Upgrades -[Zero Downtime Upgrades](../../update/zero_downtime.md) are available for standard Reference Architecture environments with HA (Cloud Native Hybrid is not supported at this time). This allows for an environment to stay up during an upgrade, but the process is more involved as a result and has some limitations as detailed in the documentation. +[Zero Downtime Upgrades](../../update/zero_downtime.md) are available for standard Reference Architecture environments with HA (Cloud Native Hybrid is not supported at this time). This allows for an environment to stay up during an upgrade, but the process is more complex as a result and has some limitations as detailed in the documentation. When going through this process it's worth noting that there may still be brief moments of downtime when the HA mechanisms tale effect. @@ -96,7 +98,7 @@ This is an alternative and more **advanced** setup compared to a standard Refere With [GitLab Geo](../geo/index.md) you can have both distributed environments in different regions and a full Disaster Recovery (DR) setup in place. With this setup you would have 2 or more separate environments, with one being a primary that gets replicated to the others. In the rare event the primary site went down completely you could fail over to one of the other environments. -This is an **advanced and involved** setup and should only be undertaken if you have DR as a key requirement. Decisions then on how each environment are configured would also need to be taken, such as if each environment itself would be the full size and / or have HA. +This is an **advanced and complex** setup and should only be undertaken if you have DR as a key requirement. Decisions then on how each environment are configured would also need to be taken, such as if each environment itself would be the full size and / or have HA. ### Decision Tree @@ -299,8 +301,8 @@ Due to performance issues that we found with several key Azure services, we only In addition to the above, you should be aware of the additional specific guidance for Azure: - **We outright strongly do not recommend [Azure Database for PostgreSQL Single Server](https://learn.microsoft.com/en-us/azure/postgresql/single-server/overview-single-server)** specifically due to significant performance and stability issues found. **For GitLab 14.0 and higher the service is not supported** due to it only supporting up to PostgreSQL 11. - - A new service, [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/) has been released but due to it missing some functionality we don't recommend it at this time. -- [Azure Blob Storage](https://azure.microsoft.com/en-gb/products/storage/blobs/) has been found to have performance limits that can impact production use at certain times. However, this has only been seen in larger architectures. + - A new service, [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/) has been released. [Internal testing](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/91) has shown that it does look to perform as expected, but this hasn't been validated in production, so generally isn't recommended at this time. Additionally, as it's a new service, you may find that it's missing some functionality depending on your requirements. +- [Azure Blob Storage](https://azure.microsoft.com/en-gb/products/storage/blobs/) has been found to have [performance limits that can impact production use at certain times](https://gitlab.com/gitlab-org/gitlab/-/issues/344861). However, this has only been seen in our largest architectures (25k+) so far. ## Validation and test results diff --git a/doc/api/users.md b/doc/api/users.md index a577dc26043..d6a4604cf51 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -946,7 +946,7 @@ Example response: ## User counts -Get the counts (same as in top right menu) of the authenticated user. +Get the counts (same as in the upper-right menu) of the authenticated user. | Attribute | Type | Description | | --------------------------------- | ------ | ---------------------------------------------------------------------------- | diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md index 3f8c40a3aba..1aa579b842a 100644 --- a/doc/ci/caching/index.md +++ b/doc/ci/caching/index.md @@ -570,7 +570,7 @@ You can clear the cache in the GitLab UI: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **CI/CD > Pipelines**. -1. In the top right, select **Clear runner caches**. +1. In the upper right, select **Clear runner caches**. On the next commit, your CI/CD jobs use a new cache. diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md index 2e78d7588ba..522b8d0af79 100644 --- a/doc/ci/environments/index.md +++ b/doc/ci/environments/index.md @@ -684,7 +684,7 @@ You can view a deployment's expiration date in the GitLab UI. 1. On the left sidebar, select **Deployments > Environments**. 1. Select the name of the deployment. -In the top left, next to the environment name, the expiration date is displayed. +In the upper left, next to the environment name, the expiration date is displayed. #### Override a deployment's scheduled stop time @@ -693,7 +693,7 @@ You can manually override a deployment's expiration date. 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Deployments > Environments**. 1. Select the deployment name. -1. On the top right, select the thumbtack (**{thumbtack}**). +1. in the upper right, select the thumbtack (**{thumbtack}**). ![Environment auto stop](img/environment_auto_stop_v13_10.png) diff --git a/doc/ci/examples/semantic-release.md b/doc/ci/examples/semantic-release.md index 8ae4cf61e37..9f299448d52 100644 --- a/doc/ci/examples/semantic-release.md +++ b/doc/ci/examples/semantic-release.md @@ -90,7 +90,7 @@ As part of publishing a package, semantic-release increases the version number i <!-- markdownlint-disable MD044 --> -1. On the top bar, on the top right, select your avatar. +1. On the top bar, in the upper right, select your avatar. 1. On the left sidebar, select **Access Tokens**. 1. In the **Token name** box, enter a token name. 1. Under **select scopes**, select the **api** checkbox. diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md index 9497083ae8d..fb9c795657d 100644 --- a/doc/ci/jobs/index.md +++ b/doc/ci/jobs/index.md @@ -337,7 +337,7 @@ In the example above: - `date +%s`: The Unix timestamp (for example `1560896352`). - `my_first_section`: The name given to the section. - `\r\e[0K`: Prevents the section markers from displaying in the rendered (colored) - job log, but they are displayed in the raw job log. To see them, in the top right + job log, but they are displayed in the raw job log. To see them, in the upper right of the job log, select **{doc-text}** (**Show complete raw**). - `\r`: carriage return. - `\e[0K`: clear line ANSI escape code. diff --git a/doc/ci/lint.md b/doc/ci/lint.md index c297cab1822..74e0f0cd5ef 100644 --- a/doc/ci/lint.md +++ b/doc/ci/lint.md @@ -26,7 +26,7 @@ To check CI/CD configuration with the CI lint tool: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **CI/CD > Pipelines**. -1. In the top right, select **CI lint**. +1. In the upper right, select **CI lint**. 1. Paste a copy of the CI/CD configuration you want to check into the text box. 1. Select **Validate**. @@ -47,7 +47,7 @@ To simulate a pipeline: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **CI/CD > Pipelines**. -1. In the top right, select **CI lint**. +1. In the upper right, select **CI lint**. 1. Paste a copy of the CI/CD configuration you want to check into the text box. 1. Select **Simulate pipeline creation for the default branch**. 1. Select **Validate**. diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md index c4416d41ab4..727977b3bc8 100644 --- a/doc/ci/pipeline_editor/index.md +++ b/doc/ci/pipeline_editor/index.md @@ -70,7 +70,7 @@ simulations in the [CI Lint tool](../lint.md#simulate-a-pipeline). > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357219) in GitLab 15.1. You can review configuration added with the [`include`](../yaml/index.md#include) -keyword in the pipeline editor. In the top right, select the file tree (**{file-tree}**) +keyword in the pipeline editor. In the upper right, select the file tree (**{file-tree}**) to see a list of all included configuration files. Selected files open in a new tab for review. diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md index 1e0b3a97714..4cbaa77b029 100644 --- a/doc/ci/pipelines/cicd_minutes.md +++ b/doc/ci/pipelines/cicd_minutes.md @@ -111,7 +111,7 @@ subgroups, sorted in descending order of CI/CD minute usage. You can view the number of CI/CD minutes being used by a personal namespace: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Usage Quotas**. @@ -161,7 +161,7 @@ namespace. To purchase additional minutes for your personal namespace: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Usage Quotas**. 1. Select **Buy additional minutes**. GitLab redirects you to the Customers Portal. diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md index 02d60c6da2f..75c9852d3d0 100644 --- a/doc/ci/pipelines/job_artifacts.md +++ b/doc/ci/pipelines/job_artifacts.md @@ -264,7 +264,7 @@ artifacts and log. You must be: To delete a job: 1. Go to a job's detail page. -1. On the top right of the job's log, select **Erase job log** (**{remove}**). +1. In the upper right of the job's log, select **Erase job log** (**{remove}**). 1. On the confirmation dialog, select **OK**. ## Expose job artifacts in the merge request UI diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md index 402478e81ba..baf5e5bfc85 100644 --- a/doc/ci/runners/runners_scope.md +++ b/doc/ci/runners/runners_scope.md @@ -172,7 +172,7 @@ To create a group runner: 1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/). 1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **CI/CD > Runners**. -1. In the top-right corner, select **Register a group runner**. +1. In the upper-right corner, select **Register a group runner**. 1. Select **Show runner installation and registration instructions**. These instructions include the token, URL, and a command to register a runner. diff --git a/doc/development/database/batched_background_migrations.md b/doc/development/database/batched_background_migrations.md index ea6bdbdab8b..c6fe6d16faf 100644 --- a/doc/development/database/batched_background_migrations.md +++ b/doc/development/database/batched_background_migrations.md @@ -349,20 +349,35 @@ background migration. `BatchedMigrationJob` is initialized with necessary arguments to execute the batch, as well as a connection to the tracking database. -1. Add a new trigger to the database to update newly created and updated routes, - similar to this example: +1. Create a database migration that adds a new trigger to the database. Example: ```ruby - execute(<<~SQL) - CREATE OR REPLACE FUNCTION example() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - NEW."namespace_id" = NEW."source_id" - RETURN NEW; - END; - $$; - SQL + class AddTriggerToRoutesToCopySourceIdToNamespaceId < Gitlab::Database::Migration[2.1] + FUNCTION_NAME = 'example_function' + TRIGGER_NAME = 'example_trigger' + + def up + execute(<<~SQL) + CREATE OR REPLACE FUNCTION #{FUNCTION_NAME}() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + NEW."namespace_id" = NEW."source_id" + RETURN NEW; + END; + $$; + + CREATE TRIGGER #{TRIGGER_NAME}() AFTER INSERT OR UPDATE + ON routes + FOR EACH ROW EXECUTE FUNCTION #{FUNCTION_NAME}(); + SQL + end + + def down + drop_trigger(TRIGGER_NAME, :routes) + drop_function(FUNCTION_NAME) + end + end ``` 1. Create a post-deployment migration that queues the migration for existing data: @@ -398,10 +413,28 @@ background migration. `restrict_gitlab_migration gitlab_schema: :gitlab_ci`. After deployment, our application: - - Continues using the data as before. - - Ensures that both existing and new data are migrated. + - Continues using the data as before. + - Ensures that both existing and new data are migrated. + +1. In the next release, add a database migration to remove the trigger. + + ```ruby + class RemoveNamepaceIdTriggerFromRoutes < Gitlab::Database::Migration[2.1] + FUNCTION_NAME = 'example_function' + TRIGGER_NAME = 'example_trigger' + + def up + drop_trigger(TRIGGER_NAME, :routes) + drop_function(FUNCTION_NAME) + end + + def down + # Should reverse the trigger and the function in the up method of the migration that added it + end + end + ``` -1. In the next release, remove the trigger. We must also add a new post-deployment migration +1. Add a new post-deployment migration that checks that the batched background migration is completed. For example: ```ruby diff --git a/doc/development/database/index.md b/doc/development/database/index.md index beae5842199..fca76c98715 100644 --- a/doc/development/database/index.md +++ b/doc/development/database/index.md @@ -20,6 +20,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w - [explain.depesz.com](https://explain.depesz.com/) or [explain.dalibo.com](https://explain.dalibo.com/) for visualizing the output of `EXPLAIN` - [pgFormatter](https://sqlformat.darold.net/) a PostgreSQL SQL syntax beautifier - [db:check-migrations job](dbcheck-migrations-job.md) +- [Database migration pipeline](database_migration_pipeline.md) ## Migrations diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md index dd5d3691bee..e4841f3cf82 100644 --- a/doc/development/documentation/styleguide/word_list.md +++ b/doc/development/documentation/styleguide/word_list.md @@ -14,6 +14,7 @@ recommends these word choices. In addition: [top misused terms](https://about.gitlab.com/handbook/communication/top-misused-terms/). - The documentation [style guide](../styleguide#language) includes details about language and capitalization. +- The GitLab handbook provides guidance on the [use of third-party trademarks](https://about.gitlab.com/handbook/legal/policies/product-third-party-trademarks-guidelines/#process-for-adding-third-party-trademarks-to-gitlab). For guidance not on this page, we defer to these style guides: diff --git a/doc/development/documentation/topic_types/task.md b/doc/development/documentation/topic_types/task.md index cd55fa0b897..8d23a5f322e 100644 --- a/doc/development/documentation/topic_types/task.md +++ b/doc/development/documentation/topic_types/task.md @@ -45,7 +45,7 @@ To create an issue: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Issues > List**. -1. In the top right corner, select **New issue**. +1. In the upper-right corner, select **New issue**. 1. Complete the fields. (If you have reference content that lists each field, link to it here.) 1. Select **Create issue**. diff --git a/doc/development/documentation/versions.md b/doc/development/documentation/versions.md index f5308d706ce..30a0d4d4cf4 100644 --- a/doc/development/documentation/versions.md +++ b/doc/development/documentation/versions.md @@ -13,7 +13,7 @@ including when features were introduced and when they were updated or removed. ## View older documentation versions Previous versions of the documentation are available on `docs.gitlab.com`. -To view a previous version, select the **Versions** button in the top right. +To view a previous version, select the **Versions** button in the upper right. To view versions that are not available on `docs.gitlab.com`: diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md index a98ba3e4ee8..fe5453a4a58 100644 --- a/doc/development/documentation/workflow.md +++ b/doc/development/documentation/workflow.md @@ -22,7 +22,7 @@ GitLab documentation is distributed under the [CC BY-SA 4.0 license](https://cre Under current law in the US and the EU, it’s possible that AI-generated works might either: - not be owned by anyone because they weren't created by a human, or -- belong to the AI training data’s creator, if the AI verbatim reproduces content that it trained on +- belong to the AI training data’s creator, if the AI verbatim reproduces content that it trained on If the documentation contains AI-generated content, GitLab probably wouldn't own this content, which would risk invalidating the CC BY-SA 4.0 license. @@ -40,11 +40,11 @@ If you are not a GitLab team member, or do not have the Developer role for the G - If you're not taking part in a Hackathon, you don't need an issue to open a merge request. If you are looking for issues to work on and don't see any that suit you, you can always fix [Vale](testing.md#vale) issues. 1. Go to the [GitLab repository](https://gitlab.com/gitlab-org/gitlab). -1. In the top right, select **Fork**. Forking makes a copy of the repository on GitLab.com. +1. In the upper right, select **Fork**. Forking makes a copy of the repository on GitLab.com. 1. In your fork, find the documentation page in the `\doc` directory. 1. If you know Git, make your changes and open a merge request. If not, follow these steps: - 1. On the top right, select **Edit** if it is visible. If it is not, select the down arrow (**{chevron-lg-down}**) next to **Open in Web IDE** or **Gitpod**, and select **Edit**. + 1. In the upper right, select **Edit** if it is visible. If it is not, select the down arrow (**{chevron-lg-down}**) next to **Open in Web IDE** or **Gitpod**, and select **Edit**. 1. In the **Commit message** text box, enter a commit message. Use 3-5 words, start with a capital letter, and do not end with a period. 1. Select **Commit changes**. 1. On the left sidebar, select **Merge requests**. diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index 7ebaa5b5611..8ae0458e47c 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -87,7 +87,7 @@ where needed. You can check all existing queries and mutations on the right side of GraphiQL in its **Documentation explorer**. You can also write queries and mutations directly on the left tab and check -their execution by clicking **Execute query** button on the top left: +their execution by selecting **Execute query** in the upper left: ![GraphiQL interface](img/graphiql_explorer_v12_4.png) diff --git a/doc/development/product_qualified_lead_guide/index.md b/doc/development/product_qualified_lead_guide/index.md index 5079c0b6723..c72110bc253 100644 --- a/doc/development/product_qualified_lead_guide/index.md +++ b/doc/development/product_qualified_lead_guide/index.md @@ -102,7 +102,7 @@ We currently use the following `glm_content` values: | `discover-project-security` | This value is used in the project security feature discovery page. | | `discover-project-security-pqltest` | This value is used in the project security feature discovery page [experiment with 3 CTAs](https://gitlab.com/gitlab-org/gitlab/-/issues/349799). | | `group-billing` | This value is used in the group billing page. | -| `trial-status-show-group` | This value is used in the top left nav when a namespace has an active trial. | +| `trial-status-show-group` | This value is used in the upper-left nav when a namespace has an active trial. | ### Test the component diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index aec053b95c9..3de51a92226 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -98,7 +98,7 @@ access on GitLab.com or any other GitLab instance. To use the repository in the examples on this page: 1. Go to [https://gitlab.com/gitlab-tests/sample-project/](https://gitlab.com/gitlab-tests/sample-project/). -1. In the top right, select **Fork**. +1. In the upper right, select **Fork**. 1. Choose a namespace for your fork. The project becomes available at `https://gitlab.com/<your-namespace>/sample-project/`. diff --git a/doc/install/installation.md b/doc/install/installation.md index 77d613b9d9d..db38616cf74 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -40,7 +40,7 @@ can't be terminated and its memory usage grows over time. ## Select a version to install Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (for example, `11-7-stable`). -You can select the branch in the version dropdown list in the top left corner of GitLab (below the menu bar). +You can select the branch in the version dropdown list in the upper-left corner of GitLab (below the menu bar). If the highest number stable branch is unclear, check the [GitLab blog](https://about.gitlab.com/blog/) for installation guide links by version. diff --git a/doc/integration/advanced_search/elasticsearch_troubleshooting.md b/doc/integration/advanced_search/elasticsearch_troubleshooting.md index e2dc143e4db..c8d11286a3c 100644 --- a/doc/integration/advanced_search/elasticsearch_troubleshooting.md +++ b/doc/integration/advanced_search/elasticsearch_troubleshooting.md @@ -100,8 +100,8 @@ Here are some common pitfalls and how to overcome them. There are a couple of ways to achieve that: -- Whenever you perform a search there is a link on the search results page - in the top right hand corner saying "Advanced search functionality is enabled". +- When you perform a search, in the upper-right corner of the search results page, + **Advanced search functionality is enabled** is displayed. This is always correctly identifying whether the current project/namespace being searched is using Elasticsearch. diff --git a/doc/integration/github.md b/doc/integration/github.md index 8f60e1b5d71..7b8927054ee 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -233,7 +233,7 @@ and then connect it to your GitHub account To fix this issue, you must activate GitHub sign-in in GitLab: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Account**. 1. In the **Service sign-in** section, select **Connect to GitHub**. diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md index 44dba2b1829..168d55b0fa5 100644 --- a/doc/integration/gitlab.md +++ b/doc/integration/gitlab.md @@ -12,7 +12,7 @@ To enable the GitLab.com OmniAuth provider you must register your application wi GitLab.com generates an application ID and secret key for you to use. 1. Sign in to GitLab.com. -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Applications**. 1. Provide the required details for **Add new application**. diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md index 737a67e2fe4..759e5297014 100644 --- a/doc/integration/gitpod.md +++ b/doc/integration/gitpod.md @@ -35,7 +35,7 @@ To learn more about Gitpod, see their [features](https://www.gitpod.io/) and With the Gitpod integration enabled for your GitLab instance, to enable it for yourself: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. Under **Preferences**, locate the **Integrations** section. 1. Select the **Enable Gitpod integration** checkbox and select **Save changes**. @@ -49,7 +49,7 @@ For self-managed GitLab instances, a GitLab administrator must: 1. On the left sidebar, select **Settings > General**. 1. Expand the **Gitpod** configuration section. 1. Select the **Enable Gitpod integration** checkbox. - 1. Add the Gitpod instance URL (for example, `https://gitpod.example.com` or `https://gitpod.io`). + 1. Enter the Gitpod instance URL (for example, `https://gitpod.example.com` or `https://gitpod.io`). 1. Select **Save changes**. 1. Register the self-managed GitLab instance in Gitpod. For more information, see the [Gitpod documentation](https://www.gitpod.io/docs/configure/authentication/gitlab#registering-a-self-hosted-gitlab-installation). diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md index a518349b1ad..f0c1a75041e 100644 --- a/doc/integration/kerberos.md +++ b/doc/integration/kerberos.md @@ -124,7 +124,7 @@ existing GitLab account. To do so: If you're not an administrator: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Account**. 1. In the **Service sign-in** section, select **Connect Kerberos**. diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md index 40b2f37122a..381924177cc 100644 --- a/doc/integration/oauth_provider.md +++ b/doc/integration/oauth_provider.md @@ -35,7 +35,7 @@ After adding an OAuth 2 application to an instance, you can use OAuth 2 to: To create a new application for your user: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Applications**. 1. Enter a **Name** and **Redirect URI**. @@ -83,7 +83,7 @@ The user authorization step is automatically skipped for this application. To see all the application you've authorized with your GitLab credentials: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile** and then select **Applications**. 1. See the **Authorized applications** section. diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index 1dfd9c95a73..b25ba6a00e2 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -235,7 +235,7 @@ created, you can activate an OmniAuth provider. For example, if you originally s provider like Twitter. 1. Sign in to GitLab with your GitLab credentials, LDAP, or another OmniAuth provider. -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Account**. 1. In the **Connected Accounts** section, select the OmniAuth provider, such as Twitter. diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md index 09f0d0aca08..a3e54204798 100644 --- a/doc/integration/sourcegraph.md +++ b/doc/integration/sourcegraph.md @@ -63,7 +63,7 @@ If a GitLab administrator has enabled Sourcegraph, you can enable this feature i In GitLab: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. In the **Integrations** section, select the checkbox under **Sourcegraph**. 1. Select **Save changes**. diff --git a/doc/integration/vault.md b/doc/integration/vault.md index ddb21e68bf8..78456596723 100644 --- a/doc/integration/vault.md +++ b/doc/integration/vault.md @@ -26,7 +26,7 @@ GitLab by using our OpenID authentication feature. First you must create a GitLab application to obtain an application ID and secret for authenticating into Vault. To do this, sign in to GitLab and follow these steps: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Applications**. 1. Fill out the application **Name** and [**Redirect URI**](https://developer.hashicorp.com/vault/docs/auth/jwt#redirect-uris). diff --git a/doc/operations/incident_management/manage_incidents.md b/doc/operations/incident_management/manage_incidents.md index 75826c2c55e..ad4de8641e5 100644 --- a/doc/operations/incident_management/manage_incidents.md +++ b/doc/operations/incident_management/manage_incidents.md @@ -220,7 +220,7 @@ Prerequisites: - You must have at least the Reporter role for the project. -To close an incident, in the top right, select **Close incident**. +To close an incident, in the upper right, select **Close incident**. When you close an incident that is linked to an [alert](alerts.md), the linked alert's status changes to **Resolved**. diff --git a/doc/operations/metrics/dashboards/index.md b/doc/operations/metrics/dashboards/index.md index 9d5641bd800..09bb8cedbf6 100644 --- a/doc/operations/metrics/dashboards/index.md +++ b/doc/operations/metrics/dashboards/index.md @@ -33,7 +33,7 @@ To create a new dashboard from the GitLab user interface: 1. Sign in to GitLab as a user with Maintainer or Owner [permissions](../../../user/permissions.md#project-members-permissions). 1. Navigate to your dashboard at **Monitor > Metrics**. -1. In the top-right corner of your dashboard, select the **{ellipsis_v}** **More actions** menu, +1. In the upper-right corner of your dashboard, select the **{ellipsis_v}** **More actions** menu, and select **Create new**: ![Monitoring Dashboard actions menu with create new item](img/actions_menu_create_new_dashboard_v13_3.png) 1. In the modal window, select **Open Repository**, then follow the instructions diff --git a/doc/operations/metrics/dashboards/settings.md b/doc/operations/metrics/dashboards/settings.md index 3fae4af9cd5..5fb0476e164 100644 --- a/doc/operations/metrics/dashboards/settings.md +++ b/doc/operations/metrics/dashboards/settings.md @@ -51,7 +51,7 @@ existing external dashboards: 1. Select **Save changes**. -GitLab displays a **View full dashboard** button in the top right corner of your +GitLab displays a **View full dashboard** button in the upper-right corner of your [monitoring dashboard](../../../ci/environments/index.md#monitor-environments) which opens the URL you provided: diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index e0ca9774706..57535641a9d 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -280,7 +280,7 @@ If you are an administrator, you can export your license usage into a CSV: 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Subscription**. -1. In the top right, select **Export license usage file**. +1. In the upper right, select **Export license usage file**. This file contains the information GitLab uses to manually process quarterly reconciliations or renewals. If your instance is firewalled or an offline environment, you must provide GitLab with this information. diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index efbe1bc7fcd..8e62718125b 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -11,7 +11,7 @@ comments: false Make sure you view [this update guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/update/patch_versions.md) from the tag (version) of GitLab you would like to install. In most cases this should be the highest numbered production tag (without `rc` in it). -You can select the tag in the version dropdown list in the top left corner of GitLab (below the menu bar). +You can select the tag in the version dropdown list in the upper-left corner of GitLab (below the menu bar). ### 0. Backup diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md index 852b54c7339..e4c2f0003af 100644 --- a/doc/update/upgrading_from_source.md +++ b/doc/update/upgrading_from_source.md @@ -8,7 +8,7 @@ comments: false # Upgrading Community Edition and Enterprise Edition from source **(FREE SELF)** Make sure you view this update guide from the branch (version) of GitLab you -would like to install (for example, `11.8`). You can select the required version of documentation in the dropdown list at the top right corner of GitLab documentation page. +would like to install (for example, `11.8`). You can select the required version of documentation in the dropdown list in the upper-right corner of GitLab documentation page. In each of the following examples, replace `BRANCH` with the branch of the version you upgrading to (for example, `11-8-stable` for `11.8`). Replace `PREVIOUS_BRANCH` with the branch for the version you are upgrading from (for example, `11-7-stable` for `11.7`). diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md index 982aa11a7b2..4796bd9334b 100644 --- a/doc/user/admin_area/settings/continuous_integration.md +++ b/doc/user/admin_area/settings/continuous_integration.md @@ -54,7 +54,7 @@ To enable a project runner for more than one project: 1. On the top bar, select **Main menu > Admin**. 1. From the left sidebar, select **CI/CD > Runners**. 1. Select the runner you want to edit. -1. In the top right, select **Edit** (**{pencil}**). +1. In the upper right, select **Edit** (**{pencil}**). 1. Under **Restrict projects for this runner**, search for a project. 1. To the left of the project, select **Enable**. 1. Repeat this process for each additional project. diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md index cd40e0983d2..b542d479c78 100644 --- a/doc/user/application_security/vulnerability_report/index.md +++ b/doc/user/application_security/vulnerability_report/index.md @@ -245,7 +245,7 @@ thousands of vulnerabilities. Do not close the page until the download finishes. You can dismiss a vulnerability for the entire project: 1. Select the vulnerability in the Security Dashboard. -1. In the top-right, from the **Status** selector menu, select **Dismissed**. +1. In the upper right, from the **Status** selector menu, select **Dismissed**. 1. Optional. Add a reason for the dismissal and select **Save comment**. To undo this action, select a different status from the same menu. diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md index 5df38550c40..71aeb463b4f 100644 --- a/doc/user/award_emojis.md +++ b/doc/user/award_emojis.md @@ -36,7 +36,7 @@ celebrate an accomplishment or agree with an opinion. To add an award emoji: -1. In the top right of the comment, select the smile (**{slight-smile}**). +1. In the upper right of the comment, select the smile (**{slight-smile}**). 1. Select an emoji from the dropdown list. To remove an award emoji, select the emoji again. diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index 44e13f70f2e..9c9b5301460 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -260,7 +260,7 @@ Prerequisites: To create a thread by replying to a comment: -1. On the top right of the comment, select **Reply to comment** (**{comment}**). +1. In the upper right of the comment, select **Reply to comment** (**{comment}**). ![Reply to comment button](img/reply_to_comment_button.png) @@ -308,7 +308,7 @@ To resolve a thread: 1. Go to the thread. 1. Do one of the following: - - In the top right of the original comment, select the **Resolve thread** (**{check-circle}**) icon. + - In the upper right of the original comment, select **Resolve thread** (**{check-circle}**). - Below the last reply, in the **Reply** field, select **Resolve thread**. - Below the last reply, in the **Reply** field, enter text, select the **Resolve thread** checkbox, and select **Add comment now**. diff --git a/doc/user/group/manage.md b/doc/user/group/manage.md index 5f082476a92..f5c4d4e614a 100644 --- a/doc/user/group/manage.md +++ b/doc/user/group/manage.md @@ -155,7 +155,7 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last 1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Group information > Members**. -1. Above the list of members, on the top right, from the **Account** list, select +1. Above the list of members, in the upper right, from the **Account** list, select the criteria to filter by. 1. To switch the sort between ascending and descending, to the right of the **Account** list, select the arrow (**{sort-lowest}** or **{sort-highest}**). diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 2f12ff68723..3d1ef3bad3e 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -492,7 +492,7 @@ group owner, and then you can unlink the account. For example, to unlink the `MyOrg` account: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Account**. 1. In the **Service sign-in** section, select **Disconnect** next to the connected account. diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index 79fc1ab310a..f02a232ea99 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -139,7 +139,7 @@ Prerequisites: To configure Okta for SCIM: 1. Sign in to Okta. -1. Ensure you are in the Admin Area by selecting the **Admin** button located in the top right. The button is not visible from the Admin Area. +1. Ensure you are in the Admin Area by selecting the **Admin** button located in the upper right. The button is not visible from the Admin Area. 1. In the **Application** tab, select **Browse App Catalog**. 1. Search for **GitLab**, find and select the **GitLab** application. 1. On the GitLab application overview page, select **Add**. diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md index 9be1027ae2f..6c7baa848e7 100644 --- a/doc/user/group/subgroups/index.md +++ b/doc/user/group/subgroups/index.md @@ -85,7 +85,7 @@ You cannot host a GitLab Pages subgroup website with a top-level domain name. Fo To create a subgroup: 1. On the top bar, select **Main menu > Groups** and find and select the parent group to add a subgroup to. -1. On the parent group's overview page, in the top right, select **New subgroup**. +1. On the parent group's overview page, in the upper right, select **New subgroup**. 1. Select **Create group**. 1. Fill in the fields. View a list of [reserved names](../../reserved_names.md) that cannot be used as group names. 1. Select **Create group**. diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md index 14f2a1c4057..c5a95779087 100644 --- a/doc/user/group/value_stream_analytics/index.md +++ b/doc/user/group/value_stream_analytics/index.md @@ -305,7 +305,7 @@ After you create a value stream, you can customize it to suit your purposes. To 1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Analytics > Value Stream**. -1. In the top right, select the dropdown list, and select a value stream. +1. In the upper right, select the dropdown list, and select a value stream. 1. Next to the value stream dropdown list, select **Edit**. 1. Optional: - Rename the value stream. @@ -324,7 +324,7 @@ To delete a custom value stream: 1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Analytics > Value Stream**. -1. In the top right, select the dropdown list and then select the value stream you would like to delete. +1. In the upper right, select the dropdown list and then select the value stream you would like to delete. 1. Select **Delete (name of value stream)**. 1. To confirm, select **Delete**. diff --git a/doc/user/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md index eb6a8db0c05..93a82023480 100644 --- a/doc/user/infrastructure/iac/terraform_state.md +++ b/doc/user/infrastructure/iac/terraform_state.md @@ -58,7 +58,10 @@ WARNING: Like any other job artifact, Terraform plan data is viewable by anyone with the Guest role on the repository. Neither Terraform nor GitLab encrypts the plan file by default. If your Terraform plan includes sensitive data, like passwords, access tokens, or certificates, you should -encrypt plan output or modify the project visibility settings. +encrypt plan output or modify the project visibility settings. We also strongly recommend that you **disable** +[public pipelines](../../../ci/pipelines/settings.md#change-pipeline-visibility-for-non-project-members-in-public-projects) +by setting the artifact's public flag to false (`public: false`). This setting ensures artifacts are +accessible only to GitLab Administrators and project members with the Reporter role and above. To configure GitLab CI/CD as a backend: diff --git a/doc/user/okrs.md b/doc/user/okrs.md index 0b6bffa97ce..a4ba1f8f646 100644 --- a/doc/user/okrs.md +++ b/doc/user/okrs.md @@ -41,7 +41,7 @@ To create an objective: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Issues**. -1. In the top right corner, next to **New issue**, select the down arrow **{chevron-lg-down}** and then select **New objective**. +1. In the upper-right corner, next to **New issue**, select the down arrow **{chevron-lg-down}** and then select **New objective**. 1. Select **New objective** again. 1. Enter the objective title. 1. Select **Create objective**. diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md index 5e2908a26e1..a74fd8d5215 100644 --- a/doc/user/profile/account/delete_account.md +++ b/doc/user/profile/account/delete_account.md @@ -19,7 +19,7 @@ Deleting a user deletes all projects in that user namespace. As a user, to delete your own account: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Account**. 1. Select **Delete account**. diff --git a/doc/user/profile/active_sessions.md b/doc/user/profile/active_sessions.md index 7a837258cb2..1f7264d740e 100644 --- a/doc/user/profile/active_sessions.md +++ b/doc/user/profile/active_sessions.md @@ -16,7 +16,7 @@ review the sessions, and revoke any you don't recognize. To list all active sessions: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Active Sessions**. @@ -33,7 +33,7 @@ exceeds 100, the oldest ones are deleted. To revoke an active session: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Active Sessions**. 1. Select **Revoke** next to a session. The current session cannot be revoked, as this would sign you out of GitLab. diff --git a/doc/user/profile/contributions_calendar.md b/doc/user/profile/contributions_calendar.md index 49e6319aa12..e9802cccef6 100644 --- a/doc/user/profile/contributions_calendar.md +++ b/doc/user/profile/contributions_calendar.md @@ -40,7 +40,7 @@ GitLab tracks the following contribution events: To view your daily contributions: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select your name from the dropdown list. 1. In the contributions calendar: - To view the number of contributions for a specific day, hover over a tile. @@ -53,7 +53,7 @@ The contributions calendar graph and recent activity list displays your To view private contributions: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Main settings** section, select the **Include private contributions on my profile** checkbox. 1. Select **Update profile settings**. @@ -83,7 +83,7 @@ GitLab provides RSS feeds of user activity. To subscribe to the RSS feed of a user's activity: 1. Go to the [user's profile](index.md#access-your-user-profile). -1. In the top right, select the feed symbol **{rss}** to display the results as an RSS feed in Atom format. +1. In the upper right, select the feed symbol **{rss}** to display the results as an RSS feed in Atom format. The URL of the result contains both a feed token, and the user's activity that you're authorized to view. @@ -96,7 +96,7 @@ If you think your feed token has been exposed, you should reset it. To reset your feed token: -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Access Tokens**. 1. Scroll down. In the **Feed token** section, select the diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md index 0179ab03dbe..11ef1d79d3f 100644 --- a/doc/user/profile/index.md +++ b/doc/user/profile/index.md @@ -15,14 +15,14 @@ Your profile also includes settings, which you use to customize your GitLab expe To access your profile: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select your name or username. ## Access your user settings To access your user settings: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. ## Change your username @@ -40,7 +40,7 @@ Prerequisites: To change your username: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Account**. 1. In the **Change username** section, enter a new username as the path. @@ -50,7 +50,7 @@ To change your username: To add new email to your account: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Emails**. 1. In the **Email** text box, enter the new email. @@ -63,7 +63,7 @@ You can make your user profile visible to only you and GitLab administrators. To make your profile private: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. Select the **Private profile** checkbox. 1. Select **Update profile settings**. @@ -129,7 +129,7 @@ They can help other users connect with you on other platforms. To add links to other accounts: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Main settings** section, add your information from: - Skype @@ -143,7 +143,7 @@ In the user contribution calendar graph and recent activity list, you can see yo To show private contributions: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Main settings** section, select the **Include private contributions on my profile** checkbox. 1. Select **Update profile settings**. @@ -157,7 +157,7 @@ your name in your profile. To specify your pronouns: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Pronouns** text box, enter your pronouns. 1. Select **Update profile settings**. @@ -171,7 +171,7 @@ your name. To add your name pronunciation: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Pronunciation** text box, enter how your name is pronounced. 1. Select **Update profile settings**. @@ -187,7 +187,7 @@ Your status is publicly visible even if your [profile is private](#make-your-use To set your current status: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Set status** or, if you have already set a status, **Edit status**. 1. Set the desired emoji and status message. Status messages must be plain text and 100 characters or less. They can also contain emoji codes like, `I'm on vacation :palm_tree:`. @@ -210,12 +210,12 @@ To indicate to others that you are busy, you can set an indicator. To set the busy status indicator, either: - Set it directly: - 1. On the top bar, in the top-right corner, select your avatar. + 1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Set status** or, if you have already set a status, **Edit status**. 1. Select the **Set yourself as busy** checkbox. - Set it on your profile: - 1. On the top bar, in the top-right corner, select your avatar. + 1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Current status** section, select the **Set yourself as busy** checkbox. @@ -249,7 +249,7 @@ You can set your local time zone to: To set your time zone: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Time settings** section, select your time zone from the dropdown list. @@ -262,7 +262,7 @@ Your primary email is used by default. To change your commit email: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Commit email** dropdown list, select an email address. 1. Select **Update profile settings**. @@ -276,7 +276,7 @@ Your primary email: To change your primary email: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Email** field, enter your new email address. 1. Select **Update profile settings**. @@ -285,7 +285,7 @@ To change your primary email: You can select one of your [configured email addresses](#add-emails-to-your-user-profile) to be displayed on your public profile: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Public email** field, select one of the available email addresses. 1. Select **Update profile settings**. @@ -297,7 +297,7 @@ so you can keep your email information private. To use a private commit email: -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. In the **Commit email** dropdown list, select **Use a private email**. 1. Select **Update profile settings**. diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md index 7343aea8ce7..dcc78dac05b 100644 --- a/doc/user/profile/notifications.md +++ b/doc/user/profile/notifications.md @@ -47,7 +47,7 @@ anyone else. To edit your notification settings: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **Notifications**. 1. Edit the desired global, group, or project notification settings. @@ -100,7 +100,7 @@ You can select a notification level and email address for each group. To select a notification level for a group, use either of these methods: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **Notifications**. 1. Locate the project in the **Groups** section. @@ -119,7 +119,7 @@ Or: You can select an email address to receive notifications for each group you belong to. You can use group notifications, for example, if you work freelance, and want to keep email about clients' projects separate. -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **Notifications**. 1. Locate the project in the **Groups** section. @@ -131,7 +131,7 @@ To help you stay up to date, you can select a notification level for each projec To select a notification level for a project, use either of these methods: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **Notifications**. 1. Locate the project in the **Projects** section. @@ -153,7 +153,7 @@ These emails are enabled by default. To opt out: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **Notifications**. 1. Clear the **Receive product marketing emails** checkbox. @@ -330,7 +330,7 @@ The participants are: If you no longer wish to receive any email notifications: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **Notifications**. 1. Clear the **Receive product marketing emails** checkbox. diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md index 0a0295459e4..0413efef0f0 100644 --- a/doc/user/profile/personal_access_tokens.md +++ b/doc/user/profile/personal_access_tokens.md @@ -54,7 +54,7 @@ Personal access tokens are not FIPS compliant and creation and use are disabled You can create as many personal access tokens as you like. -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Access Tokens**. 1. Enter a name and optional expiry date for the token. @@ -82,7 +82,7 @@ for guidance on managing personal access tokens (for example, setting a short ex At any time, you can revoke a personal access token. -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Access Tokens**. 1. In the **Active personal access tokens** area, next to the key, select **Revoke**. @@ -96,7 +96,7 @@ Token usage information is updated every 24 hours. GitLab considers a token used To view the last time a token was used: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Access Tokens**. 1. In the **Active personal access tokens** area, next to the key, view the **Last Used** date. diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md index 664d22959a2..6496ca523e6 100644 --- a/doc/user/profile/preferences.md +++ b/doc/user/profile/preferences.md @@ -12,7 +12,7 @@ of GitLab to their liking. To navigate to your profile's preferences: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. ## Navigation theme diff --git a/doc/user/profile/user_passwords.md b/doc/user/profile/user_passwords.md index 9c1ba8852d2..eac3db3c71c 100644 --- a/doc/user/profile/user_passwords.md +++ b/doc/user/profile/user_passwords.md @@ -26,7 +26,7 @@ authorization provider, you do not need to choose a password. GitLab You can change your password. GitLab enforces [password requirements](#password-requirements) when you choose your new password. -1. On the top bar, in the top-right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **Password**. 1. In the **Current password** text box, enter your current password. diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md index 8593fa50a05..a4867a6f25e 100644 --- a/doc/user/project/file_lock.md +++ b/doc/user/project/file_lock.md @@ -209,7 +209,7 @@ requests that modify locked files. Unlock the file to allow changes. To lock a file: 1. Open the file or directory in GitLab. -1. On the top right, above the file, select **Lock**. +1. In the upper right, above the file, select **Lock**. 1. On the confirmation dialog box, select **OK**. If you do not have permission to lock the file, the button is not enabled. diff --git a/doc/user/project/integrations/hangouts_chat.md b/doc/user/project/integrations/hangouts_chat.md index c6e102b1d74..563dda2b63f 100644 --- a/doc/user/project/integrations/hangouts_chat.md +++ b/doc/user/project/integrations/hangouts_chat.md @@ -28,7 +28,7 @@ notifications to Google Chat: To enable the integration in Google Chat: 1. Enter the room where you want to receive notifications from GitLab. -1. Open the room dropdown list on the top-left and select **Manage webhooks**. +1. Open the room dropdown list in the upper left and select **Manage webhooks**. 1. Enter the name for your webhook, for example "GitLab integration". 1. Optional. Add an avatar for your bot. 1. Select **Save**. diff --git a/doc/user/project/issues/create_issues.md b/doc/user/project/issues/create_issues.md index c49d203d193..18adce313d3 100644 --- a/doc/user/project/issues/create_issues.md +++ b/doc/user/project/issues/create_issues.md @@ -31,7 +31,7 @@ To create an issue: 1. On the top bar, select **Main menu > Projects** and find your project. 1. Either: - - On the left sidebar, select **Issues**, and then, in the top right corner, select **New issue**. + - On the left sidebar, select **Issues**, and then, in the upper-right corner, select **New issue**. - On the top bar, select the plus sign (**{plus-square}**) and then, under **This project**, select **New issue**. @@ -53,7 +53,7 @@ To create an issue from a group: 1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Issues**. -1. In the top right corner, select **Select project to create issue**. +1. In the upper-right corner, select **Select project to create issue**. 1. Select the project you'd like to create an issue for. The button now reflects the selected project. 1. Select **New issue in `<project name>`**. diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md index d01f22d03c9..8db04972ff3 100644 --- a/doc/user/project/issues/csv_import.md +++ b/doc/user/project/issues/csv_import.md @@ -36,7 +36,7 @@ To import issues: 1. Go to your project's Issues list page. 1. Open the import feature, depending if the project has issues: - - Existing issues are present: Select the import icon at the top right, next to **Edit issues**. + - Existing issues are present: Select the import icon in the upper right, next to **Edit issues**. - Project has no issues: Select **Import CSV** in the middle of the page. 1. Select the file you want to import, and then select **Import issues**. diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md index 27d935d0ed1..f43f87119a6 100644 --- a/doc/user/project/issues/design_management.md +++ b/doc/user/project/issues/design_management.md @@ -92,12 +92,12 @@ The design you selected opens. You can then [zoom in](#zoom-in-on-a-design) on i When viewing a design, you can move to other designs. To do so, either: -- In the top-right corner, select **Go to previous design** (**{chevron-lg-left}**) or **Go to next design** (**{chevron-lg-right}**). +- In the upper-right corner, select **Go to previous design** (**{chevron-lg-left}**) or **Go to next design** (**{chevron-lg-right}**). - Press <kbd>Left</kbd> or <kbd>Right</kbd> on your keyboard. To return to the issue view, either: -- In the top-left corner, select the close icon (**{close}**). +- In the upper-left corner, select the close icon (**{close}**). - Press <kbd>Esc</kbd> on your keyboard. When a design is added, a green icon (**{plus-square}**) is displayed on the image @@ -186,7 +186,7 @@ Prerequisites: To archive a single design: 1. Select the design to view it enlarged. -1. In the top right corner, select **Archive design** (**{archive}**). +1. In the upper-right corner, select **Archive design** (**{archive}**). 1. Select **Archive designs**. To archive multiple designs at once: @@ -235,7 +235,7 @@ When you're done discussing part of a design, you can resolve the discussion thr To mark a thread as resolved or unresolved, either: -- In the top-right corner of the first comment of the discussion, select **Resolve thread** or **Unresolve thread** (**{check-circle}**). +- In the upper-right corner of the first comment of the discussion, select **Resolve thread** or **Unresolve thread** (**{check-circle}**). - Add a new comment to the thread and select or clear the **Resolve thread** checkbox. Resolving a discussion thread also marks any pending [to-do items](../../todos.md) related to notes diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md index 53f19d544dc..212c8ee54be 100644 --- a/doc/user/project/issues/managing_issues.md +++ b/doc/user/project/issues/managing_issues.md @@ -382,7 +382,7 @@ To view all issues assigned to you: Or: - To use a [keyboard shortcut](../../shortcuts.md), press <kbd>Shift</kbd> + <kbd>i</kbd>. -- On the top bar, on the top right, select **{issues}** **Issues**. +- On the top bar, in the upper right, select **{issues}** **Issues**. ## Filter the list of issues diff --git a/doc/user/project/merge_requests/changes.md b/doc/user/project/merge_requests/changes.md index 07ee2ef90c4..8f6b1a32424 100644 --- a/doc/user/project/merge_requests/changes.md +++ b/doc/user/project/merge_requests/changes.md @@ -57,7 +57,7 @@ clear your browser's cookies or change this behavior again. To view one file at a time for all of your merge requests: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Preferences**. 1. Scroll to the **Behavior** section and select the **Show one file at a time on merge request's Changes tab** checkbox. 1. Select **Save changes**. diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md index 388c6fb55ac..9fac872ac4b 100644 --- a/doc/user/project/merge_requests/cherry_pick_changes.md +++ b/doc/user/project/merge_requests/cherry_pick_changes.md @@ -55,7 +55,7 @@ by the merge request: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Merge requests**, and find your merge request. 1. Scroll to the merge request reports section, and find the **Merged by** report. -1. In the top right, select **Cherry-pick**: +1. In the upper right, select **Cherry-pick**: ![Cherry-pick merge request](img/cherry_pick_v15_4.png) 1. In the modal window, select the project and branch to cherry-pick into. @@ -87,7 +87,7 @@ list of commits included in a merge request: 1. On the left sidebar, select **Merge requests**, and find your merge request. 1. In the merge request's secondary menu, select **Commits** to display the commit details page. 1. Select the title of the commit you want to cherry-pick. -1. In the top right corner, select **Options > Cherry-pick** to show the cherry-pick modal. +1. In the upper-right corner, select **Options > Cherry-pick** to show the cherry-pick modal. 1. In the modal window, select the project and branch to cherry-pick into. 1. Optional. Select **Start a new merge request with these changes**. 1. Select **Cherry-pick**. @@ -101,7 +101,7 @@ when you view that file in your project's Git repository: 1. On the left sidebar, select **Repository > Files** and go to the file changed by the commit. 1. Select **History**, then select the title of the commit you want to cherry-pick. -1. In the top right corner, select **Options > Cherry-pick** to show the cherry-pick modal. +1. In the upper-right corner, select **Options > Cherry-pick** to show the cherry-pick modal. 1. In the modal window, select the project and branch to cherry-pick into. 1. Optional. Select **Start a new merge request with these changes**. 1. Select **Cherry-pick**. @@ -115,7 +115,7 @@ You can cherry-pick merge requests from the same project, or forks of the same project, from the GitLab user interface: 1. In the merge request's secondary menu, select **Commits** to display the commit details page. -1. In the top right corner, select **Options > Cherry-pick** to show the cherry-pick modal. +1. In the upper-right corner, select **Options > Cherry-pick** to show the cherry-pick modal. 1. In **Pick into project** and **Pick into branch**, select the destination project and branch: ![Cherry-pick commit](img/cherry_pick_into_project_v13_11.png) 1. Optional. Select **Start a new merge request** if you're ready to create a merge request. diff --git a/doc/user/project/merge_requests/creating_merge_requests.md b/doc/user/project/merge_requests/creating_merge_requests.md index 542edc11c44..bda747671ba 100644 --- a/doc/user/project/merge_requests/creating_merge_requests.md +++ b/doc/user/project/merge_requests/creating_merge_requests.md @@ -19,7 +19,7 @@ You can create a merge request from the list of merge requests. 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left menu, select **Merge requests**. -1. In the top right, select **New merge request**. +1. In the upper right, select **New merge request**. 1. Select a source and target branch and then **Compare branches and continue**. 1. Fill out the fields and select **Create merge request**. @@ -172,7 +172,7 @@ To create a merge request by sending an email: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left menu, select **Merge requests**. -1. In the top right, select **Email a new merge request to this project**. +1. In the upper right, select **Email a new merge request to this project**. An email address is displayed. Copy this address. Ensure you keep this address private. 1. Open an email and compose a message with the following information: diff --git a/doc/user/project/merge_requests/drafts.md b/doc/user/project/merge_requests/drafts.md index c216514fff4..62820988701 100644 --- a/doc/user/project/merge_requests/drafts.md +++ b/doc/user/project/merge_requests/drafts.md @@ -25,7 +25,7 @@ the **Merge** button until you remove the **Draft** flag: There are several ways to flag a merge request as a draft: -- **Viewing a merge request**: In the top right corner of the merge request, select **Mark as draft**. +- **Viewing a merge request**: In the upper-right corner of the merge request, select **Mark as draft**. - **Creating or editing a merge request**: Add `[Draft]`, `Draft:` or `(Draft)` to the beginning of the merge request's title, or select **Mark as draft** below the **Title** field. @@ -41,7 +41,7 @@ There are several ways to flag a merge request as a draft: When a merge request is ready to be merged, you can remove the `Draft` flag in several ways: -- **Viewing a merge request**: In the top right corner of the merge request, select **Mark as ready**. +- **Viewing a merge request**: In the upper-right corner of the merge request, select **Mark as ready**. Users with at least the Developer role can also scroll to the bottom of the merge request description and select **Mark as ready**: diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 2193440d3a2..0276f3d98b6 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -65,7 +65,7 @@ or: or: -1. On the top bar, on the top right, select **{merge-request-open}** **Merge requests**. +1. On the top bar, in the upper right, select **{merge-request-open}** **Merge requests**. 1. From the dropdown list, select **Assigned to you**. ## Filter the list of merge requests @@ -258,7 +258,7 @@ On self-managed GitLab, by default this feature is not available. To make it ava On GitLab.com, this feature is enabled in the following projects: `gitlab-org/gitlab`, `gitlab-com/www-gitlab-com`, and `gitlab-org/customers-gitlab-com`. When this feature flag is enabled, you can find the following actions in -**Merge request actions** (**{ellipsis_v}**) on the top right: +**Merge request actions** (**{ellipsis_v}**) in the upper right: - The [notifications](../../profile/notifications.md#edit-notification-settings-for-issues-merge-requests-and-epics) toggle - Mark merge request as ready or [draft](../merge_requests/drafts.md) diff --git a/doc/user/project/merge_requests/revert_changes.md b/doc/user/project/merge_requests/revert_changes.md index 76f351f1346..5878873f209 100644 --- a/doc/user/project/merge_requests/revert_changes.md +++ b/doc/user/project/merge_requests/revert_changes.md @@ -62,7 +62,7 @@ To do this: 1. If you don't know the merge request the commit originated from: 1. On the left sidebar, select **Repository > Commits**. 1. Select the title of the commit to display full information about the commit. -1. In the top right corner, select **Options**, then select **Revert**. +1. In the upper-right corner, select **Options**, then select **Revert**. 1. In **Revert in branch**, select the branch to revert your changes into. 1. Optional. Select **Start a new merge request** to start a new merge request with the new revert commit. 1. Select **Revert**. diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md index 9a390364466..b17fd52ea7b 100644 --- a/doc/user/project/merge_requests/reviews/index.md +++ b/doc/user/project/merge_requests/reviews/index.md @@ -84,7 +84,7 @@ To download the changes included in a merge request as a diff: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Merge requests**. 1. Select your merge request. -1. On the top right, select **Code > Plain diff**. +1. In the upper right, select **Code > Plain diff**. If you know the URL of the merge request, you can also download the diff from the command line by appending `.diff` to the URL. This example downloads the diff @@ -107,7 +107,7 @@ To download the changes included in a merge request as a patch file: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Merge requests**. 1. Select your merge request. -1. On the top right, select **Code > Email patches**. +1. In the upper right, select **Code > Email patches**. If you know the URL of the merge request, you can also download the patch from the command line by appending `.patch` to the URL. This example downloads the patch diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md index f22509ffe81..24e9e6e15a4 100644 --- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md +++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md @@ -59,7 +59,7 @@ To add your custom domain to GitLab Pages: If this path is not visible, select **Deployments > Pages**. [This location is part of an experiment](../index.md#menu-position-test). -1. In the top-right corner, select **New Domain**. +1. In the upper-right corner, select **New Domain**. 1. In **Domain**, enter the domain name. 1. Optional. In **Certificate**, turn off the **Automatic certificate management using Let's Encrypt** toggle to add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages). You can also add the certificate and key later. 1. Select **Create New Domain**. @@ -300,7 +300,7 @@ meet these requirements. If this path is not visible, select **Deployments > Pages**. [This location is part of an experiment](../index.md#menu-position-test). - 1. In the top-right corner, select **New Domain**. + 1. In the upper-right corner, select **New Domain**. 1. In **Domain**, enter the domain name. 1. In **Certificate**, turn off the **Automatic certificate management using Let's Encrypt** toggle to add an [SSL/TLS certificate](#adding-an-ssltls-certificate-to-pages). 1. Select **Create New Domain**. diff --git a/doc/user/project/pages/getting_started/pages_forked_sample_project.md b/doc/user/project/pages/getting_started/pages_forked_sample_project.md index b991a0ebd59..509609e9b89 100644 --- a/doc/user/project/pages/getting_started/pages_forked_sample_project.md +++ b/doc/user/project/pages/getting_started/pages_forked_sample_project.md @@ -19,7 +19,7 @@ To fork a sample project and create a Pages website: 1. View the sample projects by navigating to the [GitLab Pages examples](https://gitlab.com/pages) group. 1. Select the name of the project you want to [fork](../../repository/forking_workflow.md#creating-a-fork). -1. In the top right, select **Fork** and then choose a namespace to fork to. +1. In the upper right, select **Fork** and then choose a namespace to fork to. 1. For your project, on the left sidebar, select **CI/CD > Pipelines** and then **Run pipeline**. GitLab CI/CD builds and deploys your site. diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md index 7c2d5088f17..2820e8961c1 100644 --- a/doc/user/project/releases/index.md +++ b/doc/user/project/releases/index.md @@ -194,7 +194,7 @@ Prerequisites: In the UI: 1. On the left sidebar, select **Deployments > Releases**. -1. In the top-right corner of the release you want to modify, select **Edit this release** (the pencil icon). +1. In the upper-right corner of the release you want to modify, select **Edit this release** (the pencil icon). 1. On the **Edit Release** page, change the release's details. 1. Select **Save changes**. @@ -216,7 +216,7 @@ In the UI: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Deployments > Releases**. -1. In the top-right corner of the release you want to delete, select **Edit this release** +1. In the upper-right corner of the release you want to delete, select **Edit this release** (**{pencil}**). 1. On the **Edit Release** page, select **Delete**. 1. Select **Delete release**. @@ -236,7 +236,7 @@ the [Releases API](../../../api/releases/index.md#create-a-release). In the user interface, to associate milestones to a release: 1. On the left sidebar, select **Deployments > Releases**. -1. In the top-right corner of the release you want to modify, select **Edit this release** (the pencil icon). +1. In the upper-right corner of the release you want to modify, select **Edit this release** (the pencil icon). 1. From the **Milestones** list, select each milestone you want to associate. You can select multiple milestones. 1. Select **Save changes**. diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md index f6c5ef20c82..0e8428bbbd6 100644 --- a/doc/user/project/repository/forking_workflow.md +++ b/doc/user/project/repository/forking_workflow.md @@ -23,7 +23,7 @@ submit them through a merge request to the repository you don't have access to. To fork an existing project in GitLab: -1. On the project's home page, in the top right, select **{fork}** **Fork**: +1. On the project's home page, in the upper right, select **{fork}** **Fork**: ![Fork this project](img/forking_workflow_fork_button_v13_10.png) 1. Optional. Edit the **Project name**. 1. For **Project URL**, select the [namespace](../../namespace/index.md) diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md index fdf6a7c72ab..64f19d1a92c 100644 --- a/doc/user/project/repository/gpg_signed_commits/index.md +++ b/doc/user/project/repository/gpg_signed_commits/index.md @@ -43,7 +43,7 @@ To view a user's public GPG key, you can either: - Go to `https://gitlab.example.com/<USERNAME>.gpg`. GitLab displays the GPG key, if the user has configured one, or a blank page for users without a configured GPG key. -- Go to the user's profile (such as `https://gitlab.example.com/<USERNAME>`). In the top right +- Go to the user's profile (such as `https://gitlab.example.com/<USERNAME>`). In the upper right of the user's profile, select **View public GPG keys** (**{key}**). ## Configure commit signing @@ -119,7 +119,7 @@ If you don't already have a GPG key, create one: To add a GPG key to your user settings: 1. Sign in to GitLab. -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **GPG Keys** (**{key}**). 1. In **Key**, paste your _public_ key. @@ -253,7 +253,7 @@ If a GPG key becomes compromised, revoke it. Revoking a key changes both future To revoke a GPG key: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **GPG Keys** (**{key}**). 1. Select **Revoke** next to the GPG key you want to delete. @@ -268,7 +268,7 @@ When you remove a GPG key from your GitLab account: To remove a GPG key from your account: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select **GPG Keys** (**{key}**). 1. Select **Remove** (**{remove}**) next to the GPG key you want to delete. diff --git a/doc/user/project/repository/ssh_signed_commits/index.md b/doc/user/project/repository/ssh_signed_commits/index.md index 4a6a6ebcdba..62b8e6cc44f 100644 --- a/doc/user/project/repository/ssh_signed_commits/index.md +++ b/doc/user/project/repository/ssh_signed_commits/index.md @@ -169,7 +169,7 @@ If an SSH key becomes compromised, revoke it. Revoking a key changes both future To revoke an SSH key: -1. In the top-right corner, select your avatar. +1. In the upper-right corner, select your avatar. 1. Select **Edit profile**. 1. On the left sidebar, select (**{key}**) **SSH Keys**. 1. Select **Revoke** next to the SSH key you want to delete. diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md index 922accf9d28..b04905e6b34 100644 --- a/doc/user/project/requirements/index.md +++ b/doc/user/project/requirements/index.md @@ -236,7 +236,7 @@ To import requirements: 1. In a project, go to **Issues > Requirements**. - If the project already has existing requirements, select the import icon (**{import}**) in the - top right. + upper right. - For a project without any requirements, select **Import CSV** in the middle of the page. 1. Select the file and select **Import requirements**. @@ -296,7 +296,7 @@ Prerequisite: To export requirements: 1. In a project, go to **Issues > Requirements**. -1. In the top right, select the **Export as CSV** icon (**{export}**). +1. In the upper right, select the **Export as CSV** icon (**{export}**). A confirmation modal appears. diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md index 5d89576e587..5e9f648daba 100644 --- a/doc/user/project/web_ide/index.md +++ b/doc/user/project/web_ide/index.md @@ -175,8 +175,8 @@ access to the selected branch, you see a warning, but can still create a new branch and start a merge request. To discard a change in a particular file, select **Discard changes** on that -file in the changes tab. To discard all the changes, select the trash icon on the -top-right corner of the changes sidebar. +file in the changes tab. To discard all the changes, select the trash icon in the +upper-right corner of the changes sidebar. ![Commit changes](img/commit_changes_v13_11.png) diff --git a/doc/user/project/web_ide_beta/index.md b/doc/user/project/web_ide_beta/index.md index ad9afef7139..fe110baf578 100644 --- a/doc/user/project/web_ide_beta/index.md +++ b/doc/user/project/web_ide_beta/index.md @@ -40,7 +40,7 @@ or a merge request. To open the Web IDE Beta from a file or the repository file list: -- On the top right of the page, select **Open in Web IDE**. +- In the upper right of the page, select **Open in Web IDE**. If **Open in Web IDE** is not visible: @@ -88,7 +88,7 @@ For details, see the [VS Code documentation](https://code.visualstudio.com/docs/ If you do not want to use the Web IDE Beta, you can change your personal preferences. -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Preferences**. 1. In the **Web IDE** section, select the **Opt out of the Web IDE Beta** checkbox. 1. Select **Save changes**. diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md index 04a6f9bee80..0425014a68b 100644 --- a/doc/user/project/wiki/index.md +++ b/doc/user/project/wiki/index.md @@ -252,7 +252,7 @@ replaces the default sidebar navigation: - For project wikis, select **Projects** and find your project. - For group wikis, select **Groups** and find your group. 1. On the left sidebar, select **Wiki**. -1. In the top right corner of the page, select **Edit sidebar**. +1. In the upper-right corner of the page, select **Edit sidebar**. 1. When complete, select **Save changes**. A `_sidebar` example, formatted with Markdown: diff --git a/doc/user/report_abuse.md b/doc/user/report_abuse.md index 67b9eaac4c8..aabc9c5dff1 100644 --- a/doc/user/report_abuse.md +++ b/doc/user/report_abuse.md @@ -27,7 +27,7 @@ You can report a user through their: To report abuse from a user's profile page: 1. Anywhere in GitLab, select the name of the user. -1. In the top right corner of the user's profile, select **Report abuse to administrator** (**{information-o}**). +1. In the upper-right corner of the user's profile, select **Report abuse to administrator** (**{information-o}**). 1. Select a reason for reporting the user. 1. Complete an abuse report. 1. Select **Send report**. @@ -36,7 +36,7 @@ To report abuse from a user's profile page: To report abuse from a user's comment: -1. In the comment, in the top right corner, select **More actions** (**{ellipsis_v}**). +1. In the comment, in the upper-right corner, select **More actions** (**{ellipsis_v}**). 1. Select **Report abuse to administrator**. 1. Select a reason for reporting the user. 1. Complete an abuse report. @@ -48,7 +48,7 @@ A URL to the reported user's comment is pre-filled in the abuse report's ## Report abuse from an issue -1. On the issue, in the top right corner, select the vertical ellipsis (**{ellipsis_v}**). +1. On the issue, in the upper-right corner, select the vertical ellipsis (**{ellipsis_v}**). 1. Select **Report abuse to administrator**. 1. Select a reason for reporting the user. 1. Complete an abuse report. @@ -56,7 +56,7 @@ A URL to the reported user's comment is pre-filled in the abuse report's ## Report abuse from a merge request -1. On the merge request, in the top right corner, select the vertical ellipsis (**{ellipsis_v}**). +1. On the merge request, in the upper-right corner, select the vertical ellipsis (**{ellipsis_v}**). 1. Select **Report abuse to administrator**. 1. Select a reason for reporting this user. 1. Complete an abuse report. diff --git a/doc/user/search/index.md b/doc/user/search/index.md index e5b802eed4f..c86fa136044 100644 --- a/doc/user/search/index.md +++ b/doc/user/search/index.md @@ -50,7 +50,7 @@ Global search only flags with an error any search that includes more than: ## Perform a search -To start a search, type your search query in the search bar on the top-right of the screen. +To start a search, type your search query in the search bar in the upper right of the screen. You must type at least two characters. ![search navbar](img/search_navbar_v15_7.png) diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md index 64f9b53f891..de3ff4ef6e5 100644 --- a/doc/user/shortcuts.md +++ b/doc/user/shortcuts.md @@ -15,7 +15,7 @@ To display a window in GitLab that lists its keyboard shortcuts, use one of the following methods: - Press <kbd>?</kbd>. -- In the Help menu in the top right of the application, select **Keyboard shortcuts**. +- In the Help menu in the upper right of the application, select **Keyboard shortcuts**. Although [global shortcuts](#global-shortcuts) work from any area of GitLab, you must be in specific pages for the other shortcuts to be available, as diff --git a/doc/user/snippets.md b/doc/user/snippets.md index 70669748cd8..0532ed27010 100644 --- a/doc/user/snippets.md +++ b/doc/user/snippets.md @@ -149,7 +149,7 @@ by a Git repository), through the [Snippets API](../api/snippets.md), and in the To add a new file to your snippet through the GitLab UI: 1. Go to your snippet in the GitLab UI. -1. Select **Edit** in the top right corner. +1. Select **Edit** in the upper-right corner. 1. Select **Add another file**. 1. Add your content to the file in the form fields provided. 1. Select **Save changes**. @@ -157,7 +157,7 @@ To add a new file to your snippet through the GitLab UI: To delete a file from your snippet through the GitLab UI: 1. Go to your snippet in the GitLab UI. -1. Select **Edit** in the top right corner. +1. Select **Edit** in the upper-right corner. 1. Select **Delete file** alongside the filename of each file you wish to delete. 1. Select **Save changes**. diff --git a/doc/user/ssh.md b/doc/user/ssh.md index 0e4171decd8..c21fd1ac82a 100644 --- a/doc/user/ssh.md +++ b/doc/user/ssh.md @@ -262,7 +262,7 @@ You can use [1Password](https://1password.com/) and the [1Password browser exten - Use an existing SSH in your 1Password vault to authenticate with GitLab. 1. Sign in to GitLab. -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **SSH Keys**. 1. Select **Key**, and you should see the 1Password helper appear. @@ -307,7 +307,7 @@ To use SSH with GitLab, copy your public key to your GitLab account: Replace `id_ed25519.pub` with your filename. For example, use `id_rsa.pub` for RSA. 1. Sign in to GitLab. -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **SSH Keys**. 1. In the **Key** box, paste the contents of your public key. @@ -380,7 +380,7 @@ on `ssh` command options, see the `man` pages for both `ssh` and `ssh_config`. ## View your account's SSH keys 1. Sign in to GitLab. -1. On the top bar, in the top right corner, select your avatar. +1. On the top bar, in the upper-right corner, select your avatar. 1. Select **Preferences**. 1. On the left sidebar, select **SSH Keys**. diff --git a/doc/user/todos.md b/doc/user/todos.md index cf42f371b94..cb7a7248bb2 100644 --- a/doc/user/todos.md +++ b/doc/user/todos.md @@ -21,7 +21,7 @@ You can use the To-Do List to track [actions](#actions-that-create-to-do-items) To access your To-Do List: -On the top bar, in the top right, select To-Do List (**{task-done}**). +On the top bar, in the upper right, select To-Do List (**{task-done}**). ## Search the To-Do List @@ -157,7 +157,7 @@ There are two ways to do this: You can mark all your to-do items as done at the same time. -In the To-Do List, in the top right, select **Mark all as done**. +In the To-Do List, in the upper right, select **Mark all as done**. ## How a user's To-Do List is affected when their access changes diff --git a/lib/gitlab/background_migration/encrypt_integration_properties.rb b/lib/gitlab/background_migration/encrypt_integration_properties.rb index 3843356af69..c9582da2a51 100644 --- a/lib/gitlab/background_migration/encrypt_integration_properties.rb +++ b/lib/gitlab/background_migration/encrypt_integration_properties.rb @@ -31,7 +31,7 @@ module Gitlab def encrypt_properties data = ::Gitlab::Json.parse(properties) iv = generate_iv(ALGORITHM) - ep = self.class.encrypt(:encrypted_properties_tmp, data, { iv: iv }) + ep = self.class.attr_encrypt(:encrypted_properties_tmp, data, { iv: iv }) [ep, iv] end diff --git a/lib/gitlab/doctor/secrets.rb b/lib/gitlab/doctor/secrets.rb index cd075569d10..03d3f062372 100644 --- a/lib/gitlab/doctor/secrets.rb +++ b/lib/gitlab/doctor/secrets.rb @@ -16,7 +16,7 @@ module Gitlab models_with_attributes = Hash.new { |h, k| h[k] = [] } models_with_encrypted_attributes.each do |model| - models_with_attributes[model] += model.encrypted_attributes.keys + models_with_attributes[model] += model.attr_encrypted_attributes.keys end models_with_encrypted_tokens.each do |model| @@ -79,7 +79,7 @@ module Gitlab end def models_with_encrypted_attributes - all_models.select { |d| d.encrypted_attributes.present? } + all_models.select { |d| d.attr_encrypted_attributes.present? } end def models_with_encrypted_tokens diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb index d1fd45882d3..e3813070aa4 100644 --- a/lib/gitlab/import_export/base/relation_factory.rb +++ b/lib/gitlab/import_export/base/relation_factory.rb @@ -158,9 +158,9 @@ module Gitlab end def remove_encrypted_attributes! - return unless relation_class.respond_to?(:encrypted_attributes) && relation_class.encrypted_attributes.any? + return unless relation_class.respond_to?(:attr_encrypted_attributes) && relation_class.attr_encrypted_attributes.any? - relation_class.encrypted_attributes.each_key do |key| + relation_class.attr_encrypted_attributes.each_key do |key| @relation_hash[key.to_s] = nil end end diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 99364996864..7c24bf95695 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -1005,6 +1005,7 @@ excluded_attributes: - :protected_branch_id create_access_levels: - :protected_tag_id + - :deploy_key_id deploy_access_levels: - :protected_environment_id boards: diff --git a/lib/gitlab/otp_key_rotator.rb b/lib/gitlab/otp_key_rotator.rb index 38618a0ac06..8e02486d8c6 100644 --- a/lib/gitlab/otp_key_rotator.rb +++ b/lib/gitlab/otp_key_rotator.rb @@ -67,7 +67,7 @@ module Gitlab attr_reader :old_key, :new_key def otp_secret_settings - @otp_secret_settings ||= User.encrypted_attributes[:otp_secret] + @otp_secret_settings ||= User.attr_encrypted_attributes[:otp_secret] end def reencrypt(user, old_key, new_key) diff --git a/lib/kramdown/parser/atlassian_document_format.rb b/lib/kramdown/parser/atlassian_document_format.rb index 4ceb879a04c..d27697a59a6 100644 --- a/lib/kramdown/parser/atlassian_document_format.rb +++ b/lib/kramdown/parser/atlassian_document_format.rb @@ -219,7 +219,7 @@ module Kramdown # opportunity to replace it later. Mention name can have # spaces, so double quote it mention_text = ast_node.dig('attrs', 'text')&.gsub('@', '') - mention_text = %Q("#{mention_text}") if mention_text.match?(/ /) + mention_text = %Q("#{mention_text}") if mention_text&.include?(' ') mention_text = %Q(@adf-mention:#{mention_text}) add_text(mention_text, element, :text) diff --git a/lib/prometheus/pid_provider.rb b/lib/prometheus/pid_provider.rb index 05a2d3bd0c9..4d38e9513fb 100644 --- a/lib/prometheus/pid_provider.rb +++ b/lib/prometheus/pid_provider.rb @@ -27,7 +27,7 @@ module Prometheus def puma_worker_id if matches = process_name.match(/puma.*cluster worker ([0-9]+):/) "puma_#{matches[1]}" - elsif process_name =~ /puma/ + elsif process_name.include?('puma') "puma_master" else unknown_process_id diff --git a/lib/sidebars/your_work/menus/merge_requests_menu.rb b/lib/sidebars/your_work/menus/merge_requests_menu.rb index 89471638dd2..09c84666258 100644 --- a/lib/sidebars/your_work/menus/merge_requests_menu.rb +++ b/lib/sidebars/your_work/menus/merge_requests_menu.rb @@ -60,7 +60,8 @@ module Sidebars link: link, active_routes: { page: link }, has_pill: true, - pill_count: user_merge_requests_counts[:assigned] + pill_count: user_merge_requests_counts[:assigned], + item_id: :merge_requests_assigned ) end @@ -72,7 +73,8 @@ module Sidebars link: link, active_routes: { page: link }, has_pill: true, - pill_count: user_merge_requests_counts[:review_requested] + pill_count: user_merge_requests_counts[:review_requested], + item_id: :merge_requests_to_review ) end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b63d583f3d6..c3eb02ba199 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -29215,6 +29215,9 @@ msgstr "" msgid "OnDemandScans|View results" msgstr "" +msgid "OnDemandScans|You cannot perform any action on this page because you only have %{linkStart}auditor-level access%{linkEnd} and are not a member of the project." +msgstr "" + msgid "OnDemandScans|You have unsaved changes" msgstr "" diff --git a/scripts/api/commit_merge_requests.rb b/scripts/api/commit_merge_requests.rb new file mode 100644 index 00000000000..3cf8dc87497 --- /dev/null +++ b/scripts/api/commit_merge_requests.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'gitlab' +require_relative 'default_options' + +class CommitMergeRequests + def initialize(options) + @project = options.fetch(:project) + @sha = options.fetch(:sha) + + # If api_token is nil, it's set to '' to allow unauthenticated requests (for forks). + api_token = options.fetch(:api_token, '') + + warn "No API token given." if api_token.empty? + + @client = Gitlab.client( + endpoint: options.fetch(:endpoint, API::DEFAULT_OPTIONS[:endpoint]), + private_token: api_token + ) + end + + def execute + client.commit_merge_requests(project, sha) + end + + private + + attr_reader :project, :sha, :client +end diff --git a/scripts/create-pipeline-failure-incident.rb b/scripts/create-pipeline-failure-incident.rb index 1035a680291..2b86fac680d 100755 --- a/scripts/create-pipeline-failure-incident.rb +++ b/scripts/create-pipeline-failure-incident.rb @@ -5,9 +5,10 @@ require 'optparse' require 'json' -require_relative 'api/pipeline_failed_jobs' +require_relative 'api/commit_merge_requests' require_relative 'api/create_issue' require_relative 'api/create_issue_discussion' +require_relative 'api/pipeline_failed_jobs' class CreatePipelineFailureIncident DEFAULT_OPTIONS = { @@ -29,6 +30,8 @@ class CreatePipelineFailureIncident labels: incident_labels } + payload[:assignee_ids] = assignee_ids if stable_branch_incident? + CreateIssue.new(project: project, api_token: api_token).execute(payload).tap do |incident| CreateIssueDiscussion.new(project: project, api_token: api_token) .execute(issue_iid: incident.iid, body: "## Root Cause Analysis") @@ -41,8 +44,18 @@ class CreatePipelineFailureIncident attr_reader :project, :api_token + def stable_branch_incident? + ENV['CI_COMMIT_REF_NAME'] =~ /^[\d-]+-stable(-ee)?$/ + end + def failed_jobs - @failed_jobs ||= PipelineFailedJobs.new(API::DEFAULT_OPTIONS.dup.merge(exclude_allowed_to_fail_jobs: true)).execute + @failed_jobs ||= PipelineFailedJobs.new(API::DEFAULT_OPTIONS.merge(exclude_allowed_to_fail_jobs: true)).execute + end + + def merge_request + @merge_request ||= CommitMergeRequests.new( + API::DEFAULT_OPTIONS.merge(sha: ENV['CI_COMMIT_SHA']) + ).execute.first end def now @@ -63,6 +76,12 @@ class CreatePipelineFailureIncident end def description + return broken_stable_description_content if stable_branch_incident? + + broken_master_description_content + end + + def broken_master_description_content <<~MARKDOWN ## #{project_link} pipeline #{pipeline_link} failed @@ -107,7 +126,62 @@ class CreatePipelineFailureIncident MARKDOWN end + def broken_stable_description_content + <<~MARKDOWN + ## #{project_link} pipeline #{pipeline_link} failed + + **Branch: #{branch_link}** + + **Commit: #{commit_link}** + + **Merge Request: #{merge_request_link}** + + **Triggered by** #{triggered_by_link} • **Source:** #{source} • **Duration:** #{pipeline_duration} minutes + + **Failed jobs (#{failed_jobs.size}):** + + #{failed_jobs_list} + + ### General guidelines + + A broken stable branch prevents patch releases from being built. + Fixing the pipeline is a priority to prevent any delays in releases. + + The process in the [Broken `master` handbook guide](https://about.gitlab.com/handbook/engineering/workflow/#broken-master) can be referenced since much of that process also applies here. + + ### Investigation + + **Be sure to fill the `Timeline` for this incident.** + + 1. If the failure is new, and looks like a potential flaky failure, you can retry the failing job. + Make sure to mention the retry in the `Timeline` and leave a link to the retried job. + 1. Search for similar master-broken issues in https://gitlab.com/gitlab-org/quality/engineering-productivity/master-broken-incidents/-/issues + 1. If one exists, ask the DRI of the master-broken issue to cherry-pick any resulting merge requests into the stable branch + + @gitlab-org/release/managers if the merge request author or maintainer is not available, this can be escalated using the dev-on-call process in the [#dev-escalation slack channel](https://gitlab.slack.com/archives/CLKLMSUR4). + + ### Pre-resolution + + If you believe that there's an easy resolution by either: + + - Reverting a particular merge request. + - Making a quick fix (for example, one line or a few similar simple changes in a few lines). + You can create a merge request, assign to any available maintainer, and ping people that were involved/related to the introduction of the failure. + Additionally, a message can be posted in `#backend_maintainers` or `#frontend_maintainers` to get a maintainer take a look at the fix ASAP. + - Cherry picking a change that was used to fix a similar master-broken issue. + + In both cases, make sure to add the ~"pipeline:expedite" label to speed up the `stable`-fixing pipelines. + + ### Resolution + + Add a comment to this issue describing how this incident could have been prevented earlier in the Merge Request pipeline (rather than the merge commit pipeline). + + MARKDOWN + end + def incident_labels + return ['release-blocker'] if stable_branch_incident? + master_broken_label = if ENV['CI_PROJECT_NAME'] == 'gitlab-foss' 'master:foss-broken' @@ -118,6 +192,12 @@ class CreatePipelineFailureIncident DEFAULT_LABELS.dup << master_broken_label end + def assignee_ids + ids = [ENV['GITLAB_USER_ID'].to_i] + ids << merge_request['author']['id'].to_i if merge_request + ids + end + def pipeline_link "[##{ENV['CI_PIPELINE_ID']}](#{ENV['CI_PIPELINE_URL']})" end @@ -134,6 +214,12 @@ class CreatePipelineFailureIncident "[#{ENV['CI_COMMIT_TITLE']}](#{ENV['CI_PROJECT_URL']}/-/commit/#{ENV['CI_COMMIT_SHA']})" end + def merge_request_link + return 'N/A' unless merge_request + + "[#{merge_request['title']}](#{merge_request['web_url']})" + end + def source "`#{ENV['CI_PIPELINE_SOURCE']}`" end diff --git a/scripts/generate-failed-pipeline-slack-message.rb b/scripts/generate-failed-pipeline-slack-message.rb index b695cdfdbee..eefdebd5db5 100755 --- a/scripts/generate-failed-pipeline-slack-message.rb +++ b/scripts/generate-failed-pipeline-slack-message.rb @@ -107,7 +107,7 @@ class GenerateFailedPipelineSlackMessage if incident_exist? incident['web_url'] else - "#{ENV['CI_SERVER_URL']}/#{ENV['BROKEN_MASTER_INCIDENTS_PROJECT']}/-/issues/new?" \ + "#{ENV['CI_SERVER_URL']}/#{ENV['BROKEN_BRANCH_INCIDENTS_PROJECT']}/-/issues/new?" \ "issuable_template=incident&issue%5Bissue_type%5D=incident" end end diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh index b08cf9ac832..98ad3112202 100755 --- a/scripts/review_apps/review-apps.sh +++ b/scripts/review_apps/review-apps.sh @@ -267,10 +267,10 @@ function deploy() { sentry_enabled="true" fi - ensure_namespace "${namespace}" - label_namespace "${namespace}" "tls=review-apps-tls" # label namespace for kubed to sync tls + retry "ensure_namespace \"${namespace}\"" + retry "label_namespace \"${namespace}\" \"tls=review-apps-tls\"" # label namespace for kubed to sync tls - create_application_secret + retry "create_application_secret" cat > review_apps.values.yml <<EOF gitlab: diff --git a/spec/factories/protected_tags/create_access_levels.rb b/spec/factories/protected_tags/create_access_levels.rb new file mode 100644 index 00000000000..07450b2789c --- /dev/null +++ b/spec/factories/protected_tags/create_access_levels.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :protected_tag_create_access_level, class: 'ProtectedTag::CreateAccessLevel' do + deploy_key { nil } + protected_tag + access_level { Gitlab::Access::DEVELOPER } + end +end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 4734a607ef1..40562d22a41 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -302,7 +302,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state, feature_category: :proj click_link 'Download' end - artifact_request = requests.find { |req| req.url.match(%r{artifacts/download}) } + artifact_request = requests.find { |req| req.url.include?('artifacts/download') } expect(artifact_request.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}}) expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary") diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js index aedf6bf2e2c..0c98ac794f7 100644 --- a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js +++ b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js @@ -7,6 +7,7 @@ import setWindowLocation from 'helpers/set_window_location_helper'; import { stubComponent } from 'helpers/stub_component'; import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import issueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_details.query.graphql'; +import { resolvers } from '~/graphql_shared/issuable_client'; import WidgetWrapper from '~/work_items/components/widget_wrapper.vue'; import WorkItemLinks from '~/work_items/components/work_item_links/work_item_links.vue'; import WorkItemLinkChild from '~/work_items/components/work_item_links/work_item_link_child.vue'; @@ -95,7 +96,7 @@ describe('WorkItemLinks', () => { [issueDetailsQuery, issueDetailsQueryHandler], [workItemByIidQuery, childWorkItemByIidHandler], ], - {}, + resolvers, { addTypename: true }, ); @@ -177,6 +178,24 @@ describe('WorkItemLinks', () => { expect(findAddLinksForm().exists()).toBe(false); }); + + it('adds work item child from the form', async () => { + const workItem = { + ...workItemQueryResponse.data.workItem, + id: 'gid://gitlab/WorkItem/11', + }; + await createComponent(); + findToggleFormDropdown().vm.$emit('click'); + findToggleCreateFormButton().vm.$emit('click'); + await nextTick(); + + expect(findWorkItemLinkChildItems()).toHaveLength(4); + + findAddLinksForm().vm.$emit('addWorkItemChild', workItem); + await waitForPromises(); + + expect(findWorkItemLinkChildItems()).toHaveLength(5); + }); }); describe('when no child links', () => { diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 4b5fde600a8..32746356803 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -386,6 +386,7 @@ create_access_levels: - user - protected_tag - group +- deploy_key container_repositories: - project - name diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 7e17d56def0..572f809e43b 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -18,7 +18,7 @@ RSpec.describe 'Import/Export attribute configuration' do it 'has no new columns' do relation_names_for(:project).each do |relation_name| relation_class = relation_class_for_name(relation_name) - relation_attributes = relation_class.new.attributes.keys - relation_class.encrypted_attributes.keys.map(&:to_s) + relation_attributes = relation_class.new.attributes.keys - relation_class.attr_encrypted_attributes.keys.map(&:to_s) current_attributes = parsed_attributes(relation_name, relation_attributes) safe_attributes = safe_model_attributes[relation_class.to_s].dup || [] diff --git a/spec/lib/gitlab/import_export/references_configuration_spec.rb b/spec/lib/gitlab/import_export/references_configuration_spec.rb index 6320fbed975..ad165790b77 100644 --- a/spec/lib/gitlab/import_export/references_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/references_configuration_spec.rb @@ -24,7 +24,7 @@ RSpec.describe 'Import/Export Project configuration' do context "where relation #{params[:relation_path]}" do it 'does not have prohibited keys' do relation_class = relation_class_for_name(relation_name) - relation_attributes = relation_class.new.attributes.keys - relation_class.encrypted_attributes.keys.map(&:to_s) + relation_attributes = relation_class.new.attributes.keys - relation_class.attr_encrypted_attributes.keys.map(&:to_s) current_attributes = parsed_attributes(relation_name, relation_attributes) prohibited_keys = current_attributes.select do |attribute| prohibited_key?(attribute) || !relation_class.attribute_method?(attribute) diff --git a/spec/models/concerns/sensitive_serializable_hash_spec.rb b/spec/models/concerns/sensitive_serializable_hash_spec.rb index 0bfd2d6a7de..7d646106061 100644 --- a/spec/models/concerns/sensitive_serializable_hash_spec.rb +++ b/spec/models/concerns/sensitive_serializable_hash_spec.rb @@ -46,8 +46,8 @@ RSpec.describe SensitiveSerializableHash do context "#{klass.name}\##{attribute_name}" do let(:attributes) { [attribute_name, "encrypted_#{attribute_name}", "encrypted_#{attribute_name}_iv"] } - it 'has a encrypted_attributes field' do - expect(klass.encrypted_attributes).to include(attribute_name.to_sym) + it 'has a attr_encrypted_attributes field' do + expect(klass.attr_encrypted_attributes).to include(attribute_name.to_sym) end it 'does not include the attribute in serializable_hash', :aggregate_failures do diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index a74da896cd8..337fa40b4ba 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -22,6 +22,7 @@ RSpec.describe DeployKey, :mailer do it { is_expected.to have_many(:projects) } it { is_expected.to have_many(:protected_branch_push_access_levels).inverse_of(:deploy_key) } + it { is_expected.to have_many(:protected_tag_create_access_levels).inverse_of(:deploy_key) } end describe 'notification' do diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index 600ec5fa936..4bfa3328037 100644 --- a/spec/models/hooks/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -258,7 +258,7 @@ RSpec.describe WebHook, feature_category: :integrations do end describe 'encrypted attributes' do - subject { described_class.encrypted_attributes.keys } + subject { described_class.attr_encrypted_attributes.keys } it { is_expected.to contain_exactly(:token, :url, :url_variables) } end diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb index 9b3250e3c08..7af96c7025a 100644 --- a/spec/models/integration_spec.rb +++ b/spec/models/integration_spec.rb @@ -1050,9 +1050,11 @@ RSpec.describe Integration do expect(hash['encrypted_properties']).not_to eq(record.encrypted_properties) expect(hash['encrypted_properties_iv']).not_to eq(record.encrypted_properties_iv) - decrypted = described_class.decrypt(:properties, - hash['encrypted_properties'], - { iv: hash['encrypted_properties_iv'] }) + decrypted = described_class.attr_decrypt( + :properties, + hash['encrypted_properties'], + { iv: hash['encrypted_properties_iv'] } + ) expect(decrypted).to eq db_props end diff --git a/spec/models/integrations/issue_tracker_data_spec.rb b/spec/models/integrations/issue_tracker_data_spec.rb index 233ed7b8475..285e41424c7 100644 --- a/spec/models/integrations/issue_tracker_data_spec.rb +++ b/spec/models/integrations/issue_tracker_data_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Integrations::IssueTrackerData do it_behaves_like Integrations::BaseDataFields describe 'encrypted attributes' do - subject { described_class.encrypted_attributes.keys } + subject { described_class.attr_encrypted_attributes.keys } it { is_expected.to contain_exactly(:issues_url, :new_issue_url, :project_url) } end diff --git a/spec/models/integrations/jira_tracker_data_spec.rb b/spec/models/integrations/jira_tracker_data_spec.rb index d9f91527fbb..68aa30f06ed 100644 --- a/spec/models/integrations/jira_tracker_data_spec.rb +++ b/spec/models/integrations/jira_tracker_data_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Integrations::JiraTrackerData do end describe 'encrypted attributes' do - subject { described_class.encrypted_attributes.keys } + subject { described_class.attr_encrypted_attributes.keys } it { is_expected.to contain_exactly(:api_url, :password, :url, :username) } end diff --git a/spec/models/integrations/zentao_tracker_data_spec.rb b/spec/models/integrations/zentao_tracker_data_spec.rb index dca5c4d79ae..38f2fb1b3f3 100644 --- a/spec/models/integrations/zentao_tracker_data_spec.rb +++ b/spec/models/integrations/zentao_tracker_data_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Integrations::ZentaoTrackerData do end describe 'encrypted attributes' do - subject { described_class.encrypted_attributes.keys } + subject { described_class.attr_encrypted_attributes.keys } it { is_expected.to contain_exactly(:url, :api_url, :zentao_product_xid, :api_token) } end diff --git a/spec/models/protected_tag/create_access_level_spec.rb b/spec/models/protected_tag/create_access_level_spec.rb new file mode 100644 index 00000000000..566f8695388 --- /dev/null +++ b/spec/models/protected_tag/create_access_level_spec.rb @@ -0,0 +1,144 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ProtectedTag::CreateAccessLevel, feature_category: :source_code_management do + describe 'associations' do + it { is_expected.to belong_to(:deploy_key) } + end + + describe 'validations', :aggregate_failures do + let_it_be(:protected_tag) { create(:protected_tag) } + + it 'verifies access levels' do + is_expected.to validate_inclusion_of(:access_level).in_array( + [ + Gitlab::Access::MAINTAINER, + Gitlab::Access::DEVELOPER, + Gitlab::Access::NO_ACCESS + ] + ) + end + + context 'when deploy key enabled for the project' do + let(:deploy_key) { create(:deploy_key, projects: [protected_tag.project]) } + + it 'is valid' do + level = build(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key) + + expect(level).to be_valid + end + end + + context 'when a record exists with the same access level' do + before do + create(:protected_tag_create_access_level, protected_tag: protected_tag) + end + + it 'is not valid' do + level = build(:protected_tag_create_access_level, protected_tag: protected_tag) + + expect(level).to be_invalid + expect(level.errors.full_messages).to include('Access level has already been taken') + end + end + + context 'when a deploy key already added for this access level' do + let!(:create_access_level) do + create(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key) + end + + let(:deploy_key) { create(:deploy_key, projects: [protected_tag.project]) } + + it 'is not valid' do + level = build(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key) + + expect(level).to be_invalid + expect(level.errors.full_messages).to contain_exactly('Deploy key has already been taken') + end + end + + context 'when deploy key is not enabled for the project' do + let(:create_access_level) do + build(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: create(:deploy_key)) + end + + it 'returns an error' do + expect(create_access_level).to be_invalid + expect(create_access_level.errors.full_messages).to contain_exactly( + 'Deploy key is not enabled for this project' + ) + end + end + end + + describe '#check_access' do + let_it_be(:project) { create(:project) } + let_it_be(:protected_tag) { create(:protected_tag, :no_one_can_create, project: project) } + let_it_be(:user) { create(:user) } + let_it_be(:deploy_key) { create(:deploy_key, user: user) } + + let!(:deploy_keys_project) do + create(:deploy_keys_project, project: project, deploy_key: deploy_key, can_push: can_push) + end + + let(:create_access_level) { protected_tag.create_access_levels.first } + let(:can_push) { true } + + before_all do + project.add_maintainer(user) + end + + it { expect(create_access_level.check_access(user)).to be_falsey } + + context 'when this create_access_level is tied to a deploy key' do + let(:create_access_level) do + create(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key) + end + + context 'when the deploy key is among the active keys for this project' do + it { expect(create_access_level.check_access(user)).to be_truthy } + end + + context 'when user is missing' do + it { expect(create_access_level.check_access(nil)).to be_falsey } + end + + context 'when deploy key does not belong to the user' do + let(:another_user) { create(:user) } + + it { expect(create_access_level.check_access(another_user)).to be_falsey } + end + + context 'when user cannot access the project' do + before do + allow(user).to receive(:can?).with(:read_project, project).and_return(false) + end + + it { expect(create_access_level.check_access(user)).to be_falsey } + end + + context 'when the deploy key is not among the active keys of this project' do + let(:can_push) { false } + + it { expect(create_access_level.check_access(user)).to be_falsey } + end + end + end + + describe '#type' do + let(:create_access_level) { build(:protected_tag_create_access_level) } + + it 'returns :role by default' do + expect(create_access_level.type).to eq(:role) + end + + context 'when a deploy key is tied to the protected branch' do + let(:create_access_level) { build(:protected_tag_create_access_level, deploy_key: build(:deploy_key)) } + + it 'returns :deploy_key' do + expect(create_access_level.type).to eq(:deploy_key) + end + end + end +end diff --git a/spec/scripts/api/commit_merge_requests_spec.rb b/spec/scripts/api/commit_merge_requests_spec.rb new file mode 100644 index 00000000000..461e3e2e068 --- /dev/null +++ b/spec/scripts/api/commit_merge_requests_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require_relative '../../../scripts/api/commit_merge_requests' + +RSpec.describe CommitMergeRequests, feature_category: :tooling do + describe '#execute' do + let(:options) do + { + sha: 'asdf1234', + api_token: 'token', + project: 12345, + endpoint: 'https://example.gitlab.com' + } + end + + subject { described_class.new(options).execute } + + it 'requests commit_merge_requests from the gitlab client' do + expected_result = ['results'] + client = double('Gitlab::Client', commit_merge_requests: expected_result) # rubocop:disable RSpec/VerifiedDoubles + + expect(Gitlab).to receive(:client) + .with(endpoint: options[:endpoint], private_token: options[:api_token]) + .and_return(client) + + expect(subject).to eq(expected_result) + end + end +end diff --git a/spec/scripts/create_pipeline_failure_incident_spec.rb b/spec/scripts/create_pipeline_failure_incident_spec.rb new file mode 100644 index 00000000000..8549cec1b12 --- /dev/null +++ b/spec/scripts/create_pipeline_failure_incident_spec.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require_relative '../../scripts/create-pipeline-failure-incident' +require_relative '../support/helpers/stub_env' + +RSpec.describe CreatePipelineFailureIncident, feature_category: :tooling do + include StubENV + + describe '#execute' do + let(:create_issue) { instance_double(CreateIssue) } + let(:issue) { double('Issue', iid: 1) } # rubocop:disable RSpec/VerifiedDoubles + let(:create_issue_discussion) { instance_double(CreateIssueDiscussion, execute: true) } + let(:failed_jobs) { instance_double(PipelineFailedJobs, execute: []) } + + let(:options) do + { + project: 1234, + api_token: 'asdf1234' + } + end + + let(:issue_params) do + { + issue_type: 'incident', + title: title, + description: description, + labels: incident_labels + } + end + + subject { described_class.new(options).execute } + + before do + stub_env( + 'CI_COMMIT_SHA' => 'bfcd2b9b5cad0b889494ce830697392c8ca11257', + 'CI_PROJECT_PATH' => 'gitlab.com/gitlab-org/gitlab', + 'CI_PROJECT_NAME' => 'gitlab', + 'GITLAB_USER_ID' => '1111', + 'CI_PROJECT_ID' => '13083', + 'CI_PIPELINE_ID' => '1234567', + 'CI_PIPELINE_URL' => 'https://gitlab.com/gitlab-org/gitlab/-/pipelines/1234567', + 'CI_PROJECT_URL' => 'https://gitlab.com/gitlab-org/gitlab', + 'CI_PIPELINE_CREATED_AT' => '2023-01-24 00:00:00', + 'CI_COMMIT_TITLE' => 'Commit title', + 'CI_PIPELINE_SOURCE' => 'push', + 'GITLAB_USER_NAME' => 'Foo User', + 'PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE' => 'asdf1234', + 'CI_SERVER_URL' => 'https://gitlab.com', + 'GITLAB_USER_LOGIN' => 'foo' + ) + end + + shared_examples 'creating an issue' do + it 'successfully creates an issue' do + allow(PipelineFailedJobs).to receive(:new) + .with(API::DEFAULT_OPTIONS.merge(exclude_allowed_to_fail_jobs: true)) + .and_return(failed_jobs) + + expect(CreateIssue).to receive(:new) + .with(project: options[:project], api_token: options[:api_token]) + .and_return(create_issue) + + expect(CreateIssueDiscussion).to receive(:new) + .with(project: options[:project], api_token: options[:api_token]) + .and_return(create_issue_discussion).twice + + expect(create_issue).to receive(:execute) + .with(issue_params).and_return(issue) + + expect(subject).to eq(issue) + end + end + + context 'when stable branch' do + let(:incident_labels) { ['release-blocker'] } + let(:title) { /broken `15-6-stable-ee`/ } + let(:description) { /A broken stable branch prevents patch releases/ } + + let(:commit_merge_request) do + { + 'author' => { + 'id' => '2' + }, + 'title' => 'foo', + 'web_url' => 'https://gitlab.com/test' + } + end + + let(:merge_request) { instance_double(CommitMergeRequests, execute: [commit_merge_request]) } + let(:issue_params) { super().merge(assignee_ids: [1111, 2]) } + + before do + stub_env( + 'CI_COMMIT_REF_NAME' => '15-6-stable-ee' + ) + + allow(CommitMergeRequests).to receive(:new) + .with(API::DEFAULT_OPTIONS.merge(sha: ENV['CI_COMMIT_SHA'])) + .and_return(merge_request) + end + + it_behaves_like 'creating an issue' + end + + context 'when other branch' do + let(:incident_labels) { ['Engineering Productivity', 'master-broken::undetermined', 'master:broken'] } + let(:title) { /broken `master`/ } + let(:description) { /Follow the \[Broken `master` handbook guide\]/ } + + before do + stub_env( + 'CI_COMMIT_REF_NAME' => 'master' + ) + end + + it_behaves_like 'creating an issue' + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7f2510c5ab9..2d3afb489df 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -44,7 +44,7 @@ rspec_profiling_is_configured = ENV['RSPEC_PROFILING'] branch_can_be_profiled = (ENV['CI_COMMIT_REF_NAME'] == 'master' || - ENV['CI_COMMIT_REF_NAME'] =~ /rspec-profile/) + ENV['CI_COMMIT_REF_NAME']&.include?('rspec-profile')) if rspec_profiling_is_configured && (!ENV.key?('CI') || branch_can_be_profiled) require 'rspec_profiling/rspec' @@ -105,7 +105,7 @@ RSpec.configure do |config| location = metadata[:location] metadata[:level] = quality_level.level_for(location) - metadata[:api] = true if location =~ %r{/spec/requests/api/} + metadata[:api] = true if location.include?('/spec/requests/api/') # Do not overwrite migration if it's already set unless metadata.key?(:migration) diff --git a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb index f085da26927..5382641742e 100644 --- a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb +++ b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb @@ -56,7 +56,8 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do end end - it 'generates Debian distribution and component files', :aggregate_failures do + it 'generates Debian distribution and component files', :aggregate_failures, + quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/389950' do current_time = Time.utc(2020, 01, 25, 15, 17, 18, 123456) travel_to(current_time) do diff --git a/vendor/gems/attr_encrypted/README.md b/vendor/gems/attr_encrypted/README.md index 1a332a2edd5..da0631bb18e 100644 --- a/vendor/gems/attr_encrypted/README.md +++ b/vendor/gems/attr_encrypted/README.md @@ -425,7 +425,7 @@ It is recommended that you implement a strategy to insure that you do not mix th attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: is_decrypting?(:ssn) def is_decrypting?(attribute) - encrypted_attributes[attribute][:operation] == :decrypting + attr_encrypted_attributes[attribute][:operation] == :decrypting end end diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted.rb index 88e5f65e3c8..82a14086ade 100644 --- a/vendor/gems/attr_encrypted/lib/attr_encrypted.rb +++ b/vendor/gems/attr_encrypted/lib/attr_encrypted.rb @@ -10,7 +10,7 @@ module AttrEncrypted base.class_eval do include InstanceMethods attr_writer :attr_encrypted_options - @attr_encrypted_options, @encrypted_attributes = {}, {} + @attr_encrypted_options, @attr_encrypted_attributes = {}, {} end end @@ -160,11 +160,11 @@ module AttrEncrypted end define_method(attribute) do - instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", decrypt(attribute, send(encrypted_attribute_name))) + instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", attr_decrypt(attribute, send(encrypted_attribute_name))) end define_method("#{attribute}=") do |value| - send("#{encrypted_attribute_name}=", encrypt(attribute, value)) + send("#{encrypted_attribute_name}=", attr_encrypt(attribute, value)) instance_variable_set("@#{attribute}", value) end @@ -173,7 +173,7 @@ module AttrEncrypted value.respond_to?(:empty?) ? !value.empty? : !!value end - encrypted_attributes[attribute.to_sym] = options.merge(attribute: encrypted_attribute_name) + attr_encrypted_attributes[attribute.to_sym] = options.merge(attribute: encrypted_attribute_name) end end @@ -223,7 +223,7 @@ module AttrEncrypted # User.attr_encrypted?(:name) # false # User.attr_encrypted?(:email) # true def attr_encrypted?(attribute) - encrypted_attributes.has_key?(attribute.to_sym) + attr_encrypted_attributes.has_key?(attribute.to_sym) end # Decrypts a value for the attribute specified @@ -234,9 +234,9 @@ module AttrEncrypted # attr_encrypted :email # end # - # email = User.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') - def decrypt(attribute, encrypted_value, options = {}) - options = encrypted_attributes[attribute.to_sym].merge(options) + # email = User.attr_decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') + def attr_decrypt(attribute, encrypted_value, options = {}) + options = attr_encrypted_attributes[attribute.to_sym].merge(options) if options[:if] && !options[:unless] && not_empty?(encrypted_value) encrypted_value = encrypted_value.unpack(options[:encode]).first if options[:encode] value = options[:encryptor].send(options[:decrypt_method], options.merge!(value: encrypted_value)) @@ -260,9 +260,9 @@ module AttrEncrypted # attr_encrypted :email # end # - # encrypted_email = User.encrypt(:email, 'test@example.com') - def encrypt(attribute, value, options = {}) - options = encrypted_attributes[attribute.to_sym].merge(options) + # encrypted_email = User.attr_encrypt(:email, 'test@example.com') + def attr_encrypt(attribute, value, options = {}) + options = attr_encrypted_attributes[attribute.to_sym].merge(options) if options[:if] && !options[:unless] && (options[:allow_empty_value] || not_empty?(value)) value = options[:marshal] ? options[:marshaler].send(options[:dump_method], value) : value.to_s encrypted_value = options[:encryptor].send(options[:encrypt_method], options.merge!(value: value)) @@ -286,9 +286,9 @@ module AttrEncrypted # attr_encrypted :email, key: 'my secret key' # end # - # User.encrypted_attributes # { email: { attribute: 'encrypted_email', key: 'my secret key' } } - def encrypted_attributes - @encrypted_attributes ||= superclass.encrypted_attributes.dup + # User.attr_encrypted_attributes # { email: { attribute: 'encrypted_email', key: 'my secret key' } } + def attr_encrypted_attributes + @attr_encrypted_attributes ||= superclass.attr_encrypted_attributes.dup end # Forwards calls to :encrypt_#{attribute} or :decrypt_#{attribute} to the corresponding encrypt or decrypt method @@ -303,7 +303,7 @@ module AttrEncrypted # User.encrypt_email('SOME_ENCRYPTED_EMAIL_STRING') def method_missing(method, *arguments, &block) if method.to_s =~ /^((en|de)crypt)_(.+)$/ && attr_encrypted?($3) - send($1, $3, *arguments) + send("attr_#{$1}", $3, *arguments) else super end @@ -324,11 +324,11 @@ module AttrEncrypted # end # # @user = User.new('some-secret-key') - # @user.decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') - def decrypt(attribute, encrypted_value) - encrypted_attributes[attribute.to_sym][:operation] = :decrypting - encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(encrypted_value) - self.class.decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute)) + # @user.attr_decrypt(:email, 'SOME_ENCRYPTED_EMAIL_STRING') + def attr_decrypt(attribute, encrypted_value) + attr_encrypted_attributes[attribute.to_sym][:operation] = :decrypting + attr_encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(encrypted_value) + self.class.attr_decrypt(attribute, encrypted_value, evaluated_attr_encrypted_options_for(attribute)) end # Encrypts a value for the attribute specified using options evaluated in the current object's scope @@ -345,20 +345,20 @@ module AttrEncrypted # end # # @user = User.new('some-secret-key') - # @user.encrypt(:email, 'test@example.com') - def encrypt(attribute, value) - encrypted_attributes[attribute.to_sym][:operation] = :encrypting - encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(value) - self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute)) + # @user.attr_encrypt(:email, 'test@example.com') + def attr_encrypt(attribute, value) + attr_encrypted_attributes[attribute.to_sym][:operation] = :encrypting + attr_encrypted_attributes[attribute.to_sym][:value_present] = self.class.not_empty?(value) + self.class.attr_encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute)) end # Copies the class level hash of encrypted attributes with virtual attribute names as keys # and their corresponding options as values to the instance # - def encrypted_attributes - @encrypted_attributes ||= begin + def attr_encrypted_attributes + @attr_encrypted_attributes ||= begin duplicated= {} - self.class.encrypted_attributes.map { |key, value| duplicated[key] = value.dup } + self.class.attr_encrypted_attributes.map { |key, value| duplicated[key] = value.dup } duplicated end end @@ -368,7 +368,7 @@ module AttrEncrypted # Returns attr_encrypted options evaluated in the current object's scope for the attribute specified def evaluated_attr_encrypted_options_for(attribute) evaluated_options = Hash.new - attributes = encrypted_attributes[attribute.to_sym] + attributes = attr_encrypted_attributes[attribute.to_sym] attribute_option_value = attributes[:attribute] [:if, :unless, :value_present, :allow_empty_value].each do |option| diff --git a/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb index ec8d0208e92..f3c71611b13 100644 --- a/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb +++ b/vendor/gems/attr_encrypted/lib/attr_encrypted/adapters/active_record.rb @@ -11,7 +11,7 @@ if defined?(ActiveRecord::Base) alias_method :reload_without_attr_encrypted, :reload def reload(*args, &block) result = reload_without_attr_encrypted(*args, &block) - self.class.encrypted_attributes.keys.each do |attribute_name| + self.class.attr_encrypted_attributes.keys.each do |attribute_name| instance_variable_set("@#{attribute_name}", nil) end result @@ -27,8 +27,8 @@ if defined?(ActiveRecord::Base) def perform_attribute_assignment(method, new_attributes, *args) return if new_attributes.blank? - send method, new_attributes.reject { |k, _| self.class.encrypted_attributes.key?(k.to_sym) }, *args - send method, new_attributes.reject { |k, _| !self.class.encrypted_attributes.key?(k.to_sym) }, *args + send method, new_attributes.reject { |k, _| self.class.attr_encrypted_attributes.key?(k.to_sym) }, *args + send method, new_attributes.reject { |k, _| !self.class.attr_encrypted_attributes.key?(k.to_sym) }, *args end private :perform_attribute_assignment @@ -54,7 +54,7 @@ if defined?(ActiveRecord::Base) options = attrs.extract_options! attr = attrs.pop attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0" - options.merge! encrypted_attributes[attr] + options.merge! attr_encrypted_attributes[attr] define_method("#{attr}_was") do attribute_was(attr) @@ -125,10 +125,10 @@ if defined?(ActiveRecord::Base) if match = /^(find|scoped)_(all_by|by)_([_a-zA-Z]\w*)$/.match(method.to_s) attribute_names = match.captures.last.split('_and_') attribute_names.each_with_index do |attribute, index| - if attr_encrypted?(attribute) && encrypted_attributes[attribute.to_sym][:mode] == :single_iv_and_salt + if attr_encrypted?(attribute) && attr_encrypted_attributes[attribute.to_sym][:mode] == :single_iv_and_salt args[index] = send("encrypt_#{attribute}", args[index]) warn "DEPRECATION WARNING: This feature will be removed in the next major release." - attribute_names[index] = encrypted_attributes[attribute.to_sym][:attribute] + attribute_names[index] = attr_encrypted_attributes[attribute.to_sym][:attribute] end end method = "#{match.captures[0]}_#{match.captures[1]}_#{attribute_names.join('_and_')}".to_sym diff --git a/vendor/gems/attr_encrypted/test/active_record_test.rb b/vendor/gems/attr_encrypted/test/active_record_test.rb index 4c903bc3cd8..44705989663 100644 --- a/vendor/gems/attr_encrypted/test/active_record_test.rb +++ b/vendor/gems/attr_encrypted/test/active_record_test.rb @@ -89,7 +89,7 @@ class Account < ActiveRecord::Base attr_encrypted :password, key: :password_encryption_key def encrypting?(attr) - encrypted_attributes[attr][:operation] == :encrypting + attr_encrypted_attributes[attr][:operation] == :encrypting end def password_encryption_key @@ -289,14 +289,14 @@ class ActiveRecordTest < Minitest::Test @person = PersonWithProcMode.create(email: 'test@example.com', credentials: 'password123') # Email is :per_attribute_iv_and_salt - assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc - assert_equal @person.class.encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt + assert_equal @person.class.attr_encrypted_attributes[:email][:mode].class, Proc + assert_equal @person.class.attr_encrypted_attributes[:email][:mode].call, :per_attribute_iv_and_salt refute_nil @person.encrypted_email_salt refute_nil @person.encrypted_email_iv # Credentials is :single_iv_and_salt - assert_equal @person.class.encrypted_attributes[:credentials][:mode].class, Proc - assert_equal @person.class.encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt + assert_equal @person.class.attr_encrypted_attributes[:credentials][:mode].class, Proc + assert_equal @person.class.attr_encrypted_attributes[:credentials][:mode].call, :single_iv_and_salt assert_nil @person.encrypted_credentials_salt assert_nil @person.encrypted_credentials_iv end diff --git a/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb b/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb index 84cb130aa50..a57bd773b92 100644 --- a/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb +++ b/vendor/gems/attr_encrypted/test/attr_encrypted_test.rb @@ -82,12 +82,12 @@ class AttrEncryptedTest < Minitest::Test @iv = SecureRandom.random_bytes(12) end - def test_should_store_email_in_encrypted_attributes - assert User.encrypted_attributes.include?(:email) + def test_should_store_email_in_attr_encrypted_attributes + assert User.attr_encrypted_attributes.include?(:email) end - def test_should_not_store_salt_in_encrypted_attributes - refute User.encrypted_attributes.include?(:salt) + def test_should_not_store_salt_in_attr_encrypted_attributes + refute User.attr_encrypted_attributes.include?(:salt) end def test_attr_encrypted_should_return_true_for_email @@ -95,7 +95,7 @@ class AttrEncryptedTest < Minitest::Test end def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line - refute_equal User.encrypted_attributes[:email][:attribute], User.encrypted_attributes[:without_encoding][:attribute] + refute_equal User.attr_encrypted_attributes[:email][:attribute], User.attr_encrypted_attributes[:without_encoding][:attribute] end def test_attr_encrypted_should_return_false_for_salt @@ -154,7 +154,7 @@ class AttrEncryptedTest < Minitest::Test def test_should_decrypt_email_when_reading @user = User.new assert_nil @user.email - options = @user.encrypted_attributes[:email] + options = @user.attr_encrypted_attributes[:email] iv = @user.send(:generate_iv, options[:algorithm]) encoded_iv = [iv].pack(options[:encode_iv]) salt = SecureRandom.random_bytes @@ -222,8 +222,8 @@ class AttrEncryptedTest < Minitest::Test assert_equal encrypted, @user.crypted_password_test end - def test_should_inherit_encrypted_attributes - assert_equal [User.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.encrypted_attributes.keys.collect { |key| key.to_s }.sort + def test_should_inherit_attr_encrypted_attributes + assert_equal [User.attr_encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.attr_encrypted_attributes.keys.collect { |key| key.to_s }.sort end def test_should_inherit_attr_encrypted_options @@ -233,7 +233,7 @@ class AttrEncryptedTest < Minitest::Test def test_should_not_inherit_unrelated_attributes assert SomeOtherClass.attr_encrypted_options.empty? - assert SomeOtherClass.encrypted_attributes.empty? + assert SomeOtherClass.attr_encrypted_attributes.empty? end def test_should_evaluate_a_symbol_option @@ -304,7 +304,7 @@ class AttrEncryptedTest < Minitest::Test end def test_should_work_with_aliased_attr_encryptor - assert User.encrypted_attributes.include?(:aliased) + assert User.attr_encrypted_attributes.include?(:aliased) end def test_should_always_reset_options @@ -381,12 +381,12 @@ class AttrEncryptedTest < Minitest::Test @user2 = User.new @user2.email = 'test@example.com' - assert_equal 'test@example.com', @user1.decrypt(:email, @user1.encrypted_email) + assert_equal 'test@example.com', @user1.attr_decrypt(:email, @user1.encrypted_email) end def test_should_specify_the_default_algorithm - assert YetAnotherClass.encrypted_attributes[:email][:algorithm] - assert_equal YetAnotherClass.encrypted_attributes[:email][:algorithm], 'aes-256-gcm' + assert YetAnotherClass.attr_encrypted_attributes[:email][:algorithm] + assert_equal YetAnotherClass.attr_encrypted_attributes[:email][:algorithm], 'aes-256-gcm' end def test_should_not_encode_iv_when_encode_iv_is_false @@ -475,8 +475,8 @@ class AttrEncryptedTest < Minitest::Test another_user = User.new - assert_equal :encrypting, user.encrypted_attributes[:ssn][:operation] - assert_nil another_user.encrypted_attributes[:ssn][:operation] + assert_equal :encrypting, user.attr_encrypted_attributes[:ssn][:operation] + assert_nil another_user.attr_encrypted_attributes[:ssn][:operation] end def test_should_not_by_default_generate_key_when_attribute_is_empty diff --git a/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb b/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb index 875086d2351..608a81970bb 100644 --- a/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb +++ b/vendor/gems/attr_encrypted/test/legacy_attr_encrypted_test.rb @@ -57,12 +57,12 @@ end class LegacyAttrEncryptedTest < Minitest::Test - def test_should_store_email_in_encrypted_attributes - assert LegacyUser.encrypted_attributes.include?(:email) + def test_should_store_email_in_attr_encrypted_attributes + assert LegacyUser.attr_encrypted_attributes.include?(:email) end - def test_should_not_store_salt_in_encrypted_attributes - assert !LegacyUser.encrypted_attributes.include?(:salt) + def test_should_not_store_salt_in_attr_encrypted_attributes + assert !LegacyUser.attr_encrypted_attributes.include?(:salt) end def test_attr_encrypted_should_return_true_for_email @@ -70,7 +70,7 @@ class LegacyAttrEncryptedTest < Minitest::Test end def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line - refute_equal LegacyUser.encrypted_attributes[:email][:attribute], LegacyUser.encrypted_attributes[:without_encoding][:attribute] + refute_equal LegacyUser.attr_encrypted_attributes[:email][:attribute], LegacyUser.attr_encrypted_attributes[:without_encoding][:attribute] end def test_attr_encrypted_should_return_false_for_salt @@ -200,8 +200,8 @@ class LegacyAttrEncryptedTest < Minitest::Test assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.crypted_password_test end - def test_should_inherit_encrypted_attributes - assert_equal [LegacyUser.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, LegacyAdmin.encrypted_attributes.keys.collect { |key| key.to_s }.sort + def test_should_inherit_attr_encrypted_attributes + assert_equal [LegacyUser.attr_encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, LegacyAdmin.attr_encrypted_attributes.keys.collect { |key| key.to_s }.sort end def test_should_inherit_attr_encrypted_options @@ -211,7 +211,7 @@ class LegacyAttrEncryptedTest < Minitest::Test def test_should_not_inherit_unrelated_attributes assert LegacySomeOtherClass.attr_encrypted_options.empty? - assert LegacySomeOtherClass.encrypted_attributes.empty? + assert LegacySomeOtherClass.attr_encrypted_attributes.empty? end def test_should_evaluate_a_symbol_option @@ -268,7 +268,7 @@ class LegacyAttrEncryptedTest < Minitest::Test end def test_should_work_with_aliased_attr_encryptor - assert LegacyUser.encrypted_attributes.include?(:aliased) + assert LegacyUser.attr_encrypted_attributes.include?(:aliased) end def test_should_always_reset_options |