Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

Commit

Permalink
Docker image (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
jframe committed Jul 12, 2019
1 parent b6a4e02 commit 17693f1
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 7 deletions.
50 changes: 48 additions & 2 deletions Jenkinsfile
Expand Up @@ -22,6 +22,11 @@ if (env.BRANCH_NAME == "master") {
])
}

def registry = 'https://registry.hub.docker.com'
def userAccount = 'dockerhub-pegasysengci'
def imageRepos = 'pegasyseng'
def imageTag = 'develop'

def abortPreviousBuilds() {
Run previousBuild = currentBuild.rawBuild.getPreviousBuildInProgress()

Expand All @@ -48,7 +53,7 @@ try {
node {
checkout scm
docker.image('docker:18.06.3-ce-dind').withRun('--privileged -v /volumes/jenkins-slave-workspace:/var/jenkins-slave-workspace') { d ->
docker.image('openjdk:11-jdk-stretch').inside("-e DOCKER_HOST=tcp://docker:2375 --link ${d.id}:docker") {
docker.image('pegasyseng/pantheon-build:0.0.7-jdk11').inside("-e DOCKER_HOST=tcp://docker:2375 --link ${d.id}:docker") {
try {
stage('Build') {
sh './gradlew --no-daemon --parallel build'
Expand All @@ -62,6 +67,47 @@ try {
stage('Acceptance Test') {
sh './gradlew --no-daemon --parallel acceptanceTest'
}
stage('Docker') {
def image = imageRepos + '/ethsigner:' + imageTag
def docker_folder = 'docker'
def version_property_file = 'gradle.properties'
def reports_folder = docker_folder + '/reports'
def dockerfile = docker_folder + '/Dockerfile'

// dockerfile lint
sh "docker run --rm -i hadolint/hadolint < ${dockerfile}"

// build image
sh './gradlew distDocker'

// test image labels
shortCommit = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
version = sh(returnStdout: true, script: "grep -oE \"version=(.*)\" ${version_property_file} | cut -d= -f2").trim()
sh "docker image inspect \
--format='{{index .Config.Labels \"org.label-schema.vcs-ref\"}}' \
${image} \
| grep ${shortCommit}"
sh "docker image inspect \
--format='{{index .Config.Labels \"org.label-schema.version\"}}' \
${image} \
| grep ${version}"

// test image
try {
sh "mkdir -p ${reports_folder}"
sh "cd ${docker_folder} && bash test.sh ${image}"
} finally {
junit "${reports_folder}/*.xml"
sh "rm -rf ${reports_folder}"
}

// push image
if (env.BRANCH_NAME == "master") {
docker.withRegistry(registry, userAccount) {
docker.image(image).push()
}
}
}
} finally {
archiveArtifacts '**/build/reports/**'
archiveArtifacts '**/build/test-results/**'
Expand All @@ -71,7 +117,7 @@ try {
}
}
}
} catch (e) {
} catch (ignored) {
currentBuild.result = 'FAILURE'
} finally {
// If we're on master and it failed, notify slack
Expand Down
66 changes: 61 additions & 5 deletions Jenkinsfile.release
@@ -1,4 +1,5 @@
#!/usr/bin/env groovy

void tryAddKnownHost(String hostUrl){
// ssh-keygen -F ${hostUrl} will fail (in bash that means status code != 0) if ${hostUrl} is not yet a known host
def statusCode = sh script:"ssh-keygen -F ${hostUrl}", returnStatus:true
Expand All @@ -8,18 +9,25 @@ void tryAddKnownHost(String hostUrl){
}
}

@NonCPS
String getShortVersion(String version) {
def regexCheck = (version =~ /^(\d+)\.(\d+)\.\d+.*$/)
def shortReleaseVersion = (regexCheck.size() > 0) ? "${regexCheck[0][1]}.${regexCheck[0][2]}" : ""
return shortReleaseVersion
}

properties([
parameters([
string(name: 'BRANCH_NAME', defaultValue: 'master', description: '[MANDATORY] The name of the branch to create the release from'),
string(name: 'RELEASE_VERSION', defaultValue: '', description: '[OPTIONAL] When empty: defaults to the current project version'),
string(name: 'RELEASE_VERSION', defaultValue: '', description: '[MANDATORY] The version you are deploying'),
string(name: 'NEXT_VERSION', defaultValue: '', description: '[OPTIONAL] When empty: defaults to next patch version after current project version')
])
])

node {
checkout scm
docker.image('docker:18.06.3-ce-dind').withRun('--privileged -v /volumes/jenkins-slave-workspace:/var/jenkins-slave-workspace') { d ->
docker.image('openjdk:11-jdk-stretch').inside("-e DOCKER_HOST=tcp://docker:2375 --link ${d.id}:docker") {
docker.image('pegasyseng/pantheon-build:0.0.7-jdk11').inside("-e DOCKER_HOST=tcp://docker:2375 --link ${d.id}:docker") {
stage('Release') {
sshagent(
credentials: ['pegasys-admin-github-ssh-private-key']
Expand All @@ -45,17 +53,65 @@ node {
releaseVersion = "-Prelease.releaseVersion=${params.RELEASE_VERSION}"
}

nextVersion = ''
if( params.NEXT_VERSION?.trim() ){
nextVersion = ''
if( params.NEXT_VERSION?.trim() ){
nextVersion = "-Prelease.newVersion=${params.NEXT_VERSION}"
}
}
}

sh "./gradlew release -Prelease.useAutomaticVersion=true -Prelease.branch=${params.BRANCH_NAME} ${releaseVersion} ${nextVersion}"
}
}
}
}
stage('Docker') {
script {
def docker_folder = 'docker'
def reports_folder = docker_folder + '/reports'
def ethsigner = "pegasyseng/ethsigner:develop"
def releaseVersion = "${params.RELEASE_VERSION.trim()}"
def shortReleaseVersion = getShortVersion(releaseVersion)
def additionalTags = [releaseVersion]

stage(stage_name + 'Build image') {
sh "echo Building docker image for release ${releaseVersion} with short version ${shortReleaseVersion}"
sh "./gradlew distDocker -x test -Prelease.releaseVersion=${releaseVersion} "
}

try {
stage(stage_name + 'Test image') {
sh "mkdir -p ${reports_folder}"
sh "cd ${docker_folder} && bash test.sh ${ethsigner}"
}
} finally {
junit "${reports_folder}/*.xml"
sh "rm -rf ${reports_folder}"
}

stage(stage_name + 'Push image') {

def dockerImage = docker.image(ethsigner)
docker.withRegistry('https://registry.hub.docker.com', 'dockerhub-pegasysengci') {
dockerImage.push()

// if this is a stable release add extra docker image tags
if (!releaseVersion.contains('-')) {
additionalTags.add('latest')
if (shortReleaseVersion != "") {
additionalTags.add(shortReleaseVersion)
}
}

additionalTags.each { tag ->
dockerImage.push tag.trim()
}

}

}

}
}
}
}
}
48 changes: 48 additions & 0 deletions build.gradle
Expand Up @@ -13,6 +13,8 @@

import net.ltgt.gradle.errorprone.CheckSeverity

import java.text.SimpleDateFormat

plugins {
id 'com.diffplug.gradle.spotless' version '3.17.0'
id 'com.jfrog.bintray' version '1.8.4'
Expand Down Expand Up @@ -360,6 +362,44 @@ distZip {
}
}

// rename the top level dir from ethsigner-<version> to ethsigner and this makes it really
// simple for use in docker
tasks.register("dockerDistUntar") {
dependsOn distTar
dependsOn distZip
def dockerBuildDir = "build/docker-ethsigner/"
def distTarFile = distTar.outputs.files.singleFile
def distTarFileName = distTar.outputs.files.singleFile.name.replace(".tar.gz", "")

doFirst {
new File(dockerBuildDir).mkdir()
copy {
from tarTree(distTarFile)
into(dockerBuildDir)
}
file("${dockerBuildDir}/${distTarFileName}").renameTo("${dockerBuildDir}/ethsigner")
}
}

task distDocker(type: Exec) {
dependsOn dockerDistUntar
def dockerBuildVersion = project.hasProperty('release.releaseVersion') ? project.property('release.releaseVersion') : "${rootProject.version}"
def image="pegasyseng/ethsigner:develop"
def dockerBuildDir = "build/docker-ethsigner/"
workingDir "${dockerBuildDir}"


doFirst {
copy {
from file("${projectDir}/docker/Dockerfile")
into(workingDir)
}
}

executable "sh"
args "-c", "docker build --build-arg BUILD_DATE=${buildTime()} --build-arg VERSION=${dockerBuildVersion} --build-arg VCS_REF=${getCheckedOutGitCommitHash()} -t ${image} ."
}

task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
additionalSourceDirs.from files(subprojects.sourceSets.main.allSource.srcDirs)
sourceDirectories.from files(subprojects.sourceSets.main.allSource.srcDirs)
Expand Down Expand Up @@ -389,6 +429,14 @@ configurations { annotationProcessor }
}
*/

// http://label-schema.org/rc1/
// using the RFC3339 format "2016-04-12T23:20:50.52Z"
def buildTime() {
def df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'")
df.setTimeZone(TimeZone.getTimeZone("UTC"))
return df.format(new Date())
}

// Takes the version, and if -SNAPSHOT is part of it replaces SNAPSHOT
// with the git commit version.
def calculateVersion() {
Expand Down
25 changes: 25 additions & 0 deletions docker/Dockerfile
@@ -0,0 +1,25 @@

FROM openjdk:11.0.2-jre-slim-stretch

COPY ethsigner /opt/ethsigner/
WORKDIR /opt/ethsigner

# Expose services ports
# 8545 HTTP JSON-RPC
EXPOSE 8545

ENTRYPOINT ["/opt/ethsigner/bin/ethsigner"]

# Build-time metadata as defined at http://label-schema.org
ARG BUILD_DATE
ARG VCS_REF
ARG VERSION
LABEL org.label-schema.build-date=$BUILD_DATE \
org.label-schema.name="Ethsigner" \
org.label-schema.description="Ethereum transaction signing application" \
org.label-schema.url="https://docs.ethsigner.pegasys.tech/" \
org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.vcs-url="https://github.com/PegaSysEng/ethsigner.git" \
org.label-schema.vendor="Pegasys" \
org.label-schema.version=$VERSION \
org.label-schema.schema-version="1.0"
34 changes: 34 additions & 0 deletions docker/test.sh
@@ -0,0 +1,34 @@
#!/bin/bash

set -e

export GOSS_PATH=tests/goss-linux-amd64
export GOSS_OPTS="$GOSS_OPTS --format junit"
export GOSS_FILES_STRATEGY=cp

DOCKER_IMAGE=$1
DOCKER_TEST_IMAGE=ethsigner_goss

# create test docker image that includes the test key file and password files
TEST_CONTAINER_ID=$(docker create ${DOCKER_IMAGE})
docker cp ./tests/test_keyfile.json ${TEST_CONTAINER_ID}:/tmp/test_keyfile.json
docker cp ./tests/test_password ${TEST_CONTAINER_ID}:/tmp/test_password
docker commit ${TEST_CONTAINER_ID} ${DOCKER_TEST_IMAGE}

i=0

# Test for normal startup with ports opened
GOSS_FILES_PATH=tests/01 \
bash tests/dgoss \
run ${DOCKER_TEST_IMAGE} \
--chain-id=2018 \
--http-listen-host=0.0.0.0 \
--downstream-http-port=8590 \
file-based-signer \
--key-file /tmp/test_keyfile.json \
--password-file /tmp/test_password \
> ./reports/01.xml || i=`expr $i + 1`

docker image rm ${DOCKER_TEST_IMAGE}

exit $i
16 changes: 16 additions & 0 deletions docker/tests/01/goss.yaml
@@ -0,0 +1,16 @@
file:
/opt/ethsigner/bin/ethsigner:
exists: true
mode: "0755"
owner: root
group: root
filetype: file
contains: []
port:
tcp:8545:
listening: true
ip:
- 0.0.0.0
process:
java:
running: true
5 changes: 5 additions & 0 deletions docker/tests/01/goss_wait.yaml
@@ -0,0 +1,5 @@
port:
tcp:8545:
listening: true
ip:
- 0.0.0.0

0 comments on commit 17693f1

Please sign in to comment.