mongoid 7.6.2 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data/README.md +3 -3
  4. data/Rakefile +21 -85
  5. data/lib/config/locales/en.yml +46 -56
  6. data/lib/mongoid/association/accessors.rb +32 -3
  7. data/lib/mongoid/association/bindable.rb +48 -0
  8. data/lib/mongoid/association/builders.rb +4 -2
  9. data/lib/mongoid/association/depending.rb +4 -8
  10. data/lib/mongoid/association/eager_loadable.rb +29 -7
  11. data/lib/mongoid/association/embedded/batchable.rb +28 -5
  12. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  13. data/lib/mongoid/association/embedded/embedded_in.rb +2 -1
  14. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  15. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  16. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +40 -18
  17. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  18. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +21 -2
  19. data/lib/mongoid/association/macros.rb +2 -1
  20. data/lib/mongoid/association/many.rb +5 -0
  21. data/lib/mongoid/association/nested/many.rb +5 -39
  22. data/lib/mongoid/association/nested/nested_buildable.rb +0 -14
  23. data/lib/mongoid/association/proxy.rb +12 -0
  24. data/lib/mongoid/association/referenced/auto_save.rb +3 -2
  25. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  26. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  27. data/lib/mongoid/association/referenced/belongs_to.rb +1 -1
  28. data/lib/mongoid/association/referenced/counter_cache.rb +8 -8
  29. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +64 -11
  30. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +4 -1
  31. data/lib/mongoid/association/referenced/has_many/enumerable.rb +10 -18
  32. data/lib/mongoid/association/referenced/has_many/proxy.rb +11 -107
  33. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  34. data/lib/mongoid/association/referenced/has_one/proxy.rb +8 -11
  35. data/lib/mongoid/association/referenced/syncable.rb +2 -2
  36. data/lib/mongoid/association/relatable.rb +38 -4
  37. data/lib/mongoid/attributes/processing.rb +9 -2
  38. data/lib/mongoid/attributes.rb +30 -27
  39. data/lib/mongoid/cacheable.rb +2 -2
  40. data/lib/mongoid/changeable.rb +37 -2
  41. data/lib/mongoid/clients/factory.rb +0 -4
  42. data/lib/mongoid/clients/options.rb +4 -0
  43. data/lib/mongoid/clients/sessions.rb +2 -14
  44. data/lib/mongoid/config.rb +15 -73
  45. data/lib/mongoid/contextual/aggregable/memory.rb +22 -20
  46. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  47. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  48. data/lib/mongoid/contextual/memory.rb +63 -47
  49. data/lib/mongoid/contextual/mongo.rb +173 -287
  50. data/lib/mongoid/contextual/none.rb +33 -15
  51. data/lib/mongoid/copyable.rb +32 -8
  52. data/lib/mongoid/criteria/includable.rb +24 -20
  53. data/lib/mongoid/criteria/marshalable.rb +10 -2
  54. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -15
  55. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  56. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  57. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  58. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  59. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -16
  60. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  61. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  62. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  63. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +1 -1
  64. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  65. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  66. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  67. data/lib/mongoid/criteria/queryable/mergeable.rb +0 -12
  68. data/lib/mongoid/criteria/queryable/optional.rb +3 -9
  69. data/lib/mongoid/criteria/queryable/options.rb +1 -1
  70. data/lib/mongoid/criteria/queryable/selectable.rb +2 -133
  71. data/lib/mongoid/criteria/queryable/selector.rb +90 -5
  72. data/lib/mongoid/criteria/queryable/smash.rb +39 -6
  73. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  74. data/lib/mongoid/criteria/queryable.rb +11 -6
  75. data/lib/mongoid/criteria.rb +1 -28
  76. data/lib/mongoid/deprecable.rb +36 -0
  77. data/lib/mongoid/deprecation.rb +25 -0
  78. data/lib/mongoid/document.rb +88 -33
  79. data/lib/mongoid/equality.rb +4 -4
  80. data/lib/mongoid/errors/document_not_found.rb +6 -2
  81. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  82. data/lib/mongoid/errors/invalid_field.rb +5 -1
  83. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  84. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  85. data/lib/mongoid/errors.rb +2 -3
  86. data/lib/mongoid/extensions/array.rb +8 -6
  87. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  88. data/lib/mongoid/extensions/binary.rb +42 -0
  89. data/lib/mongoid/extensions/boolean.rb +8 -2
  90. data/lib/mongoid/extensions/date.rb +26 -20
  91. data/lib/mongoid/extensions/date_time.rb +1 -1
  92. data/lib/mongoid/extensions/float.rb +4 -5
  93. data/lib/mongoid/extensions/hash.rb +13 -32
  94. data/lib/mongoid/extensions/integer.rb +4 -5
  95. data/lib/mongoid/extensions/object.rb +2 -0
  96. data/lib/mongoid/extensions/range.rb +41 -10
  97. data/lib/mongoid/extensions/regexp.rb +11 -4
  98. data/lib/mongoid/extensions/set.rb +11 -4
  99. data/lib/mongoid/extensions/string.rb +2 -13
  100. data/lib/mongoid/extensions/symbol.rb +3 -14
  101. data/lib/mongoid/extensions/time.rb +27 -16
  102. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  103. data/lib/mongoid/extensions.rb +1 -0
  104. data/lib/mongoid/factory.rb +42 -7
  105. data/lib/mongoid/fields/foreign_key.rb +7 -0
  106. data/lib/mongoid/fields/validators/macro.rb +3 -9
  107. data/lib/mongoid/fields.rb +49 -7
  108. data/lib/mongoid/findable.rb +21 -16
  109. data/lib/mongoid/indexable/specification.rb +1 -1
  110. data/lib/mongoid/indexable/validators/options.rb +4 -1
  111. data/lib/mongoid/interceptable.rb +69 -9
  112. data/lib/mongoid/matchable.rb +1 -6
  113. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +5 -3
  114. data/lib/mongoid/matcher/regex.rb +9 -8
  115. data/lib/mongoid/matcher.rb +0 -1
  116. data/lib/mongoid/persistable/creatable.rb +14 -5
  117. data/lib/mongoid/persistable/updatable.rb +12 -5
  118. data/lib/mongoid/persistence_context.rb +8 -42
  119. data/lib/mongoid/query_cache.rb +6 -258
  120. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  121. data/lib/mongoid/reloadable.rb +7 -3
  122. data/lib/mongoid/scopable.rb +9 -11
  123. data/lib/mongoid/selectable.rb +1 -2
  124. data/lib/mongoid/shardable.rb +11 -35
  125. data/lib/mongoid/stateful.rb +27 -1
  126. data/lib/mongoid/threaded.rb +0 -3
  127. data/lib/mongoid/timestamps/created.rb +1 -1
  128. data/lib/mongoid/timestamps/updated.rb +1 -1
  129. data/lib/mongoid/touchable.rb +2 -3
  130. data/lib/mongoid/traversable.rb +1 -0
  131. data/lib/mongoid/validatable/uniqueness.rb +2 -1
  132. data/lib/mongoid/version.rb +1 -5
  133. data/lib/mongoid/warnings.rb +3 -5
  134. data/lib/mongoid.rb +1 -0
  135. data/spec/config/mongoid.yml +16 -0
  136. data/spec/integration/app_spec.rb +8 -20
  137. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  138. data/spec/integration/associations/embedded_spec.rb +15 -0
  139. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  140. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  141. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  142. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  143. data/spec/integration/associations/has_one_spec.rb +97 -1
  144. data/spec/integration/associations/scope_option_spec.rb +1 -1
  145. data/spec/integration/callbacks_models.rb +95 -1
  146. data/spec/integration/callbacks_spec.rb +226 -4
  147. data/spec/integration/criteria/range_spec.rb +95 -1
  148. data/spec/integration/discriminator_key_spec.rb +115 -76
  149. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  150. data/spec/integration/i18n_fallbacks_spec.rb +1 -15
  151. data/spec/integration/matcher_examples_spec.rb +20 -13
  152. data/spec/integration/matcher_operator_data/regex.yml +0 -21
  153. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  154. data/spec/integration/matcher_operator_spec.rb +3 -5
  155. data/spec/integration/persistence/range_field_spec.rb +350 -0
  156. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  157. data/spec/mongoid/association/depending_spec.rb +9 -9
  158. data/spec/mongoid/association/eager_spec.rb +2 -1
  159. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  160. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  161. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  162. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  163. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +198 -8
  164. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  165. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  166. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  167. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  168. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  169. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  170. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  171. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  172. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  173. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  174. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  175. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +36 -51
  176. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  177. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  178. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  179. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  180. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +60 -156
  181. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  182. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  183. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  184. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  185. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  186. data/spec/mongoid/association/syncable_spec.rb +14 -0
  187. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  188. data/spec/mongoid/attributes/nested_spec.rb +73 -198
  189. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  190. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  191. data/spec/mongoid/attributes_spec.rb +480 -27
  192. data/spec/mongoid/cacheable_spec.rb +3 -3
  193. data/spec/mongoid/changeable_spec.rb +130 -13
  194. data/spec/mongoid/clients/factory_spec.rb +22 -60
  195. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  196. data/spec/mongoid/clients_spec.rb +2 -2
  197. data/spec/mongoid/config_spec.rb +52 -15
  198. data/spec/mongoid/contextual/aggregable/memory_spec.rb +371 -231
  199. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  200. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  201. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  202. data/spec/mongoid/contextual/memory_spec.rb +467 -156
  203. data/spec/mongoid/contextual/mongo_spec.rb +566 -426
  204. data/spec/mongoid/contextual/none_spec.rb +11 -19
  205. data/spec/mongoid/copyable_spec.rb +451 -2
  206. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  207. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  208. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  209. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  210. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  211. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  212. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +1 -2
  213. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  214. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  215. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +1 -2
  216. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  217. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  218. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  219. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  220. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  221. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -2
  222. data/spec/mongoid/criteria/queryable/selectable_spec.rb +77 -85
  223. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +0 -200
  224. data/spec/mongoid/criteria/queryable/selector_spec.rb +16 -77
  225. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  226. data/spec/mongoid/criteria_spec.rb +469 -1203
  227. data/spec/mongoid/document_fields_spec.rb +173 -24
  228. data/spec/mongoid/document_spec.rb +32 -41
  229. data/spec/mongoid/equality_spec.rb +12 -12
  230. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  231. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  232. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  233. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  234. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  235. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  236. data/spec/mongoid/extensions/array_spec.rb +16 -2
  237. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  238. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  239. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  240. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  241. data/spec/mongoid/extensions/date_spec.rb +71 -1
  242. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  243. data/spec/mongoid/extensions/float_spec.rb +48 -76
  244. data/spec/mongoid/extensions/hash_spec.rb +30 -236
  245. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  246. data/spec/mongoid/extensions/range_spec.rb +255 -54
  247. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  248. data/spec/mongoid/extensions/set_spec.rb +106 -0
  249. data/spec/mongoid/extensions/string_spec.rb +53 -25
  250. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  251. data/spec/mongoid/extensions/time_spec.rb +634 -66
  252. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  253. data/spec/mongoid/factory_spec.rb +61 -1
  254. data/spec/mongoid/fields_spec.rb +321 -50
  255. data/spec/mongoid/findable_spec.rb +64 -29
  256. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  257. data/spec/mongoid/indexable_spec.rb +16 -19
  258. data/spec/mongoid/interceptable_spec.rb +584 -5
  259. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  260. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  261. data/spec/mongoid/mongoizable_spec.rb +285 -0
  262. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  263. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  264. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  265. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  266. data/spec/mongoid/persistence_context_spec.rb +24 -0
  267. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  268. data/spec/mongoid/query_cache_spec.rb +1 -156
  269. data/spec/mongoid/reloadable_spec.rb +35 -2
  270. data/spec/mongoid/scopable_spec.rb +36 -34
  271. data/spec/mongoid/serializable_spec.rb +14 -7
  272. data/spec/mongoid/shardable_models.rb +0 -14
  273. data/spec/mongoid/shardable_spec.rb +61 -153
  274. data/spec/mongoid/stateful_spec.rb +28 -0
  275. data/spec/mongoid/timestamps_spec.rb +390 -0
  276. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  277. data/spec/mongoid/touchable_spec.rb +116 -0
  278. data/spec/mongoid/touchable_spec_models.rb +12 -8
  279. data/spec/mongoid/traversable_spec.rb +4 -11
  280. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  281. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  282. data/spec/mongoid/warnings_spec.rb +35 -0
  283. data/spec/mongoid_spec.rb +1 -7
  284. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  285. data/spec/rails/mongoid_spec.rb +4 -16
  286. data/spec/shared/lib/mrss/cluster_config.rb +40 -5
  287. data/spec/shared/lib/mrss/constraints.rb +46 -7
  288. data/spec/shared/lib/mrss/docker_runner.rb +21 -17
  289. data/spec/shared/lib/mrss/eg_config_utils.rb +31 -0
  290. data/spec/shared/lib/mrss/event_subscriber.rb +5 -15
  291. data/spec/shared/lib/mrss/lite_constraints.rb +2 -10
  292. data/spec/shared/lib/mrss/server_version_registry.rb +29 -18
  293. data/spec/shared/lib/mrss/spec_organizer.rb +3 -32
  294. data/spec/shared/lib/mrss/utils.rb +6 -28
  295. data/spec/shared/share/Dockerfile.erb +114 -38
  296. data/spec/shared/shlib/distro.sh +0 -10
  297. data/spec/shared/shlib/server.sh +83 -64
  298. data/spec/shared/shlib/set_env.sh +81 -16
  299. data/spec/support/constraints.rb +24 -0
  300. data/spec/support/expectations.rb +17 -20
  301. data/spec/support/macros.rb +30 -0
  302. data/spec/support/models/augmentation.rb +12 -0
  303. data/spec/support/models/band.rb +3 -0
  304. data/spec/support/models/catalog.rb +24 -0
  305. data/spec/support/models/circus.rb +3 -0
  306. data/spec/support/models/fanatic.rb +8 -0
  307. data/spec/support/models/implant.rb +9 -0
  308. data/spec/support/models/label.rb +2 -0
  309. data/spec/support/models/passport.rb +9 -0
  310. data/spec/support/models/person.rb +1 -0
  311. data/spec/support/models/player.rb +2 -0
  312. data/spec/support/models/powerup.rb +12 -0
  313. data/spec/support/models/registry.rb +1 -0
  314. data/spec/support/models/school.rb +14 -0
  315. data/spec/support/models/shield.rb +18 -0
  316. data/spec/support/models/student.rb +14 -0
  317. data/spec/support/models/weapon.rb +12 -0
  318. data.tar.gz.sig +0 -0
  319. metadata +695 -650
  320. metadata.gz.sig +0 -0
  321. data/lib/mongoid/errors/eager_load.rb +0 -23
  322. data/lib/mongoid/errors/in_memory_regexp_timeout.rb +0 -26
  323. data/lib/mongoid/errors/invalid_value.rb +0 -17
  324. data/lib/mongoid/field_readable.rb +0 -70
  325. data/lib/mongoid/matcher/regexp_budget.rb +0 -389
  326. data/spec/integration/matcher_regexp_timeout_spec.rb +0 -215
  327. data/spec/integration/query_operator_guard_spec.rb +0 -89
  328. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
  329. data/spec/mongoid/matcher/regexp_budget_spec.rb +0 -570
  330. data/spec/shared/CANDIDATE.md +0 -28
  331. data/spec/shared/lib/mrss/release/candidate.rb +0 -287
  332. data/spec/shared/lib/mrss/release/product_data.rb +0 -144
  333. data/spec/shared/lib/tasks/candidate.rake +0 -64
@@ -1,287 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- require_relative 'product_data'
6
-
7
- module Mrss
8
- module Release
9
- class Candidate
10
- # Release note section titles, by pr type
11
- SECTION_TITLE = {
12
- bcbreak: "Breaking Changes",
13
- feature: "New Features",
14
- bug: "Bug Fixes",
15
- }.freeze
16
-
17
- # GitHub labels
18
- BCBREAK = 'bcbreak'
19
- FEATURE = 'feature'
20
- BUG = 'bug'
21
- PATCH = 'patch'
22
-
23
- def self.instance
24
- @instance ||= new
25
-
26
- yield @instance if block_given?
27
-
28
- @instance
29
- end
30
-
31
- def product
32
- @product ||= ProductData.new
33
- end
34
-
35
- def bump_version
36
- product.bump_version(release_type)
37
- end
38
-
39
- def bump_version!
40
- product.bump_version!(release_type)
41
- end
42
-
43
- def branch_name
44
- @branch_name ||= "rc-#{product.version}"
45
- end
46
-
47
- # return a string of commit names since the last release
48
- def pending_changes
49
- @changes ||= begin
50
- range = product.tag_exists? ? "#{product.tag_name}.." : ""
51
- `git log --pretty=format:"%s" #{range}`
52
- end
53
- end
54
-
55
- # return a list of PR numbers since the last release
56
- def pending_pr_numbers
57
- @pending_pr_numbers ||= pending_changes.
58
- lines.
59
- map { |line| line.match(/\(#(\d+)\)$/).then { |m| m && m[1] } }.
60
- compact.
61
- sort.reverse
62
- end
63
-
64
- # return a JSON string of PR data
65
- def pending_pr_dump
66
- @pending_pr_dump ||= `gh pr list --state all --limit 256 --json number,title,labels,url,body --jq 'map(select([.number] | inside([#{pending_pr_numbers.join(',')}]))) | sort_by(.number)'`
67
- end
68
-
69
- # return a list of PR data since the last release
70
- def pending_prs
71
- @pending_prs ||= JSON.parse(pending_pr_dump)
72
- end
73
-
74
- # return a list of pending prs with additional attributes (summary,
75
- # short title, jira issue number).
76
- def decorated_prs
77
- @decorated_prs ||= pending_prs.map do |pr|
78
- jira_issue, pr_title = split_pr_title(pr)
79
- summary = extract_summary(pr)
80
- type = pr_type(pr)
81
- type_code = pr_type_code(type)
82
- patch_flag = pr_patch_flag?(pr)
83
-
84
- pr.merge('jira' => jira_issue,
85
- 'short-title' => pr_title,
86
- 'summary' => summary,
87
- 'type' => type,
88
- 'type-code' => type_code,
89
- 'patch' => patch_flag)
90
- end
91
- end
92
-
93
- # return a hash of decorated prs grouped by :bcbreak, :feature, or :bug
94
- def prs_by_type
95
- @prs_by_type ||= decorated_prs.group_by { |pr| pr['type'] }
96
- end
97
-
98
- # returns 'major', 'minor', or 'patch', depending on the presence of
99
- # (respectively) :bcbreak, :feature, or :bug labels.
100
- #
101
- # If the RELEASE environment variable is set, its value will be used
102
- # directly, ignoring whatever PR labels might exist.
103
- def release_type
104
- @release_type ||= if ENV['RELEASE']
105
- ENV['RELEASE']
106
- elsif prs_by_type[:bcbreak]
107
- 'major'
108
- elsif prs_by_type[:feature] && prs_by_type[:feature].any? { |pr| !pr['patch'] }
109
- 'minor'
110
- else
111
- 'patch'
112
- end
113
- end
114
-
115
- # returns the generated release notes as a string
116
- def release_notes
117
- @release_notes ||= release_notes_intro +
118
- %i[ bcbreak feature bug ].
119
- flat_map { |type| release_notes_for_type(type) }.join("\n")
120
- end
121
-
122
- private
123
-
124
- # returns an array of strings, each string representing a single line
125
- # in the release notes for the PR's of the given type.
126
- def release_notes_for_type(type)
127
- return [] unless prs_by_type[type]
128
-
129
- [].tap do |lines|
130
- lines << "\# #{SECTION_TITLE[type]}"
131
- lines << ''
132
-
133
- prs = prs_by_type[type]
134
- summarized, unsummarized = prs.partition { |pr| pr['summary'] }
135
-
136
- summarized.each do |pr|
137
- header = [ '### ' ]
138
- header << "[#{pr['jira']}](#{jira_url(pr['jira'])}) " if pr['jira']
139
- header << "#{pr['short-title']} ([PR](#{pr['url']}))"
140
- lines << header.join
141
- lines << ''
142
- lines << pr['summary']
143
- lines << ''
144
- end
145
-
146
- if summarized.any? && unsummarized.any?
147
- lines << ''
148
- lines << [ '### Other ', SECTION_TITLE[type] ].join
149
- lines << ''
150
- end
151
-
152
- unsummarized.each do |pr|
153
- line = [ '* ' ]
154
- line << "[#{pr['jira']}](#{jira_url(pr['jira'])}) " if pr['jira']
155
- line << "#{pr['short-title']} ([PR](#{pr['url']}))"
156
-
157
- lines << line.join
158
- end
159
-
160
- lines << ''
161
- end
162
- end
163
-
164
- # returns the URL of for the given jira issue
165
- def jira_url(issue)
166
- "https://jira.mongodb.org/browse/#{issue}"
167
- end
168
-
169
- # assumes a pr title in the format of "JIRA-1234 PR Title (#1234)",
170
- # returns a tuple of [ jira-issue, title ], where jira-issue may be
171
- # blank (if no jira issue is in the title).
172
- def split_pr_title(pr)
173
- title = pr['title'].gsub(/\(#\d+\)/, '').strip
174
-
175
- if title =~ /^(\w+-\d+) (.*)$/
176
- [ $1, $2 ]
177
- else
178
- [ nil, title ]
179
- end
180
- end
181
-
182
- # extracts the summary section from the pr and returns it (or returns nil
183
- # if no summary section is detected)
184
- def extract_summary(pr)
185
- summary = []
186
- accumulating = false
187
- in_code_block = false
188
- level = nil
189
-
190
- pr['body'].lines.each do |line|
191
- if !accumulating
192
- # a header of any level titled "summary" will begin the summary
193
- if line =~ /^(\#+)\s+summary\s+$/i
194
- accumulating = true
195
- level = $1.length
196
- end
197
- else
198
- # if we encounter a code block, we don't let its contents affect our
199
- # header-level counting (i.e. we don't want to accidentally end the
200
- # summary just because there's a comment in a code block)
201
- in_code_block = !in_code_block if line =~ /^```/
202
-
203
- # a header of any level less than or equal to the summary header's
204
- # level will end the summary
205
- break if !in_code_block && line =~ /^\#{1,#{level}}\s+/
206
-
207
- # otherwise, the line is part of the summary
208
- summary << line
209
- end
210
- end
211
-
212
- summary.any? ? summary.join.strip : nil
213
- end
214
-
215
- # Returns a symbol (:bcbreak, :feature, or :bug) that identifies the
216
- # type of this PR that would most strongly influence what type of release
217
- # it requires.
218
- def pr_type(pr)
219
- if pr['labels'].any? { |l| l['name'] == BCBREAK }
220
- :bcbreak
221
- elsif pr['labels'].any? { |l| l['name'] == FEATURE }
222
- :feature
223
- elsif pr['labels'].any? { |l| l['name'] == BUG }
224
- :bug
225
- else
226
- nil
227
- end
228
- end
229
-
230
- # `true` if the `patch` label is applied to the PR. This is used to
231
- # indicate that a "feature" PR should be treated as a patch, for
232
- # determining the release type only.
233
- def pr_patch_flag?(pr)
234
- pr['labels'].any? { |l| l['name'] == PATCH }
235
- end
236
-
237
- def pr_type_code(type)
238
- case type
239
- when :bcbreak then 'x'
240
- when :feature then 'f'
241
- when :bug then 'b'
242
- else '?'
243
- end
244
- end
245
-
246
- def series
247
- major, minor, = product.version_parts
248
-
249
- case release_type
250
- when 'minor' then
251
- "#{major}.x"
252
- when 'patch' then
253
- "#{major}.#{minor}.x"
254
- end
255
- end
256
-
257
- # Return a string containing the markdown-formatted intro block for
258
- # the release notes of this candidate.
259
- def release_notes_intro
260
- release_description = case release_type
261
- when 'major' then 'major release'
262
- when 'minor' then "minor release in the #{series} series"
263
- when 'patch' then "patch release in the #{series} series"
264
- end
265
-
266
- <<~INTRO
267
- The MongoDB Ruby team is pleased to announce version #{product.version} of the `#{product.package}` gem - #{product.description}. This is a new #{release_description} of #{product.name}.
268
-
269
- Install this release using [RubyGems](https://rubygems.org/) via the command line as follows:
270
-
271
- ~~~
272
- gem install -v #{product.version} #{product.package}
273
- ~~~
274
-
275
- Or simply add it to your `Gemfile`:
276
-
277
- ~~~
278
- gem '#{product.package}', '#{product.version}'
279
- ~~~
280
-
281
- Have any feedback? Click on through to MongoDB's JIRA and [open a new ticket](#{product.jira_project_url}) to let us know what's on your mind 🧠.
282
-
283
- INTRO
284
- end
285
- end
286
- end
287
- end
@@ -1,144 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
-
5
- module Mrss
6
- module Release
7
- class ProductData
8
- FILE_PATH = 'product.yml'
9
-
10
- def self.init!
11
- if File.exist?(FILE_PATH)
12
- raise "#{FILE_PATH} already exists; refusing to overwrite it"
13
- end
14
-
15
- initial_data = {
16
- 'name' => 'Product Name',
17
- 'description' => 'a very short description of the product',
18
- 'package' => 'product_package',
19
- 'jira' => 'https://url.to.jira/project',
20
- 'version' => { 'number' => '1.0.0',
21
- 'file' => 'path/to/version.rb' }
22
- }
23
-
24
- File.write(FILE_PATH, initial_data.to_yaml)
25
- end
26
-
27
- def initialize
28
- @hash = YAML.load_file(FILE_PATH)
29
- end
30
-
31
- def save_product_file!
32
- File.write(FILE_PATH, @hash.to_yaml)
33
- end
34
-
35
- def rewrite_version_file!
36
- version_module = File.read(version_file)
37
- new_module = version_module.
38
- sub(/^(\s*)(VERSION\s*=\s*).*$/) { "#{$1}#{$2}#{quoted_version}" }
39
- File.write(version_file, new_module)
40
- end
41
-
42
- def version
43
- @hash['version']['number']
44
- end
45
-
46
- def quoted_version
47
- if version.include?("'")
48
- version.inspect
49
- else
50
- "'#{version}'"
51
- end
52
- end
53
-
54
- def version=(number)
55
- @hash['version']['number'] = number
56
- end
57
-
58
- # returns an array of [ major, minor, patch, suffix ].
59
- #
60
- # each element will be returned as a String.
61
- def version_parts
62
- version.split(/\./, 4)
63
- end
64
-
65
- # bump the version according to the given release type:
66
- #
67
- # 'major' -> increment major component, zero the others
68
- # 'minor' -> increment minor component, zero the patch
69
- # 'patch' -> increment the patch component
70
- def bump_version(release)
71
- major, minor, patch, suffix = version_parts
72
-
73
- case release
74
- when 'major' then
75
- major = major.to_i + 1
76
- minor = patch = 0
77
- when 'minor'
78
- minor = minor.to_i + 1
79
- patch = 0
80
- when 'patch'
81
- patch = patch.to_i + 1
82
- else
83
- raise ArgumentError, "invalid release type: #{release.inspect}"
84
- end
85
-
86
- self.version = [ major, minor, patch ].join('.')
87
- end
88
-
89
- # Invokes `#bump_version`, and then saves the new version to the
90
- # product.yml file and to the version.rb file.
91
- def bump_version!(release)
92
- bump_version(release)
93
- save_product_file!
94
- rewrite_version_file!
95
- end
96
-
97
- def version_file
98
- @hash['version']['file']
99
- end
100
-
101
- def name
102
- @hash['name']
103
- end
104
-
105
- # The description is intended to be used in places where it can be
106
- # appended to the end of a sentence, e.g.
107
- #
108
- # "We just released #{product.name} - #{product.description}!"
109
- #
110
- # Markdown formatting is allowed (even expected).
111
- def description
112
- @hash['description']
113
- end
114
-
115
- def package
116
- @hash['package']
117
- end
118
-
119
- def jira_project_url
120
- @hash['jira']
121
- end
122
-
123
- def tag_name
124
- "v#{version}"
125
- end
126
-
127
- def tag_exists?(tag = tag_name)
128
- `git tag -l #{tag}`.strip == tag
129
- end
130
-
131
- def branch_exists?(branch)
132
- `git branch -l #{branch}`.strip == branch
133
- end
134
-
135
- def base_branch
136
- @base_branch ||= begin
137
- major, minor, = version_parts
138
- branch = "#{major}.#{minor}-stable"
139
- branch_exists?(branch) ? branch : 'master'
140
- end
141
- end
142
- end
143
- end
144
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../mrss/release/candidate'
4
-
5
- namespace :candidate do
6
- desc 'Initialize a new product.yml file'
7
- task :init do
8
- Mrss::Release::ProductData.init!
9
- puts "product.yml file created"
10
- end
11
-
12
- desc 'Print the release notes for the next candidate release'
13
- task :preview do
14
- Mrss::Release::Candidate.instance do |candidate|
15
- # load the pending changes before bumping the version, since it
16
- # depends on the value of the current version.
17
- candidate.pending_changes
18
- candidate.bump_version
19
- puts candidate.release_notes
20
- end
21
- end
22
-
23
- desc 'List the pull requests to be included in the next release'
24
- task :prs do
25
- Mrss::Release::Candidate.instance.decorated_prs.each do |pr|
26
- print "\##{pr['number']}[#{pr['type-code']}] "
27
- print "#{pr['jira']} " if pr['jira']
28
- puts pr['short-title']
29
- end
30
- end
31
-
32
- desc 'Create a new branch and pull request for the candidate'
33
- task create: :check_branch_status do
34
- Mrss::Release::Candidate.instance do |candidate|
35
- origin = `git config get remote.origin.url`
36
- match = origin.match(/:(.*?)\//) or raise "origin url is not in expected format: #{origin.inspect}"
37
- user = match[1]
38
-
39
- puts 'gathering candidate info and bumping version...'
40
- candidate.bump_version!
41
-
42
- puts 'writing release notes to /tmp/pr-body.md...'
43
- File.write('/tmp/pr-body.md', candidate.release_notes)
44
-
45
- sh 'git', 'checkout', '-b', candidate.branch_name
46
- sh 'git', 'commit', '-am', "Bump version to #{candidate.product.version}"
47
- sh 'git', 'push', 'origin', candidate.branch_name
48
-
49
- sh 'gh', 'pr', 'create',
50
- '--head', "#{user}:#{candidate.branch_name}",
51
- '--base', candidate.product.base_branch,
52
- '--title', "Release candidate for #{candidate.product.version}",
53
- '--label', 'release-candidate',
54
- '--body-file', '/tmp/pr-body.md'
55
- end
56
- end
57
-
58
- # Ensures the current branch is up-to-date with no uncommitted changes
59
- task :check_branch_status do
60
- sh 'git pull >/dev/null', verbose: false
61
- changes = `git status --short --untracked-files=no`.strip
62
- abort "There are uncommitted changes. Commit (or revert) the changes and try again." if changes.length > 0
63
- end
64
- end