// Initialize variables to signal that a given stage finished. // We use them to build a graph of interconnected steps/dependencies. // - Incoming edges use "waitUntil" and reference the given variables of dependencies. // - Outgoing edges set the given variable to true. def action_test_frontend_ct_build = false def action_build_deps = false def action_copy_external_pages = false def action_build_dev = false def action_test_acceptance_app_server_pro = false def action_build_webpack = false def action_test_acceptance_app_saas = false def action_build_pug = false def action_build_production = false pipeline { agent { node { // Select a VM with the given tabel. label 'jenkins-agent-web' // Use the monorepo checkout in /workspace. customWorkspace '/workspace' } } options { // Print timestamp next to each log line. timestamps() // Abort build after hitting first failure. parallelsAlwaysFailFast() retry(3) timeout(time: 15, unit: 'MINUTES') } environment { IMAGE_NAME = 'web' PROJECT_NAME = 'web' IMAGE_REPO = 'us-east1-docker.pkg.dev/overleaf-ops/ol-docker/web' AR_REPO_LOCATION = 'us-east1' AR_URL = 'us-east1-docker.pkg.dev/overleaf-ops/ol-docker' DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" // preserve original BUILD_NUMBER BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" // mimic the format used for Cloud Build COMMIT_SHA = "${GIT_COMMIT}" SHORT_SHA = "${GIT_COMMIT.take(7)}" CDN_STAG = "gs://ol-stag-web-assets-1" CDN_PROD = "gs://mgcp-1117973-ol-prod-web-assets-1" } stages { // Retries will use the same pipeline instance. Reset the vars. stage('Reset vars') { steps { script { action_test_frontend_ct_build = false action_build_deps = false action_copy_external_pages = false action_build_dev = false action_test_acceptance_app_server_pro = false action_build_webpack = false action_test_acceptance_app_saas = false action_build_pug = false action_build_production = false } } } stage ('Build, Test and Push') { parallel { stage('Copy external pages') { steps { dir('services/web') { sh 'bin/copy_external_pages' script { action_copy_external_pages = true } } } } stage('Prefetch Tests Images') { steps { dir('services/web') { sh 'docker compose -f docker-compose.ci.yml pull --quiet test_frontend_ct mongo redis_test ldap saml' } } } stage('Build Deps') { steps { dir('services/web') { sh 'make build_deps' } script { action_build_deps = true } } } stage('Push Deps') { steps { script { waitUntil { return action_build_deps } } dir('services/web') { sh 'docker push ${AR_URL}/${IMAGE_NAME}:${BRANCH_NAME}-deps' } } } stage('Build Dev') { steps { script { waitUntil { return action_build_deps && action_copy_external_pages } } dir('services/web') { sh 'make build_dev' } script { action_build_dev = true } } } stage ('Format') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh 'make format_in_docker' } } } stage('Lint') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh 'make lint_in_docker' } } } stage('Shellcheck') { steps { dir('services/web') { sh 'make shellcheck' } } } stage('Acceptance SaaS') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh 'make test_acceptance_app_saas' } script { action_test_acceptance_app_saas = true } } } stage('Acceptance Server CE') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_app_server_ce" } } } stage('Acceptance Server Pro') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_app_server_pro" } script { action_test_acceptance_app_server_pro = true } } } stage('test_acceptance_modules_merged_saas_1') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_modules_merged_saas_1" } } } stage('test_acceptance_modules_merged_saas_2') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_modules_merged_saas_2" } } } stage('test_acceptance_modules_merged_saas_3') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_modules_merged_saas_3" } } } stage('test_acceptance_modules_merged_saas_4') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_modules_merged_saas_4" } } } stage('test_acceptance_modules_merged_server_ce') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_modules_merged_server_ce" } } } stage('test_acceptance_modules_merged_server_pro') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_acceptance_modules_merged_server_pro" } } } stage('test_frontend') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_frontend" } } } stage('test_writefull') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_writefull" } } } stage('test_frontend_ct_build') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make build_test_frontend_ct" } script { action_test_frontend_ct_build = true } } } stage('test_frontend_ct_core_other') { environment { CYPRESS_INTERNAL_BROWSER_CONNECT_TIMEOUT = '120000' } steps { script { waitUntil { return action_test_frontend_ct_build } } dir('services/web') { sh "make test_frontend_ct_core_other" } } } stage('test_frontend_ct_core_features') { environment { CYPRESS_INTERNAL_BROWSER_CONNECT_TIMEOUT = '120000' } steps { script { waitUntil { return action_test_frontend_ct_build } } dir('services/web') { sh "make test_frontend_ct_core_features" } } } stage('test_frontend_ct_modules') { environment { CYPRESS_INTERNAL_BROWSER_CONNECT_TIMEOUT = '120000' } steps { script { waitUntil { return action_test_frontend_ct_build } } dir('services/web') { sh "make test_frontend_ct_modules" } } } stage('test_frontend_ct_editor_visual') { steps { script { waitUntil { return action_test_frontend_ct_build } } dir('services/web') { sh "make test_frontend_ct_editor_visual" } } } stage('test_frontend_ct_editor_other') { steps { script { waitUntil { return action_test_frontend_ct_build } } dir('services/web') { sh "make test_frontend_ct_editor_other" } } } stage('Test Unit ESM') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_unit_esm" } } } stage('Test Unit Mocha') { steps { script { waitUntil { return action_build_dev } } dir('services/web') { sh "make test_unit_mocha" } } } stage('Build Webpack') { steps { script { waitUntil { return action_build_dev && action_test_acceptance_app_server_pro } } dir('services/web') { sh 'make build_webpack' } script { action_build_webpack = true } } } stage('Build Pug') { steps { script { waitUntil { return action_build_dev && action_test_acceptance_app_server_pro } } dir('services/web') { sh 'make build_pug' } script { action_build_pug = true } } } stage('CDN Upload Image') { steps { script { waitUntil { return action_build_webpack } } dir('services/web') { sh 'make tar' sh 'bin/cdn_upload' } } } stage('Build Production') { steps { script { waitUntil { return action_build_webpack && action_build_pug } } dir('services/web') { sh 'make build' } script { action_build_production = true } } } stage('Sentry Upload') { steps { script { waitUntil { return action_build_webpack && action_build_production } } dir('services/web') { sh 'gcloud secrets versions access latest --secret=web-sentryclirc > .sentryclirc' sh 'make sentry_upload' } } post { cleanup { dir('services/web') { sh 'rm -f .sentryclirc' } } } } } } stage('Push Production') { steps { dir('services/web') { sh 'make publish' } } } } post { // Ensure tear down of test containers, then run general Jenkins VM cleanup. cleanup { dir('services/web') { sh 'make clean' } sh 'make clean_jenkins' } } } // vim: set ft=groovy :