Created
August 16, 2021 22:40
-
-
Save renoirb/71afc1aa2e2e5e243e00a0b96cf177e1 to your computer and use it in GitHub Desktop.
Jenkinsfile when using RushJS.io and releasing only on CI
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
#!/usr/bin/groovy | |
/* groovylint-disable LineLength, NestedBlockDepth, DuplicateStringLiteral */ | |
/* groovylint-disable-next-line CompileStatic, NoDef, UnusedVariable, VariableName, VariableTypeRequired */ | |
@Library('jenkins-pipeline-library@release/3') _ | |
import com.corp.PipelineUtils | |
// https://gist.github.com/wbern/f7f45f1b940a13f9b9389e23029608e7#file-jenkinsfile-rush-publish-step-L5 | |
PipelineUtils pipelineUtils = new PipelineUtils() | |
String githubCredentials = 'my-vault-app-credential-name' | |
String githubSshAgentCredentialId = '00000000-0000-0000-0000-000000000000' | |
String githubUserEmail = 'FIXME+john.doe@mycorp.com' | |
String githubUserName = 'MyApp Team' | |
String repoHeadBranchName = 'master' | |
String nexusRegistry = 'https://nexus.example.org/repository/npm-all/' | |
String slackChannel = '#myappteam-ci' | |
def branchName = pipelineUtils.getBranchName() | |
def branchNameSlug = branchName.toLowerCase().replaceAll('[^a-z0-9]', '-') | |
def repositoryUrl = pipelineUtils.getRepositoryUrl() | |
// git@github.com:mycorp/repo-example-sandbox.git => 'https://github.com/mycorp/repo-example-sandbox | |
String repositoryUrlWeb = repositoryUrl.replaceAll('git@github.com:mycorp', 'https://github.com/mycorp').replaceAll('.git\$', '') | |
String projectSlug = repositoryUrl.tokenize('/').last().replaceFirst(".git\$", '') | |
Map pipelineVars = [ | |
/** | |
* This might happen when we're on a branch, where all test pass | |
* AND we are ready for merging on master. | |
*/ | |
readyToPublish: false, | |
] | |
pipeline { | |
environment { | |
CI_SERVER = 'yes-please so that @renoirb/conventions-use-bili to be in CI mode' | |
GITHUB_REPO_URL = "${repositoryUrl}" | |
GITHUB_REPO_URL_WEB = "${repositoryUrlWeb}" | |
GITHUB_REPO_BRANCH = "${branchName}" | |
GITHUB_REPO_BRANCH_SLUG = "${branchNameSlug}" | |
SLACK_CHANNEL = "${slackChannel}" | |
GITHUB_ACTION = 'Jenkins' | |
} | |
options { | |
timestamps() | |
skipStagesAfterUnstable() | |
ansiColor('xterm') | |
timeout(time: 120, unit: 'MINUTES') | |
buildDiscarder(logRotator(daysToKeepStr: '10', numToKeepStr: '30')) | |
skipDefaultCheckout() | |
} | |
agent { | |
docker { | |
label 'ec2-fleet' | |
image 'jcr.io/builder/node:14-3.1.2' | |
args '-e HOME=/tmp --group-add docker -v /var/run/docker.sock:/var/run/docker.sock:rw' | |
} | |
} | |
// https://rushjs.io/pages/maintainer/enabling_ci_builds/ | |
stages { | |
stage('Checkout') { | |
steps { | |
script { | |
println "=== On stage 0 Checkout (${branchName}) ===\n" | |
scmVars = checkout([ | |
$class: 'GitSCM', | |
userRemoteConfigs: [ | |
[ | |
name: 'origin', | |
refspec: "+refs/heads/${branchName}:refs/origin/${branchName} +refs/heads/${repoHeadBranchName}:refs/origin/${repoHeadBranchName}", | |
credentialsId: githubCredentials, | |
url: env.GITHUB_REPO_URL | |
], | |
], | |
branches: [ | |
[name: "refs/heads/${branchName}"], | |
], | |
browser: [ | |
$class: 'GithubWeb', | |
repoUrl: repositoryUrlWeb, | |
], | |
doGenerateSubmoduleConfigurations: false, | |
extensions: [ | |
[$class: 'CleanBeforeCheckout'] | |
], | |
submoduleCfg: [], | |
]) | |
for (arg in scmVars) { | |
env["${arg.key}"] = arg.value.toString() | |
} | |
// Some user custom scripts rely on GIT_COMMIT_MESSAGE. Do not remove it event if unused in this script | |
String commitMessage = sh(returnStdout: true, script: 'git log -1 --pretty=%B | cat').trim() | |
env.GIT_COMMIT_MESSAGE = commitMessage | |
githubUserName = sh(returnStdout: true, script: "git log --name-status HEAD^..HEAD --format='%an' | head -n 1").trim() | |
env.GIT_COMMITTER_NAME = githubUserName | |
sh "git config --global user.name '${githubUserName}'" | |
githubUserEmail = sh(returnStdout: true, script: "git log --name-status HEAD^..HEAD --format='%ae' | head -n 1").trim() | |
env.GIT_COMMITTER_EMAIL = githubUserEmail | |
sh "git config --global user.email '${githubUserEmail}'" | |
println '\n---- BEGIN DEBUGGING ----\n' | |
sh 'node common/scripts/install-run-rush.js meta' | |
sh 'printenv | sort' | |
sh 'git config --global --list' | |
sh 'git config --local --list' | |
sh 'git remote -v' | |
sh 'git branch' | |
sh 'git branch -a' | |
sh 'test -f .git/config && cat .git/config' | |
println '---- END DEBUGGING ----\n' | |
sh 'node common/scripts/install-run-rush.js install' | |
// sh 'node common/scripts/install-run-rush.js install --debug-package-manager' | |
} | |
} | |
post { | |
failure { | |
script { | |
slack.danger channel: slackChannel, stage: 'Setup', project: projectSlug | |
} | |
} | |
} | |
} | |
stage('Build') { | |
when { | |
not { | |
anyOf { | |
/** | |
* Rush when doing the "rush publish" command creates and pushes a timestamped branch starting with "publish-" (e.g. publish-1628890734019) | |
* we do not want to run CI on those temporary branches | |
*/ | |
expression { return branchName =~ '^publish-' } | |
/** | |
* Rush when doing the "rush version --bump ..." command creates and pushes a timestamped branch starting with "version/bump-" (e.g. version/bump-1628890734019) | |
* we do not want to run CI on those temporary branches. | |
* Also, i'm unsure if Jenkinsfile =~ RegEx will require escaping slash. So we'll use the branchNameSlug. | |
*/ | |
expression { return branchNameSlug =~ '^version-bump-' } | |
} | |
} | |
} | |
steps { | |
script { | |
println '=== On stage 2 Build ===\n' | |
sh 'node common/scripts/install-run-rush.js rebuild --verbose' | |
} | |
} | |
post { | |
failure { | |
script { | |
slack.danger channel: slackChannel, stage: 'Build', project: projectSlug | |
} | |
} | |
} | |
} | |
stage('Verify') { | |
failFast true | |
parallel { | |
stage('Lint') { | |
steps { | |
script { | |
println 'Verify 1/2 Lint' | |
withCredentials([usernamePassword(credentialsId: githubCredentials, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')]) { | |
sh "node common/scripts/install-run-rush.js prettier --branch origin/${repoHeadBranchName} --check" | |
} | |
} | |
} | |
} | |
stage('Test') { | |
steps { | |
script { | |
println 'Verify 2/2 Test' | |
sh 'node common/scripts/install-run-rush.js test' | |
} | |
} | |
} | |
stage('Changelog') { | |
when { | |
not { | |
anyOf { | |
branch repoHeadBranchName | |
expression { return branchName =~ '^publish-' } | |
expression { return branchNameSlug =~ '^version-bump-' } | |
} | |
} | |
} | |
steps { | |
script { | |
println 'Verify 3/2 Changelog' | |
sh 'node common/scripts/install-run-rush.js list --version --path' | |
// env['DEBUG'] = '*' | |
// https://nodejs.org/dist/latest-v14.x/docs/api/all.html#cli_node_debug_module | |
// https://www.alxolr.com/articles/debugging-tools-and-practices-in-node-js#debug-nodejs-internals-with-node_debug | |
// env['NODE_DEBUG'] = 'net,fs,http' | |
// Bookmarks: | |
// - https://gist.github.com/wbern/f7f45f1b940a13f9b9389e23029608e7#file-jenkinsfile-rush-publish-step-L5 | |
// - https://github.com/microsoft/rushstack/issues/1558#issuecomment-545707200 | |
sshagent([githubSshAgentCredentialId]) { | |
println '---- BEGIN DEBUGGING ----\n' | |
// sh 'node common/scripts/install-run-rush.js meta' | |
// sh 'printenv | sort' | |
// sh 'test -f .git/config && cat .git/config' | |
sh 'git status' | |
sh 'git log --pretty=format:"%C(blue)%ad%Creset %C(yellow)%h%C(green)%d%Creset %C(blue)%s %C(magenta) [%an]%Creset"' | |
println '---- END DEBUGGING ----\n' | |
// sh "node common/scripts/install-run-rush.js change --target-branch origin/${repoHeadBranchName} --verify --no-fetch" | |
// outcome = sh(returnStatus: true, script: 'node common/scripts/install-run-rush.js change --verify --no-fetch') | |
outcome = sh(returnStatus: true, script: 'node common/scripts/install-run-rush.js change --verify') | |
pipelineVars.readyToPublish = outcome == 0 | |
println "=== readyToPublish?: ${pipelineVars.readyToPublish} ====" | |
if (outcome > 0) { | |
error "The branch ${branchName} is not ready for releasing, it misses changelog" | |
} | |
} | |
} | |
} | |
} | |
} | |
post { | |
failure { | |
script { | |
slack.danger channel: slackChannel, stage: 'Verify', project: projectSlug | |
} | |
} | |
} | |
} | |
/** | |
* Any change MUST be done BEFORE being merged to the HEAD branch (e.g. master) | |
* meaning that publish should be part of it too but not add changes | |
*/ | |
stage('Release') { | |
when { | |
allOf { | |
expression { return pipelineVars.readyToPublish } | |
} | |
} | |
stages { | |
stage('Publish') { | |
when { | |
/** | |
* In contrast to rush automatically generated branch "publish-", we will have to create a | |
* "release-" branch that should be forked from master to do the publishing to Nexus | |
*/ | |
expression { return branchName =~ '^release-' } | |
} | |
steps { | |
script { | |
println '=== On stage 5 Release Publish ===\n' | |
// We get ENOBUFS | |
// https://developer.ibm.com/articles/nodejs-memory-management-in-container-environments/ | |
// sh "test -f /sys/fs/cgroup/memory/memory.limit_in_bytes && cat /sys/fs/cgroup/memory/memory.limit_in_bytes" | |
withCredentials([usernamePassword(credentialsId: githubCredentials, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')]) { | |
sshagent([githubSshAgentCredentialId]) { | |
println '---------- BEGIN DEBUGGING ----------\n' | |
println '--- THE FOLLOWING SHOULD BE EMPTY ---\n' | |
println '-------------------------------------\n' | |
sh 'git ls-files --others --exclude-standard' | |
println '---------- END DEBUGGING ----------\n' | |
// What we want is to do is to make rush publish to NPM and write the changelog, but not push to master, let GitHub do the squashing | |
// Lets make the tagging from when we are on master instead. | |
// Take changes, publish to Nexus | |
sh "node common/scripts/install-run-rush.js publish --apply --publish --regenerate-changelogs --set-access-level public --registry ${nexusRegistry}" | |
// sh "node common/scripts/install-run-rush.js publish --publish --apply -b ${repoHeadBranchName} --add-commit-details --commit ${env.GIT_COMMIT}" | |
// Make changes to Git, push | |
sh "node common/scripts/install-run-rush.js publish --apply --add-commit-details --ignore-git-hooks --target-branch ${branchName}" | |
} | |
} | |
} | |
} | |
} | |
stage('Version Bump') { | |
when { | |
expression { return branchNameSlug =~ '^version-bump-' } | |
} | |
} | |
} | |
post { | |
failure { | |
script { | |
slack.danger channel: slackChannel, stage: 'Release', project: projectSlug | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment