theoremlp / rules_multitool

Bazel rules for ergonomic tool definitions
Apache License 2.0
24 stars 6 forks source link

Consider supporting multiple versions of the same tool #32

Closed alexeagle closed 6 months ago

alexeagle commented 6 months ago

rules_lint uses rules_multitool for lots of tools like formatters https://github.com/aspect-build/rules_lint/blob/main/lint/multitool.lock.json

But some linters have subtle breaking changes between versions, so forcing users to the latest version as of a rules_lint release may be newer than they can tolerate. To decouple these, it would be nice if a file like https://github.com/aspect-build/rules_lint/blob/main/lint/ruff_versions.bzl could be translated to a multitool.lock.json (I'm not loving any schema design changes I played with)

Then at the configuration site, where multitool.hub(lockfile = "//lint:multitool.lock.json") appears, a version for a given binary could be selected. By default, the latest (or first declared?) one would be used.

mark-thm commented 6 months ago

I think in this case you could have a 'compilation' step that picks the versions -- in rules_lint, imagine a macro that's something like:

generate_multitool_lockfile(
    ruff = "v0.4.1",
    # ... other tools as desired
)

Which under the covers should produce the desired multitool.lock.json and a difftest.

mark-thm commented 6 months ago

I think if you want multiple versions available concurrently we'd have to include the version information in the toolchain and somehow your users would need to propagate a constraint on version. I don't know how that would impact downloads.

We probably don't have to break the schema too badly, for each tool, today, we have a single key binaries, but we could instead support a key versions, something like:

{
  "tool-name": {
    "versions": {
      "v0.1.0": {
        "artifacts": [
          { url ... }
        ]
       }
    }
  }
}

One more alternative to consider is embedding the version in the toolname, if ruff-v0.4.2 is really very different than e.g. ruff-v0.3.7, it might be better to declare them as if they were different tools. Again, I'm less clear on how badly this affects downloads given the way we structure the underlying repositories.

mark-thm commented 6 months ago

One more thing you can consider is declaring many lockfiles, and then your users can choose which one(s) in their module/workspace. Multitool will take the union over the definitions.

e.g.:

multitool.hub(lockfile = “//lint:ruff-v0.3.7.lock.json”)
multitool.hub(lockfile = “//lint:prettier-3.2.5.lock.json”)
mark-thm commented 6 months ago

Going to close this out since there’s a number of options presented above. Feel free to reopen or find me on Bazel slack if you’d like to discuss further.