1+ pipeline {
2+ agent any
3+ options { ansiColor('xterm') }
4+
5+ parameters {
6+ string(name: 'PROJECT_REPO', defaultValue: 'https://github.com/instructure/instructure-ui', description: 'The target project repository URL')
7+ string(name: 'TARGET_BRANCH', defaultValue: 'master', description: 'The name of the branch which is the target of the pull requests')
8+ string(name: 'DOC_FOLDER', defaultValue: 'openapi', description: 'The documentation folder path')
9+ string(name: 'URL_SEGMENT', defaultValue: 'instui', description: 'The URL segment for the target project, under which your documentation will be available')
10+ string(name: 'SLACK_CHANNEL', defaultValue: 'instui-bud', description: 'The Slack channel for notifications')
11+ }
12+
13+ stages {
14+ stage('Display Parameters and Environment Variables') {
15+ steps {
16+ script {
17+ echo 'Environment Variables:'
18+ sh 'env | sort'
19+
20+ echo 'Build Parameters:'
21+ params.each { param -> echo "${param.key} = ${param.value}" }
22+ }
23+ }
24+ }
25+ stage ('Detect Build Cause') {
26+ steps {
27+ script {
28+ if (env.TAG_NAME) {
29+ // A new tag was created
30+ def tagPattern = ~/^v[0-9]+\.[0-9]+\.[0-9]+$/
31+ if (env.TAG_NAME ==~ tagPattern) {
32+ env.TARGET_ENV = 'prod'
33+ echo "Build was triggered by a Tag: ${env.TAG_NAME}. ==> Deploying to ${env.TARGET_ENV}"
34+ } else {
35+ echo "Build was triggered by a Tag: ${env.TAG_NAME}. But the tag does not match the pattern ${tagPattern}. No action required."
36+ env.TARGET_ENV = ''
37+ }
38+ }
39+ else if (env.BRANCH_NAME == params.TARGET_BRANCH) {
40+ // Push to master branch - deploy to both test and beta
41+ env.TARGET_ENVS = 'test,beta'
42+ echo "Build was triggered by a Push to '${params.TARGET_BRANCH}' branch. ==> Deploying to test and beta"
43+ }
44+ else {
45+ echo "Build was triggered by a not monitored Github event or unsupported branch. No action required."
46+ currentBuild.description = 'Skip unsupported Github event or branch'
47+ currentBuild.result = 'SUCCESS'
48+ return
49+ }
50+ }
51+ }
52+ }
53+ stage ('Build Documentation') {
54+ when {
55+ expression {
56+ return (env.TARGET_ENV && env.TARGET_ENV != '') || (env.TARGET_ENVS && env.TARGET_ENVS != '')
57+ }
58+ }
59+ steps {
60+ script {
61+ // Determine which environments to deploy to
62+ def environments = []
63+ if (env.TARGET_ENV) {
64+ environments.add(env.TARGET_ENV)
65+ } else if (env.TARGET_ENVS) {
66+ environments = env.TARGET_ENVS.split(',')
67+ }
68+
69+ // Check if the change contains documentation files (skip for tags - we deploy all tagged releases)
70+ def shouldCheckDocFiles = environments.any { it == 'test' || it == 'beta' }
71+ if (shouldCheckDocFiles) {
72+ def containsDocFiles = isChangeRelevant(params.PROJECT_REPO, env.GIT_COMMIT, params.DOC_FOLDER)
73+ if (!containsDocFiles) {
74+ echo 'No documentation files found in the change'
75+ currentBuild.description = 'No doc files in the change'
76+ currentBuild.result = 'SUCCESS'
77+ return
78+ }
79+ }
80+
81+ // Deploy to each environment
82+ for (targetEnv in environments) {
83+ echo "Building documentation for ${params.PROJECT_REPO} with refspec: ${env.GIT_COMMIT} ==> Deploying to ${targetEnv}"
84+ build(job: 'Restructure/Documentation Portal/Workers/DocSync',
85+ parameters: [
86+ string(name: 'TARGET_ENV', value: "test"),
87+ // string(name: 'TARGET_ENV', value: targetEnv),
88+ string(name: 'SOURCE_KIND', value: "git"),
89+ string(name: 'SOURCE_PROJECT', value: "${params.PROJECT_REPO}"),
90+ string(name: 'SOURCE_PROJECT_REFSPEC', value: env.GIT_COMMIT),
91+ string(name: 'SOURCE_PROJECT_DOC_FOLDER', value: "${params.DOC_FOLDER}"),
92+ string(name: 'URL_SEGMENT', value: "${params.URL_SEGMENT}"),
93+ string(name: 'SLACK_CHANNEL', value: "${params.SLACK_CHANNEL}")
94+ ],
95+ wait: true,
96+ propagate: true
97+ )
98+ }
99+ }
100+ }
101+ }
102+ }
103+ }
104+
105+ /**
106+ * Check if the change contains files in a specific folder
107+ * @param docFolder The name of the folder to check
108+ * @return true if the change contains files in the specified folder, false otherwise
109+ */
110+ def isChangeRelevant(String projectUrl, String refSpec, String docFolder) {
111+ if (docFolder == null || docFolder.isEmpty()) {
112+ echo 'No documentation folder specified. Skipping the check.'
113+ return false
114+ } else if (docFolder == '.') {
115+ echo 'Documentation folder is set to the root of the repository. Any change is considered relevant.'
116+ return true
117+ }
118+
119+ def result = false
120+ def tempDir = "${UUID.randomUUID().toString()}"
121+ sh "mkdir -p ${tempDir}"
122+
123+ echo "Cloning ${projectUrl} with refspec: ${refSpec}. Checking for changes in ${docFolder} folder"
124+ withCredentials([gitUsernamePassword(credentialsId: 'github-api-credentials', gitToolName: 'git-tool')]) {
125+ sh "git clone ${projectUrl} ${tempDir} && cd ${tempDir} && git checkout ${refSpec}"
126+ }
127+
128+ dir(tempDir) {
129+ def changedFiles = sh(script: "git diff --name-only HEAD~1 HEAD", returnStdout: true).trim()
130+ printf("Changed files:\n%s", changedFiles)
131+ changedFiles = changedFiles.split("\n")
132+ result = changedFiles.any { it.startsWith "${params.DOC_FOLDER}/" }
133+ }
134+
135+ sh "rm -rf ${tempDir}"
136+ return result
137+ }
0 commit comments