Refactor the generation of the VERSION file to live in ServiceArtifactExtension

This should make it more logical and break the coupling between the language
specific implementations and the overall service artifact work
This commit is contained in:
R. Tyler Croy 2015-06-16 13:48:56 -07:00
parent d0b7b2ea29
commit 7d7929f3a2
No known key found for this signature in database
GPG Key ID: 1426C7DC3F51E16F
7 changed files with 214 additions and 69 deletions

View File

@ -35,7 +35,9 @@
<root url="jar://$USER_HOME$/.gradle/wrapper/dists/gradle-2.0-all/evtta6k9rngqxp6sxbf6unsdw/gradle-2.0/lib/groovy-all-2.3.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
<SOURCES>
<root url="jar://$USER_HOME$/.ideaLibSources/groovy-all-2.3.3-sources.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library" exported="">

View File

@ -1,7 +1,5 @@
package com.github.lookout.serviceartifact
import com.github.lookout.serviceartifact.scm.AbstractScmHandler
import groovy.json.JsonBuilder
import org.gradle.api.Project
import org.gradle.api.Task
@ -15,56 +13,27 @@ abstract class AbstractServiceExtension {
/**
* Properly update the compressed archive tasks with the appropriate
* configurations after the serviceJar task has been set up
* configurations after a serviceJar task has been set up
*
* @param project
* @return
*/
protected void setupCompressedArchives(Project project, AbstractScmHandler scmHandler) {
protected void setupCompressedArchives(Object serviceExtension) {
Project project = serviceExtension.project
Task tar = project.tasks.findByName('serviceTar')
Task zip = project.tasks.findByName('serviceZip')
Task jar = project.tasks.findByName('serviceJar')
Task version = project.tasks.create('serviceVersionInfo') {
group ServiceArtifactPlugin.GROUP_NAME
description "Generate the service artifact version information"
def versionFilePath = "${this.project.buildDir}/VERSION"
outputs.file(versionFilePath).upToDateWhen { false }
doFirst {
JsonBuilder builder = new JsonBuilder()
builder(buildDate: new Date(),
version: project.version,
name: project.name,
revision: scmHandler?.revision,
builtOn: InetAddress.localHost.hostName)
new File(versionFilePath).write(builder.toPrettyString())
}
}
/* Ensure our service (distribution) artifact tasks depend on this
* jar task
*/
[tar, zip].each {
String directory = String.format("%s-%s", project.name, project.version)
it.dependsOn(jar)
it.into(directory) { from(jar.outputs.files) }
it.into("${directory}/bin") { from("${project.projectDir}/bin") }
/* Pack a handy VERSION file containing some built metadata about
* this artifact to help trace it back to builds in the future
*/
it.into(directory) { from version.outputs.files }
it.into(serviceExtension.archiveDirName) { from(jar.outputs.files) }
it.into("${serviceExtension.archiveDirName}/bin") { from("${project.projectDir}/bin") }
}
}
protected void disableJarTask() {
Task jarTask = this.project.tasks.findByName('jar')
if (jarTask instanceof Task) {
jarTask.enabled = false
}
this.project.tasks.findByName('jar')?.enabled = false
}
}

View File

@ -1,6 +1,8 @@
package com.github.lookout.serviceartifact
import groovy.json.JsonBuilder
import org.gradle.api.Project
import org.gradle.api.Task
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -22,6 +24,8 @@ class ServiceArtifactExtension {
/** SCM Handler appropriate for this execution */
protected AbstractScmHandler _scmHandler
/** Map of metadata that should be written into the artifact's etc/metadata.conf */
protected Map<String, Object> metadata = [:]
ServiceArtifactExtension(final Project project) {
this(project, [:])
@ -33,6 +37,73 @@ class ServiceArtifactExtension {
this.env = env
}
/**
* Bootstrap and set up whatever internal tasks/helpers we need to set up
*/
void bootstrap() {
String versionFilePath = String.format("%s/VERSION", this.project.buildDir)
Task version = project.tasks.create('serviceVersionInfo') {
group ServiceArtifactPlugin.GROUP_NAME
description "Generate the service artifact version information"
outputs.file(versionFilePath).upToDateWhen { false }
doFirst {
JsonBuilder builder = new JsonBuilder()
builder(generateVersionMap())
new File(versionFilePath).write(builder.toPrettyString())
}
}
[ServiceArtifactPlugin.TAR_TASK, ServiceArtifactPlugin.ZIP_TASK].each {
Task archiveTask = this.project.tasks.findByName(it)
if (archiveTask instanceof Task) {
archiveTask.dependsOn(version)
/* Pack the VERSION file containing some built metadata about
* this artifact to help trace it back to builds in the future
*/
archiveTask.into(this.archiveDirName) { from version.outputs.files }
}
}
}
/**
*
* @return A map containing the necessary version information we want to drop into archives
*/
Map<String, Object> generateVersionMap() {
return [
'version' : this.project.version,
'name' : this.project.name,
'buildDate' : new Date(),
'revision': scmHandler?.revision,
'builtOn': this.hostname,
]
}
/**
* Return a hostname or unknown if we can't resolve our localhost (as seen on Mavericks)
*
* @return Local host's name or 'unknown'
*/
String getHostname() {
try {
return InetAddress.localHost.hostName
}
catch (UnknownHostException) {
return 'unknown'
}
}
/**
* @return A (name)-(version) String for the directory name inside a compressed archive
*/
String getArchiveDirName() {
return String.format("%s-%s", this.project.name, this.project.version)
}
/**
* Lazily look up our SCM Handler
*/
@ -64,5 +135,31 @@ class ServiceArtifactExtension {
return baseVersion
}
/**
* Return the computed Map<> of metadata that is to be written to the etc/metadata.conf
* inside of the service artifact
*/
Map<String, Object> getMetadata() {
return this.metadata
}
void metadata(Object... arguments) {
arguments.each {
this.metadata.putAll(it as Map)
}
}
void setMetadata(Object... arguments) {
this.metadata = [:]
this.metadata arguments
}
/**
* return the configured project for this service{} extension
*/
Project getProject() {
return this.project
}
}

View File

@ -10,6 +10,8 @@ import org.gradle.api.tasks.bundling.Tar
class ServiceArtifactPlugin implements Plugin<Project> {
static final String GROUP_NAME = 'Service Artifact'
static final String ARCHIVES_CONFIG = "serviceArchives"
static final String ZIP_TASK = 'serviceZip'
static final String TAR_TASK = 'serviceTar'
void apply(Project project) {
/* Add the asciidoctor plugin because...docs are important */
@ -37,13 +39,13 @@ class ServiceArtifactPlugin implements Plugin<Project> {
description "stub task for preparing the bin scripts for the artifact"
}
Task tarTask = project.task('serviceTar', type: Tar) {
Task tarTask = project.task(TAR_TASK, type: Tar) {
group GROUP_NAME
description "Create a .tar.gz artifact containing the service"
dependsOn prepareTask
}
Task zipTask = project.task('serviceZip', type: Zip) {
Task zipTask = project.task(ZIP_TASK, type: Zip) {
group GROUP_NAME
description "Create a .zip artifact containing the service"
dependsOn prepareTask
@ -63,5 +65,8 @@ class ServiceArtifactPlugin implements Plugin<Project> {
project.artifacts.add(ARCHIVES_CONFIG, zipTask)
project.artifacts.add(ARCHIVES_CONFIG, tarTask)
/* With everything defined, let's bootstrap the service extension internals */
service.bootstrap()
}
}

View File

@ -68,7 +68,7 @@ class JRuby extends AbstractServiceExtension {
disableJarTask()
setupJRubyJar()
setupCompressedArchives(this.project, serviceExtension.scmHandler)
setupCompressedArchives(serviceExtension)
extraConfig.delegate = new JRubyDSL(this.project)
extraConfig.call(this.project)

View File

@ -41,8 +41,10 @@ class Scala extends AbstractServiceExtension {
}
this.project.tasks.findByName('assemble').dependsOn(jar)
this.project.artifacts.add(ServiceArtifactPlugin.ARCHIVES_CONFIG, jar)
jar.configurations.add(this.project.configurations.getByName('compile'))
setupCompressedArchives(this.project, serviceExtension.scmHandler)
setupCompressedArchives(serviceExtension)
disableJarTask()
}

View File

@ -6,6 +6,17 @@ import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.testfixtures.ProjectBuilder
import com.github.lookout.serviceartifact.scm.GerritHandler
abstract class AppliedExtensionSpec extends Specification {
protected Project project
def setup() {
this.project = ProjectBuilder.builder().build()
this.project.apply plugin: 'com.github.lookout.service-artifact'
}
}
class ServiceArtifactExtensionSpec extends Specification {
protected Project project
@ -30,23 +41,15 @@ class ServiceArtifactExtensionSpec extends Specification {
expect:
extension instanceof ServiceArtifactExtension
}
}
class ServiceArtifactExtensionInstanceSpec extends ServiceArtifactExtensionSpec {
def "getScmHandler() instantiate a handler instance"() {
given: "we're inside of a Gerrit-triggered Jenkins job"
def ext = new ServiceArtifactExtension(this.project, gerritEnv())
expect:
ext.scmHandler instanceof scm.GerritHandler
ext.scmHandler instanceof GerritHandler
}
}
class ServiceArtifactExtensionVersionSpec extends ServiceArtifactExtensionSpec {
def "version() should return an unmolested string by default"() {
given:
def ext = Spy(ServiceArtifactExtension, constructorArgs: [this.project])
@ -69,14 +72,95 @@ class ServiceArtifactExtensionVersionSpec extends ServiceArtifactExtensionSpec {
then:
version == '1.0.1.1+0xded'
}
def "bootstrap() should define a serviceVersionInfo task"() {
given:
def extension = new ServiceArtifactExtension(this.project)
when:
extension.bootstrap()
then:
this.project.tasks.findByName('serviceVersionInfo')
}
@Ignore
def "bootstrap() should define serviceMetadata"() {
given:
def extension = new ServiceArtifactExtension(this.project)
when:
extension.bootstrap()
then:
this.project.tasks.findByName('serviceMetadata')
}
def "generateVersionMap()"() {
given:
def extension = new ServiceArtifactExtension(this.project)
Map versionMap = extension.generateVersionMap()
expect:
versionMap instanceof Map
versionMap['version']
versionMap['name']
versionMap['buildDate']
versionMap['revision']
versionMap['builtOn']
}
}
class ServiceArtifactExtensionShadowSpec extends Specification {
protected Project project
class ExtensionIntegrationSpec extends AppliedExtensionSpec {
def "bootstrap() should have set up dependencies for serviceVersionInfo"() {
given:
Closure matcher = { (it instanceof Task) && (it.name == 'serviceVersionInfo') }
Task zip = this.project.tasks.findByName('serviceZip')
Task tar = this.project.tasks.findByName('serviceTar')
expect: "the compressed archives to rely on serviceVersionInfo"
zip.dependsOn.find(matcher)
tar.dependsOn.find(matcher)
}
}
/**
* Test the functionality of the service { metadata [:] } property
*/
class ServiceArtifactExtensionMetadataSpec extends AppliedExtensionSpec {
def "its metadata should be a map by default"() {
expect:
this.project.service.metadata instanceof Map
}
def "I should be able to set metadata"() {
given:
this.project.service.metadata 'success' : true
expect:
this.project.service.metadata == ['success' : true]
}
def "I should be able to completely overwrite it with setMetadata"() {
given:
this.project.service.metadata 'overwrite' : 1
when:
this.project.service.setMetadata 'success' : true
then:
this.project.service.metadata == ['success' : true]
}
}
/**
* Test the functionality of the service { jruby{} } closure
*/
class ServiceArtifactExtensionJRubyIntegrationSpec extends AppliedExtensionSpec {
def setup() {
this.project = ProjectBuilder.builder().build()
this.project.apply plugin: 'com.github.lookout.service-artifact'
this.project.service { jruby {} }
}
@ -105,19 +189,6 @@ class ServiceArtifactExtensionShadowSpec extends Specification {
task.manifest.attributes['Main-Class']
}
}
/**
* Test the behaviors of the setupCompressedArchives() functionality
*/
class ServiceArtifactExtensionArchivesSpec extends Specification {
protected Project project
def setup() {
this.project = ProjectBuilder.builder().build()
this.project.apply plugin: 'com.github.lookout.service-artifact'
this.project.service { jruby {} }
}
def "the serviceTar task should depend on serviceJar"() {
given:
@ -135,4 +206,3 @@ class ServiceArtifactExtensionArchivesSpec extends Specification {
tar.dependsOn.find { (it instanceof Task) && (it.name == 'serviceJar') }
}
}