diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile index 6c5f54178..44a12e106 100644 --- a/ci/Jenkinsfile +++ b/ci/Jenkinsfile @@ -1,33 +1,110 @@ -node(label: 'linux') { - stage('git:checkout') { - cleanWs() - checkout scm - sh 'printenv' - sh 'git show-ref --head HEAD | head -c 7 > git-HEAD' - sh 'cat git-HEAD' +import groovy.transform.Field +// Global for which node version to use on macos and windows +@Field final String nodeVersion = '9.2.0' + +// Run targets in parallel +parallel( + // the 'proper' CI pipeline runs in docker + "docker": { + node(label: 'linux') { ws("${env.WORKSPACE}/docker") { + def ciContext = 'continuous-integration/jenkins/docker/' + githubNotify description: 'Build in progress', status: 'PENDING', context: ciContext + cleanWs() + checkout scm + fileExists 'package.json' + // sh 'printenv' + sh 'git show-ref --head HEAD | head -c 7 > git-HEAD' + sh 'cat git-HEAD' + try { + stage('ci:install') { + sh 'docker build -t ipfs-companion:$(cat git-HEAD) .' + } + try { + stage('ci:test') { + sh 'docker run -i --rm -e JUNIT_REPORT_PATH=test/report.xml -v $(pwd)/test:/usr/src/app/test:rw ipfs-companion:$(cat git-HEAD) npm run ci:test' + } + } finally { + junit allowEmptyResults: true, testResults: 'test/report.xml' + } + stage('ci:build') { + sh 'mkdir -p $(pwd)/build' + sh 'docker run -i --rm -v $(pwd)/build:/usr/src/app/build:rw -v $(pwd)/add-on:/usr/src/app/add-on:rw ipfs-companion:$(cat git-HEAD) npm run ci:build' + sh 'ls -Rlh build' + archiveArtifacts artifacts: 'build/**/*.zip', fingerprint: true + } + stage('lint:web-ext') { + sh 'docker run -i --rm -v $(pwd)/add-on:/usr/src/app/add-on:ro ipfs-companion:$(cat git-HEAD) npm run lint:web-ext' + } + githubNotify description: 'Reproducible build looks good', status: 'SUCCESS', context: ciContext + } catch (err) { + echo "Caught: ${err}" + currentBuild.result = 'FAILURE' + githubNotify description: 'Reproducible build failed', status: 'FAILURE', context: ciContext + } finally { + sh 'docker rmi -f ipfs-companion:$(cat git-HEAD)' + cleanWs() + } + }} + }, + // run dev-build under windows as a smoke-test to ensure it can be built on that platform + "windows": { + node(label: 'windows') { ansiColor('xterm') { withEnv(['CI=true']) { ws("${env.JOB_NAME}/windows") { + def ciContext = 'continuous-integration/jenkins/windows/' + githubNotify description: 'Build in progress', status: 'PENDING', context: ciContext + cleanWs() + bat 'git config --global core.autocrlf input' + checkout scm + fileExists 'package.json' + nodejs(nodeVersion) { try { + stage('win:dev-build') { + // remove node_modules if any + bat 'del /s /q node_modules >nul 2>&1' + // https://github.com/yarnpkg/yarn/issues/3110#issuecomment-293347341 + bat 'npx yarn@1.6.0 config set msvs_version 2015 --global' + // run developer build as a smoke-test for windows + bat 'npm run dev-build' + bat 'dir /s /b /o:gn build' + } + stage('win:test') { + bat 'npm test' + } + githubNotify description: 'Dev build looks good', status: 'SUCCESS', context: ciContext + } catch (err) { + echo "Caught: ${err}" + currentBuild.result = 'FAILURE' + githubNotify description: 'Dev build failed', status: 'FAILURE', context: ciContext + } finally { + cleanWs() + }} + }}}} + }, + // run dev-build under macos as a smoke-test to ensure it can be built on that platform + "macos": { + node(label: 'macos') { ansiColor('xterm') { withEnv(['CI=true']) { ws("${env.JOB_NAME}/macos") { + def ciContext = 'continuous-integration/jenkins/macos/' + githubNotify description: 'Build in progress', status: 'PENDING', context: ciContext + cleanWs() + checkout scm + fileExists 'package.json' + nodejs(nodeVersion) { try { + stage('mac:dev-build') { + sh 'rm -rf node_modules/' + // run developer build as a smoke-test + sh 'npm run dev-build' + sh 'ls -Rlh build' + } + stage('mac:test') { + sh 'npm test' + } + githubNotify description: 'Dev build looks good', status: 'SUCCESS', context: ciContext + } catch (err) { + echo "Caught: ${err}" + currentBuild.result = 'FAILURE' + githubNotify description: 'Dev build failed', status: 'FAILURE', context: ciContext + } finally { + cleanWs() + }} + }}}} } - stage('ci:install') { - sh 'docker build -t ipfs-companion:$(cat git-HEAD) .' - } - catchError { - stage('ci:test') { - sh 'docker run -i --rm -e JUNIT_REPORT_PATH=test/report.xml -v $(pwd)/test:/usr/src/app/test:rw ipfs-companion:$(cat git-HEAD) npm run ci:test' - } - } - junit allowEmptyResults: true, testResults: 'test/report.xml' - catchError { - stage('ci:build') { - sh 'mkdir -p $(pwd)/build' - sh 'docker run -i --rm -v $(pwd)/build:/usr/src/app/build:rw -v $(pwd)/add-on:/usr/src/app/add-on:rw ipfs-companion:$(cat git-HEAD) npm run ci:build' - archiveArtifacts artifacts: 'build/**/*.zip', fingerprint: true - } - stage('lint:web-ext') { - sh 'docker run -i --rm -v $(pwd)/add-on:/usr/src/app/add-on:ro ipfs-companion:$(cat git-HEAD) npm run lint:web-ext' - } - } - sh 'docker rmi -f ipfs-companion:$(cat git-HEAD)' - sh 'ls -lh .' - sh 'ls -Rlh add-on' - sh 'ls -Rlh build' - cleanWs() -} +) +