higherkindness/rules_scala

Feature Request: Command to automatically apply buildozer suggestions

kerinin opened this issue · 1 comments

I love the deps errors and buildozer command suggestions - I would love being able to apply all of them automatically even more. I'm imagining something similar to how gazelle works for golang: bazel run //:ensure_scala_deps or something similar.

I'm not sure if this is exactly what you are looking for, but ibazel has a way to automatically run commands based on the output of a build. The downside is you have to run ibazel build instead of bazel build. Sometimes you don't know you want the output runner until it's too late. So we wrote this script that looks at the log from the last bazel command and does the same thing as the ibazel output runner would have done (hopefully).

tools/bazel-fix-deps.py:

#!/usr/bin/python3
import json
from os.path import realpath
import os
import re
import subprocess

parsers = {}
cwd = os.path.dirname(os.path.realpath(__file__))
with open(os.path.join(cwd, '../.bazel_fix_commands.json')) as f:
    parsers = json.load(f)

log = ""
with open(realpath(os.path.join(cwd, '../bazel-main/../../command.log'))) as f:
    log = f.read()

for parser in parsers:
    matches = re.finditer(parser['regex'].replace("\\\\", "\\"), log, re.MULTILINE)
    for m in matches:
        args = []
        def repl(matchobj):
            return m[int(matchobj.group(1))]
        # Make a list of args
        for arg in parser['args']:
            args.append(re.sub("\$([0-9]+)", repl, arg))
        # Replace numbers with their groups
        command = re.sub("\$([0-9]+)", repl, parser['command'])
        # Run a subprocess to do a thing
        print(os.path.join(cwd, '../', command), args)
        subprocess.run([os.path.join(cwd, '../', command)] + args)

Is it super hacky? Yeah. But it seems to work for us for now.