-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Indent Jenkinsfile with 2 spaces Signed-off-by: Marvin A. Ruder <signed@mruder.dev>
- Loading branch information
1 parent
4e24289
commit 2e018ce
Showing
2 changed files
with
123 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,137 @@ | ||
node('rating-tracker-build') { | ||
withEnv([ | ||
'IMAGE_NAME=marvinruder/rating-tracker', | ||
'FORCE_COLOR=true', | ||
'DOCKER_CI_FLAGS=-f docker/Dockerfile-ci --network=host --cache-from=registry.internal.mruder.dev/cache:rating-tracker-wasm' | ||
]) { | ||
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) { | ||
// Use random job identifier and test port numbers to avoid collisions | ||
def JOB_ID = sh (script: "#!/bin/bash\nprintf \"%04d\" \$((1 + RANDOM % 4096))", returnStdout: true) | ||
def PGPORT = sh (script: "#!/bin/bash\necho -n \$((49151 + 10#$JOB_ID))", returnStdout: true) | ||
def REDISPORT = sh (script: "#!/bin/bash\necho -n \$((53247 + 10#$JOB_ID))", returnStdout: true) | ||
def TESTPORT = sh (script: "#!/bin/bash\necho -n \$((57343 + 10#$JOB_ID))", returnStdout: true) | ||
withEnv([ | ||
'IMAGE_NAME=marvinruder/rating-tracker', | ||
'FORCE_COLOR=true', | ||
'DOCKER_CI_FLAGS=-f docker/Dockerfile-ci --network=host --cache-from=registry.internal.mruder.dev/cache:rating-tracker-wasm' | ||
]) { | ||
withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) { | ||
// Use random job identifier and test port numbers to avoid collisions | ||
def JOB_ID = sh (script: "#!/bin/bash\nprintf \"%04d\" \$((1 + RANDOM % 4096))", returnStdout: true) | ||
def PGPORT = sh (script: "#!/bin/bash\necho -n \$((49151 + 10#$JOB_ID))", returnStdout: true) | ||
def REDISPORT = sh (script: "#!/bin/bash\necho -n \$((53247 + 10#$JOB_ID))", returnStdout: true) | ||
def TESTPORT = sh (script: "#!/bin/bash\necho -n \$((57343 + 10#$JOB_ID))", returnStdout: true) | ||
|
||
try { | ||
parallel( | ||
scm: { | ||
stage('Clone repository') { | ||
checkout scm | ||
} | ||
}, | ||
docker_env: { | ||
stage('Start Docker environment') { | ||
// Log in to Docker Hub | ||
sh('echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin') | ||
try { | ||
parallel( | ||
scm: { | ||
stage('Clone repository') { | ||
checkout scm | ||
} | ||
}, | ||
docker_env: { | ||
stage('Start Docker environment') { | ||
// Log in to Docker Hub | ||
sh('echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin') | ||
|
||
// Create builder instance and prefetch Docker base images | ||
sh """ | ||
JENKINS_NODE_COOKIE=DONT_KILL_ME /bin/sh -c '(curl -Ls https://raw.githubusercontent.com/$IMAGE_NAME/\$BRANCH_NAME/docker/Dockerfile-prefetch | docker build -) &' | ||
docker builder create --name rating-tracker --driver docker-container --driver-opt network=host --bootstrap || : | ||
JENKINS_NODE_COOKIE=DONT_KILL_ME /bin/sh -c '(curl -Ls https://raw.githubusercontent.com/$IMAGE_NAME/\$BRANCH_NAME/docker/Dockerfile-prefetch-buildx | docker buildx build --builder rating-tracker --network=host --cache-from=registry.internal.mruder.dev/cache:rating-tracker-wasm -) &' | ||
""" | ||
} | ||
} | ||
) | ||
// Create builder instance and prefetch Docker base images | ||
sh """ | ||
JENKINS_NODE_COOKIE=DONT_KILL_ME /bin/sh -c '(curl -Ls https://raw.githubusercontent.com/$IMAGE_NAME/\$BRANCH_NAME/docker/Dockerfile-prefetch | docker build -) &' | ||
docker builder create --name rating-tracker --driver docker-container --driver-opt network=host --bootstrap || : | ||
JENKINS_NODE_COOKIE=DONT_KILL_ME /bin/sh -c '(curl -Ls https://raw.githubusercontent.com/$IMAGE_NAME/\$BRANCH_NAME/docker/Dockerfile-prefetch-buildx | docker buildx build --builder rating-tracker --network=host --cache-from=registry.internal.mruder.dev/cache:rating-tracker-wasm -) &' | ||
""" | ||
} | ||
} | ||
) | ||
|
||
parallel( | ||
testenv: { | ||
stage('Start test environment') { | ||
// Inject IP and ports into test environment | ||
sh """ | ||
sed -i \"s/postgres-test:5432/127.0.0.1:$PGPORT/ ; s/redis-test:6379/127.0.0.1:$REDISPORT/ ; s/30001/$TESTPORT/\" packages/backend/test/env.ts | ||
PGPORT=$PGPORT REDISPORT=$REDISPORT docker compose -p rating-tracker-test-job$JOB_ID -f packages/backend/test/docker-compose.yml up --force-recreate -V -d | ||
""" | ||
} | ||
}, | ||
wasm: { | ||
stage ('Compile WebAssembly utils') { | ||
// Build the WebAssembly image while using registry cache | ||
sh("docker buildx build --builder rating-tracker $DOCKER_CI_FLAGS --target=wasm --cache-to=registry.internal.mruder.dev/cache:rating-tracker-wasm .") | ||
} | ||
}, | ||
dep: { | ||
stage ('Install dependencies') { | ||
// Change config files for use in CI, copy cache to workspace and install dependencies | ||
sh """ | ||
echo \"enableInlineBuilds: true\" >> .yarnrc.yml | ||
echo \"globalFolder: /root/.cache/yarn\" >> .yarnrc.yml | ||
mkdir -p \$HOME/.cache/yarn \$HOME/.cache/node \$HOME/.cache/prisma ./cache | ||
cp -arln \$HOME/.cache/yarn \$HOME/.cache/node \$HOME/.cache/prisma ./cache || : | ||
docker build $DOCKER_CI_FLAGS --target=yarn . | ||
""" | ||
} | ||
} | ||
) | ||
parallel( | ||
testenv: { | ||
stage('Start test environment') { | ||
// Inject IP and ports into test environment | ||
sh """ | ||
sed -i \"s/postgres-test:5432/127.0.0.1:$PGPORT/ ; s/redis-test:6379/127.0.0.1:$REDISPORT/ ; s/30001/$TESTPORT/\" packages/backend/test/env.ts | ||
PGPORT=$PGPORT REDISPORT=$REDISPORT docker compose -p rating-tracker-test-job$JOB_ID -f packages/backend/test/docker-compose.yml up --force-recreate -V -d | ||
""" | ||
} | ||
}, | ||
wasm: { | ||
stage ('Compile WebAssembly utils') { | ||
// Build the WebAssembly image while using registry cache | ||
sh("docker buildx build --builder rating-tracker $DOCKER_CI_FLAGS --target=wasm --cache-to=registry.internal.mruder.dev/cache:rating-tracker-wasm .") | ||
} | ||
}, | ||
dep: { | ||
stage ('Install dependencies') { | ||
// Change config files for use in CI, copy cache to workspace and install dependencies | ||
sh """ | ||
echo \"globalFolder: /root/.cache/yarn\" >> .yarnrc.yml | ||
mkdir -p \$HOME/.cache/yarn \$HOME/.cache/node \$HOME/.cache/prisma ./cache | ||
cp -arln \$HOME/.cache/yarn \$HOME/.cache/node \$HOME/.cache/prisma ./cache || : | ||
docker build $DOCKER_CI_FLAGS --target=yarn . | ||
""" | ||
} | ||
} | ||
) | ||
|
||
stage ('Run tests and build bundles') { | ||
docker.build("$IMAGE_NAME:job$JOB_ID-ci", "$DOCKER_CI_FLAGS --force-rm .") | ||
stage ('Run tests and build bundles') { | ||
docker.build("$IMAGE_NAME:job$JOB_ID-ci", "$DOCKER_CI_FLAGS --force-rm .") | ||
|
||
// Copy build artifacts and cache files to workspace | ||
sh """ | ||
id=\$(docker create $IMAGE_NAME:job$JOB_ID-ci) | ||
docker cp \$id:/app/. ./app | ||
docker cp \$id:/cache/. ./cache | ||
docker rm -v \$id | ||
""" | ||
} | ||
// Copy build artifacts and cache files to workspace | ||
sh """ | ||
id=\$(docker create $IMAGE_NAME:job$JOB_ID-ci) | ||
docker cp \$id:/app/. ./app | ||
docker cp \$id:/cache/. ./cache | ||
docker rm -v \$id | ||
""" | ||
} | ||
|
||
parallel( | ||
codacy: { | ||
stage ('Publish coverage results to Codacy') { | ||
withCredentials([string(credentialsId: 'codacy-project-token-rating-tracker', variable: 'CODACY_PROJECT_TOKEN')]) { | ||
// Publish coverage results by running a container from the test image | ||
sh('docker run --rm -e CODACY_PROJECT_TOKEN=$CODACY_PROJECT_TOKEN ' + "$IMAGE_NAME:job$JOB_ID-ci report --commit-uuid \$(git log -n 1 --pretty=format:'%H'); docker rmi $IMAGE_NAME:job$JOB_ID-ci") | ||
} | ||
} | ||
}, | ||
dockerhub: { | ||
stage ('Assemble and publish Docker Image') { | ||
// Identify image tags | ||
def tags = "" | ||
if (env.TAG_NAME) { | ||
// A version tag is present | ||
def VERSION = sh (script: "echo -n \$TAG_NAME | sed 's/^v//'", returnStdout: true) | ||
def MAJOR = sh (script: "#!/bin/bash\nif [[ \$TAG_NAME =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+\$ ]]; then echo -n \$TAG_NAME | sed -E 's/^v([0-9]+)\\.([0-9]+)\\.([0-9]+)\$/\\1/'; fi", returnStdout: true) | ||
def MINOR = sh (script: "#!/bin/bash\nif [[ \$TAG_NAME =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+\$ ]]; then echo -n \$TAG_NAME | sed -E 's/^v([0-9]+)\\.([0-9]+)\\.([0-9]+)\$/\\1.\\2/'; fi", returnStdout: true) | ||
parallel( | ||
codacy: { | ||
stage ('Publish coverage results to Codacy') { | ||
withCredentials([string(credentialsId: 'codacy-project-token-rating-tracker', variable: 'CODACY_PROJECT_TOKEN')]) { | ||
// Publish coverage results by running a container from the test image | ||
sh('docker run --rm -e CODACY_PROJECT_TOKEN=$CODACY_PROJECT_TOKEN ' + "$IMAGE_NAME:job$JOB_ID-ci report --commit-uuid \$(git log -n 1 --pretty=format:'%H'); docker rmi $IMAGE_NAME:job$JOB_ID-ci") | ||
} | ||
} | ||
}, | ||
dockerhub: { | ||
stage ('Assemble and publish Docker Image') { | ||
// Identify image tags | ||
def tags = "" | ||
if (env.TAG_NAME) { | ||
// A version tag is present | ||
def VERSION = sh (script: "echo -n \$TAG_NAME | sed 's/^v//'", returnStdout: true) | ||
def MAJOR = sh (script: "#!/bin/bash\nif [[ \$TAG_NAME =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+\$ ]]; then echo -n \$TAG_NAME | sed -E 's/^v([0-9]+)\\.([0-9]+)\\.([0-9]+)\$/\\1/'; fi", returnStdout: true) | ||
def MINOR = sh (script: "#!/bin/bash\nif [[ \$TAG_NAME =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+\$ ]]; then echo -n \$TAG_NAME | sed -E 's/^v([0-9]+)\\.([0-9]+)\\.([0-9]+)\$/\\1.\\2/'; fi", returnStdout: true) | ||
|
||
// Use the tag explicitly | ||
tags += " -t $IMAGE_NAME:$VERSION" | ||
// Use the tag explicitly | ||
tags += " -t $IMAGE_NAME:$VERSION" | ||
|
||
// Check for semver syntax | ||
if (MAJOR) { | ||
// Use the major and minor version as additional tags | ||
tags += " -t $IMAGE_NAME:$MINOR -t $IMAGE_NAME:$MAJOR -t $IMAGE_NAME:latest" | ||
} | ||
} else if (env.BRANCH_NAME == 'main') { | ||
// Images with tag `edge` are built from the main branch | ||
tags += " -t $IMAGE_NAME:edge" | ||
// Check for semver syntax | ||
if (MAJOR) { | ||
// Use the major and minor version as additional tags | ||
tags += " -t $IMAGE_NAME:$MINOR -t $IMAGE_NAME:$MAJOR -t $IMAGE_NAME:latest" | ||
} | ||
} else if (env.BRANCH_NAME == 'main') { | ||
// Images with tag `edge` are built from the main branch | ||
tags += " -t $IMAGE_NAME:edge" | ||
|
||
// Prepare update of README.md | ||
sh("mkdir -p \$HOME/.cache/README && cat README.md | sed 's|^<!-- <div id|<div id|g;s|</div> -->\$|</div>|g;s|\"/packages/frontend/public/assets|\"https://raw.githubusercontent.com/$IMAGE_NAME/main/packages/frontend/public/assets|g' > \$HOME/.cache/README/job$JOB_ID") | ||
// sh("docker run --rm -t -v /tmp:/tmp -e DOCKER_USER -e DOCKER_PASS chko/docker-pushrm --file /tmp/jenkins-cache/README/job$JOB_ID $IMAGE_NAME") | ||
} else if (!(env.BRANCH_NAME).startsWith('renovate')) { | ||
// Images with tag `snapshot` are built from other branches, except when updating dependencies only | ||
tags += " -t $IMAGE_NAME:SNAPSHOT" | ||
} | ||
// Prepare update of README.md | ||
sh("mkdir -p \$HOME/.cache/README && cat README.md | sed 's|^<!-- <div id|<div id|g;s|</div> -->\$|</div>|g;s|\"/packages/frontend/public/assets|\"https://raw.githubusercontent.com/$IMAGE_NAME/main/packages/frontend/public/assets|g' > \$HOME/.cache/README/job$JOB_ID") | ||
// sh("docker run --rm -t -v /tmp:/tmp -e DOCKER_USER -e DOCKER_PASS chko/docker-pushrm --file /tmp/jenkins-cache/README/job$JOB_ID $IMAGE_NAME") | ||
} else if (!(env.BRANCH_NAME).startsWith('renovate')) { | ||
// Images with tag `snapshot` are built from other branches, except when updating dependencies only | ||
tags += " -t $IMAGE_NAME:SNAPSHOT" | ||
} | ||
|
||
// If tags are present, build and push the image for both amd64 and arm64 architectures | ||
if (tags.length() > 0) { | ||
sh("docker buildx build --builder rating-tracker -f docker/Dockerfile --force-rm --push --platform=linux/amd64,linux/arm64 --build-arg BUILD_DATE=\$(date -u +'%Y-%m-%dT%H:%M:%SZ') $tags .") | ||
} | ||
} | ||
} | ||
) | ||
} finally { | ||
stage ('Cleanup') { | ||
// Upload cache to external storage and remove build artifacts | ||
sh """#!/bin/bash | ||
cp -arln ./cache/yarn ./cache/node ./cache/prisma \$HOME/.cache | ||
putcache | ||
PGPORT=$PGPORT REDISPORT=$REDISPORT docker compose -p rating-tracker-test-job$JOB_ID -f packages/backend/test/docker-compose.yml down -t 0 | ||
docker rmi $IMAGE_NAME:job$JOB_ID-wasm $IMAGE_NAME:job$JOB_ID-ci || : | ||
rm -rf app cache | ||
""" | ||
} | ||
// If tags are present, build and push the image for both amd64 and arm64 architectures | ||
if (tags.length() > 0) { | ||
sh("docker buildx build --builder rating-tracker -f docker/Dockerfile --force-rm --push --platform=linux/amd64,linux/arm64 --build-arg BUILD_DATE=\$(date -u +'%Y-%m-%dT%H:%M:%SZ') $tags .") | ||
} | ||
} | ||
} | ||
) | ||
} finally { | ||
stage ('Cleanup') { | ||
// Upload cache to external storage and remove build artifacts | ||
sh """#!/bin/bash | ||
cp -arln ./cache/yarn ./cache/node ./cache/prisma \$HOME/.cache | ||
putcache | ||
PGPORT=$PGPORT REDISPORT=$REDISPORT docker compose -p rating-tracker-test-job$JOB_ID -f packages/backend/test/docker-compose.yml down -t 0 | ||
docker rmi $IMAGE_NAME:job$JOB_ID-wasm $IMAGE_NAME:job$JOB_ID-ci || : | ||
rm -rf app cache | ||
""" | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters