Both are tools tool to manage and configure Git hooks. These tools don’t allow you to push if in your code something is not satisfactory with your configuration file. Configuration files:
- .scalafmt - use by pre-commit-hook (by default)
- scalastyle-config.xml - use by overcommit (by default)
overcommit
is a Git hook manager that includes out-of-the-box support for running scalastyle as a Git pre-commit hook. It doens't support scalafmt git hook by default.
pre-commit-hook is a Git hook manager that runs scalafmt on CHANGED .scala and .sbt files each time you commit them. It support only local git hook for scalastyle and for that your local machine should has a runnable scalastyle from commandline.
Please add your opinion? I would go with second approach. See Alternative B
- use pre-commit-hook with scalafmt and setup scalastyle for your project as a part of compilation. See Alternative A
- use pre-commit-hook with scalafmt (allows to store hooks on Github) and scalastyle (local git hook). See Alternative B
- use overcommit with scalastyle and and add custom script. See Alternative C
- write custom script and add it to your .git/hooks folder or run it manually like:
bash ./pre-commit-hook.sh
The latest version of sbt has support Def.sequential
function to run tasks under semi-sequential semantics.
How to setup scalastyle as a part of compile time:
add scalastyle plugin to your project/style.sbt
or project/plugins.sbt
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")
in build.sbt
lazy val compilecheck = taskKey[Unit]("compile and then scalastyle")
lazy val root = (project in file("."))
.settings(
compilecheck in Compile := Def.sequential(
compile in Compile,
(scalastyle in Compile).toTask("")
).value
)
To call this task type in compilecheck from the shell. If the compilation fails, compilecheck would stop the execution.
root> compilecheck
[info] Compiling 1 Scala source to /Users/x/proj/target/scala-2.10/classes...
[error] /Users/x/proj/src/main/scala/Foo.scala:3: Unmatched closing brace '}' ignored here
[error] }
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
We could just add a hook to our pre-commit-config.yaml which looks like this:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.0.0
hooks:
- id: check-json
- id: check-merge-conflict
- id: check-xml
- id: check-yaml
- id: detect-private-key
- repo: [email protected]:coyainsurance/pre-commit-scalafmt.git
sha: master
hooks:
- id: scalafmt
args: [-t ]
- repo: local
hooks:
- id: scalastyle
name: scalastyle
entry: scalastyle --config scalastyle-config.xml
language: system
files: \.(scala|sbt)$
types: [file, text]
Create a custom-script for running scalafmt:
#!/usr/bin/env bash
# This script creates a pre-commit git hook that run scalafmt before each commit
# http://scalameta.org/scalafmt/
# Need scalafmt installed in CLI mode.
[ -d .git/hooks/ ] || (echo "It's not a git directory";exit 1)
[ -d .git/hooks/ ] && echo '#!/usr/bin/env bash
echo -e "\e[0;33m Scalafmt RUNNING \e[0m"
scalafmt --git true --diff-branch $(git branch | head -n1 | cut -d " " -f2)
RESULT=$?
if [ ${RESULT} -ne 0 ]; then
echo -e "\e[0;31m Scalafmt FAILED \e[0m"
exit ${RESULT}
fi
echo -e "\e[0;32m Scalafmt SUCCEEDED \e[0m"
exit 0
And add your .sh file as a part of pre-commit stage:
PreCommit:
RuboCop:
enabled: true
on_warn: pass # Treat all warnings as failures
Scalastyle:
enabled: true
flags: ['-c', 'scalastyle-config.xml']
CustomScript:
enabled: true
required_executable: './scalafmt.sh'
Here I want to mention also about Jenkins: Remove scalastyle and scalafmt runners. If we setup these two things on each developer machine we don't need to worry about style and format on prod or stage machine. I think this will also help to reduce duration of running the Jenkins task.
- https://github.com/scalameta/scalafmt
- https://github.com/coyainsurance/pre-commit-scalafmt
- http://www.scalastyle.org/
- http://www.scalastyle.org/git-pre-commit-hook.html
- https://github.com/sds/overcommit
- http://www.scalastyle.org/sbt.html
- https://www.scala-sbt.org/1.0/docs/Howto-Sequential-Task.html