go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/starlark/stdlib/internal/experiments.star (about) 1 # Copyright 2020 The LUCI Authors. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 """Internal API for registering and checking experiments.""" 16 17 load("@stdlib//internal/strutil.star", "strutil") 18 19 def _register(experiment_id, enable_on_min_version = None): 20 """Register an experiment with the given ID. 21 22 This ID becomes a valid target for lucicfg.enable_experiment(...) call. 23 Returns an object that can be used to check whether the experiment was 24 enabled. It is fine and even recommended to register the experiments during 25 the module loading time: 26 27 ```python 28 load('@stdlib//internal/experiments.star', 'experiments') 29 new_cool_feature_experiment = experiments.register('new_cool_feature') 30 31 ... 32 33 def something(...): 34 new_cool_feature_experiment.require() 35 ``` 36 37 Registering the same experiment ID multiple times is fine, it results in the 38 exact same experiment. 39 40 Args: 41 experiment_id: an ID of the experiment to register. Required. 42 enable_on_min_version: if present, should be a lucicfg version string (as 43 `major.minor.revision`) indicating when to auto-enable this experiment: 44 calling lucicfg.check_version(...) with some version `X` will implicitly 45 enable all experiments with `enable_on_min_version >= X`. Experiments 46 that don't have `enable_on_min_version` can only be enabled explicitly 47 via lucicfg.enable_experiment(...). Be careful when using this 48 mechanism. Once an experiment gated by a min lucicfg version is 49 released, it is not really an experiment anymore, but a stable (albeit 50 non-default) functionality. It must remain backward compatible. Projects 51 that opt-in into it using lucicfg.check_version(...) don't expect the 52 generated files to change if a newer lucicfg version is released. If you 53 need to change an already released auto-enabled experiment, you'll need 54 to create a new experiment that "mutates" the behavior of the old one, 55 and gets auto-enabled in a newer lucicfg version. 56 57 Returns: 58 A struct with methods `require()` and `is_enabled()`: 59 `is_enabled()` returns True if the experiment is enabled. 60 `require()` fails the execution if the experiment is not enabled. 61 """ 62 min_ver = () 63 if enable_on_min_version != None: 64 min_ver = strutil.parse_version(enable_on_min_version) 65 __native__.register_experiment(experiment_id, min_ver) 66 return struct( 67 is_enabled = lambda: _is_enabled(experiment_id), 68 require = lambda: _require(experiment_id), 69 ) 70 71 def _require(experiment_id): 72 """Fails the execution if the given experiment ID is not enabled. 73 74 Args: 75 experiment_id: a string with the ID of the experiment to check. 76 """ 77 if not _is_enabled(experiment_id): 78 fail( 79 "This feature requires enabling the experiment %r.\n" % experiment_id + 80 "To enable it, add this line somewhere early in your script:\n" + 81 " lucicfg.enable_experiment(%r)\n" % experiment_id + 82 "Note that using experimental features comes with zero guarantees. " + 83 "See the doc for lucicfg.enable_experiment(...) for more information", 84 ) 85 86 def _is_enabled(experiment_id): 87 """Returns True if the experiment was enabled.""" 88 return __native__.is_experiment_enabled(experiment_id) 89 90 experiments = struct( 91 register = _register, 92 )