Build: add a `rat` task that runs Apache Rat on the whole codebase It is not tied to the `check` task yet as it fails. HTML report is generated into `build/rat`
Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/fd0c2126 Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/fd0c2126 Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/fd0c2126 Branch: refs/heads/develop Commit: fd0c2126af51ab4f984f3fbf0b3a8352b968ea7d Parents: c465b16 Author: Paul Merlin <[email protected]> Authored: Tue Apr 28 08:44:07 2015 +0200 Committer: Paul Merlin <[email protected]> Committed: Tue Apr 28 08:44:07 2015 +0200 ---------------------------------------------------------------------- build.gradle | 43 +++++++ etc/apache-rat-output-to-html.xsl | 204 +++++++++++++++++++++++++++++++++ gradle/apache-rat.gradle | 117 +++++++++++++++++++ 3 files changed, 364 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/fd0c2126/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index 20f215e..706823b 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,49 @@ project.ext { def releaseApprovedProjects = allprojects.findAll( { project -> rootProject.ext.releaseSpec.satisfiedBy( project ) } ) +apply from: 'gradle/apache-rat.gradle' +rat { + excludes = [ + '**/.DS_Store/**', + 'bin/**', + // Git Files + '**/.git/**', + '**/.gitignore', + // Gradle Wrapper + 'gradle/wrapper/**', + 'gradlew', + 'gradlew.bat', + '**/.gradle/**', + // Build Output + '**/build/**', + // IDE Files + '**/.idea/**', + '**/*.iml', + '**/*.ipr', + '**/*.iws', + '**/.settings/**', + '**/.classpath', + '**/.project', + '**/.nb-gradle-properties', + '**/.gradletasknamecache', + '**/.nb-gradle/**', + '**/private/cache/**', + // Graphic Resources + '**/*.svg', + '**/*.gif', + '**/*.png', + '**/*.jpg', + '**/*.psd', + // Syntax Highlighter - MIT + 'manual/**/sh*.css', + 'manual/**/sh*.js', + // jQuery & plugins - MIT + 'manual/**/jquery*.js', + // Keystores + '**/*.jceks', + ] +} + buildscript { repositories { mavenCentral() http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/fd0c2126/etc/apache-rat-output-to-html.xsl ---------------------------------------------------------------------- diff --git a/etc/apache-rat-output-to-html.xsl b/etc/apache-rat-output-to-html.xsl new file mode 100644 index 0000000..dcf19c5 --- /dev/null +++ b/etc/apache-rat-output-to-html.xsl @@ -0,0 +1,204 @@ +<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> + +<!--*********************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + ***********************************************************--> + +<!-- This style sheet converts any rat-report.xml file. --> + +<xsl:template match="/"> + + <html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + <style type="text/css"> + <!-- +body {margin-top: 0px;font-size: 0.8em;background-color: #F9F7ED;} + +h1 {color:red;} +h2 {color:blue;} +h3 {color:green;} +h4 {color:orange;} + +/* Table Design */ + +table,tr,td {text-align:center;font-weight:bold;border:1px solid #000;} +caption {color:blue;text-align:left;} +.notes, .binaries, .archives, .standards {width:25%;} +.notes {background:#D7EDEE;} +.binaries {background:#D0F2F4;} +.archives {background:#ABE7E9;} +.standards {background:#A0F0F4;} +.licenced, .generated {width:50%;} +.licenced {background:#C6EBDD;} +.generated {background:#ABE9D2;} +.java_note {background:#D6EBC6;} +.generated_note {background:#C9E7A9;} +.unknown {width:100%;background:#E92020;} +.unknown-zero {color:#00CC00;} +.center{text-align:center;margin:0 auto;} +--> + </style> + </head> + <body> + <xsl:apply-templates/> + <xsl:call-template name="generated"/> + </body> + </html> +</xsl:template> + +<xsl:template match="rat-report"> + + <h1>Rat Report</h1> +<div class="center"> +<table id="rat-reports summary" cellspacing="0" summary="A snapshot summary of this rat report"> +<caption> +Table 1: A snapshot summary of this rat report. +</caption> + <tr> + <td colspan="1" class="notes">Notes: <xsl:value-of select="count(descendant::type[attribute::name="notice"])"/></td> + <td colspan="1" class="binaries">Binaries: <xsl:value-of select="count(descendant::type[attribute::name="binary"])"/></td> + <td colspan="1" class="archives">Archives: <xsl:value-of select="count(descendant::type[attribute::name="archive"])"/></td> + <td colspan="1" class="standards">Standards: <xsl:value-of select="count(descendant::type[attribute::name="standard"])"/></td> + </tr> + <tr> + <td colspan="2" class="licenced">Apache Licensed: <xsl:value-of select="count(descendant::header-type[attribute::name="AL "])"/></td> + <td colspan="2" class="generated">Generated Documents: <xsl:value-of select="count(descendant::header-type[attribute::name="GEN "])"/></td> + </tr> + <tr> + <td colspan="2" class="java_note">Note: JavaDocs are generated and so license header is optional</td> + <td colspan="2" class="generated_note">Note: Generated files do not require license headers</td> + </tr> + <tr> +<xsl:choose> + <xsl:when test="count(descendant::header-type[attribute::name="?????"]) > 0"> + <td colspan="4" class="unknown"><xsl:value-of select="count(descendant::header-type[attribute::name="?????"])"/> Unknown Licenses - or files without a license.</td> + </xsl:when> + <xsl:otherwise> + <td colspan="4" class="unknown-zero"><xsl:value-of select="count(descendant::header-type[attribute::name="?????"])"/> Unknown Licenses - or files without a license.</td> + </xsl:otherwise> +</xsl:choose> + </tr> +</table> +</div> +<hr/> + <h3>Unapproved Licenses:</h3> + + <xsl:for-each select="descendant::resource[license-approval/@name="false"]"> + <xsl:text> </xsl:text> + <xsl:value-of select="@name"/><br/> + <xsl:text> +</xsl:text> +</xsl:for-each> +<hr/> + +<h3>Archives:</h3> + +<xsl:for-each select="descendant::resource[type/@name="archive"]"> + + <xsl:value-of select="@name"/> + <br/> + </xsl:for-each> + <hr/> + + <p> + Files with Apache License headers will be marked AL<br/> + Binary files (which do not require AL headers) will be marked B<br/> + Compressed archives will be marked A<br/> + Notices, licenses etc will be marked N<br/> + </p> + + <xsl:for-each select="descendant::resource"> + <xsl:choose> + <xsl:when test="license-approval/@name="false"">!</xsl:when> + <xsl:otherwise><xsl:text> </xsl:text></xsl:otherwise> + </xsl:choose> + <xsl:choose> + <xsl:when test="type/@name="notice"">N </xsl:when> + <xsl:when test="type/@name="archive"">A </xsl:when> + <xsl:when test="type/@name="binary"">B </xsl:when> + <xsl:when test="type/@name="standard""><xsl:value-of select="header-type/@name"/></xsl:when> + <xsl:otherwise>!!!!!</xsl:otherwise> + </xsl:choose> + <xsl:text> </xsl:text> + <xsl:value-of select="@name"/><br/> + <xsl:text> + </xsl:text> + </xsl:for-each> + <hr/> + + <h3>Printing headers for files without AL header...</h3> + + <xsl:for-each select="descendant::resource[header-type/@name="?????"]"> + + <h4><xsl:value-of select="@name"/></h4> + <xsl:value-of select="header-sample"/> + <hr/> +</xsl:for-each> +<br/> + + <!-- <xsl:apply-templates select="resource"/> + <xsl:apply-templates select="header-sample"/> + <xsl:apply-templates select="header-type"/> + <xsl:apply-templates select="license-family"/> + <xsl:apply-templates select="license-approval"/> + <xsl:apply-templates select="type"/> --> + +</xsl:template> + +<xsl:template match="resource"> + <div> + <h3>Resource: <xsl:value-of select="@name"/></h3> + <xsl:apply-templates/> + </div> +</xsl:template> + +<xsl:template match="header-sample"> + <xsl:if test="normalize-space(.) != ''"> + <h4>First few lines of non-compliant file</h4> + <p> + <xsl:value-of select="."/> + </p> + </xsl:if> + <h4>Other Info:</h4> +</xsl:template> + +<xsl:template match="header-type"> + Header Type: <xsl:value-of select="@name"/> + <br/> +</xsl:template> + +<xsl:template match="license-family"> + License Family: <xsl:value-of select="@name"/> + <br/> +</xsl:template> + +<xsl:template match="license-approval"> + License Approval: <xsl:value-of select="@name"/> + <br/> +</xsl:template> + +<xsl:template match="type"> + Type: <xsl:value-of select="@name"/> + <br/> +</xsl:template> + +<xsl:template name="generated"> +</xsl:template> +</xsl:transform> http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/fd0c2126/gradle/apache-rat.gradle ---------------------------------------------------------------------- diff --git a/gradle/apache-rat.gradle b/gradle/apache-rat.gradle new file mode 100644 index 0000000..dc0bcd6 --- /dev/null +++ b/gradle/apache-rat.gradle @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.internal.project.IsolatedAntBuilder + +apply plugin: RatPlugin + +class RatTask extends DefaultTask { + @Input + List<String> excludes + + def reportPath = 'build/rat' + def stylesheet = 'etc/apache-rat-output-to-html.xsl' + def xmlReport = reportPath + '/rat-report.xml' + def htmlReport = reportPath + '/rat-report.html' + + def generateXmlReport(File reportDir) { + def antBuilder = services.get(IsolatedAntBuilder) + def ratClasspath = project.configurations.rat + antBuilder.withClasspath(ratClasspath).execute { + ant.taskdef(resource: 'org/apache/rat/anttasks/antlib.xml') + ant.report(format: 'xml', reportFile: xmlReport) { + fileset(dir: ".") { + patternset { + excludes.each { exclude(name: it) } + } + } + } + } + } + + def printUnknownFiles() { + def ratXml = new XmlParser().parse(xmlReport) + def unknownLicenses = 0 + ratXml.resource.each { resource -> + if (resource.'license-approval'.@name[0] == "false") { + println('Unknown license: ' + resource.@name) + unknownLicenses++ + } + } + return unknownLicenses + } + + def generateHtmlReport() { + def antBuilder = services.get(IsolatedAntBuilder) + def ratClasspath = project.configurations.rat + antBuilder.withClasspath(ratClasspath).execute { + ant.xslt( + in: xmlReport, + style: stylesheet, + out: htmlReport, + classpath: ratClasspath + ) + } + println('Rat report: ' + htmlReport) + } + + @TaskAction + def rat() { + File reportDir = new File(reportPath) + if (!reportDir.exists()) { + reportDir.mkdirs() + } + generateXmlReport(reportDir) + def errorCount = printUnknownFiles() + generateHtmlReport() + if (errorCount > 0) { + throw new GradleException("Found $errorCount files with unknown licenses.") + } + } +} + +class RatPlugin implements Plugin<Project> { + void apply(Project project) { + configureDependencies(project) + project.plugins.apply(JavaBasePlugin); + Task ratTask = project.task( + 'rat', + type: RatTask, + group: 'Apache', + description: 'Runs Apache Rat checks.' + ) + // TODO Uncomment this to hook into `check` tasks + // project.tasks[JavaBasePlugin.CHECK_TASK_NAME].dependsOn ratTask + } + + void configureDependencies(final Project project) { + project.configurations { + rat + } + project.repositories { + mavenCentral() + } + project.dependencies { + rat 'org.apache.rat:apache-rat-tasks:0.11' + } + } +}
