From 12afc16dfa2c53f1947358449025741ac39d2d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 7 Jan 2019 14:39:22 +0100 Subject: [PATCH 1/6] Moved pre-package testing that depends on building --- Jenkinsfile | 70 ++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7202257c4..c51d460d9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -159,40 +159,44 @@ pipeline { sh 'npm run check:package-lock' } } + } + } - stage('Pre-package tests') { - agent { - dockerfile { - filename 'Dockerfile.testing' - label 'docker' - // /etc/passwd is mapped so a jenkins users is available from within the container - // ~/.ssh is mapped to allow pushing to GitHub via SSH - args '-e "HOME=${WORKSPACE}" -v /etc/passwd:/etc/passwd:ro -v /home/jenkins/.ssh:/home/jenkins/.ssh:ro' - } - } - steps { - // Remove any node_modules that might already be here - sh 'rm -rf node_modules' - // Link in the node_modules from the image - sh 'ln -s /tmp/node_modules .' - // Run the tests - sh 'MOCHA_FILE=pre-test-results.xml xvfb-run npm run test:ci' - } - post { - always { - // Archive the test results - junit( - allowEmptyResults: true, - keepLongStdio: true, - testResults: 'pre-test-results.xml' - ) - // Archive any screenshots emitted by failing tests - archiveArtifacts( - artifacts: 'failure-*.png', - allowEmptyArchive: true, - ) - } - } + stage('Pre-package tests') { + when { + // Don't do this when preparing for a release + not { environment name: 'PREPARE', value: 'true' } + } + agent { + dockerfile { + filename 'Dockerfile.testing' + label 'docker' + // /etc/passwd is mapped so a jenkins users is available from within the container + // ~/.ssh is mapped to allow pushing to GitHub via SSH + args '-e "HOME=${WORKSPACE}" -v /etc/passwd:/etc/passwd:ro -v /home/jenkins/.ssh:/home/jenkins/.ssh:ro' + } + } + steps { + // Remove any node_modules that might already be here + sh 'rm -rf node_modules' + // Link in the node_modules from the image + sh 'ln -s /tmp/node_modules .' + // Run the tests + sh 'MOCHA_FILE=pre-test-results.xml xvfb-run npm run test:ci' + } + post { + always { + // Archive the test results + junit( + allowEmptyResults: true, + keepLongStdio: true, + testResults: 'pre-test-results.xml' + ) + // Archive any screenshots emitted by failing tests + archiveArtifacts( + artifacts: 'failure-*.png', + allowEmptyArchive: true, + ) } } } From b431481484b0c9635c41f7828904163a4725f39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 7 Jan 2019 14:39:40 +0100 Subject: [PATCH 2/6] Deleted the unused Jenkinsfile.release --- Jenkinsfile.release | 137 -------------------------------------------- 1 file changed, 137 deletions(-) delete mode 100644 Jenkinsfile.release diff --git a/Jenkinsfile.release b/Jenkinsfile.release deleted file mode 100644 index a086a83a9..000000000 --- a/Jenkinsfile.release +++ /dev/null @@ -1,137 +0,0 @@ -#!groovy - -@Library('realm-ci') _ - -setBuildName(env.VERSION_TAG); - -jobWrapper { - node('macos-cph-02.cph.realm') { - stage('Checkout') { - checkoutAtVersion() - } - - def packageJson = readJSON(file: 'package.json') - def nodeVersion = readFile('.nvmrc').trim() - def nvmInstallDir = sh(returnStdout: true, script: 'brew --prefix nvm').trim() - - nvm('version': nodeVersion, 'nvmInstallDir': nvmInstallDir) { - stage('Prechecks') { - assert "v${packageJson.version}" == env.VERSION_TAG : "Tag doesn't match package.json version" - // Test that we're actually using the right node version, this has been a problem before - def actualNodeVersion = sh(returnStdout: true, script: 'node --version').trim() - assert nodeVersion == actualNodeVersion : "Node version doesn't match" - } - - // Start installing, building, testing and packaging the app - stage('Install') { - sh 'npm install' - } - - stage('Build') { - withCredentials([ - string(credentialsId: 'realm-studio-sentry-token', variable: 'SENTRY_AUTH_TOKEN') - ]) { - sh 'npm run build' - } - } - - stage('Test') { - try { - // Runs the tests with reporting using the junit reporter - sh 'npm run test:ci' - } catch (err) { - error "Tests failed - see results on CI" - } finally { - junit( - keepLongStdio: true, - testResults: 'test-results.xml' - ) - // Archive any screenshots emitted by failing tests - archiveArtifacts( - artifacts: 'failure-*.png', - allowEmptyArchive: true, - ) - } - } - - stage('Package') { - withCredentials([ - file(credentialsId: 'cose-sign-certificate-windows', variable: 'WIN_CSC_LINK'), - string(credentialsId: 'cose-sign-password-windows', variable: 'WIN_CSC_KEY_PASSWORD') - ]) { - sh 'npx build -mlw -c.forceCodeSigning --publish never' - } - // Archive the packaged artifacts - archiveArtifacts 'dist/*' - } - - stage('Post-package test') { - sh 'npm run check:auto-update-files' - // TODO: Perform post-package tests on each of all platforms - } - - stage('Publish & notify') { - // Wait for input - input(message: "Ready to publish v${packageJson.version}?", id: 'publish') - - // Upload the build artifacts to S3 - def s3Config = packageJson.build.publish[0] - // Delete all the unpackaged directories - sh 'rm -rf dist/*/' - // Move yml files to another folder and upload them after other archives. - // This is to prevent clients from trying to upgrade before the files are there. - sh 'mkdir dist-finally && mv dist/*.yml dist-finally' - dir('dist') { - rlmS3Put(bucket: s3Config.bucket, path: s3Config.path) - } - // Upload the json and yml files - dir('dist-finally') { - rlmS3Put(bucket: s3Config.bucket, path: s3Config.path) - } - - // Publish GitHub release - if (env.GITHUB_RELEASE_ID) { - withCredentials([string(credentialsId: 'github-release-token', variable: 'GITHUB_TOKEN')]) { - // Update to publish the release - sh """ - curl \ - -H "Content-Type: application/json" \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -X PATCH \ - -d '{"draft": false}' \ - https://api.github.com/repos/realm/realm-studio/releases/${env.GITHUB_RELEASE_ID} - """ - } - } - - // Notify by posting to Slack - def url = "https://studio-releases.realm.io/${env.VERSION_TAG}" - def slackPost = [[ - 'title': "Realm Studio ${env.VERSION_TAG} has been released!", - 'title_link': url, - 'text': "Release notes and artifacts are available <${url}|here>", - 'color': 'good', - 'unfurl_links': false - ]] - postToSlack('slack-studio-team-url', slackPost) - postToSlack('slack-releases-webhook', slackPost) - } - } - } -} - -def checkoutAtVersion() { - return checkout([ - $class: 'GitSCM', - branches: [[name: "refs/tags/${VERSION_TAG}"]], - extensions: [ - [$class: 'WipeWorkspace'], - [$class: 'CleanCheckout'] - ], - gitTool: 'native git', - userRemoteConfigs: [[ - credentialsId: 'realm-ci-ssh', - url: 'git@github.com:realm/realm-studio.git' - ]] - ]) -} From c54dc7628e8960d2788d332420aea9c06a64df24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 7 Jan 2019 14:39:49 +0100 Subject: [PATCH 3/6] Adding a release note --- RELEASENOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f97938042..edb293abf 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -14,3 +14,4 @@ - Fixed the Dockerfile used when testing PRs. ([#1057](https://github.com/realm/realm-studio/pull/1057)) - Removing all existing and future unused locals. ([#1058](https://github.com/realm/realm-studio/pull/1058)) - Refactored singleton windows. ([#1066](https://github.com/realm/realm-studio/pull/1066)) +- Refactored the Jenkins CI pipeline. ([#1069](https://github.com/realm/realm-studio/pull/1069) & [#1073](https://github.com/realm/realm-studio/pull/1073)) From ccde7ac713c818755312120750dff58805c8f9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 7 Jan 2019 14:50:22 +0100 Subject: [PATCH 4/6] Reusing the node to checkout only once --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index c51d460d9..5f2adc10e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -170,7 +170,7 @@ pipeline { agent { dockerfile { filename 'Dockerfile.testing' - label 'docker' + reuseNode true // /etc/passwd is mapped so a jenkins users is available from within the container // ~/.ssh is mapped to allow pushing to GitHub via SSH args '-e "HOME=${WORKSPACE}" -v /etc/passwd:/etc/passwd:ro -v /home/jenkins/.ssh:/home/jenkins/.ssh:ro' From 139a52106b2b1603e88539d72df2ee310d89a3aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 7 Jan 2019 15:00:51 +0100 Subject: [PATCH 5/6] Don't skip the default checkout --- Jenkinsfile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5f2adc10e..6e62a1fc6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,11 +11,6 @@ pipeline { GITHUB_REPO="realm-studio" } - options { - // Prevent checking out multiple times - skipDefaultCheckout() - } - parameters { booleanParam( name: 'PREPARE', @@ -167,10 +162,11 @@ pipeline { // Don't do this when preparing for a release not { environment name: 'PREPARE', value: 'true' } } + // Testing in a nested stage to work around an issue that would otherwise require a pipeline checkout. agent { dockerfile { filename 'Dockerfile.testing' - reuseNode true + label 'docker' // /etc/passwd is mapped so a jenkins users is available from within the container // ~/.ssh is mapped to allow pushing to GitHub via SSH args '-e "HOME=${WORKSPACE}" -v /etc/passwd:/etc/passwd:ro -v /home/jenkins/.ssh:/home/jenkins/.ssh:ro' From 20f466ecf8f641297bed85f232fdb5f1e17e3e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 7 Jan 2019 15:10:04 +0100 Subject: [PATCH 6/6] Restore previous behaviour, but building before testing --- Jenkinsfile | 78 +++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6e62a1fc6..c30b71b28 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,6 +11,11 @@ pipeline { GITHUB_REPO="realm-studio" } + options { + // Prevent checking out multiple times + skipDefaultCheckout() + } + parameters { booleanParam( name: 'PREPARE', @@ -154,45 +159,42 @@ pipeline { sh 'npm run check:package-lock' } } - } - } - stage('Pre-package tests') { - when { - // Don't do this when preparing for a release - not { environment name: 'PREPARE', value: 'true' } - } - // Testing in a nested stage to work around an issue that would otherwise require a pipeline checkout. - agent { - dockerfile { - filename 'Dockerfile.testing' - label 'docker' - // /etc/passwd is mapped so a jenkins users is available from within the container - // ~/.ssh is mapped to allow pushing to GitHub via SSH - args '-e "HOME=${WORKSPACE}" -v /etc/passwd:/etc/passwd:ro -v /home/jenkins/.ssh:/home/jenkins/.ssh:ro' - } - } - steps { - // Remove any node_modules that might already be here - sh 'rm -rf node_modules' - // Link in the node_modules from the image - sh 'ln -s /tmp/node_modules .' - // Run the tests - sh 'MOCHA_FILE=pre-test-results.xml xvfb-run npm run test:ci' - } - post { - always { - // Archive the test results - junit( - allowEmptyResults: true, - keepLongStdio: true, - testResults: 'pre-test-results.xml' - ) - // Archive any screenshots emitted by failing tests - archiveArtifacts( - artifacts: 'failure-*.png', - allowEmptyArchive: true, - ) + stage('Pre-package tests') { + agent { + dockerfile { + filename 'Dockerfile.testing' + label 'docker' + // /etc/passwd is mapped so a jenkins users is available from within the container + // ~/.ssh is mapped to allow pushing to GitHub via SSH + args '-e "HOME=${WORKSPACE}" -v /etc/passwd:/etc/passwd:ro -v /home/jenkins/.ssh:/home/jenkins/.ssh:ro' + } + } + steps { + // Remove any node_modules that might already be here + sh 'rm -rf node_modules' + // Link in the node_modules from the image + sh 'ln -s /tmp/node_modules .' + // Build the app for the spectron tests to run + sh 'npm run build' + // Run the tests + sh 'MOCHA_FILE=pre-test-results.xml xvfb-run npm run test:ci' + } + post { + always { + // Archive the test results + junit( + allowEmptyResults: true, + keepLongStdio: true, + testResults: 'pre-test-results.xml' + ) + // Archive any screenshots emitted by failing tests + archiveArtifacts( + artifacts: 'failure-*.png', + allowEmptyArchive: true, + ) + } + } } } }