From 9b40bb288d7d214acfef3d6b84296e38ed64f13a Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 8 Mar 2023 16:22:07 +1000 Subject: [PATCH] Improvements to CI: comment on PR when syntax checking fails --- Jenkinsfile | 88 +++++++++++++-------------------- scripts/{ => ci}/frontend-build | 4 +- scripts/ci/test-and-build | 23 +++++++++ 3 files changed, 59 insertions(+), 56 deletions(-) rename scripts/{ => ci}/frontend-build (93%) create mode 100755 scripts/ci/test-and-build diff --git a/Jenkinsfile b/Jenkinsfile index f451eeb3..6c95a913 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,9 @@ +import groovy.transform.Field + +@Field +def shOutput = "" +def buildxPushTags = "" + pipeline { agent { label 'docker-multiarch' @@ -16,6 +22,8 @@ pipeline { COMPOSE_FILE = 'docker/docker-compose.ci.yml' COMPOSE_INTERACTIVE_NO_CLI = 1 BUILDX_NAME = "${COMPOSE_PROJECT_NAME}" + DOCS_BUCKET = 'jc21-npm-site' + DOCS_CDN = 'EN1G6DEWZUTDT' } stages { stage('Environment') { @@ -26,7 +34,7 @@ pipeline { } steps { script { - env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest" + buildxPushTags = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest" } } } @@ -39,7 +47,7 @@ pipeline { steps { script { // Defaults to the Branch name, which is applies to all branches AND pr's - env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}" + buildxPushTags = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}" } } } @@ -54,35 +62,28 @@ pipeline { } } } - stage('Frontend') { + stage('Build and Test') { steps { - sh './scripts/frontend-build' + script { + // Frontend and Backend + def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: ''' + set -e + ./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1 + ./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1 + ''') + shOutput = readFile "${env.WORKSPACE}/tmp-sh-build" + if (shStatusCode != 0) { + error "${shOutput}" + } + } } - } - stage('Backend') { - steps { - echo 'Checking Syntax ...' - sh 'docker pull nginxproxymanager/nginx-full:certbot-node' - // See: https://github.com/yarnpkg/yarn/issues/3254 - sh '''docker run --rm \\ - -v "$(pwd)/backend:/app" \\ - -v "$(pwd)/global:/app/global" \\ - -w /app \\ - nginxproxymanager/nginx-full:certbot-node \\ - sh -c "yarn install && yarn eslint . && rm -rf node_modules" - ''' - - echo 'Docker Build ...' - sh '''docker build --pull --no-cache --squash --compress \\ - -t "${IMAGE}:ci-${BUILD_NUMBER}" \\ - -f docker/Dockerfile \\ - --build-arg TARGETPLATFORM=linux/amd64 \\ - --build-arg BUILDPLATFORM=linux/amd64 \\ - --build-arg BUILD_VERSION="${BUILD_VERSION}" \\ - --build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\ - --build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\ - . - ''' + post { + always { + sh 'rm -f ${WORKSPACE}/tmp-sh-build' + } + failure { + npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true) + } } } stage('Integration Tests Sqlite') { @@ -164,10 +165,8 @@ pipeline { } steps { withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) { - // Docker Login - sh "docker login -u '${duser}' -p '${dpass}'" - // Buildx with push from cache - sh "./scripts/buildx --push ${BUILDX_PUSH_TAGS}" + sh 'docker login -u "${duser}" -p "${dpass}"' + sh "./scripts/buildx --push ${buildxPushTags}" } } } @@ -181,26 +180,7 @@ pipeline { } } steps { - withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'npm-s3-docs', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { - sh """docker run --rm \\ - --name \${COMPOSE_PROJECT_NAME}-docs-upload \\ - -e S3_BUCKET=jc21-npm-site \\ - -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\ - -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\ - -v \$(pwd):/app \\ - -w /app \\ - jc21/ci-tools \\ - scripts/docs-upload /app/docs/.vuepress/dist/ - """ - - sh """docker run --rm \\ - --name \${COMPOSE_PROJECT_NAME}-docs-invalidate \\ - -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\ - -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\ - jc21/ci-tools \\ - aws cloudfront create-invalidation --distribution-id EN1G6DEWZUTDT --paths '/*' - """ - } + npmDocsRelease("$DOCS_BUCKET", "$DOCS_CDN") } } stage('PR Comment') { @@ -214,7 +194,7 @@ pipeline { } steps { script { - def comment = pullRequest.comment("This is an automated message from CI:\n\nDocker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.") + npmGithubPrComment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.", true) } } } diff --git a/scripts/frontend-build b/scripts/ci/frontend-build similarity index 93% rename from scripts/frontend-build rename to scripts/ci/frontend-build index 0e12cf06..8efabe48 100755 --- a/scripts/frontend-build +++ b/scripts/ci/frontend-build @@ -1,14 +1,14 @@ #!/bin/bash -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -. "$DIR/.common.sh" +. "$DIR/../.common.sh" DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node # Ensure docker exists if hash docker 2>/dev/null; then docker pull "${DOCKER_IMAGE}" - cd "${DIR}/.." + cd "${DIR}/../.." echo -e "${BLUE}❯ ${CYAN}Building Frontend ...${RESET}" docker run --rm -e CI=true -v "$(pwd)/frontend:/app/frontend" -v "$(pwd)/global:/app/global" -w /app/frontend "$DOCKER_IMAGE" sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend" echo -e "${BLUE}❯ ${GREEN}Building Frontend Complete${RESET}" diff --git a/scripts/ci/test-and-build b/scripts/ci/test-and-build new file mode 100755 index 00000000..1c0036b6 --- /dev/null +++ b/scripts/ci/test-and-build @@ -0,0 +1,23 @@ +#!/bin/bash -e + +DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node +docker pull "${DOCKER_IMAGE}" + +# Test +docker run --rm \ + -v "$(pwd)/backend:/app" \ + -v "$(pwd)/global:/app/global" \ + -w /app \ + "${DOCKER_IMAGE}" \ + sh -c 'yarn install && yarn eslint . && rm -rf node_modules' + +# Build +docker build --pull --no-cache --squash --compress \ + -t "${IMAGE}:ci-${BUILD_NUMBER}" \ + -f docker/Dockerfile \ + --build-arg TARGETPLATFORM=linux/amd64 \ + --build-arg BUILDPLATFORM=linux/amd64 \ + --build-arg BUILD_VERSION="${BUILD_VERSION}" \ + --build-arg BUILD_COMMIT="${BUILD_COMMIT}" \ + --build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \ + .