Skip to content

Commit e2484a6

Browse files
authored
Update index.js
1 parent c8f9e22 commit e2484a6

File tree

1 file changed

+169
-97
lines changed

1 file changed

+169
-97
lines changed

index.js

Lines changed: 169 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const YAML = require('yaml')
44
const path = require('path')
55
const fs = require('fs')
6+
const fetch = require('node-fetch')
67
process.env.DISABLE_BOX_BANNER = true
78
const simplify = require('simplify-sdk')
89
const { options } = require('yargs');
@@ -50,6 +51,63 @@ var argv = yargs.usage('simplify-pipeline create|list [stage] [options]')
5051

5152
showBoxBanner()
5253

54+
function parseIncludes(yamlObject) {
55+
return new Promise((resolve, reject) => {
56+
let stages = [...yamlObject.stages]
57+
if (yamlObject.include) {
58+
let remoteUrls = []
59+
yamlObject.include.map(item => {
60+
if (item.local) {
61+
if (fs.existsSync(path.resolve(item.local))) {
62+
const ymlObj = fs.readFileSync(path.resolve(item.local)).toString()
63+
const includedObj = YAML.parse(ymlObj)
64+
yamlObject = { ...yamlObject, ...includedObj }
65+
if (includedObj.stages) {
66+
stages = [...stages, ...includedObj.stages]
67+
}
68+
}
69+
} else if (item.template) {
70+
remoteUrls.push(`https://gitlab.com/gitlab-org/gitlab/-/raw/master/lib/gitlab/ci/templates/${item.template}`)
71+
}
72+
})
73+
function arrayBuffer2String(buf, callback) {
74+
var bb = new BlobBuilder();
75+
bb.append(buf);
76+
var f = new FileReader();
77+
f.onload = function(e) {
78+
callback(e.target.result)
79+
}
80+
f.readAsText(bb.getBlob());
81+
}
82+
/** fetching remote templates from GitLab... */
83+
if (remoteUrls.length > 0) {
84+
Promise.all(remoteUrls.map((url) => fetch(url))).then((responses) => {
85+
return Promise.all(responses.map((res) => res.text())).then((buffers) => {
86+
return buffers.map((buffer) => {
87+
return YAML.parse(buffer)
88+
});
89+
});
90+
}).then((finalObjects) => {
91+
yamlObject.stages = [ ...new Set(stages)]
92+
finalObjects.map(m => {
93+
if (m.stages) {
94+
stages = [...stages, ...m.stages]
95+
}
96+
yamlObject = { ...yamlObject, ...m }
97+
})
98+
yamlObject.stages = [ ...new Set(stages)]
99+
resolve(yamlObject)
100+
});
101+
} else {
102+
yamlObject.stages = [ ...new Set(stages)]
103+
resolve(yamlObject)
104+
}
105+
} else {
106+
resolve(yamlObject)
107+
}
108+
})
109+
}
110+
53111
var cmdOPS = (argv._[0] || 'create').toUpperCase()
54112
var optCMD = (argv._.length > 1 ? argv._[1] : undefined)
55113
var index = -1
@@ -60,109 +118,123 @@ if (!fs.existsSync(path.resolve(`${filename}`))) {
60118
process.exit()
61119
}
62120
const file = fs.readFileSync(path.resolve(`${filename}`), 'utf8')
63-
const yamlObject = YAML.parse(file)
64-
if (cmdOPS == 'CREATE') {
65-
if (!optCMD) {
66-
index = readlineSync.keyInSelect(yamlObject.stages, `Select a stage to execute ?`, {
67-
cancel: `${CBRIGHT}None${CRESET} - (Escape)`
68-
})
69-
} else {
70-
index = yamlObject.stages.indexOf(optCMD)
71-
}
72-
let dockerfileContent = ['FROM scratch']
73-
if (index >= 0) {
74-
const executedStage = yamlObject.stages[index]
75-
let dockerComposeContent = { version: '3.8', services: {}, volumes: {} }
76-
dockerComposeContent.volumes[`shared`] = {
77-
"driver": "local",
78-
"driver_opts": {
79-
"type": "none",
80-
"device": "$PWD",
81-
"o": "bind"
121+
let yamlObject = YAML.parse(file)
122+
if (yamlObject.include) {
123+
parseIncludes(yamlObject).then(result => {
124+
yamlObject = result
125+
if (cmdOPS == 'CREATE') {
126+
if (!optCMD) {
127+
index = readlineSync.keyInSelect(yamlObject.stages, `Select a stage to execute ?`, {
128+
cancel: `${CBRIGHT}None${CRESET} - (Escape)`
129+
})
130+
} else {
131+
index = yamlObject.stages.indexOf(optCMD)
82132
}
83-
}
84-
let stageExecutionChains = []
85-
let dockerCacheVolumes = []
86-
let dockerBaseContent = [`FROM ${yamlObject.image}`, 'WORKDIR /source', 'VOLUME /source', 'COPY . /source']
87-
let dockerBasePath = `${projectName}/Dockerfile`
88-
const baseImage = `base-${yamlObject.image.split(':')[0]}`
89-
const baseDirName = path.dirname(path.resolve(dockerBasePath))
90-
if (!fs.existsSync(baseDirName)) {
91-
fs.mkdirSync(baseDirName, { recursive: true })
92-
}
93-
if (yamlObject.cache && yamlObject.cache.paths && yamlObject.cache.paths.length) {
94-
dockerCacheVolumes.push()
95-
}
96-
fs.writeFileSync(dockerBasePath, dockerBaseContent.join('\n'))
97-
dockerComposeContent.services[baseImage] = { build: { context: `../`, dockerfile: `${projectName}/Dockerfile`, args: {} } }
98-
99-
const variables = simplify.getContentArgs(yamlObject.variables, { ...process.env })
100-
Object.keys(yamlObject).map((key, idx) => {
101-
if (yamlObject[key].stage === executedStage) {
102-
const stageName = `${idx}-${executedStage}.${key}`
103-
dockerComposeContent.services[key] = { build: { context: `../`, dockerfile: `${projectName}/${stageName}.Dockerfile`, args: {} }, volumes: [`shared:/source`] }
104-
stageExecutionChains.push(`${stageName}`)
105-
dockerfileContent = [`FROM ${projectName.replace(/\./g, '')}_${baseImage}`, 'WORKDIR /source']
106-
let dockerCommands = []
107-
let dockerBeforeCommands = []
133+
let dockerfileContent = ['FROM scratch']
134+
if (index >= 0) {
135+
const executedStage = yamlObject.stages[index]
136+
let dockerComposeContent = { version: '3.8', services: {}, volumes: {} }
137+
dockerComposeContent.volumes[`shared`] = {
138+
"driver": "local",
139+
"driver_opts": {
140+
"type": "none",
141+
"device": "$PWD",
142+
"o": "bind"
143+
}
144+
}
145+
let stageExecutionChains = []
146+
let dockerCacheVolumes = []
147+
let dockerBaseContent = [`FROM ${yamlObject.image}`, 'WORKDIR /source', 'VOLUME /source', 'COPY . /source']
148+
let dockerBasePath = `${projectName}/Dockerfile`
149+
const baseImage = `base-${yamlObject.image.split(':')[0]}`
150+
const baseDirName = path.dirname(path.resolve(dockerBasePath))
151+
if (!fs.existsSync(baseDirName)) {
152+
fs.mkdirSync(baseDirName, { recursive: true })
153+
}
154+
if (yamlObject.cache && yamlObject.cache.paths && yamlObject.cache.paths.length) {
155+
dockerCacheVolumes.push()
156+
}
157+
fs.writeFileSync(dockerBasePath, dockerBaseContent.join('\n'))
158+
dockerComposeContent.services[baseImage] = { build: { context: `../`, dockerfile: `${projectName}/Dockerfile`, args: {} } }
159+
160+
const variables = simplify.getContentArgs(yamlObject.variables, { ...process.env })
161+
Object.keys(yamlObject).map((key, idx) => {
162+
if (yamlObject[key].stage === executedStage) {
163+
const stageName = `${idx}-${executedStage}.${key}`
164+
dockerComposeContent.services[key] = { build: { context: `../`, dockerfile: `${projectName}/${stageName}.Dockerfile`, args: {} }, volumes: [`shared:/source`] }
165+
stageExecutionChains.push(`${stageName}`)
166+
dockerfileContent = [`FROM ${projectName.replace(/\./g, '')}_${baseImage}`, 'WORKDIR /source']
167+
let dockerCommands = []
168+
let dockerBeforeCommands = []
169+
170+
simplify.getContentArgs(yamlObject[key].before_script, { ...process.env }, { ...variables }).map(script => {
171+
let scriptContent = script
172+
if (script.startsWith('export ')) {
173+
let dockerOpts = 'ENV'
174+
scriptContent = script.replace('export ', '')
175+
const argKeyValue = scriptContent.split('=')
176+
dockerComposeContent.services[key].build.args[`${argKeyValue[0].trim()}`] = `${argKeyValue[1].trim()}`
177+
scriptContent = `${argKeyValue[0].trim()}="${argKeyValue[1].trim()}"`
178+
dockerfileContent.push(`${dockerOpts} ${scriptContent}`)
179+
} else {
180+
dockerBeforeCommands.push(`${scriptContent}`)
181+
}
182+
})
108183

109-
simplify.getContentArgs(yamlObject[key].before_script, { ...process.env }, { ...variables }).map(script => {
110-
let scriptContent = script
111-
if (script.startsWith('export ')) {
112-
let dockerOpts = 'ENV'
113-
scriptContent = script.replace('export ', '')
114-
const argKeyValue = scriptContent.split('=')
115-
dockerComposeContent.services[key].build.args[`${argKeyValue[0].trim()}`] = `${argKeyValue[1].trim()}`
116-
scriptContent = `${argKeyValue[0].trim()}="${argKeyValue[1].trim()}"`
117-
dockerfileContent.push(`${dockerOpts} ${scriptContent}`)
118-
} else {
119-
dockerBeforeCommands.push(`${scriptContent}`)
184+
simplify.getContentArgs(yamlObject[key].script, { ...process.env }, { ...variables }).map(script => {
185+
let scriptContent = script
186+
if (script.startsWith('export ')) {
187+
let dockerOpts = 'ENV'
188+
scriptContent = script.replace('export ', '')
189+
const argKeyValue = scriptContent.split('=')
190+
dockerComposeContent.services[key].build.args[`${argKeyValue[0].trim()}`] = `${argKeyValue[1].trim()}`
191+
scriptContent = `${argKeyValue[0].trim()}="${argKeyValue[1].trim()}"`
192+
dockerfileContent.push(`${dockerOpts} ${scriptContent}`)
193+
} else {
194+
dockerCommands.push(`${scriptContent}`)
195+
}
196+
})
197+
dockerfileContent.push(`RUN ${dockerBeforeCommands.join(' && ')}`)
198+
dockerfileContent.push(`RUN ${dockerCommands.join(' && ')}`)
199+
let dockerfilePath = `${projectName}/${stageName}.Dockerfile`
200+
const pathDirName = path.dirname(path.resolve(dockerfilePath))
201+
if (!fs.existsSync(pathDirName)) {
202+
fs.mkdirSync(pathDirName, { recursive: true })
203+
}
204+
fs.writeFileSync(dockerfilePath, dockerfileContent.join('\n'))
120205
}
121206
})
122-
123-
simplify.getContentArgs(yamlObject[key].script, { ...process.env }, { ...variables }).map(script => {
124-
let scriptContent = script
125-
if (script.startsWith('export ')) {
126-
let dockerOpts = 'ENV'
127-
scriptContent = script.replace('export ', '')
128-
const argKeyValue = scriptContent.split('=')
129-
dockerComposeContent.services[key].build.args[`${argKeyValue[0].trim()}`] = `${argKeyValue[1].trim()}`
130-
scriptContent = `${argKeyValue[0].trim()}="${argKeyValue[1].trim()}"`
131-
dockerfileContent.push(`${dockerOpts} ${scriptContent}`)
132-
} else {
133-
dockerCommands.push(`${scriptContent}`)
207+
let dockerComposePath = `${projectName}/docker-compose.${executedStage}.yml`
208+
fs.writeFileSync(dockerComposePath, YAML.stringify(dockerComposeContent))
209+
console.log(`Created ${projectName} docker-compose for stage '${optCMD}' cached to '${projectName}' volume`)
210+
fs.writeFileSync(`pipeline.bash`, [
211+
'#!/bin/bash',
212+
`cd ${projectName}`,
213+
`docker volume rm ${projectName.replace(/\./g, '')}_shared > /dev/null`,
214+
`docker-compose -f docker-compose.$1.yml --project-name ${projectName} up --force-recreate`
215+
].join('\n'))
216+
}
217+
} else if (cmdOPS == 'LIST') {
218+
if (!optCMD) {
219+
yamlObject.stages.map((cmd, idx) => {
220+
console.log(`\t- ${CPROMPT}${cmd.toLowerCase()}${CRESET}`)
221+
})
222+
} else {
223+
Object.keys(yamlObject).map((key, idx) => {
224+
if (yamlObject[key].stage === optCMD) {
225+
const stageName = `[${optCMD}] ${key}`
226+
console.log(`\t- ${CPROMPT}${stageName.toLowerCase()}${CRESET}`)
134227
}
135228
})
136-
dockerfileContent.push(`RUN ${dockerBeforeCommands.join(' && ')}`)
137-
dockerfileContent.push(`RUN ${dockerCommands.join(' && ')}`)
138-
let dockerfilePath = `${projectName}/${stageName}.Dockerfile`
139-
const pathDirName = path.dirname(path.resolve(dockerfilePath))
140-
if (!fs.existsSync(pathDirName)) {
141-
fs.mkdirSync(pathDirName, { recursive: true })
142-
}
143-
fs.writeFileSync(dockerfilePath, dockerfileContent.join('\n'))
144229
}
145-
})
146-
let dockerComposePath = `${projectName}/docker-compose.${executedStage}.yml`
147-
fs.writeFileSync(dockerComposePath, YAML.stringify(dockerComposeContent))
148-
console.log(`Created ${projectName} docker-compose for stage '${optCMD}' cached to '${projectName}' volume`)
149-
fs.writeFileSync(`pipeline.bash`, [
150-
'#!/bin/bash',
151-
`cd ${projectName}`,
152-
`docker volume rm ${projectName.replace(/\./g,'')}_shared > /dev/null`,
153-
`docker-compose -f docker-compose.$1.yml --project-name ${projectName} up --force-recreate`
154-
].join('\n'))
155-
}
156-
} else if (cmdOPS == 'LIST') {
157-
yamlObject.stages.map((cmd, idx) => {
158-
console.log(`\t- ${CPROMPT}${cmd.toLowerCase()}${CRESET}`)
159-
})
160-
} else {
161-
yargs.showHelp()
162-
console.log(`\n`, ` * ${CBRIGHT}Supported command list${CRESET}:`, '\n')
163-
OPT_COMMANDS.map((cmd, idx) => {
164-
console.log(`\t- ${CPROMPT}${cmd.name.toLowerCase()}${CRESET} : ${cmd.desc}`)
230+
} else {
231+
yargs.showHelp()
232+
console.log(`\n`, ` * ${CBRIGHT}Supported command list${CRESET}:`, '\n')
233+
OPT_COMMANDS.map((cmd, idx) => {
234+
console.log(`\t- ${CPROMPT}${cmd.name.toLowerCase()}${CRESET} : ${cmd.desc}`)
235+
})
236+
console.log(`\n`)
237+
process.exit(0)
238+
}
165239
})
166-
console.log(`\n`)
167-
process.exit(0)
168240
}

0 commit comments

Comments
 (0)