Disclosure: This article was translated from original in Japanese and I did some ajustments, but it still needs an english review. 😅
Since I touched go/gofmt a few years ago, if code format on Save isn’t done, I’ll have a sloppy code, and even
"ruby.format": "rubocop"in Rails development at work, I 've done Format on Save.
However, rubocop is slow to start, and it takes 1-2 seconds from Ctrl + S to Format & Save, which is very stressful ...
So I tried to run rubocop fast and satisfactorily in Docker environment.
I added rubocop-daemon to docker-compose of the existing project, and created an environment where it can be run as rubocop by sending commands locally.
Fork and function addition of rubocop-daemon main body, compose setting, environment-specific wrapper script (
rubocopthing that works as) was created, and the environment that can be executed as formatter from vscode is described.
The daemon that requires rubocop is started, and the actual CLI is a tool that only sends commands to the daemon and receives the results (processing is executed by the daemon). It is a mechanism that does not generate startup overhead at each execution and is fast.
This one! This is what I was looking for! If you move this with docker-compose, eh!
I thought …, but this is not a docker environment, but rather an implementation that can be used in a way that multiple hosts can be set up, so it seems that it will be a good idea to run it in a docker environment.
I will move it for the time being
However, first try to make it work at least.
The directory structure of the project is assumed as a standard Rails project
Also, the Dockerfile is assumed to be as simple as the following.
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . /app
Add rubocop-daemon to this environment adding the following to your Gemfile.
gem 'rubocop-daemon', github: 'cumet04/rubocop-daemon', branch: 'binding_option', require: false
Now let’s add rubocop to your docker-compose.yml
command: bundle exec rubocop-daemon start --no-daemon --binding 0.0.0.0 --port 3001
Write a wrapper script
Now that the daemon side is ready, prepare the client side.
Since the original
rubocop-daemon-wrappercannot be used due to differences in usage assumptions and file paths, we will create it with this environment specialization. Also, since it is troublesome to branch, it is optimized to be used only as a vscode formatter.
NETCAT="nc -N" # Remove the -N if you not using Linux
COMMAND="$(cat $DAEMON_DIR/token) /app exec $@"
printf '%s\n%s\n' "$COMMAND" "$STDIN_CONTENT" | $NETCAT 127.0.0.1 $(cat $DAEMON_DIR/port)
exit $(cat $DAEMON_DIR/status)
The command adopted an expression that directly rewrites the code. For Linux users
nc -N, git exclude it. I wanted to be able to overwrite it with an environment variable, but I gave up because it didn't load properly when I ran it from vscode.
Subsequent processing is simplified with reference to the original.
-sIt is a definite option if it is specified. We also handle error handling
set -e. This is fine as long as it is used in the project.
At this point, the above file
-scan be used as an optional rubocop command as shown below.
ncThe operation is fast because it is a simple script using commands.
You can test it in the host terminal with:
$ cat config/application.rb | ./bin/rubocop -s config/application.rb
Inspecting 1 file
config/application.rb:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment.
config/application.rb:1:18: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
config/application.rb:3:9: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
config/application.rb:10:3: C: Style/Documentation: Missing top-level class documentation comment.
class Application < Rails::Application
1 file inspected, 4 offenses detected, 3 offenses auto-correctable
vscode settings & launch
At this point, your VScode can use the script as rubocop, install the rubocop extension and set the following in vscode settings.json:
This is a version of the original article in japanese https://zenn.dev/cumet04/articles/fast-rubocop-on-docker