-
Notifications
You must be signed in to change notification settings - Fork 19
Package Creation Guide
Sometimes you may need to create SEU-as-Code package yourself. Usually, this happens when you want to install a newer version of an existing package or you need a totally new software for a current project. This page will describe the necessary steps required to create these packages.
The directory layout of this repository mimics a Maven repository structure. The top level directory usually conforms to the top level domain of the 3rd party open source software. Within this directory you will then create a directory with the actual name of the software package. For each version of the package you will create a further subdirectory. By now you should have a 3-level directory structure.
The SEU-as-Code package projects are Gradle builds. In the project directory of the package version you usually have the following files and directories:
| Name | Type | Description |
|---|---|---|
| files/ | Directory | This is where you will put all your customization files for the software package. |
| files/META-INF/hooks/ | Directory | This is where you will put your Groovy hook files if required. |
| build.gradle | File | The main Gradle build file with the task definitions to create and publish the package. |
| gradle.properties | File | Contains project and Gradle properties. You must set the group and version properties. |
| settings.gradle | File | You need to set the rootProject.name property to the correct artifact name. |
At this point you have an empty but working Gradle project to build your software package. Usually, you already have an idea where to get the desired software package from, ideally as a ZIP distribution from the official website. If so, you can use the Gradle download task to obtain the file directly:
plugins {
id 'de.undercouch.download' version '1.2'
}
import de.undercouch.gradle.tasks.download.Download
task downloadArchive(type: Download) {
src "http://archive.apache.org/dist/ant/binaries/${project.name}-${version}-bin.zip"
dest buildDir
}If the desired software package does not provide a convenient way of downloading a ZIP file, or even only provides an MSI bases installer, you have to perform this step manually. What I usually do is to install the software locally on my computer, then repackage the software as a ZIP and copy the archive to a network share.
The next step is to unpack the ZIP distribution of the software into the build directory so it can be customized and repackaged as a SEU as Code software archive later on. Again you can use a Gradle task to achieve just this:
task extractArchive(type: Copy, dependsOn: downloadArchive) {
from { zipTree("$buildDir/${project.name}-${version}-bin.zip") }
into "$buildDir/files"
}You usually will have to customize the original software distribution you are building the package for. You may need
to set environment variables, provide start scripts, overwrite or patch certain files with installation specific values,
or even create Windows shortcuts for more convenience. All these customization files should be located in the files
folder of the software package's project directory.
If you need CMD files at all highly depends upon your software package. If you need to set specific environment variables
or extends the path with the bin/ directory you will need a custom set-env-<project>.cmd. Mind the naming convention:
the file should start with set-env-, followed by the project name and have .cmd as suffix. All files following this
scheme will later be included automatically in the overall shell environment.
Another type of CMD files you sometimes need are specialized start and stop command files. These files usually setup the overall shell environment and then call the required executable or whatever is required to run or terminate the application. The following script shows how to start and open a console with the complete environment setup:
@echo off
call set-env.cmd
:: change working directory
cd %SEU_HOME%\codebase
cmd /kThe hook script mechanism is useful to execute arbitrary actions after the bootstrap mechanism has extracted and installed
the software into the final location. The hook files need to be in the files/META-INF/hooks directory, the files are ordinary
Groovy files with custom installation logic. Please note that the filename must be unique to make sure the hook script is
not overwritten by another software package during the installation process.
| Variable name | Type | Description |
|---|---|---|
seuHome |
String | The seuHome property from the seuAsCode configuration. |
seuLayout |
SeuacLayout | The seuLayout property from the seuAsCode configuration. |
projectName |
String | The project name property from the seuAsCode configuration. |
directory |
File | The installation directory the hooks are executed for. |
logger |
Logger | The Gradle API logger. Provides logging capabilities like debug, info, warn and error. |
The following example will show the processing and parsing of a file to include the $seuHome variable value. The file
is opened, parsed and written back to the original file. You need to take care that for this example the parsed file
needs to be a valid Groovy template. For example, your will need to escape certain characters like \ as \\.
import groovy.text.GStringTemplateEngine
def setEnvCmd = new File("$seuHome/software/set-env.cmd")
def binding = [ seuHome : seuHome ]
def engine = new GStringTemplateEngine()
def template = engine.createTemplate(setEnvCmd).make(binding)
setEnvCmd.write(template.toString())import org.codehaus.groovy.scriptom.*
Scriptom.inApartment
{
def wshShell = new ActiveXObject("WScript.Shell")
def shortcut = wshShell.CreateShortcut("$seuHome\\console.lnk")
shortcut.TargetPath = "$directory\\start-console.bat"
// shortcut.IconLocation =
shortcut.WorkingDirectory = "$directory"
shortcut.Save()
}Once you are done with the customization it is time to repackage the software into a compatible archive. Again, you
can use a Gradle task to do the work for you. You must defined a task with name buildPackage. The following example
will package everything from the "$buildDir/files" and "files" directories into a JAR.
task buildPackage(type: Jar, dependsOn: extractArchive) {
baseName project.name
version version
extension 'jar'
destinationDir buildDir
from "$buildDir/files"
from "files"
}There are a few things to note about the archive and the internal structure:
- The package will later be extracted and installed into either the software or the home directory directly. All the required environment files and the main software directory itself must be at the root level of the archive.
- The archive name must comply with the standard artifact naming convention:
${project.name}-${version}.jar
In your build.gradle file you need to define the artifacts you want to publish as well as the repository.
For consistency reason you should name the publishing method according to your artifact name. A usual section
will look like this:
apply plugin: 'maven-publish'
publishing {
publications {
ant(MavenPublication) {
artifact "${buildDir}/${project.name}-${version}.jar"
}
}
repositories {
// set the properties via -P to publish to your company repo
maven {
url = project.hasProperty('nexusUrl') ? project.nexusUrl : ''
credentials {
username = project.hasProperty('nexusUsername') ? project.nexusUsername : ''
password = project.hasProperty('nexusPassword') ? project.nexusPassword : ''
}
}
}
}In case you want to publish the package to Bintray, include the following plugin and configuration section in your build file:
plugins {
id 'com.jfrog.bintray' version '1.2'
}
bintray {
user = project.hasProperty('bintrayUsername') ? project.bintrayUsername : 'unknown'
key = project.hasProperty('bintrayApiKey') ? project.bintrayApiKey : 'unknown'
publications = ['ant']
publish = true
dryRun = false
pkg {
repo = project.bintrayRepo
name = project.name
desc = project.description
licenses = ['Apache-2.0']
labels = ['ant', 'seu-as-code', 'package']
websiteUrl = project.websiteUrl
issueTrackerUrl = project.issueTrackerUrl
vcsUrl = project.scmUrl
publicDownloadNumbers = true
version {
name = project.version
desc = "${project.description} ${project.version}"
released = new Date().format("yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
mavenCentralSync {
sync = false
}
}
}
}