diff --git a/Makefile b/Makefile index dfdbbcc57..ce2b8db06 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,9 @@ RELEASE_TAG := $(shell cat VERSION) RELEASE_BRANCH := "develop" -RELEASE_DIRECTORY := /tmp/release-$(RELEASE_TAG) +RELEASE_DIR := /tmp/release-$(RELEASE_TAG) PRE_RELEASE := "1" +RELEASE_TYPE := $(shell if [ $(PRE_RELEASE) = "0" ] ; then echo release; else echo pre-release ; fi) help: ##@other Show this help @perl -e '$(HELP_FUN)' $(MAKEFILE_LIST) @@ -55,6 +56,9 @@ DOCKER_IMAGE_CUSTOM_TAG ?= $(RELEASE_TAG) DOCKER_TEST_WORKDIR = /go/src/github.com/status-im/status-go/ DOCKER_TEST_IMAGE = golang:1.10 +XGO_NAME ?= status-go +XGO_TARGETS ?= linux/amd64,windows/amd64,darwin/amd64 + # This is a code for automatic help generator. # It supports ANSI colors and categories. # To add new item into help output, simply add comments @@ -122,10 +126,13 @@ statusgo-ios: ##@cross-compile Build status-go for iOS @gomobile bind -target=ios -ldflags="-s -w" $(BUILD_FLAGS) -o build/bin/Statusgo.framework github.com/status-im/status-go/mobile @echo "iOS framework cross compilation done in build/bin/Statusgo.framework" -statusgo-linux: xgo ##@cross-compile Build status-go for Linux - ./_assets/patches/patcher -b . -p geth-xgo - $(GOPATH)/bin/xgo --image $(XGOIMAGE) --go=$(XGO_GO) -out statusgo --dest=$(GOBIN) --targets=linux/amd64 -v -tags '$(BUILD_TAGS)' $(BUILD_FLAGS) ./cmd/statusd - ./_assets/patches/patcher -b . -p geth-xgo -r +statusgo-xgo: xgo-install ##@cross-compile Build status-go for xgo targets + $(GOPATH)/bin/xgo -v \ + -out=$(XGO_NAME) \ + -dest=$(GOBIN) \ + -targets=$(XGO_TARGETS) \ + -tags '$(BUILD_TAGS)' \ + $(BUILD_FLAGS) ./cmd/statusd @echo "Linux cross compilation done." statusgo-library: ##@cross-compile Build status-go as static library for current platform @@ -201,28 +208,37 @@ generate: ##@other Regenerate assets and other auto-generated stuff $(shell cd ./services/shhext/chat && exec protoc --go_out=. ./*.proto) prepare-release: clean-release - mkdir -p $(RELEASE_DIRECTORY) - mv build/bin/statusgo.aar $(RELEASE_DIRECTORY)/status-go-android.aar + mkdir -p $(RELEASE_DIR) + mv build/bin/statusgo.aar $(RELEASE_DIR)/status-go-android.aar zip -r build/bin/Statusgo.framework.zip build/bin/Statusgo.framework - mv build/bin/Statusgo.framework.zip $(RELEASE_DIRECTORY)/status-go-ios.zip - zip -r $(RELEASE_DIRECTORY)/status-go-desktop.zip . -x *.git* + mv build/bin/Statusgo.framework.zip $(RELEASE_DIR)/status-go-ios.zip + zip -r $(RELEASE_DIR)/status-go-desktop.zip . -x *.git* ${MAKE} clean clean-release: - rm -rf $(RELEASE_DIRECTORY) + rm -rf $(RELEASE_DIR) release: - @read -p "Are you sure you want to create a new GitHub $(shell if [ $(PRE_RELEASE) = "0" ] ; then echo release; else echo pre-release ; fi) against $(RELEASE_BRANCH) branch? (y/n): " REPLY; \ + @read -p "Are you sure you want to create a new GitHub $(RELEASE_TYPE} against $(RELEASE_BRANCH) branch? (y/n): " REPLY; \ if [ $$REPLY = "y" ]; then \ latest_tag=$$(git describe --tags `git rev-list --tags --max-count=1`); \ comparison="$$latest_tag..HEAD"; \ if [ -z "$$latest_tag" ]; then comparison=""; fi; \ changelog=$$(git log $$comparison --oneline --no-merges --format="* %h %s"); \ - github-release $(shell if [ $(PRE_RELEASE) != "0" ] ; then echo "-prerelease" ; fi) "status-im/status-go" "v$(RELEASE_TAG)" "$(RELEASE_BRANCH)" "$(changelog)" "$(RELEASE_DIRECTORY)/*" ; \ + github-release \ + $(shell if [ $(PRE_RELEASE) != "0" ] ; then echo "-prerelease" ; fi) \ + "status-im/status-go" \ + "v$(RELEASE_TAG)" \ + "$(RELEASE_BRANCH)" \ + "$(changelog)" \ + "$(RELEASE_DIR)/*" ; \ else \ echo "Aborting." && exit 1; \ fi +xgo-install: + go get -u github.com/karalabe/xgo + gomobile-install: go get -u golang.org/x/mobile/cmd/gomobile diff --git a/_assets/ci/Jenkinsfile b/_assets/ci/Jenkinsfile index 25c9c8b61..d787ec50d 100644 --- a/_assets/ci/Jenkinsfile +++ b/_assets/ci/Jenkinsfile @@ -31,7 +31,7 @@ pipeline { GOPATH = "${env.WORKSPACE}" PATH = "${env.PATH}:${env.GOPATH}/bin" /* This will override the var in Makefile */ - RELEASE_DIRECTORY = "${env.WORKSPACE}/pkg" + RELEASE_DIR = "${env.WORKSPACE}/pkg" } stages { @@ -64,16 +64,19 @@ pipeline { stage('Docker') { steps { script { dock = lib.buildBranch('status-go/platforms/docker') } } } + stage('XGO') { steps { script { + xgo = lib.buildBranch('status-go/platforms/xgo') + } } } } // parallel } // stage(Build) stage('Archive') { steps { script { - sh("rm -fr ${env.RELEASE_DIRECTORY}/*") - lib.copyArts('status-go/platforms/ios', ios.number) - lib.copyArts('status-go/platforms/android', android.number) - lib.copyArts('status-go/platforms/linux', linux.number) - dir(env.RELEASE_DIRECTORY) { + sh("rm -fr ${env.RELEASE_DIR}/*") + [ios, android, linux, xgo].each { platformBuild -> + lib.copyArts(platformBuild) + } + dir(env.RELEASE_DIR) { /* generate sha256 checksums for upload */ sh 'sha256sum * | tee checksum.sha256' archiveArtifacts('*') @@ -82,12 +85,13 @@ pipeline { } // stage(Archive) stage('Release') { when { expression { params.RELEASE == true } } - steps { + steps { script { /* rename build files to not include versions */ - dir(env.RELEASE_DIRECTORY) { - sh 'mv status-go-ios-*.zip status-go-ios.zip' - sh 'mv status-go-android-*.aar status-go-android.aar' - sh 'mv status-go-desktop-*.zip status-go-desktop.zip' + dir(env.RELEASE_DIR) { + def pkgs = findFiles(glob: 'status-go-*') + pkgs.each { pkg -> + sh "mv ${pkg.path} ${pkg.path.replace("-"+lib.suffix(), "")}" + } } /* perform the release */ dir(env.STATUS_PATH) { @@ -97,14 +101,12 @@ pipeline { usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN' ]]) { - sh """ - yes | make release \ - RELEASE_BRANCH=${lib.gitBranch()} \ - RELEASE_DIRECTORY=${env.RELEASE_DIRECTORY} - """ + env.RELEASE_BRANCH = lib.gitBranch() + env.RELEASE_DIR = env.RELEASE_DIR + sh 'yes | make release' } } - } + } } } // stage(Release) stage('Cleanup') { steps { dir(env.STATUS_PATH) { diff --git a/_assets/ci/Jenkinsfile.android b/_assets/ci/Jenkinsfile.android index a544e6fcf..f4da81941 100644 --- a/_assets/ci/Jenkinsfile.android +++ b/_assets/ci/Jenkinsfile.android @@ -28,7 +28,7 @@ pipeline { environment { BUILD_PLATFORM = 'android' - STATUS_PATH = 'src/github.com/status-im/status-go' + STATUS_PATH = "${env.WORKSPACE}/src/github.com/status-im/status-go" CI_DIR = "${env.STATUS_PATH}/_assets/ci" GOPATH = "${env.WORKSPACE}" PATH = "${env.PATH}:${env.GOPATH}/bin" diff --git a/_assets/ci/Jenkinsfile.docker b/_assets/ci/Jenkinsfile.docker index 978bfabe4..ca1df0a77 100644 --- a/_assets/ci/Jenkinsfile.docker +++ b/_assets/ci/Jenkinsfile.docker @@ -27,7 +27,7 @@ pipeline { } environment { - STATUS_PATH = 'src/github.com/status-im/status-go' + STATUS_PATH = "${env.WORKSPACE}/src/github.com/status-im/status-go" CI_DIR = "${env.STATUS_PATH}/_assets/ci" GOPATH = "${env.WORKSPACE}" PATH = "${env.PATH}:${env.GOPATH}/bin" diff --git a/_assets/ci/Jenkinsfile.ios b/_assets/ci/Jenkinsfile.ios index d8cfb082b..7c3148bf3 100644 --- a/_assets/ci/Jenkinsfile.ios +++ b/_assets/ci/Jenkinsfile.ios @@ -28,7 +28,7 @@ pipeline { environment { BUILD_PLATFORM = 'ios' - STATUS_PATH = 'src/github.com/status-im/status-go' + STATUS_PATH = "${env.WORKSPACE}/src/github.com/status-im/status-go" CI_DIR = "${env.STATUS_PATH}/_assets/ci" GOPATH = "${env.WORKSPACE}" PATH = "${env.PATH}:${env.GOPATH}/bin" diff --git a/_assets/ci/Jenkinsfile.linux b/_assets/ci/Jenkinsfile.linux index 8a443980d..1092bf4f0 100644 --- a/_assets/ci/Jenkinsfile.linux +++ b/_assets/ci/Jenkinsfile.linux @@ -28,7 +28,7 @@ pipeline { environment { BUILD_PLATFORM = 'linux' - STATUS_PATH = 'src/github.com/status-im/status-go' + STATUS_PATH = "${env.WORKSPACE}/src/github.com/status-im/status-go" CI_DIR = "${env.STATUS_PATH}/_assets/ci" GOPATH = "${env.WORKSPACE}" PATH = "${env.PATH}:${env.GOPATH}/bin" diff --git a/_assets/ci/Jenkinsfile.xgo b/_assets/ci/Jenkinsfile.xgo new file mode 100644 index 000000000..82b4151c9 --- /dev/null +++ b/_assets/ci/Jenkinsfile.xgo @@ -0,0 +1,79 @@ +pipeline { + agent { label 'linux' } + + parameters { + string( + name: 'BRANCH', + defaultValue: 'publis-status-go-bin', + description: 'Name of branch to build.' + ) + booleanParam( + name: 'RELEASE', + defaultValue: false, + description: 'Enable to create build for release.', + ) + } + + options { + timestamps() + disableConcurrentBuilds() + /* Go requires a certain directory structure */ + checkoutToSubdirectory('src/github.com/status-im/status-go') + /* manage how many builds we keep */ + buildDiscarder(logRotator( + numToKeepStr: '30', + daysToKeepStr: '30', + )) + } + + + environment { + BUILD_PLATFORM = 'xgo' + STATUS_PATH = "${env.WORKSPACE}/src/github.com/status-im/status-go" + CI_DIR = "${env.STATUS_PATH}/_assets/ci" + GOPATH = "${env.WORKSPACE}" + PATH = "${env.PATH}:${env.GOPATH}/bin" + GOCACHE = "off" + } + + stages { + stage('Prep') { + steps { script { dir(env.STATUS_PATH) { + lib = load("${env.STATUS_PATH}/_assets/ci/lib.groovy") + /* clarify what we're building */ + println("Version: ${lib.getVersion()}") + println("Git Branch: ${lib.gitBranch()}") + println("Git Commit: ${lib.gitCommit()}") + /* prepare dependencies */ + sh 'make xgo-install' + } } } + } + + stage('Build') { + steps { script { dir(env.STATUS_PATH) { + sh 'make statusgo-xgo' + /* append timestamp and commit to names */ + def results = findFiles(glob: 'build/bin/status-go-*') + results.each { file -> + def newName = file.path.replace("amd64", "amd64-${lib.suffix()}") + sh "mv ${file.path} ${newName}" + } + } } } + } + + stage('Archive') { + steps { dir(env.STATUS_PATH) { + archiveArtifacts('build/bin/status-go-*') + } } + } + + stage('Upload') { steps { dir(env.STATUS_PATH) { script { + def binaries = findFiles(glob: 'build/bin/status-go-*') + binaries.each { binary -> lib.uploadArtifact(binary.path) } + } } } } + } + post { + success { script { load("${CI_DIR}/ghcmgr.groovy").postBuild(true) } } + failure { script { load("${CI_DIR}/ghcmgr.groovy").postBuild(false) } } + } // post +} diff --git a/_assets/ci/lib.groovy b/_assets/ci/lib.groovy index 8669abbd5..b8826eb4c 100644 --- a/_assets/ci/lib.groovy +++ b/_assets/ci/lib.groovy @@ -1,13 +1,19 @@ def getVersion() { - return readFile("${env.WORKSPACE}/${env.STATUS_PATH}/VERSION").trim() + return readFile("${env.STATUS_PATH}/VERSION").trim() } def gitCommit() { return GIT_COMMIT.take(6) } +def parentOrCurrentBuild() { + def c = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause) + if (c == null) { return currentBuild } + return c.getUpstreamRun() +} + def timestamp() { - def now = new Date(currentBuild.timeInMillis) + def now = new Date(parentOrCurrentBuild().timeInMillis) return now.format('yyMMdd-HHmmss', TimeZone.getTimeZone('UTC')) } @@ -74,14 +80,17 @@ def buildBranch(name = null, buildType = null) { return resp } -def copyArts(projectName, buildNo) { +def copyArts(build) { + /** + * The build argument is of class RunWrapper. + * https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html + **/ copyArtifacts( - projectName: projectName, + projectName: build.fullProjectName, target: 'pkg', flatten: true, - selector: specific("${buildNo}") + selector: specific("${build.number}") ) } return this -