go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/README.md (about) 1 # LUCI Configuration Generator 2 3 `lucicfg` is a tool for generating low-level LUCI configuration files based on a 4 high-level configuration given as a [Starlark] script that uses APIs exposed by 5 `lucicfg`. In other words, it takes a \*.star file (or files) as input and spits 6 out a bunch of \*.cfg files (such us `cr-buildbucket.cfg` and 7 `luci-scheduler.cfg`) as outputs. 8 9 [Starlark]: https://github.com/google/starlark-go 10 11 ## Overview of the design 12 13 `lucicfg` follows a "microkernel" architecture. The kernel is implemented in Go. 14 It provides a private interface (used internally by the lucicfg's Starlark 15 standard library) by registering a bunch of builtins. The functionality provided 16 by the kernel is pretty generic: 17 18 * A notion of Starlark packages, `load(...)` and `exec(...)` implementation. 19 * `lucicfg.var(...)` implementation. 20 * A node graph structure to carry the state across module boundaries. 21 * Support for traversing the node graph and emitting files to an output. 22 * Support for Protobuf messages. 23 * Implementation of `lucicfg generate` and `lucicfg validate` logic. 24 * Various utilities (regexp, hashes, Go templates, etc.) 25 26 The builtins are wrapped in two layers of Starlark code: 27 28 * [starlark/stdlib/internal], excluding `.../luci`: generic (not LUCI 29 specific) Starlark standard library that documents and exposes the builtins 30 via a nicer API. It can be used to build all kinds of config generators 31 ([1], [2], [3]), as well as extend the LUCI config generator. This API 32 surface is currently marked as "internal" (meaning there's no backward 33 compatibility guarantees for it), but it will some day become a part of 34 lucicfg's public interface, so it should be treated as such (no hacks, no 35 undocumented functions, adequate test coverage, etc). 36 * [starlark/stdlib/internal/luci]: all LUCI-specific APIs and declarations, 37 implementing the logic of generating LUCI configs specifically. It is built 38 39 The standard library and LUCI configs library are bundled with `lucicfg` binary 40 via starlark/assets.gen.go file generated from the contents of 41 [starlark/stdlib/internal] by `go generate`. 42 43 [starlark/stdlib/internal]: ./starlark/stdlib/internal 44 [starlark/stdlib/internal/luci]: ./starlark/stdlib/internal/luci 45 [1]: https://chrome-internal.googlesource.com/infradata/config/+/refs/heads/main/starlark/common/lib 46 [2]: https://chrome-internal.googlesource.com/infradata/k8s/+/refs/heads/main/starlark/lib 47 [3]: https://chrome-internal.googlesource.com/infradata/gae/+/refs/heads/main/starlark/lib 48 49 ## Making changes to the Starlark portion of the code 50 51 1. Modify a `*.star` file. 52 2. In the `lucicfg` directory, where this README.md file is, run 53 `./fmt-lint.sh` to auto-format and lint new code. Fix all linter warnings. 54 3. In the same directory run `go generate ./...` to regenerate 55 `examples/.../generated` and [doc/README.md]. 56 4. Run `go test ./...` to verify existing tests pass. If your change modifies 57 the format of emitted files you need to update the expected output in test 58 case files. It will most likely happen for [testdata/full_example.star]. 59 Update `Expect configs:` section there. 60 5. If your change warrants a new test, add a file somewhere under [testdata/]. 61 See existing files there for examples. There are two kinds of tests: 62 * "Expectation style" tests. They have `Expect configs:` or `Expect errors 63 like:` sections at the bottom. The test runner will execute the Starlark 64 code and compare the produced output (or errors) to the expectations. 65 * More traditional unit tests that use `assert.eq(...)` etc. See 66 [testdata/misc/version.star] for an example. 67 6. Once you are done with the change, evaluate whether you need to bump lucicfg 68 version. See the section below. 69 70 [doc/README.md]: ./doc/README.md 71 [testdata/full_example.star]: ./testdata/full_example.star 72 [testdata/]: ./testdata 73 [testdata/misc/version.star]: ./testdata/misc/version.star 74 75 ## Updating lucicfg version 76 77 `lucicfg` uses a variant of semantic versioning to identify its own version and 78 a version of the bundled Starlark libraries. The version string is set in 79 [version.go] and looks like `MAJOR.MINOR.PATCH`. 80 81 If a user script is relying on a feature which is available only in some recent 82 lucicfg version, it can perform a check, like so: 83 84 ```starlark 85 lucicfg.check_version('1.7.8', 'Please update depot_tools') 86 ``` 87 88 That way if the script is executed by an older lucicfg version, the user will 89 get a nice actionable error message instead of some obscure stack trace. 90 91 Thus it is **very important** to update [version.go] before releasing changes: 92 93 * Increment `PATCH` version when you make backward compatible changes. A 94 change is backward compatible if it doesn't reduce Starlark API surface and 95 doesn't affect lucicfg's emitted output (assuming inputs do not change). In 96 particular, adding a new feature that doesn't affect existing features is 97 backward compatible. 98 * Increment `MINOR` version when you make backward incompatible changes. 99 Releasing such changes may require modifying user scripts or asking users to 100 regenerate their configs to get an updated output. Note that both these 101 things are painful, since there are dozens of repositories with lucicfg 102 scripts and, strictly speaking, all of them should be eventually updated. 103 * `MAJOR` version is reserved for major architecture changes or rewrites. 104 105 If your new feature is experimental and you don't want to commit to any backward 106 compatibility promises, hide it behind an experiment. Users will need to opt-in 107 to use it. See [starlark/stdlib/internal/experiments.star] for more info. 108 109 [version.go]: ./version.go 110 [starlark/stdlib/internal/experiments.star]: ./starlark/stdlib/internal/experiments.star 111 112 ## Making a release 113 114 1. Land the code change. For concreteness sake let's assume it resulted in this 115 [luci-go commit]. 116 2. Wait until it is rolled into [infra.git]. The roll will look like this 117 [infra.git commit]. Notice its git hash `86afde8bddae...`. 118 3. Wait until the [CIPD package builders] produce per-platform lucicfg 119 [CIPD packages] tagged with infra.git's hash `git_revision:86afde8bddae...`. 120 Like [this one]. 121 4. Land a depot_tools CL to release the new version to developer workstations: 122 1. Modify [cipd_manifest.txt]: `infra/tools/luci/lucicfg/${platform} 123 git_revision:86afde8bddae...`. 124 2. As instructed in the comments, regenerate cipd_manifest.versions: `cipd 125 ensure-file-resolve -ensure-file cipd_manifest.txt`. 126 3. Send a CL [like this], describing in the commit message what's new. 127 5. Modify [cr-buildbucket/settings.cfg] like [so] to release the change to 128 bots. This step is necessary since bots don't use depot_tools. 129 130 Steps 2 and 3 usually take about 30 minutes total, and steps 4 and 5 verify 131 CIPD packages actually exist. So in practice it is OK to just land a lucicfg 132 CL, go do other things, then come back >30 min later, look up the revision of 133 the necessary infra.git DEPS roll (or just use the latest one) and proceed to 134 steps 4 and 5. 135 136 [infra.git]: https://chromium.googlesource.com/infra/infra/ 137 [luci-go commit]: https://chromium.googlesource.com/infra/luci/luci-go.git/+/7ac4bfbe5a282766ea2e8afa5a6a06e8b71879f3 138 [infra.git commit]: https://chromium.googlesource.com/infra/infra/+/86afde8bddaefce47381b7cc4638b36717803d3a 139 [CIPD package builders]: https://ci.chromium.org/p/infra-internal/g/infra-packagers/console 140 [CIPD packages]: https://chrome-infra-packages.appspot.com/p/infra/tools/luci/lucicfg 141 [this one]: https://chrome-infra-packages.appspot.com/p/infra/tools/luci/lucicfg/linux-amd64/+/git_revision:86afde8bddaefce47381b7cc4638b36717803d3a 142 [cipd_manifest.txt]: https://chromium.googlesource.com/chromium/tools/depot_tools/+/refs/heads/main/cipd_manifest.txt 143 [like this]: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2137983 144 [cr-buildbucket/settings.cfg]: https://chrome-internal.googlesource.com/infradata/config/+/refs/heads/main/configs/cr-buildbucket/settings.cfg 145 [so]: https://chrome-internal-review.googlesource.com/c/infradata/config/+/2849250