Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									d6348d22dd
								
							
						
					
					
						commit
						d081e00aa7
					
				|  | @ -4,15 +4,13 @@ import { GlIcon } from '@gitlab/ui'; | ||||||
| import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils'; | import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils'; | ||||||
| import DiffGutterAvatars from './diff_gutter_avatars.vue'; | import DiffGutterAvatars from './diff_gutter_avatars.vue'; | ||||||
| import { | import { | ||||||
|   MATCH_LINE_TYPE, |  | ||||||
|   CONTEXT_LINE_TYPE, |   CONTEXT_LINE_TYPE, | ||||||
|   LINE_POSITION_RIGHT, |   LINE_POSITION_RIGHT, | ||||||
|   EMPTY_CELL_TYPE, |   EMPTY_CELL_TYPE, | ||||||
|   OLD_LINE_TYPE, |  | ||||||
|   OLD_NO_NEW_LINE_TYPE, |   OLD_NO_NEW_LINE_TYPE, | ||||||
|  |   OLD_LINE_TYPE, | ||||||
|   NEW_NO_NEW_LINE_TYPE, |   NEW_NO_NEW_LINE_TYPE, | ||||||
|   LINE_HOVER_CLASS_NAME, |   LINE_HOVER_CLASS_NAME, | ||||||
|   LINE_UNFOLD_CLASS_NAME, |  | ||||||
| } from '../constants'; | } from '../constants'; | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|  | @ -29,10 +27,6 @@ export default { | ||||||
|       type: String, |       type: String, | ||||||
|       required: true, |       required: true, | ||||||
|     }, |     }, | ||||||
|     contextLinesPath: { |  | ||||||
|       type: String, |  | ||||||
|       required: true, |  | ||||||
|     }, |  | ||||||
|     isHighlighted: { |     isHighlighted: { | ||||||
|       type: Boolean, |       type: Boolean, | ||||||
|       required: true, |       required: true, | ||||||
|  | @ -52,11 +46,6 @@ export default { | ||||||
|       required: false, |       required: false, | ||||||
|       default: '', |       default: '', | ||||||
|     }, |     }, | ||||||
|     isContentLine: { |  | ||||||
|       type: Boolean, |  | ||||||
|       required: false, |  | ||||||
|       default: false, |  | ||||||
|     }, |  | ||||||
|     isBottom: { |     isBottom: { | ||||||
|       type: Boolean, |       type: Boolean, | ||||||
|       required: false, |       required: false, | ||||||
|  | @ -68,6 +57,11 @@ export default { | ||||||
|       default: false, |       default: false, | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       isCommentButtonRendered: false, | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|   computed: { |   computed: { | ||||||
|     ...mapGetters(['isLoggedIn']), |     ...mapGetters(['isLoggedIn']), | ||||||
|     lineCode() { |     lineCode() { | ||||||
|  | @ -81,13 +75,7 @@ export default { | ||||||
|       return `#${this.line.line_code || ''}`; |       return `#${this.line.line_code || ''}`; | ||||||
|     }, |     }, | ||||||
|     shouldShowCommentButton() { |     shouldShowCommentButton() { | ||||||
|       return ( |       return this.isHover && !this.isContextLine && !this.isMetaLine && !this.hasDiscussions; | ||||||
|         this.isHover && |  | ||||||
|         !this.isMatchLine && |  | ||||||
|         !this.isContextLine && |  | ||||||
|         !this.isMetaLine && |  | ||||||
|         !this.hasDiscussions |  | ||||||
|       ); |  | ||||||
|     }, |     }, | ||||||
|     hasDiscussions() { |     hasDiscussions() { | ||||||
|       return this.line.discussions && this.line.discussions.length > 0; |       return this.line.discussions && this.line.discussions.length > 0; | ||||||
|  | @ -99,6 +87,10 @@ export default { | ||||||
|       return this.showCommentButton && this.hasDiscussions; |       return this.showCommentButton && this.hasDiscussions; | ||||||
|     }, |     }, | ||||||
|     shouldRenderCommentButton() { |     shouldRenderCommentButton() { | ||||||
|  |       if (!this.isCommentButtonRendered) { | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|       if (this.isLoggedIn && this.showCommentButton) { |       if (this.isLoggedIn && this.showCommentButton) { | ||||||
|         const isDiffHead = parseBoolean(getParameterByName('diff_head')); |         const isDiffHead = parseBoolean(getParameterByName('diff_head')); | ||||||
|         return !isDiffHead || gon.features?.mergeRefHeadComments; |         return !isDiffHead || gon.features?.mergeRefHeadComments; | ||||||
|  | @ -106,9 +98,6 @@ export default { | ||||||
| 
 | 
 | ||||||
|       return false; |       return false; | ||||||
|     }, |     }, | ||||||
|     isMatchLine() { |  | ||||||
|       return this.line.type === MATCH_LINE_TYPE; |  | ||||||
|     }, |  | ||||||
|     isContextLine() { |     isContextLine() { | ||||||
|       return this.line.type === CONTEXT_LINE_TYPE; |       return this.line.type === CONTEXT_LINE_TYPE; | ||||||
|     }, |     }, | ||||||
|  | @ -126,13 +115,8 @@ export default { | ||||||
|         type, |         type, | ||||||
|         { |         { | ||||||
|           hll: this.isHighlighted, |           hll: this.isHighlighted, | ||||||
|           [LINE_UNFOLD_CLASS_NAME]: this.isMatchLine, |  | ||||||
|           [LINE_HOVER_CLASS_NAME]: |           [LINE_HOVER_CLASS_NAME]: | ||||||
|             this.isLoggedIn && |             this.isLoggedIn && this.isHover && !this.isContextLine && !this.isMetaLine, | ||||||
|             this.isHover && |  | ||||||
|             !this.isMatchLine && |  | ||||||
|             !this.isContextLine && |  | ||||||
|             !this.isMetaLine, |  | ||||||
|         }, |         }, | ||||||
|       ]; |       ]; | ||||||
|     }, |     }, | ||||||
|  | @ -140,6 +124,17 @@ export default { | ||||||
|       return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line; |       return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line; | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |   mounted() { | ||||||
|  |     this.unwatchShouldShowCommentButton = this.$watch('shouldShowCommentButton', newVal => { | ||||||
|  |       if (newVal) { | ||||||
|  |         this.isCommentButtonRendered = true; | ||||||
|  |         this.unwatchShouldShowCommentButton(); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }, | ||||||
|  |   beforeDestroy() { | ||||||
|  |     this.unwatchShouldShowCommentButton(); | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     ...mapActions('diffs', ['showCommentForm', 'setHighlightedRow', 'toggleLineDiscussions']), |     ...mapActions('diffs', ['showCommentForm', 'setHighlightedRow', 'toggleLineDiscussions']), | ||||||
|     handleCommentButton() { |     handleCommentButton() { | ||||||
|  | @ -151,34 +146,32 @@ export default { | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <td ref="td" :class="classNameMap"> |   <td ref="td" :class="classNameMap"> | ||||||
|     <div> |     <button | ||||||
|       <button |       v-if="shouldRenderCommentButton" | ||||||
|         v-if="shouldRenderCommentButton" |       v-show="shouldShowCommentButton" | ||||||
|         v-show="shouldShowCommentButton" |       ref="addDiffNoteButton" | ||||||
|         ref="addDiffNoteButton" |       type="button" | ||||||
|         type="button" |       class="add-diff-note js-add-diff-note-button qa-diff-comment" | ||||||
|         class="add-diff-note js-add-diff-note-button qa-diff-comment" |       title="Add a comment to this line" | ||||||
|         title="Add a comment to this line" |       @click="handleCommentButton" | ||||||
|         @click="handleCommentButton" |     > | ||||||
|       > |       <gl-icon :size="12" name="comment" /> | ||||||
|         <gl-icon :size="12" name="comment" /> |     </button> | ||||||
|       </button> |     <a | ||||||
|       <a |       v-if="lineNumber" | ||||||
|         v-if="lineNumber" |       ref="lineNumberRef" | ||||||
|         ref="lineNumberRef" |       :data-linenumber="lineNumber" | ||||||
|         :data-linenumber="lineNumber" |       :href="lineHref" | ||||||
|         :href="lineHref" |       @click="setHighlightedRow(lineCode)" | ||||||
|         @click="setHighlightedRow(lineCode)" |     > | ||||||
|       > |     </a> | ||||||
|       </a> |     <diff-gutter-avatars | ||||||
|       <diff-gutter-avatars |       v-if="shouldShowAvatarsOnGutter" | ||||||
|         v-if="shouldShowAvatarsOnGutter" |       :discussions="line.discussions" | ||||||
|         :discussions="line.discussions" |       :discussions-expanded="line.discussionsExpanded" | ||||||
|         :discussions-expanded="line.discussionsExpanded" |       @toggleLineDiscussions=" | ||||||
|         @toggleLineDiscussions=" |         toggleLineDiscussions({ lineCode, fileHash, expanded: !line.discussionsExpanded }) | ||||||
|           toggleLineDiscussions({ lineCode, fileHash, expanded: !line.discussionsExpanded }) |       " | ||||||
|         " |     /> | ||||||
|       /> |  | ||||||
|     </div> |  | ||||||
|   </td> |   </td> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -28,10 +28,6 @@ export default { | ||||||
|       type: String, |       type: String, | ||||||
|       required: true, |       required: true, | ||||||
|     }, |     }, | ||||||
|     contextLinesPath: { |  | ||||||
|       type: String, |  | ||||||
|       required: true, |  | ||||||
|     }, |  | ||||||
|     line: { |     line: { | ||||||
|       type: Object, |       type: Object, | ||||||
|       required: true, |       required: true, | ||||||
|  | @ -106,7 +102,6 @@ export default { | ||||||
|   > |   > | ||||||
|     <diff-table-cell |     <diff-table-cell | ||||||
|       :file-hash="fileHash" |       :file-hash="fileHash" | ||||||
|       :context-lines-path="contextLinesPath" |  | ||||||
|       :line="line" |       :line="line" | ||||||
|       :line-type="oldLineType" |       :line-type="oldLineType" | ||||||
|       :is-bottom="isBottom" |       :is-bottom="isBottom" | ||||||
|  | @ -117,7 +112,6 @@ export default { | ||||||
|     /> |     /> | ||||||
|     <diff-table-cell |     <diff-table-cell | ||||||
|       :file-hash="fileHash" |       :file-hash="fileHash" | ||||||
|       :context-lines-path="contextLinesPath" |  | ||||||
|       :line="line" |       :line="line" | ||||||
|       :line-type="newLineType" |       :line-type="newLineType" | ||||||
|       :is-bottom="isBottom" |       :is-bottom="isBottom" | ||||||
|  |  | ||||||
|  | @ -65,7 +65,6 @@ export default { | ||||||
|           :key="`${line.line_code || index}`" |           :key="`${line.line_code || index}`" | ||||||
|           :file-hash="diffFile.file_hash" |           :file-hash="diffFile.file_hash" | ||||||
|           :file-path="diffFile.file_path" |           :file-path="diffFile.file_path" | ||||||
|           :context-lines-path="diffFile.context_lines_path" |  | ||||||
|           :line="line" |           :line="line" | ||||||
|           :is-bottom="index + 1 === diffLinesLength" |           :is-bottom="index + 1 === diffLinesLength" | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|  | @ -31,10 +31,6 @@ export default { | ||||||
|       type: String, |       type: String, | ||||||
|       required: true, |       required: true, | ||||||
|     }, |     }, | ||||||
|     contextLinesPath: { |  | ||||||
|       type: String, |  | ||||||
|       required: true, |  | ||||||
|     }, |  | ||||||
|     line: { |     line: { | ||||||
|       type: Object, |       type: Object, | ||||||
|       required: true, |       required: true, | ||||||
|  | @ -144,7 +140,6 @@ export default { | ||||||
|     <template v-if="line.left && !isMatchLineLeft"> |     <template v-if="line.left && !isMatchLineLeft"> | ||||||
|       <diff-table-cell |       <diff-table-cell | ||||||
|         :file-hash="fileHash" |         :file-hash="fileHash" | ||||||
|         :context-lines-path="contextLinesPath" |  | ||||||
|         :line="line.left" |         :line="line.left" | ||||||
|         :line-type="oldLineType" |         :line-type="oldLineType" | ||||||
|         :is-bottom="isBottom" |         :is-bottom="isBottom" | ||||||
|  | @ -172,7 +167,6 @@ export default { | ||||||
|     <template v-if="line.right && !isMatchLineRight"> |     <template v-if="line.right && !isMatchLineRight"> | ||||||
|       <diff-table-cell |       <diff-table-cell | ||||||
|         :file-hash="fileHash" |         :file-hash="fileHash" | ||||||
|         :context-lines-path="contextLinesPath" |  | ||||||
|         :line="line.right" |         :line="line.right" | ||||||
|         :line-type="newLineType" |         :line-type="newLineType" | ||||||
|         :is-bottom="isBottom" |         :is-bottom="isBottom" | ||||||
|  |  | ||||||
|  | @ -67,7 +67,6 @@ export default { | ||||||
|           :key="line.line_code" |           :key="line.line_code" | ||||||
|           :file-hash="diffFile.file_hash" |           :file-hash="diffFile.file_hash" | ||||||
|           :file-path="diffFile.file_path" |           :file-path="diffFile.file_path" | ||||||
|           :context-lines-path="diffFile.context_lines_path" |  | ||||||
|           :line="line" |           :line="line" | ||||||
|           :is-bottom="index + 1 === diffLinesLength" |           :is-bottom="index + 1 === diffLinesLength" | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ module ReactiveCaching | ||||||
|     self.reactive_cache_lease_timeout = 2.minutes |     self.reactive_cache_lease_timeout = 2.minutes | ||||||
|     self.reactive_cache_refresh_interval = 1.minute |     self.reactive_cache_refresh_interval = 1.minute | ||||||
|     self.reactive_cache_lifetime = 10.minutes |     self.reactive_cache_lifetime = 10.minutes | ||||||
|     self.reactive_cache_hard_limit = 1.megabyte |     self.reactive_cache_hard_limit = nil # this value should be set in megabytes. E.g: 1.megabyte | ||||||
|     self.reactive_cache_work_type = :default |     self.reactive_cache_work_type = :default | ||||||
|     self.reactive_cache_worker_finder = ->(id, *_args) do |     self.reactive_cache_worker_finder = ->(id, *_args) do | ||||||
|       find_by(primary_key => id) |       find_by(primary_key => id) | ||||||
|  | @ -159,8 +159,12 @@ module ReactiveCaching | ||||||
|       WORK_TYPE.fetch(self.class.reactive_cache_work_type.to_sym) |       WORK_TYPE.fetch(self.class.reactive_cache_work_type.to_sym) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     def reactive_cache_limit_enabled? | ||||||
|  |       !!self.reactive_cache_hard_limit | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     def check_exceeded_reactive_cache_limit!(data) |     def check_exceeded_reactive_cache_limit!(data) | ||||||
|       return unless Feature.enabled?(:reactive_cache_limit) |       return unless reactive_cache_limit_enabled? | ||||||
| 
 | 
 | ||||||
|       data_deep_size = Gitlab::Utils::DeepSize.new(data, max_size: self.class.reactive_cache_hard_limit) |       data_deep_size = Gitlab::Utils::DeepSize.new(data, max_size: self.class.reactive_cache_hard_limit) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -362,6 +362,11 @@ class Environment < ApplicationRecord | ||||||
|   def generate_slug |   def generate_slug | ||||||
|     self.slug = Gitlab::Slug::Environment.new(name).generate |     self.slug = Gitlab::Slug::Environment.new(name).generate | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   # Overrides ReactiveCaching default to activate limit checking behind a FF | ||||||
|  |   def reactive_cache_limit_enabled? | ||||||
|  |     Feature.enabled?(:reactive_caching_limit_environment, project) | ||||||
|  |   end | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| Environment.prepend_if_ee('EE::Environment') | Environment.prepend_if_ee('EE::Environment') | ||||||
|  |  | ||||||
|  | @ -26,7 +26,6 @@ class MergeRequest < ApplicationRecord | ||||||
|   self.reactive_cache_key = ->(model) { [model.project.id, model.iid] } |   self.reactive_cache_key = ->(model) { [model.project.id, model.iid] } | ||||||
|   self.reactive_cache_refresh_interval = 10.minutes |   self.reactive_cache_refresh_interval = 10.minutes | ||||||
|   self.reactive_cache_lifetime = 10.minutes |   self.reactive_cache_lifetime = 10.minutes | ||||||
|   self.reactive_cache_hard_limit = 20.megabytes |  | ||||||
| 
 | 
 | ||||||
|   SORTING_PREFERENCE_FIELD = :merge_requests_sort |   SORTING_PREFERENCE_FIELD = :merge_requests_sort | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | --- | ||||||
|  | title: Updated the Android CI Script | ||||||
|  | merge_request: 34007 | ||||||
|  | author: s-ayush2903 | ||||||
|  | type: fixed | ||||||
|  | @ -1,13 +1,5 @@ | ||||||
| # WARNING: If you add a new secret to this file, make sure you also | # WARNING: Before you make a change to secrets.yml, read the development guide for GitLab secrets | ||||||
| # update Omnibus GitLab or updates will fail. Omnibus is responsible for | # doc/development/application_secrets.md. | ||||||
| # writing the `secrets.yml` file.  If Omnibus doesn't know about a |  | ||||||
| # secret, Rails will attempt to write to the file, but this will fail |  | ||||||
| # because Rails doesn't have write access. |  | ||||||
| # |  | ||||||
| # As an example: |  | ||||||
| # * https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27581 |  | ||||||
| # * https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3267 |  | ||||||
| # |  | ||||||
| # | # | ||||||
| # This file needs to be loaded BEFORE any initializers that attempt to | # This file needs to be loaded BEFORE any initializers that attempt to | ||||||
| # prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb). | # prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb). | ||||||
|  |  | ||||||
|  | @ -0,0 +1,41 @@ | ||||||
|  | # Application secrets | ||||||
|  | 
 | ||||||
|  | This page is a development guide for application secrets. | ||||||
|  | 
 | ||||||
|  | ## Secret entries | ||||||
|  | 
 | ||||||
|  | |Entry                             |Description                                                        | | ||||||
|  | |---                               |---                                                                | | ||||||
|  | |`secret_key_base`                 | The base key to be used for generating a various secrets          | | ||||||
|  | | `otp_key_base`                   | The base key for One Time Passwords, described in [User management](../raketasks/user_management.md#rotate-two-factor-authentication-encryption-key)              | | ||||||
|  | |`db_key_base`                     | The base key to encrypt the data for `attr_encrypted` columns     | | ||||||
|  | |`openid_connect_signing_key`      | The singing key for OpenID Connect                                | | ||||||
|  | 
 | ||||||
|  | ## Where the secrets are stored | ||||||
|  | 
 | ||||||
|  | |Installation type                  |Location                                                          | | ||||||
|  | |---                                |---                                                               | | ||||||
|  | |Omnibus                            |[`/etc/gitlab/gitlab-secrets.json`](https://docs.gitlab.com/omnibus/settings/backups.html#backup-and-restore-omnibus-gitlab-configuration)                                 | | ||||||
|  | |Cloud Native GitLab Charts         |[Kubernets Secrets](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/f65c3d37fc8cf09a7987544680413552fb666aac/doc/installation/secrets.md#gitlab-rails-secret)| | ||||||
|  | |Source                             |`<path-to-gitlab-rails>/config/secrets.yml` (Automatically generated by [01_secret_token.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/01_secret_token.rb))                       | | ||||||
|  | 
 | ||||||
|  | ## Warning: Before you add a new secret to application secrets | ||||||
|  | 
 | ||||||
|  | Before you add a new secret to [`config/initializers/01_secret_token.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/initializers/01_secret_token.rb), | ||||||
|  | make sure you also update Omnibus GitLab or updates will fail. Omnibus is responsible for writing the `secrets.yml` file. | ||||||
|  | If Omnibus doesn't know about a secret, Rails will attempt to write to the file, but this will fail because Rails doesn't have write access. | ||||||
|  | The same rules apply to Cloud Native GitLab charts, you must update the charts at first. | ||||||
|  | In case you need the secret to have same value on each node (which is usually the case) you need to make sure it's configured for all | ||||||
|  | GitLab.com environments prior to changing this file. | ||||||
|  | 
 | ||||||
|  | **Examples** | ||||||
|  | 
 | ||||||
|  | - [Change for source installation](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27581) | ||||||
|  | - [Change for omnibus installation](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3267) | ||||||
|  | - [Change for omnibus installation](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4158) | ||||||
|  | - [Change for Cloud Native installation](https://gitlab.com/gitlab-org/charts/gitlab/-/merge_requests/1318) | ||||||
|  | 
 | ||||||
|  | ## Further iteration | ||||||
|  | 
 | ||||||
|  | We might deprecate/remove this automatic secret generation '01_secret_token.rb' in the future. | ||||||
|  | Please see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/222690) for more information. | ||||||
|  | @ -35,6 +35,17 @@ When adding a foreign key in PostgreSQL the column is not indexed automatically, | ||||||
| thus you must also add a concurrent index. Not doing so will result in cascading | thus you must also add a concurrent index. Not doing so will result in cascading | ||||||
| deletes being very slow. | deletes being very slow. | ||||||
| 
 | 
 | ||||||
|  | ## Naming foreign keys | ||||||
|  | 
 | ||||||
|  | By default Ruby on Rails uses the `_id` suffix for foreign keys. So we should | ||||||
|  | only use this suffix for associations between two tables. If you want to | ||||||
|  | reference an ID on a third party platform the `_xid` suffix is recommended. | ||||||
|  | 
 | ||||||
|  | The spec `spec/db/schema_spec.rb` will test if all columns with the `_id` suffix | ||||||
|  | have a foreign key constraint. So if that spec fails, don't add the column to | ||||||
|  | `IGNORED_FK_COLUMNS`, but instead add the FK constraint, or consider naming it | ||||||
|  | differently. | ||||||
|  | 
 | ||||||
| ## Dependent Removals | ## Dependent Removals | ||||||
| 
 | 
 | ||||||
| Don't define options such as `dependent: :destroy` or `dependent: :delete` when | Don't define options such as `dependent: :destroy` or `dependent: :delete` when | ||||||
|  |  | ||||||
|  | @ -846,6 +846,29 @@ templating: | ||||||
|           default: true                  # (Optional) This option should be the default value of this variable. |           default: true                  # (Optional) This option should be the default value of this variable. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ##### `metric_label_values` variable type | ||||||
|  | 
 | ||||||
|  | CAUTION: **Warning:** | ||||||
|  | This variable type is an _alpha_ feature, and is subject to change at any time | ||||||
|  | without prior notice! | ||||||
|  | 
 | ||||||
|  | ###### Full syntax | ||||||
|  | 
 | ||||||
|  | This example creates a variable called `variable2`. The values of the dropdown will | ||||||
|  | be all the different values of the `backend` label in the Prometheus series described by | ||||||
|  | `up{env="production"}`. | ||||||
|  | 
 | ||||||
|  | ```yaml | ||||||
|  | templating: | ||||||
|  |   variables: | ||||||
|  |     variable2:                           # The variable name that can be interpolated in queries. | ||||||
|  |       label: 'Variable 2'                # (Optional) label that will appear in the UI for this dropdown. | ||||||
|  |       type: metric_label_values | ||||||
|  |       options: | ||||||
|  |         series_selector: 'up{env="production"}' | ||||||
|  |         label: 'backend' | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ### Add related links to custom dashboards | ### Add related links to custom dashboards | ||||||
| 
 | 
 | ||||||
| > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216385) in GitLab 13.1. | > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216385) in GitLab 13.1. | ||||||
|  |  | ||||||
|  | @ -4,32 +4,65 @@ | ||||||
| image: openjdk:8-jdk | image: openjdk:8-jdk | ||||||
| 
 | 
 | ||||||
| variables: | variables: | ||||||
|   ANDROID_COMPILE_SDK: "28" |  | ||||||
|   ANDROID_BUILD_TOOLS: "28.0.2" |  | ||||||
|   ANDROID_SDK_TOOLS: "4333796" |  | ||||||
| 
 | 
 | ||||||
|  |   # ANDROID_COMPILE_SDK is the version of Android you're compiling with. | ||||||
|  |   # It should match compileSdkVersion. | ||||||
|  |   ANDROID_COMPILE_SDK: "29" | ||||||
|  | 
 | ||||||
|  |   # ANDROID_BUILD_TOOLS is the version of the Android build tools you are using. | ||||||
|  |   # It should match buildToolsVersion. | ||||||
|  |   ANDROID_BUILD_TOOLS: "29.0.3" | ||||||
|  | 
 | ||||||
|  |   # It's what version of the command line tools we're going to download from the official site. | ||||||
|  |   # Official Site-> https://developer.android.com/studio/index.html | ||||||
|  |   # There, look down below at the cli tools only, sdk tools package is of format: | ||||||
|  |   #        commandlinetools-os_type-ANDROID_SDK_TOOLS_latest.zip | ||||||
|  |   # when the script was last modified for latest compileSdkVersion, it was which is written down below | ||||||
|  |   ANDROID_SDK_TOOLS: "6514223" | ||||||
|  | 
 | ||||||
|  | # Packages installation before running script | ||||||
| before_script: | before_script: | ||||||
|   - apt-get --quiet update --yes |   - apt-get --quiet update --yes | ||||||
|   - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1 |   - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1 | ||||||
|   - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip |  | ||||||
|   - unzip -d android-sdk-linux android-sdk.zip |  | ||||||
|   - echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null |  | ||||||
|   - echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" >/dev/null |  | ||||||
|   - echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null |  | ||||||
|   - export ANDROID_HOME=$PWD/android-sdk-linux |  | ||||||
|   - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/ |  | ||||||
|   - chmod +x ./gradlew |  | ||||||
|   # temporarily disable checking for EPIPE error and use yes to accept all licenses |  | ||||||
|   - set +o pipefail |  | ||||||
|   - yes | android-sdk-linux/tools/bin/sdkmanager --licenses |  | ||||||
|   - set -o pipefail |  | ||||||
| 
 | 
 | ||||||
|  |   # Setup path as android_home for moving/exporting the downloaded sdk into it | ||||||
|  |   - export ANDROID_HOME="${PWD}/android-home" | ||||||
|  |   # Create a new directory at specified location | ||||||
|  |   - install -d $ANDROID_HOME | ||||||
|  |   # Here we are installing androidSDK tools from official source, | ||||||
|  |   # (the key thing here is the url from where you are downloading these sdk tool for command line, so please do note this url pattern there and here as well) | ||||||
|  |   # after that unzipping those tools and | ||||||
|  |   # then running a series of SDK manager commands to install necessary android SDK packages that'll allow the app to build | ||||||
|  |   - wget --output-document=$ANDROID_HOME/cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip | ||||||
|  |   # move to the archive at ANDROID_HOME | ||||||
|  |   - pushd $ANDROID_HOME | ||||||
|  |   - unzip -d cmdline-tools cmdline-tools.zip | ||||||
|  |   - popd | ||||||
|  |   - export PATH=$PATH:${ANDROID_HOME}/cmdline-tools/tools/bin/ | ||||||
|  | 
 | ||||||
|  |   # Nothing fancy here, just checking sdkManager version | ||||||
|  |   - sdkmanager --version | ||||||
|  | 
 | ||||||
|  |   # use yes to accept all licenses | ||||||
|  |   - yes | sdkmanager --sdk_root=${ANDROID_HOME} --licenses || true | ||||||
|  |   - sdkmanager --sdk_root=${ANDROID_HOME} "platforms;android-${ANDROID_COMPILE_SDK}" | ||||||
|  |   - sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools" | ||||||
|  |   - sdkmanager --sdk_root=${ANDROID_HOME} "build-tools;${ANDROID_BUILD_TOOLS}" | ||||||
|  | 
 | ||||||
|  |   # Not necessary, but just for surity | ||||||
|  |   - chmod +x ./gradlew | ||||||
|  | 
 | ||||||
|  | # Basic android and gradle stuff | ||||||
|  | # Check linting | ||||||
| lintDebug: | lintDebug: | ||||||
|  |   interruptible: true | ||||||
|   stage: build |   stage: build | ||||||
|   script: |   script: | ||||||
|     - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint |     - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint | ||||||
| 
 | 
 | ||||||
|  | # Make Project | ||||||
| assembleDebug: | assembleDebug: | ||||||
|  |   interruptible: true | ||||||
|   stage: build |   stage: build | ||||||
|   script: |   script: | ||||||
|     - ./gradlew assembleDebug |     - ./gradlew assembleDebug | ||||||
|  | @ -37,7 +70,9 @@ assembleDebug: | ||||||
|     paths: |     paths: | ||||||
|       - app/build/outputs/ |       - app/build/outputs/ | ||||||
| 
 | 
 | ||||||
|  | # Run all tests, if any fails, interrupt the pipeline(fail it) | ||||||
| debugTests: | debugTests: | ||||||
|  |   interruptible: true | ||||||
|   stage: test |   stage: test | ||||||
|   script: |   script: | ||||||
|     - ./gradlew -Pci --console=plain :app:testDebug |     - ./gradlew -Pci --console=plain :app:testDebug | ||||||
|  |  | ||||||
|  | @ -25434,6 +25434,9 @@ msgstr "" | ||||||
| msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later." | msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later." | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later." | msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,8 +10,8 @@ RSpec.describe 'Database schema' do | ||||||
|   let(:tables) { connection.tables } |   let(:tables) { connection.tables } | ||||||
|   let(:columns_name_with_jsonb) { retrieve_columns_name_with_jsonb } |   let(:columns_name_with_jsonb) { retrieve_columns_name_with_jsonb } | ||||||
| 
 | 
 | ||||||
|   # Use if you are certain that this column should not have a foreign key |   # List of columns historically missing a FK, don't add more columns | ||||||
|   # EE: edit the ee/spec/db/schema_support.rb |   # See: https://docs.gitlab.com/ce/development/foreign_keys.html#naming-foreign-keys | ||||||
|   IGNORED_FK_COLUMNS = { |   IGNORED_FK_COLUMNS = { | ||||||
|     abuse_reports: %w[reporter_id user_id], |     abuse_reports: %w[reporter_id user_id], | ||||||
|     application_settings: %w[performance_bar_allowed_group_id slack_app_id snowplow_app_id eks_account_id eks_access_key_id], |     application_settings: %w[performance_bar_allowed_group_id slack_app_id snowplow_app_id eks_account_id eks_access_key_id], | ||||||
|  | @ -119,7 +119,11 @@ RSpec.describe 'Database schema' do | ||||||
|           let(:ignored_columns) { ignored_fk_columns(table) } |           let(:ignored_columns) { ignored_fk_columns(table) } | ||||||
| 
 | 
 | ||||||
|           it 'do have the foreign keys' do |           it 'do have the foreign keys' do | ||||||
|             expect(column_names_with_id - ignored_columns).to contain_exactly(*foreign_keys_columns) |             expect(column_names_with_id - ignored_columns).to match_array(foreign_keys_columns) | ||||||
|  |           end | ||||||
|  | 
 | ||||||
|  |           it 'and having foreign key are not in the ignore list' do | ||||||
|  |             expect(ignored_columns).to match_array(ignored_columns - foreign_keys) | ||||||
|           end |           end | ||||||
|         end |         end | ||||||
|       end |       end | ||||||
|  |  | ||||||
|  | @ -100,7 +100,11 @@ describe('DiffTableCell', () => { | ||||||
|         setWindowLocation({ href: `${TEST_HOST}?${query}` }); |         setWindowLocation({ href: `${TEST_HOST}?${query}` }); | ||||||
|         createComponent({ showCommentButton }); |         createComponent({ showCommentButton }); | ||||||
| 
 | 
 | ||||||
|         expect(findNoteButton().exists()).toBe(expectation); |         wrapper.setData({ isCommentButtonRendered: showCommentButton }); | ||||||
|  | 
 | ||||||
|  |         return wrapper.vm.$nextTick().then(() => { | ||||||
|  |           expect(findNoteButton().exists()).toBe(expectation); | ||||||
|  |         }); | ||||||
|       }, |       }, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  | @ -108,7 +112,6 @@ describe('DiffTableCell', () => { | ||||||
|       isHover  | otherProps                                      | discussions | expectation |       isHover  | otherProps                                      | discussions | expectation | ||||||
|       ${true}  | ${{}}                                           | ${[]}       | ${true} |       ${true}  | ${{}}                                           | ${[]}       | ${true} | ||||||
|       ${false} | ${{}}                                           | ${[]}       | ${false} |       ${false} | ${{}}                                           | ${[]}       | ${false} | ||||||
|       ${true}  | ${{ line: { ...line, type: 'match' } }}         | ${[]}       | ${false} |  | ||||||
|       ${true}  | ${{ line: { ...line, type: 'context' } }}       | ${[]}       | ${false} |       ${true}  | ${{ line: { ...line, type: 'context' } }}       | ${[]}       | ${false} | ||||||
|       ${true}  | ${{ line: { ...line, type: 'old-nonewline' } }} | ${[]}       | ${false} |       ${true}  | ${{ line: { ...line, type: 'old-nonewline' } }} | ${[]}       | ${false} | ||||||
|       ${true}  | ${{}}                                           | ${[{}]}     | ${false} |       ${true}  | ${{}}                                           | ${[{}]}     | ${false} | ||||||
|  | @ -122,7 +125,13 @@ describe('DiffTableCell', () => { | ||||||
|           ...otherProps, |           ...otherProps, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         expect(findNoteButton().isVisible()).toBe(expectation); |         wrapper.setData({ | ||||||
|  |           isCommentButtonRendered: true, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         return wrapper.vm.$nextTick().then(() => { | ||||||
|  |           expect(findNoteButton().isVisible()).toBe(expectation); | ||||||
|  |         }); | ||||||
|       }, |       }, | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  | @ -19,6 +19,30 @@ RSpec.describe 'create_tokens' do | ||||||
|     allow(self).to receive(:exit) |     allow(self).to receive(:exit) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   describe 'ensure acknowledged secrets in any installations' do | ||||||
|  |     let(:acknowledged_secrets) do | ||||||
|  |       %w[secret_key_base otp_key_base db_key_base openid_connect_signing_key] | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     it 'does not allow to add a new secret without a proper handling' do | ||||||
|  |       create_tokens | ||||||
|  | 
 | ||||||
|  |       secrets_hash = YAML.load_file(Rails.root.join('config/secrets.yml')) | ||||||
|  | 
 | ||||||
|  |       secrets_hash.each do |environment, secrets| | ||||||
|  |         new_secrets = secrets.keys - acknowledged_secrets | ||||||
|  | 
 | ||||||
|  |         expect(new_secrets).to be_empty, | ||||||
|  |          <<~EOS | ||||||
|  |            CAUTION: | ||||||
|  |            It looks like you have just added new secret(s) #{new_secrets.inspect} to the secrets.yml. | ||||||
|  |            Please read the development guide for GitLab secrets at doc/development/application_secrets.md before you proceed this change. | ||||||
|  |            If you're absolutely sure that the change is safe, please add the new secrets to the 'acknowledged_secrets' in order to silence this warning. | ||||||
|  |          EOS | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   context 'setting secret keys' do |   context 'setting secret keys' do | ||||||
|     context 'when none of the secrets exist' do |     context 'when none of the secrets exist' do | ||||||
|       before do |       before do | ||||||
|  |  | ||||||
|  | @ -285,38 +285,30 @@ describe ReactiveCaching, :use_clean_rails_memory_store_caching do | ||||||
|         go! |         go! | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       context 'when calculated object size exceeds default reactive_cache_hard_limit' do |       context 'when reactive_cache_hard_limit is set' do | ||||||
|         let(:calculation) { -> { 'a' * 2 * 1.megabyte } } |         let(:test_class) { Class.new(cache_class_test) { self.reactive_cache_hard_limit = 1.megabyte } } | ||||||
|  |         let(:instance) { test_class.new(666, &calculation) } | ||||||
|  | 
 | ||||||
|  |         context 'when cache size is over the overridden limit' do | ||||||
|  |           let(:calculation) { -> { 'a' * 2 * 1.megabyte } } | ||||||
| 
 | 
 | ||||||
|         shared_examples 'ExceededReactiveCacheLimit' do |  | ||||||
|           it 'raises ExceededReactiveCacheLimit exception and does not cache new data' do |           it 'raises ExceededReactiveCacheLimit exception and does not cache new data' do | ||||||
|             expect { go! }.to raise_exception(ReactiveCaching::ExceededReactiveCacheLimit) |             expect { go! }.to raise_exception(ReactiveCaching::ExceededReactiveCacheLimit) | ||||||
| 
 | 
 | ||||||
|             expect(read_reactive_cache(instance)).not_to eq(calculation.call) |             expect(read_reactive_cache(instance)).not_to eq(calculation.call) | ||||||
|           end |           end | ||||||
|         end |  | ||||||
| 
 | 
 | ||||||
|         context 'when reactive_cache_hard_limit feature flag is enabled' do |           context 'when reactive_cache_limit_enabled? is overriden to return false' do | ||||||
|           it_behaves_like 'ExceededReactiveCacheLimit' |             before do | ||||||
| 
 |               allow(instance).to receive(:reactive_cache_limit_enabled?).and_return(false) | ||||||
|           context 'when reactive_cache_hard_limit is overridden' do |             end | ||||||
|             let(:test_class) { Class.new(cache_class_test) { self.reactive_cache_hard_limit = 3.megabytes } } |  | ||||||
|             let(:instance) { test_class.new(666, &calculation) } |  | ||||||
| 
 | 
 | ||||||
|             it_behaves_like 'successful cache' |             it_behaves_like 'successful cache' | ||||||
| 
 |  | ||||||
|             context 'when cache size is over the overridden limit' do |  | ||||||
|               let(:calculation) { -> { 'a' * 4 * 1.megabyte } } |  | ||||||
| 
 |  | ||||||
|               it_behaves_like 'ExceededReactiveCacheLimit' |  | ||||||
|             end |  | ||||||
|           end |           end | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         context 'when reactive_cache_limit feature flag is disabled' do |         context 'when cache size is within the overridden limit' do | ||||||
|           before do |           let(:calculation) { -> { 'Smaller than 1Mb reactive_cache_hard_limit' } } | ||||||
|             stub_feature_flags(reactive_cache_limit: false) |  | ||||||
|           end |  | ||||||
| 
 | 
 | ||||||
|           it_behaves_like 'successful cache' |           it_behaves_like 'successful cache' | ||||||
|         end |         end | ||||||
|  | @ -377,7 +369,7 @@ describe ReactiveCaching, :use_clean_rails_memory_store_caching do | ||||||
|     it { expect(subject.reactive_cache_refresh_interval).to be_a(ActiveSupport::Duration) } |     it { expect(subject.reactive_cache_refresh_interval).to be_a(ActiveSupport::Duration) } | ||||||
|     it { expect(subject.reactive_cache_lifetime).to be_a(ActiveSupport::Duration) } |     it { expect(subject.reactive_cache_lifetime).to be_a(ActiveSupport::Duration) } | ||||||
|     it { expect(subject.reactive_cache_key).to respond_to(:call) } |     it { expect(subject.reactive_cache_key).to respond_to(:call) } | ||||||
|     it { expect(subject.reactive_cache_hard_limit).to be_a(Integer) } |     it { expect(subject.reactive_cache_hard_limit).to be_nil } | ||||||
|     it { expect(subject.reactive_cache_worker_finder).to respond_to(:call) } |     it { expect(subject.reactive_cache_worker_finder).to respond_to(:call) } | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -847,6 +847,20 @@ describe Environment, :use_clean_rails_memory_store_caching do | ||||||
| 
 | 
 | ||||||
|     subject { environment.calculate_reactive_cache } |     subject { environment.calculate_reactive_cache } | ||||||
| 
 | 
 | ||||||
|  |     it 'overrides default reactive_cache_hard_limit to 10 Mb' do | ||||||
|  |       expect(described_class.reactive_cache_hard_limit).to eq(10.megabyte) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     it 'overrides reactive_cache_limit_enabled? with a FF' do | ||||||
|  |       environment_with_enabled_ff = FactoryBot.build(:environment) | ||||||
|  |       environment_with_disabled_ff = FactoryBot.build(:environment) | ||||||
|  | 
 | ||||||
|  |       stub_feature_flags(reactive_caching_limit_environment: environment_with_enabled_ff.project) | ||||||
|  | 
 | ||||||
|  |       expect(environment_with_enabled_ff.send(:reactive_cache_limit_enabled?)).to be_truthy | ||||||
|  |       expect(environment_with_disabled_ff.send(:reactive_cache_limit_enabled?)).to be_falsey | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     it 'returns cache data from the deployment platform' do |     it 'returns cache data from the deployment platform' do | ||||||
|       expect(environment.deployment_platform).to receive(:calculate_reactive_cache_for) |       expect(environment.deployment_platform).to receive(:calculate_reactive_cache_for) | ||||||
|         .with(environment).and_return(pods: %w(pod1 pod2)) |         .with(environment).and_return(pods: %w(pod1 pod2)) | ||||||
|  |  | ||||||
|  | @ -88,6 +88,62 @@ RSpec.describe Tooling::TestFileFinder do | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     context 'when given a factory file' do | ||||||
|  |       let(:file) { 'spec/factories/users.rb' } | ||||||
|  | 
 | ||||||
|  |       it 'returns spec/factories_spec.rb file' do | ||||||
|  |         expect(subject.test_files).to contain_exactly('spec/factories_spec.rb') | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when given an ee factory file' do | ||||||
|  |       let(:file) { 'ee/spec/factories/users.rb' } | ||||||
|  | 
 | ||||||
|  |       it 'returns spec/factories_spec.rb file' do | ||||||
|  |         expect(subject.test_files).to contain_exactly('spec/factories_spec.rb') | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when given db/structure.sql' do | ||||||
|  |       let(:file) { 'db/structure.sql' } | ||||||
|  | 
 | ||||||
|  |       it 'returns spec/db/schema_spec.rb' do | ||||||
|  |         expect(subject.test_files).to contain_exactly('spec/db/schema_spec.rb') | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when given an initializer' do | ||||||
|  |       let(:file) { 'config/initializers/action_mailer_hooks.rb' } | ||||||
|  | 
 | ||||||
|  |       it 'returns the matching initializer spec' do | ||||||
|  |         expect(subject.test_files).to contain_exactly('spec/initializers/action_mailer_hooks_spec.rb') | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when given a migration file' do | ||||||
|  |       let(:file) { 'db/migrate/20191023152913_add_default_and_free_plans.rb' } | ||||||
|  | 
 | ||||||
|  |       it 'returns the matching migration spec' do | ||||||
|  |         test_files = %w[ | ||||||
|  |           spec/migrations/add_default_and_free_plans_spec.rb | ||||||
|  |           spec/migrations/20191023152913_add_default_and_free_plans_spec.rb | ||||||
|  |         ] | ||||||
|  |         expect(subject.test_files).to contain_exactly(*test_files) | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'when given a post-migration file' do | ||||||
|  |       let(:file) { 'db/post_migrate/20200608072931_backfill_imported_snippet_repositories.rb' } | ||||||
|  | 
 | ||||||
|  |       it 'returns the matching migration spec' do | ||||||
|  |         test_files = %w[ | ||||||
|  |           spec/migrations/backfill_imported_snippet_repositories_spec.rb | ||||||
|  |           spec/migrations/20200608072931_backfill_imported_snippet_repositories_spec.rb | ||||||
|  |         ] | ||||||
|  |         expect(subject.test_files).to contain_exactly(*test_files) | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     context 'with foss_test_only: true' do |     context 'with foss_test_only: true' do | ||||||
|       subject { Tooling::TestFileFinder.new(file, foss_test_only: true) } |       subject { Tooling::TestFileFinder.new(file, foss_test_only: true) } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ module Tooling | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def test_files |     def test_files | ||||||
|       impacted_tests = ee_impact | non_ee_impact |       impacted_tests = ee_impact | non_ee_impact | either_impact | ||||||
|       impacted_tests.impact(@file) |       impacted_tests.impact(@file) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  | @ -23,20 +23,22 @@ module Tooling | ||||||
|     class ImpactedTestFile |     class ImpactedTestFile | ||||||
|       attr_reader :pattern_matchers |       attr_reader :pattern_matchers | ||||||
| 
 | 
 | ||||||
|       def initialize |       def initialize(prefix: nil) | ||||||
|         @pattern_matchers = {} |         @pattern_matchers = {} | ||||||
|  |         @prefix = prefix | ||||||
| 
 | 
 | ||||||
|         yield self if block_given? |         yield self if block_given? | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def associate(pattern, &block) |       def associate(pattern, &block) | ||||||
|         @pattern_matchers[pattern] = block |         @pattern_matchers[%r{^#{@prefix}#{pattern}}] = block | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def impact(file) |       def impact(file) | ||||||
|         @pattern_matchers.each_with_object(Set.new) do |(pattern, block), result| |         @pattern_matchers.each_with_object(Set.new) do |(pattern, block), result| | ||||||
|           if (match = pattern.match(file)) |           if (match = pattern.match(file)) | ||||||
|             result << block.call(match) |             test_files = block.call(match) | ||||||
|  |             result.merge(Array(test_files)) | ||||||
|           end |           end | ||||||
|         end.to_a |         end.to_a | ||||||
|       end |       end | ||||||
|  | @ -54,24 +56,37 @@ module Tooling | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def ee_impact |     def ee_impact | ||||||
|       ImpactedTestFile.new do |impact| |       ImpactedTestFile.new(prefix: EE_PREFIX) do |impact| | ||||||
|         unless foss_test_only |         unless foss_test_only | ||||||
|           impact.associate(%r{^#{EE_PREFIX}app/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/#{match[1]}_spec.rb" } |           impact.associate(%r{app/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/#{match[1]}_spec.rb" } | ||||||
|           impact.associate(%r{^#{EE_PREFIX}app/(.*/)ee/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/#{match[1]}#{match[2]}_spec.rb" } |           impact.associate(%r{app/(.*/)ee/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/#{match[1]}#{match[2]}_spec.rb" } | ||||||
|           impact.associate(%r{^#{EE_PREFIX}lib/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/lib/#{match[1]}_spec.rb" } |           impact.associate(%r{lib/(.+)\.rb$}) { |match| "#{EE_PREFIX}spec/lib/#{match[1]}_spec.rb" } | ||||||
|           impact.associate(%r{^#{EE_PREFIX}spec/(.+)_spec.rb$}) { |match| match[0] } |  | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         impact.associate(%r{^#{EE_PREFIX}(?!spec)(.*/)ee/(.+)\.rb$}) { |match| "spec/#{match[1]}#{match[2]}_spec.rb" } |         impact.associate(%r{(?!spec)(.*/)ee/(.+)\.rb$}) { |match| "spec/#{match[1]}#{match[2]}_spec.rb" } | ||||||
|         impact.associate(%r{^#{EE_PREFIX}spec/(.*/)ee/(.+)\.rb$}) { |match| "spec/#{match[1]}#{match[2]}.rb" } |         impact.associate(%r{spec/(.*/)ee/(.+)\.rb$}) { |match| "spec/#{match[1]}#{match[2]}.rb" } | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def non_ee_impact |     def non_ee_impact | ||||||
|       ImpactedTestFile.new do |impact| |       ImpactedTestFile.new do |impact| | ||||||
|         impact.associate(%r{^app/(.+)\.rb$}) { |match| "spec/#{match[1]}_spec.rb" } |         impact.associate(%r{app/(.+)\.rb$}) { |match| "spec/#{match[1]}_spec.rb" } | ||||||
|         impact.associate(%r{^(tooling/)?lib/(.+)\.rb$}) { |match| "spec/#{match[1]}lib/#{match[2]}_spec.rb" } |         impact.associate(%r{(tooling/)?lib/(.+)\.rb$}) { |match| "spec/#{match[1]}lib/#{match[2]}_spec.rb" } | ||||||
|         impact.associate(%r{^spec/(.+)_spec.rb$}) { |match| match[0] } |         impact.associate(%r{config/initializers/(.+).rb$}) { |match| "spec/initializers/#{match[1]}_spec.rb" } | ||||||
|  |         impact.associate('db/structure.sql') { 'spec/db/schema_spec.rb' } | ||||||
|  |         impact.associate(%r{db/(?:post_)?migrate/([0-9]+)_(.+).rb$}) do |match| | ||||||
|  |           [ | ||||||
|  |             "spec/migrations/#{match[2]}_spec.rb", | ||||||
|  |             "spec/migrations/#{match[1]}_#{match[2]}_spec.rb" | ||||||
|  |           ] | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def either_impact | ||||||
|  |       ImpactedTestFile.new(prefix: %r{^(#{EE_PREFIX})?}) do |impact| | ||||||
|  |         impact.associate(%r{spec/(.+)_spec.rb$}) { |match| match[0] } | ||||||
|  |         impact.associate(%r{spec/factories/.+\.rb$}) { 'spec/factories_spec.rb' } | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue