sf jug - gradle lint
TRANSCRIPT
Netflix = freedom and responsibility
(The assignment operator is intentional)
What can Gradle Lint do?
4 Remove cruft
4 Bar practices that are universally bad
4 Sanitize dependencies
4 Keep Gradle version up-to-date
4 Auto-fix violations!
Gradle Lint in action
Apply it:allprojects { apply plugin: 'nebula.lint' gradleLint.rules = ['dependency-parentheses', 'dependency-tuple', ...]}
Run it:./gradlew lintGradle./gradlew build <-- also causes lintGradle to run
./gradlew fixGradleLint <-- fixes all problems for you
Unused dependencies4 Remove unused first-order dependencies
4 Add transitive dependencies with compile time references as first-order dependencies
4 Align fixed first-order dependency versions with transitives when conflict resolved
4 Shuffle first-order dependencies to the correct configurations (e.g. junit to testCompile)
Creating a simple lint rule
"All wars should be published to our binary repository"
1: Apply immediately after the war plugin
class AllWarsShouldBePublishedRule extends GradleLintRule {
@Override void visitApplyPlugin(MethodCallExpression call, String plugin) { if(plugin == 'war') { addLintViolation('WARs must be published') .insertAfter(call, "apply plugin: 'netflix.war-publish'") } }}
2: Apply only if it isn't already applied
class AllWarsShouldBePublishedRule extends GradleLintRule {
@Override void visitApplyPlugin(MethodCallExpression call, String plugin) { if(plugin == 'war') bookmark('applyWar', call) else if(plugin == 'netflix.war-publish') bookmark('applyWarPublish', call) }
@Override protected void visitClassComplete(ClassNode node) { if(bookmark('applyWar') && !bookmark('applyWarPublish')) { addLintViolation('WARs must be published') .insertAfter(bookmark('applyWar'), "apply plugin: 'netflix.war-publish'") }}
3: Replace the war plugin entirely
class AllWarsShouldBePublishedRule extends GradleLintRule {
@Override void visitApplyPlugin(MethodCallExpression call, String plugin) { if(plugin == 'war') bookmark('applyWar', call) else if(plugin == 'netflix.war-publish') bookmark('applyWarPublish', call) }
@Override protected void visitClassComplete(ClassNode node) { if(bookmark('applyWar') && !bookmark('applyWarPublish')) { addLintViolation('WARs must be published') .replaceWith(bookmark('applyWar'), "apply plugin: 'netflix.war-publish'") }}
4: Become Gradle model awareclass AllWarsShouldBePublishedRule extends GradleLintRule implements GradleModelAware {
@Override void visitApplyPlugin(MethodCallExpression call, String plugin) { bookmark('lastApplyPlugin', call) }
@Override protected void visitClassComplete(ClassNode node) { if(project.plugins.hasPlugin(WarPlugin) && !project.plugins.hasPlugin('netflix.war-publish')) { addLintViolation('WARs must be published') .insertAfter(bookmark('lastApplyPlugin'), "apply plugin: 'netflix.war-publish'") } }}
Resources
"How We Build Code at Netflix" -- Netflix techblog
github.com/nebula-plugins/gradle-lint-plugin