pact_broker 2.85.1 → 2.86.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release_gem.yml +1 -1
  3. data/.github/workflows/trigger_pact_docs_update.yml +22 -0
  4. data/CHANGELOG.md +10 -0
  5. data/DEVELOPER_DOCUMENTATION.md +0 -2
  6. data/db/migrations/20210914_add_labels_to_webhooks.rb +14 -0
  7. data/db/migrations/20210915_add_verified_by_to_verification.rb +6 -0
  8. data/docker-compose-ci-mysql.yml +1 -0
  9. data/docs/CONFIGURATION.md +255 -66
  10. data/docs/configuration.yml +166 -101
  11. data/lib/db.rb +0 -1
  12. data/lib/pact_broker/api/contracts/webhook_contract.rb +24 -2
  13. data/lib/pact_broker/api/decorators/verification_decorator.rb +4 -0
  14. data/lib/pact_broker/api/decorators/webhook_decorator.rb +27 -4
  15. data/lib/pact_broker/api/pact_broker_urls.rb +4 -0
  16. data/lib/pact_broker/api/resources/all_webhooks.rb +2 -2
  17. data/lib/pact_broker/config/runtime_configuration.rb +4 -0
  18. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +1 -1
  19. data/lib/pact_broker/db/clean.rb +1 -2
  20. data/lib/pact_broker/doc/views/pacticipant/label.markdown +12 -0
  21. data/lib/pact_broker/doc/views/webhooks.markdown +17 -0
  22. data/lib/pact_broker/domain/pacticipant.rb +4 -0
  23. data/lib/pact_broker/domain/verification.rb +16 -4
  24. data/lib/pact_broker/domain/webhook.rb +5 -5
  25. data/lib/pact_broker/domain/webhook_pacticipant.rb +6 -0
  26. data/lib/pact_broker/locale/en.yml +1 -0
  27. data/lib/pact_broker/matrix/head_row.rb +1 -1
  28. data/lib/pact_broker/matrix/quick_row.rb +0 -1
  29. data/lib/pact_broker/matrix/repository.rb +0 -1
  30. data/lib/pact_broker/matrix/row.rb +2 -2
  31. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +0 -1
  32. data/lib/pact_broker/pacts/pact_publication.rb +7 -0
  33. data/lib/pact_broker/pacts/pact_publication_clean_selector_dataset_module.rb +19 -0
  34. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +30 -2
  35. data/lib/pact_broker/pacts/pact_version.rb +24 -1
  36. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +2 -2
  37. data/lib/pact_broker/pacts/repository.rb +50 -47
  38. data/lib/pact_broker/test/http_test_data_builder.rb +37 -10
  39. data/lib/pact_broker/test/test_data_builder.rb +22 -5
  40. data/lib/pact_broker/verifications/repository.rb +5 -2
  41. data/lib/pact_broker/verifications/service.rb +4 -1
  42. data/lib/pact_broker/version.rb +1 -1
  43. data/lib/pact_broker/webhooks/event_listener.rb +4 -2
  44. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +1 -0
  45. data/lib/pact_broker/webhooks/repository.rb +10 -4
  46. data/lib/pact_broker/webhooks/webhook.rb +66 -8
  47. data/script/data/verify-pact-for-multiple-selectors.rb +30 -0
  48. data/script/docs/generate-configuration-docs.rb +24 -3
  49. data/script/generate-erd +55 -0
  50. data/spec/features/create_webhook_spec.rb +55 -10
  51. data/spec/features/get_pact_spec.rb +2 -3
  52. data/spec/fixtures/verification.json +4 -0
  53. data/spec/integration/webhooks/pact_publication_spec.rb +51 -0
  54. data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +50 -0
  55. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +8 -1
  56. data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +3 -1
  57. data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +4 -4
  58. data/spec/lib/pact_broker/config/runtime_configuration_documentation_spec.rb +30 -0
  59. data/spec/lib/pact_broker/deployments/environment_service_spec.rb +1 -1
  60. data/spec/lib/pact_broker/matrix/head_row_spec.rb +9 -5
  61. data/spec/lib/pact_broker/pacts/{latest_tagged_pact_publications_spec.rb → pact_publication_clean_selector_dataset_module_spec.rb} +7 -9
  62. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +32 -0
  63. data/spec/lib/pact_broker/pacts/repository_spec.rb +33 -0
  64. data/spec/lib/pact_broker/verifications/service_spec.rb +16 -2
  65. data/spec/lib/pact_broker/webhooks/repository_spec.rb +158 -15
  66. data/spec/lib/pact_broker/webhooks/webhook_spec.rb +8 -5
  67. metadata +16 -11
  68. data/lib/pact_broker/pacts/all_pact_publications.rb +0 -158
  69. data/lib/pact_broker/pacts/latest_pact_publications.rb +0 -48
  70. data/lib/pact_broker/pacts/latest_pact_publications_by_consumer_version.rb +0 -26
  71. data/lib/pact_broker/pacts/latest_tagged_pact_publications.rb +0 -45
  72. data/lib/pact_broker/verifications/latest_verification_for_pact_version.rb +0 -39
  73. data/spec/lib/pact_broker/verifications/latest_verification_for_pact_version_spec.rb +0 -18
@@ -1,4 +1,42 @@
1
1
  groups:
2
+ - title: Logging
3
+ vars:
4
+ log_level:
5
+ description: "The application log level"
6
+ default_value: info
7
+ allowed_values:
8
+ - debug
9
+ - info
10
+ - warn
11
+ - error
12
+ - fatal
13
+ log_format:
14
+ description: "The application log format. Can be any value supported by Semantic Logger."
15
+ default_value: "default"
16
+ allowed_values:
17
+ - default
18
+ - json
19
+ - color
20
+ more_info: https://github.com/rocketjob/semantic_logger/tree/master/lib/semantic_logger/formatters
21
+ log_dir:
22
+ description: "The log file directory"
23
+ default_value: "./logs"
24
+ log_stream:
25
+ description: |-
26
+ The stream to which the logs will be sent.
27
+
28
+ While the default is `file` for the Ruby application, it is set to `stdout` on the supported Docker images.
29
+ default_value: "file"
30
+ allowed_values:
31
+ - stdout
32
+ - file
33
+ hide_pactflow_messages:
34
+ description: "Set to `true` to hide the messages in the logs about Pactflow"
35
+ default_value: true
36
+ allowed_values:
37
+ - true
38
+ - false
39
+ more_info: https://pactflow.io
2
40
  - title: Database
3
41
  vars:
4
42
  database_adapter:
@@ -7,7 +45,7 @@ groups:
7
45
 
8
46
  For investigations/spikes on a development machine, you can use SQlite. It is not supported as a production database, as it does not support
9
47
  concurrent requests.
10
- default: "postgres"
48
+ default_value: "postgres"
11
49
  allowed_values:
12
50
  - postgres (for production use)
13
51
  - sqlite (for spikes only)
@@ -28,13 +66,14 @@ groups:
28
66
  database_url:
29
67
  description: |-
30
68
  The full database URL may be specified instead of the separate adapter, username, password, name, host and port.
31
- format: "{database_adapter}://{database_username}:{database_password}@{database_host}:{database_port}/{database_name}"
69
+ format: "`{database_adapter}://{database_username}:{database_password}@{database_host}:{database_port}/{database_name}`"
32
70
  examples:
33
71
  - postgres://pact_broker_user:pact_broker_password@pact_broker_db_host/pact_broker
34
- - sqlite:////tmp/pact_broker.sqlite3
72
+ - sqlite:///tmp/pact_broker.sqlite3 (relative path to working directory)
73
+ - sqlite:////tmp/pact_broker.sqlite3 (absolute path)
35
74
  database_sslmode:
36
75
  description: The Postgresql ssl mode.
37
- default: prefer
76
+ default_value: prefer
38
77
  allowed_values:
39
78
  - disable
40
79
  - allow
@@ -48,7 +87,7 @@ groups:
48
87
  The log level that will be used when the SQL query statements are logged.
49
88
 
50
89
  To disable noisy SQL query logging when the application `log_level` is set to `debug` for other reasons, use the value `none`.
51
- default: debug
90
+ default_value: debug
52
91
  allowed_values:
53
92
  - none
54
93
  - debug
@@ -57,98 +96,71 @@ groups:
57
96
  - error
58
97
  - fatal
59
98
  sql_log_warn_duration:
60
- description: ""
61
- default: 5
62
- allowed_values:
63
- more_info:
99
+ description: "The number of seconds after which to log an SQL query at warn level. Use this for detecting slow queries."
100
+ default_value: 5
101
+ allowed_values_description: A positive integer or float, as a string.
102
+ more_info: https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
64
103
  database_max_connections:
65
- description: ""
66
- default: nil
67
- allowed_values:
68
- more_info:
104
+ description: "The maximum size of the connection pool (4 connections by default on most databases)"
105
+ default_value: 4
106
+ allowed_values_description: A positive integer value.
107
+ more_info: https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
69
108
  database_pool_timeout:
70
- description: ""
71
- default: 5
72
- allowed_values:
73
- more_info:
109
+ description: "The number of seconds to wait if a connection cannot be acquired before raising an error"
110
+ default_value: 5
111
+ allowed_values_description: A positive integer.
112
+ more_info: https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options
74
113
  database_connect_max_retries:
75
- description: ""
76
- default: 0
77
- allowed_values:
78
- more_info:
114
+ description: |-
115
+ When running the Pact Broker Docker image experimentally using Docker Compose on a local development machine,
116
+ the Broker application process may be ready before the database is available for connection, causing the application
117
+ container to exit with an error. Setting the max retries to a non-zero number will allow it to retry the connection the
118
+ configured number of times, waiting 3 seconds between attempts.
119
+ default_value: 0
120
+ allowed_values_description: A positive integer value.
79
121
  auto_migrate_db:
80
- description: ""
81
- default: true
122
+ description: "Whether or not to run the database schema migrations on start up. It is recommended to set this to `true`."
123
+ default_value: true
82
124
  allowed_values:
83
- more_info:
125
+ - true
126
+ - false
84
127
  auto_migrate_db_data:
85
- description: ""
86
- default: true
128
+ description: "Whether or not to run the database data migrations on start up. It is recommended to set this to `true`."
129
+ default_value: true
87
130
  allowed_values:
88
- more_info:
131
+ - true
132
+ - false
89
133
  allow_missing_migration_files:
90
- description: ""
91
- default: true
92
- allowed_values:
93
- more_info:
94
- validate_database_connection_config:
95
- description: ""
96
- default: true
134
+ description: |-
135
+ If `true`, will not raise an error if a database migration is recorded in the database that does not have an
136
+ equivalent file in the codebase. If this is true, an older version of the code may be used with a newer version of the database,
137
+ however, data integrity issues may occur.
138
+ default_value: true
97
139
  allowed_values:
98
- more_info:
140
+ more_info: https://sequel.jeremyevans.net/rdoc/classes/Sequel/Migrator.html
99
141
  database_statement_timeout:
100
- description: ""
101
- default: 15
102
- allowed_values:
103
- more_info:
142
+ description: "The number of seconds after which an SQL query will be aborted. Only supported for Postgresql connections."
143
+ default_value: 15
144
+ allowed_values_description: A positive integer or float.
145
+ more_info: https://www.postgresql.org/docs/9.3/runtime-config-client.html
104
146
  metrics_sql_statement_timeout:
105
- description: ""
106
- default: 30
107
- allowed_values:
108
- more_info:
147
+ description: |-
148
+ The number of seconds after which the SQL queries used for the metrics endpoint will be aborted.
149
+ This is configurable separately from the standard `database_statement_timeout` as it may need to be significantly
150
+ longer than the desired value for standard queries.
151
+ default_value: 30
152
+ allowed_values_description: A positive integer.
109
153
  database_connection_validation_timeout:
110
- description: ""
111
- default:
112
- allowed_values:
113
- more_info:
114
- - title: Logging
115
- vars:
116
- log_level:
117
- description: "The application log level"
118
- default: info
119
- allowed_values:
120
- - debug
121
- - info
122
- - warn
123
- - error
124
- - fatal
125
- log_format:
126
- description: "The application log format. Can be any value supported by Semantic Logger."
127
- default: "default"
128
- allowed_values:
129
- - default
130
- - json
131
- - color
132
- more_info: https://github.com/rocketjob/semantic_logger/tree/master/lib/semantic_logger/formatters
133
- log_dir:
134
- description: "The log file directory"
135
- default: "./logs"
136
- log_stream:
137
154
  description: |-
138
- The stream to which the logs will be sent.
155
+ The number of seconds after which to check the health of a connection from a connection pool before passing it to the application.
139
156
 
140
- While the default is `file` for the Ruby application, it is set to `stdout` on the supported Docker images.
141
- default: "file"
142
- allowed_values:
143
- - stdout
144
- - file
145
- hide_pactflow_messages:
146
- description: "Set to `true` to hide the messages in the logs about Pactflow"
147
- default: true
148
- allowed_values:
149
- - true
150
- - false
151
- more_info: https://pactflow.io
157
+ `-1` means that connections will be validated every time, which avoids errors
158
+ when databases are restarted and connections are killed. This has a performance
159
+ penalty, so consider increasing this timeout if building a frequently accessed service.
160
+
161
+ default_description: -1 for v2.85.1 and earlier, 3600 for later versions.
162
+ allowed_values_description: -1 or any positive integer.
163
+ more_info: https://sequel.jeremyevans.net/rdoc-plugins/files/lib/sequel/extensions/connection_validator_rb.html
152
164
  - title: Authentication and authorization
153
165
  comments: |
154
166
  The Pact Broker comes with 2 configurable basic auth users - one with read/write privileges, and one with read only privileges.
@@ -156,8 +168,8 @@ groups:
156
168
  should be used for CI/CD.
157
169
  vars:
158
170
  basic_auth_enabled:
159
- description: "Whether to enable basic authorization"
160
- default: false
171
+ description: "Whether to enable basic authorization. This is automatically set to true for the Docker images if the `basic_auth_username` and `basic_auth_password` are set."
172
+ default_value: false
161
173
  allowed_values:
162
174
  - true
163
175
  - false
@@ -171,19 +183,19 @@ groups:
171
183
  description: "The password for the read only basic auth user."
172
184
  allow_public_read:
173
185
  description: "If you want to allow public read access, but still require credentials for writing, then leave `basic_auth_read_only_username` and `basic_auth_read_only_password` unset, and set `allow_public_read` to `true`."
174
- default: false
186
+ default_value: false
175
187
  allowed_values:
176
188
  - true
177
189
  - false
178
190
  public_heartbeat:
179
191
  description: "If you have enabled basic auth, but require unauthenticated access to the heartbeat URL (eg. for use within an AWS autoscaling group), set `public_heartbeat` to `true`."
180
- default: false
192
+ default_value: false
181
193
  allowed_values:
182
194
  - true
183
195
  - false
184
196
  enable_public_badge_access:
185
197
  description: "Set this to true to allow status badges to be embedded in README files without requiring a hardcoded password."
186
- default: false
198
+ default_value: false
187
199
  allowed_values:
188
200
  - true
189
201
  - false
@@ -193,13 +205,13 @@ groups:
193
205
  description: |-
194
206
  The schedule of seconds to wait between webhook execution attempts.
195
207
  The default schedule is 10 sec, 1 min, 2 min, 5 min, 10 min, 20 min (38 minutes in total).
196
- default: "10 60 120 300 600 1200"
208
+ default_value: "10 60 120 300 600 1200"
197
209
  format: A space separated list of integers.
198
210
  webhook_http_method_whitelist:
199
211
  description: |-
200
212
  The allowed HTTP methods for webhooks.
201
213
  It is highly recommended that only `POST` requests are allowed to ensure that webhooks cannot be used to retrieve sensitive information from hosts within the same network.
202
- default: "POST"
214
+ default_value: "POST"
203
215
  format: A space separated list.
204
216
  allowed_values:
205
217
  - POST
@@ -214,13 +226,13 @@ groups:
214
226
 
215
227
  In most cases, configuring this is not necessary, but there are some CI systems that return a non 200 status for a success,
216
228
  which is why this feature exists.
217
- default: "200 201 202 203 204 205 206"
229
+ default_value: "200 201 202 203 204 205 206"
218
230
  format: A space separated list of integers.
219
231
  allowed_values:
220
232
  - Any valid HTTP status code
221
233
  webhook_scheme_whitelist:
222
234
  description: "The allowed URL schemes for webhooks."
223
- default: "https"
235
+ default_value: "https"
224
236
  format: "A space delimited list."
225
237
  allowed_values:
226
238
  - https
@@ -230,8 +242,8 @@ groups:
230
242
  A list of hosts, network ranges, or host regular expressions.
231
243
  Regular expressions should start and end with a `/` to differentiate them from Strings.
232
244
  Note that backslashes need to be escaped with a second backslash when setting via an environment variable.
233
- Please read the Webhook whitelists section of the Pact Broker configuration documentation to understand how the whitelist is used.
234
- default:
245
+ Please read the [Webhook whitelists section](https://docs.pact.io/pact_broker/configuration/features#webhooks) of the Pact Broker configuration documentation to understand how the whitelist is used.
246
+ default_value:
235
247
  examples:
236
248
  - github.com
237
249
  - 10.2.3.41/24
@@ -239,18 +251,22 @@ groups:
239
251
  more_info: https://docs.pact.io/pact_broker/configuration/#webhook-whitelists
240
252
  disable_ssl_verification:
241
253
  description: "If set to true, SSL verification will be disabled for the HTTP requests made by the webhooks"
242
- default: false
254
+ default_value: false
243
255
  allowed_values:
244
256
  - true
245
257
  - false
246
- - title: HTTP
258
+ user_agent:
259
+ description: |-
260
+ The user agent to set when making HTTP requests for webhooks.
261
+ default_value: "Pact Broker v{VERSION}"
262
+ - title: Resources
247
263
  vars:
248
264
  port:
249
265
  description: |-
250
266
  The HTTP port that the Pact Broker application will run on. This will only be honoured if you are deploying the Pact Broker using
251
267
  a package that actually reads this property (eg. one of the supported Docker images). If you are running the vanilla Ruby application,
252
268
  the application will run on the port the server has been configured to run on (eg. `bundle exec rackup -p 9393`)
253
- default: 9292
269
+ default_value: 9292
254
270
  base_url:
255
271
  description: |-
256
272
  The full URL (including port, if non-standard for the protocol) at which the application will be made available to users.
@@ -270,8 +286,27 @@ groups:
270
286
  example: "http://my-internal-pact-broker:9292 https://my-external-pact-broker"
271
287
  shields_io_base_url:
272
288
  description: The URL of the shields.io server used to generate the README badges.
273
- default: https://img.shields.io
289
+ default_value: https://img.shields.io
274
290
  more_info: https://shields.io
291
+ badge_provider_mode:
292
+ description: |-
293
+ The method by which the badges are generated. When set to `redirect`, a request to the Pact Broker for a badge will be sent a redirect response
294
+ to render the badge from the shields.io server directly in the browser. This is the recommended value.
295
+ When set to `proxy`, the Pact Broker will make a request directly to the configured shields.io server, and then send the returned file
296
+ back to the browser. This mode is not recommended for security and performance reasons.
297
+ default_value: redirect
298
+ allowed_values:
299
+ - redirect
300
+ - proxy
301
+ enable_diagnostic_endpoints:
302
+ description: |-
303
+ Whether or not to enable the diagnostic endpoints at `/diagnostic/status/heartbeat` and `"diagnostic/status/dependencies`.
304
+ The heartbeat endpoint is for use by load balancers, and the dependencies endpoint is for checking that the database
305
+ is available (do not use this for load balancing, as it makes a database connection).
306
+ default_value: true
307
+ allowed_values:
308
+ - true
309
+ - false
275
310
  - title: Domain
276
311
  vars:
277
312
  check_for_potential_duplicate_pacticipant_names:
@@ -287,7 +322,7 @@ groups:
287
322
 
288
323
  To turn this feature off, set `check_for_potential_duplicate_pacticipant_names` to `false`, and make sure everyone is very careful with their naming!
289
324
  The usefulness of the Broker depends on the integrity of the data, which in turn depends on the correctness of the pacticipant names.
290
- default: true
325
+ default_value: true
291
326
  allowed_values:
292
327
  - true
293
328
  - false
@@ -298,7 +333,8 @@ groups:
298
333
  also created for the pacticipant version.
299
334
 
300
335
  This is to assist in the migration from using tags to track deployments to using the deployed and released versions feature.
301
- default: true
336
+ supported_versions: From v2.81.0
337
+ default_value: true
302
338
  allowed_values:
303
339
  - true
304
340
  - false
@@ -309,10 +345,39 @@ groups:
309
345
  will be used to populate the `branch` property of the version.
310
346
 
311
347
  This is to assist in the migration from using tags to track branches to using the branches feature.
312
- default: true
348
+ supported_versions: From v2.82.0
349
+ default_value: true
350
+ allowed_values:
351
+ - true
352
+ - false
353
+ auto_detect_main_branch:
354
+ description: |-
355
+ When `true` and a pacticipant version is created with a tag or a branch that matches one of the names in `main_branch_candidates`,
356
+ the `mainBranch` property is set for that pacticipant if it is not already set.
357
+
358
+ This is to assist in the migration from using tags to track branches to using the branches feature.
359
+ supported_versions: From v2.82.0
360
+ default_value: true
361
+ allowed_values:
362
+ - true
363
+ - false
364
+ main_branch_candidates:
365
+ description: |-
366
+ An array of potential main branch names used when automatically detecting the main branch for a pacticipant.
367
+ format: "A space delimited list."
368
+ default_value: "develop main master"
369
+ supported_versions: From v2.82.0
370
+ allow_dangerous_contract_modification:
371
+ description: |-
372
+ Whether or not to allow the pact content for an existing consumer version to be modified. It is strongly recommended that this is set to false,
373
+ as allowing modification makes the results of can-i-deploy unreliable. When this is set to false as recommended, each commit must publish pacts
374
+ with a unique version number.
375
+ default_description: For new installations of v2.82.0 and later, this defaults to `false`.
376
+ supported_versions: From v2.82.0
313
377
  allowed_values:
314
378
  - true
315
379
  - false
380
+ more_info: https://docs.pact.io/versioning
316
381
  - title: Miscellaneous
317
382
  vars:
318
383
  features:
data/lib/db.rb CHANGED
@@ -45,7 +45,6 @@ module DB
45
45
  end
46
46
  # rubocop: enable Lint/NestedMethodDefinition
47
47
  end
48
- con.pool.connection_validation_timeout = -1 #Check the connection on every request
49
48
  con.timezone = :utc
50
49
  con.run("SET sql_mode='STRICT_TRANS_TABLES';") if db_credentials[:adapter].to_s =~ /mysql/
51
50
  con
@@ -40,6 +40,7 @@ module PactBroker
40
40
 
41
41
  property :consumer do
42
42
  property :name
43
+ property :label
43
44
 
44
45
  validation do
45
46
  configure do
@@ -50,12 +51,23 @@ module PactBroker
50
51
  end
51
52
  end
52
53
 
53
- required(:name).filled(:pacticipant_exists?)
54
+ optional(:name)
55
+ .maybe(:pacticipant_exists?)
56
+ .when(:none?) { value(:label).filled? }
57
+
58
+ optional(:label)
59
+ .maybe(:str?)
60
+ .when(:none?) { value(:name).filled? }
61
+
62
+ rule(label: [:name, :label]) do |name, label|
63
+ (name.filled? & label.filled?) > label.none?
64
+ end
54
65
  end
55
66
  end
56
67
 
57
68
  property :provider do
58
69
  property :name
70
+ property :label
59
71
 
60
72
  validation do
61
73
  configure do
@@ -66,7 +78,17 @@ module PactBroker
66
78
  end
67
79
  end
68
80
 
69
- required(:name).filled(:pacticipant_exists?)
81
+ optional(:name)
82
+ .maybe(:pacticipant_exists?)
83
+ .when(:none?) { value(:label).filled? }
84
+
85
+ optional(:label)
86
+ .maybe(:str?)
87
+ .when(:none?) { value(:name).filled? }
88
+
89
+ rule(label: [:name, :label]) do |name, label|
90
+ (name.filled? & label.filled?) > label.none?
91
+ end
70
92
  end
71
93
  end
72
94