contensis-cli 1.0.0-beta.94 ā 1.0.0-beta.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/localisation/en-GB.js +23 -2
- package/dist/localisation/en-GB.js.map +2 -2
- package/dist/mappers/DevInit-to-CIWorkflow.js +140 -11
- package/dist/mappers/DevInit-to-CIWorkflow.js.map +3 -3
- package/dist/models/DevService.d.js.map +1 -1
- package/dist/services/ContensisDevService.js +25 -15
- package/dist/services/ContensisDevService.js.map +2 -2
- package/dist/util/diff.js +8 -2
- package/dist/util/diff.js.map +2 -2
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/localisation/en-GB.ts +22 -2
- package/src/mappers/DevInit-to-CIWorkflow.ts +202 -19
- package/src/models/DevService.d.ts +22 -1
- package/src/models/JsModules.d.ts +1 -0
- package/src/services/ContensisDevService.ts +25 -16
- package/src/util/diff.ts +5 -3
- package/src/version.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/services/ContensisDevService.ts"],
|
|
4
|
-
"sourcesContent": ["import to from 'await-to-js';\nimport { execFile, spawn } from 'child_process';\nimport inquirer from 'inquirer';\nimport path from 'path';\n\nimport { Role } from 'contensis-management-api/lib/models';\nimport { MigrateRequest } from 'migratortron';\n\nimport ContensisRole from './ContensisRoleService';\nimport { OutputOptionsConstructorArg } from '~/models/CliService';\nimport { EnvContentsToAdd } from '~/models/DevService';\nimport { mapSiteConfigYaml } from '~/mappers/DevRequests-to-RequestHanderSiteConfigYaml';\nimport { mapCIWorkflowContent } from '~/mappers/DevInit-to-CIWorkflow';\nimport {\n deployKeyRole,\n devKeyRole,\n} from '~/mappers/DevInit-to-RolePermissions';\nimport { appRootDir, readFile, writeFile } from '~/providers/file-provider';\nimport { diffFileContent } from '~/util/diff';\nimport { mergeDotEnvFileContents } from '~/util/dotenv';\nimport { findByIdOrName } from '~/util/find';\nimport { GitHelper } from '~/util/git';\nimport { jsonFormatter } from '~/util/json.formatter';\nimport { normaliseLineEndings } from '~/util/os';\nimport { stringifyYaml } from '~/util/yaml';\n\nclass ContensisDev extends ContensisRole {\n constructor(\n args: string[],\n outputOpts?: OutputOptionsConstructorArg,\n contensisOpts: Partial<MigrateRequest> = {}\n ) {\n super(args, outputOpts, contensisOpts);\n }\n\n DevelopmentInit = async (projectHome: string, opts: any) => {\n const { dryRun = false } = opts || {};\n const { currentEnv, currentProject, log, messages } = this;\n const contensis = await this.ConnectContensis();\n\n if (contensis) {\n // Retrieve keys list for env\n const [keysErr, apiKeys] = await contensis.apiKeys.GetKeys();\n if (keysErr) {\n log.error(messages.keys.noList(currentEnv));\n log.error(jsonFormatter(keysErr));\n return;\n }\n const apiKeyExists = (findKey: string) =>\n apiKeys?.find(\n k => k.name.trim().toLowerCase() === findKey?.trim().toLowerCase()\n );\n\n // Retrieve git info\n const git = new GitHelper(projectHome);\n\n // Retrieve ci workflow info\n const workflowFiles = git.workflows;\n\n // Set variables for performing operations and logging etc.\n let ciFileName = git.ciFileName;\n\n const devKeyName = `${git.name} development`;\n const devKeyDescription = `${git.name} [contensis-cli]`;\n let existingDevKey = apiKeyExists(devKeyName);\n\n const deployKeyName = `${git.name} deployment`;\n const deployKeyDescription = `${git.name} deploy [contensis-cli]`;\n\n let existingDeployKey = apiKeyExists(deployKeyName);\n\n const blockId = git.name;\n const errors = [] as AppError[];\n\n // Start render console output\n log.raw('');\n log.success(messages.devinit.intro());\n log.raw('');\n log.raw(\n log.infoText(\n messages.devinit.projectDetails(\n git.name,\n currentEnv,\n currentProject,\n git\n )\n )\n );\n log.raw(\n log.infoText(\n messages.devinit.developmentKey(devKeyName, !!existingDevKey)\n )\n );\n log.raw(\n log.infoText(\n messages.devinit.deploymentKey(deployKeyName, !!existingDeployKey)\n )\n );\n log.raw('');\n\n if (Array.isArray(workflowFiles) && workflowFiles.length > 1) {\n // Choose GitHub workflow file (if multiple)\n ({ ciFileName } = await inquirer.prompt([\n {\n type: 'list',\n message: messages.devinit.ciMultipleChoices(),\n name: 'ciFileName',\n choices: workflowFiles,\n default: workflowFiles.find(f => f.includes('docker')),\n },\n ]));\n log.raw('');\n git.ciFileName = ciFileName;\n }\n\n log.raw(log.infoText(messages.devinit.ciDetails(ciFileName)));\n\n // Look at the workflow file content and make updates\n const mappedWorkflow = mapCIWorkflowContent(this, git);\n\n log.help(messages.devinit.ciIntro(git));\n\n if (!dryRun) {\n // Confirm prompt\n const { confirm } = await inquirer.prompt([\n {\n type: 'confirm',\n message: messages.devinit.confirm(),\n name: 'confirm',\n default: false,\n },\n ]);\n log.raw('');\n if (!confirm) return;\n }\n\n // Access token prompt\n const { accessToken }: { accessToken: string } = await inquirer.prompt([\n {\n type: 'input',\n message: messages.devinit.accessTokenPrompt(),\n name: 'accessToken',\n },\n ]);\n log.raw('');\n\n // Magic happens...\n const checkpoint = (op: string) => {\n if (errors.length) throw errors[0];\n else log.debug(`${op} completed ok`);\n return true;\n };\n\n // Arrange API keys for development and deployment\n const [getRolesErr, roles] = await to(contensis.roles.GetRoles());\n if (!roles && getRolesErr) errors.push(getRolesErr);\n checkpoint(`fetched ${roles?.length} roles`);\n if (dryRun) {\n checkpoint(`skip api key creation (dry-run)`);\n } else {\n existingDevKey = await this.CreateOrUpdateApiKey(\n existingDevKey,\n devKeyName,\n devKeyDescription\n );\n checkpoint('dev key created');\n\n existingDeployKey = await this.CreateOrUpdateApiKey(\n existingDeployKey,\n deployKeyName,\n deployKeyDescription\n );\n checkpoint('deploy key created');\n\n // Ensure dev API key is assigned to a role\n let existingDevRole = findByIdOrName(roles || [], devKeyName, true) as\n | Role\n | undefined;\n existingDevRole = await this.CreateOrUpdateRole(\n existingDevRole,\n devKeyRole(devKeyName, devKeyDescription)\n );\n checkpoint('dev key role assigned');\n log.success(messages.devinit.createDevKey(devKeyName, true));\n\n // Ensure deploy API key is assigned to a role with the right permissions\n let existingDeployRole = findByIdOrName(\n roles || [],\n deployKeyName,\n true\n ) as Role | undefined;\n existingDeployRole = await this.CreateOrUpdateRole(\n existingDeployRole,\n deployKeyRole(deployKeyName, deployKeyDescription)\n );\n\n checkpoint('deploy key role assigned');\n log.success(messages.devinit.createDeployKey(deployKeyName, true));\n checkpoint('api keys done');\n }\n\n // Update or create a file called .env in project home\n const envContentsToAdd: EnvContentsToAdd = {\n ALIAS: currentEnv,\n PROJECT: currentProject,\n };\n if (accessToken) envContentsToAdd['ACCESS_TOKEN'] = accessToken;\n\n const envFilePath = `${projectHome}/.env`;\n const existingEnvFile = readFile(envFilePath);\n const envFileLines = mergeDotEnvFileContents(\n (existingEnvFile || '').split('\\n').filter(l => !!l),\n envContentsToAdd\n );\n const newEnvFileContent = normaliseLineEndings(\n `${envFileLines.join('\\n')}\\n`\n );\n const envDiff = diffFileContent(existingEnvFile || '', newEnvFileContent);\n\n if (dryRun) {\n if (envDiff) {\n log.info(`updating .env file ${envFilePath}: ${envDiff}`);\n log.raw('');\n }\n checkpoint('skip .env file update (dry-run)');\n } else {\n if (envDiff) log.info(`updating .env file ${envFilePath}`);\n writeFile(envFilePath, envFileLines.join('\\n'));\n checkpoint('.env file updated');\n log.success(messages.devinit.writeEnvFile());\n // log.help(messages.devinit.useEnvFileTip());\n }\n\n // Update CI file -- different for GH/GL -- create a sample one with build?\n if (dryRun) {\n if (mappedWorkflow?.diff) {\n log.info(`updating${ciFileName} file: ${mappedWorkflow.diff}`);\n log.raw('');\n }\n checkpoint('skip CI file update (dry-run)');\n //log.object(ciFileLines);\n } else {\n if (mappedWorkflow?.diff) log.info(`updating${ciFileName} file`);\n writeFile(git.ciFilePath, [].join('\\n'));\n log.success(messages.devinit.writeCiFile(`./${ciFileName}`));\n log.info(\n messages.devinit.ciBlockTip(blockId, currentEnv, currentProject)\n );\n checkpoint('CI file updated');\n }\n\n // Echo Deployment API key to console, ask user to add secrets to repo\n log.warning(messages.devinit.addGitSecretsIntro());\n log.help(\n messages.devinit.addGitSecretsHelp(\n git,\n existingDeployKey?.id,\n existingDeployKey?.sharedSecret\n )\n );\n\n if (dryRun) {\n log.success(messages.devinit.dryRun());\n log.help(messages.devinit.noChanges());\n } else {\n log.success(messages.devinit.success());\n log.help(messages.devinit.startProjectTip());\n }\n }\n };\n\n ExecRequestHandler = async (blockIds: string[], overrideArgs?: string[]) => {\n // if no request handler exe\n // download it.\n\n // if update arg, redownload it\n\n const { log } = this;\n // const getPrefixOld = log.getPrefix;\n const exeHome = path.join(appRootDir, 'reqhan');\n const exe = 'Zengenti.Contensis.RequestHandler.LocalDevelopment';\n const exePath = path.join(exeHome, exe);\n const siteConfigPath = path.join(appRootDir, 'site_config.yaml');\n\n const siteConfig = await mapSiteConfigYaml(this);\n writeFile('site_config.yaml', stringifyYaml(siteConfig));\n\n const args = overrideArgs\n ? typeof overrideArgs?.[0] === 'string' &&\n overrideArgs[0].includes(' ', 2)\n ? overrideArgs[0].split(' ')\n : overrideArgs\n : []; // args could be [ '-c .\\\\site_config.yaml' ] or [ '-c', '.\\\\site_config.yaml' ]\n\n // Add required args\n if (!args.find(a => a === '-c')) args.push('-c', siteConfigPath);\n\n // const child = execFile(exePath, args);\n\n const child = spawn(exePath, args, { stdio: 'inherit' });\n\n // log.raw('');\n log.info(`Launching request handler...`);\n if (overrideArgs?.length)\n this.log.warning(\n `Spawning process with supplied args: ${JSON.stringify(\n child.spawnargs,\n null,\n 2\n )}`\n );\n\n let isRunning = false;\n\n // Log child output through event listeners\n child?.stdout?.on('data', data => {\n isRunning = true;\n log.raw(data);\n });\n\n child?.stderr?.on('data', data => {\n log.error(data);\n });\n\n child.on('spawn', () => {\n isRunning = true;\n log.help(\n `You may see a firewall popup requesting network access, it is safe to approve`\n );\n // log.getPrefix = () => Logger.infoText(`[rqh]`);\n });\n\n child.on('exit', code => {\n isRunning = false;\n\n log[code === 0 ? 'success' : 'warning'](\n `Request handler exited with code ${code}\\n`\n );\n });\n\n child.on('error', error => {\n isRunning = false;\n log.error(`Could not launch request handler due to error \\n${error}`);\n });\n\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n // keep the method running until we can return\n while (true === true) {\n if (!isRunning) {\n // log.getPrefix = getPrefixOld; // restore logger state\n return;\n }\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n };\n}\nexport const devCommand = (\n commandArgs: string[],\n outputOpts: OutputOptionsConstructorArg,\n contensisOpts: Partial<MigrateRequest> = {}\n) => {\n return new ContensisDev(['', '', ...commandArgs], outputOpts, contensisOpts);\n};\n\nexport default ContensisDev;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAe;AACf,2BAAgC;AAChC,sBAAqB;AACrB,kBAAiB;AAKjB,kCAA0B;AAG1B,wDAAkC;AAClC,mCAAqC;AACrC,wCAGO;AACP,2BAAgD;AAChD,kBAAgC;AAChC,oBAAwC;AACxC,kBAA+B;AAC/B,iBAA0B;AAC1B,kBAA8B;AAC9B,
|
|
4
|
+
"sourcesContent": ["import to from 'await-to-js';\nimport { execFile, spawn } from 'child_process';\nimport inquirer from 'inquirer';\nimport path from 'path';\n\nimport { Role } from 'contensis-management-api/lib/models';\nimport { MigrateRequest } from 'migratortron';\n\nimport ContensisRole from './ContensisRoleService';\nimport { OutputOptionsConstructorArg } from '~/models/CliService';\nimport { EnvContentsToAdd } from '~/models/DevService';\nimport { mapSiteConfigYaml } from '~/mappers/DevRequests-to-RequestHanderSiteConfigYaml';\nimport { mapCIWorkflowContent } from '~/mappers/DevInit-to-CIWorkflow';\nimport {\n deployKeyRole,\n devKeyRole,\n} from '~/mappers/DevInit-to-RolePermissions';\nimport { appRootDir, readFile, writeFile } from '~/providers/file-provider';\nimport { diffFileContent } from '~/util/diff';\nimport { mergeDotEnvFileContents } from '~/util/dotenv';\nimport { findByIdOrName } from '~/util/find';\nimport { GitHelper } from '~/util/git';\nimport { jsonFormatter } from '~/util/json.formatter';\nimport { normaliseLineEndings, winSlash } from '~/util/os';\nimport { stringifyYaml } from '~/util/yaml';\n\nclass ContensisDev extends ContensisRole {\n constructor(\n args: string[],\n outputOpts?: OutputOptionsConstructorArg,\n contensisOpts: Partial<MigrateRequest> = {}\n ) {\n super(args, outputOpts, contensisOpts);\n }\n\n DevelopmentInit = async (projectHome: string, opts: any) => {\n const { dryRun = false } = opts || {};\n const { currentEnv, currentProject, log, messages } = this;\n const contensis = await this.ConnectContensis();\n\n if (contensis) {\n // Retrieve keys list for env\n const [keysErr, apiKeys] = await contensis.apiKeys.GetKeys();\n if (keysErr) {\n log.error(messages.keys.noList(currentEnv));\n log.error(jsonFormatter(keysErr));\n return;\n }\n const apiKeyExists = (findKey: string) =>\n apiKeys?.find(\n k => k.name.trim().toLowerCase() === findKey?.trim().toLowerCase()\n );\n\n // Retrieve git info\n const git = new GitHelper(projectHome);\n\n // Retrieve ci workflow info\n const workflowFiles = git.workflows;\n\n // Set variables for performing operations and logging etc.\n let ciFileName = git.ciFileName;\n\n const devKeyName = `${git.name} development`;\n const devKeyDescription = `${git.name} [contensis-cli]`;\n let existingDevKey = apiKeyExists(devKeyName);\n\n const deployKeyName = `${git.name} deployment`;\n const deployKeyDescription = `${git.name} deploy [contensis-cli]`;\n\n let existingDeployKey = apiKeyExists(deployKeyName);\n\n const blockId = git.name;\n const errors = [] as AppError[];\n\n // Start render console output\n log.raw('');\n log.success(messages.devinit.intro());\n log.raw('');\n log.raw(\n log.infoText(\n messages.devinit.projectDetails(\n git.name,\n currentEnv,\n currentProject,\n git\n )\n )\n );\n log.raw(\n log.infoText(\n messages.devinit.developmentKey(devKeyName, !!existingDevKey)\n )\n );\n log.raw(\n log.infoText(\n messages.devinit.deploymentKey(deployKeyName, !!existingDeployKey)\n )\n );\n log.raw('');\n\n if (Array.isArray(workflowFiles) && workflowFiles.length > 1) {\n // Choose GitHub workflow file (if multiple)\n ({ ciFileName } = await inquirer.prompt([\n {\n type: 'list',\n prefix: '\u29F0',\n message: messages.devinit.ciMultipleChoices(),\n name: 'ciFileName',\n choices: workflowFiles,\n default: workflowFiles.find(f => f.includes('docker')),\n },\n ]));\n log.raw('');\n git.ciFileName = ciFileName;\n }\n\n log.raw(log.infoText(messages.devinit.ciDetails(ciFileName)));\n\n // Look at the workflow file content and make updates\n const mappedWorkflow = await mapCIWorkflowContent(this, git);\n\n log.help(messages.devinit.ciIntro(git));\n\n if (!dryRun) {\n // Confirm prompt\n const { confirm } = await inquirer.prompt([\n {\n type: 'confirm',\n message: messages.devinit.confirm(),\n name: 'confirm',\n default: false,\n },\n ]);\n log.raw('');\n if (!confirm) return;\n }\n\n // Access token prompt\n const { accessToken }: { accessToken: string } = await inquirer.prompt([\n {\n type: 'input',\n prefix: '\uD83D\uDEE1\uFE0F',\n message: messages.devinit.accessTokenPrompt(),\n name: 'accessToken',\n },\n ]);\n log.raw('');\n\n // Magic happens...\n const checkpoint = (op: string) => {\n if (errors.length) throw errors[0];\n else log.debug(`${op} completed ok`);\n return true;\n };\n\n // Arrange API keys for development and deployment\n const [getRolesErr, roles] = await to(contensis.roles.GetRoles());\n if (!roles && getRolesErr) errors.push(getRolesErr);\n checkpoint(`fetched ${roles?.length} roles`);\n if (dryRun) {\n checkpoint(`skip api key creation (dry-run)`);\n } else {\n existingDevKey = await this.CreateOrUpdateApiKey(\n existingDevKey,\n devKeyName,\n devKeyDescription\n );\n checkpoint('dev key created');\n\n existingDeployKey = await this.CreateOrUpdateApiKey(\n existingDeployKey,\n deployKeyName,\n deployKeyDescription\n );\n checkpoint('deploy key created');\n\n // Ensure dev API key is assigned to a role\n let existingDevRole = findByIdOrName(roles || [], devKeyName, true) as\n | Role\n | undefined;\n existingDevRole = await this.CreateOrUpdateRole(\n existingDevRole,\n devKeyRole(devKeyName, devKeyDescription)\n );\n checkpoint('dev key role assigned');\n log.success(messages.devinit.createDevKey(devKeyName, true));\n\n // Ensure deploy API key is assigned to a role with the right permissions\n let existingDeployRole = findByIdOrName(\n roles || [],\n deployKeyName,\n true\n ) as Role | undefined;\n existingDeployRole = await this.CreateOrUpdateRole(\n existingDeployRole,\n deployKeyRole(deployKeyName, deployKeyDescription)\n );\n\n checkpoint('deploy key role assigned');\n log.success(messages.devinit.createDeployKey(deployKeyName, true));\n checkpoint('api keys done');\n }\n\n // Update or create a file called .env in project home\n const envContentsToAdd: EnvContentsToAdd = {\n ALIAS: currentEnv,\n PROJECT: currentProject,\n };\n if (accessToken) envContentsToAdd['ACCESS_TOKEN'] = accessToken;\n\n const envFilePath = `${projectHome}/.env`;\n const existingEnvFile = readFile(envFilePath);\n const envFileLines = mergeDotEnvFileContents(\n (existingEnvFile || '').split('\\n').filter(l => !!l),\n envContentsToAdd\n );\n const newEnvFileContent = normaliseLineEndings(\n `${envFileLines.join('\\n')}\\n`\n );\n const envDiff = diffFileContent(existingEnvFile || '', newEnvFileContent);\n\n if (dryRun) {\n if (envDiff) {\n log.info(`Updating .env file ${winSlash(envFilePath)}:\\n${envDiff}`);\n log.raw('');\n }\n checkpoint('skip .env file update (dry-run)');\n } else {\n if (envDiff) log.info(`updating .env file ${winSlash(envFilePath)}`);\n writeFile(envFilePath, envFileLines.join('\\n'));\n checkpoint('.env file updated');\n log.success(messages.devinit.writeEnvFile());\n // log.help(messages.devinit.useEnvFileTip());\n }\n\n // Update CI file -- different for GH/GL\n if (mappedWorkflow?.diff) {\n log.info(\n `Updating ${winSlash(ciFileName)} file:\\n${mappedWorkflow.diff}`\n );\n log.raw('');\n }\n if (dryRun) {\n checkpoint('skip CI file update (dry-run)');\n //log.object(ciFileLines);\n } else {\n if (mappedWorkflow?.newWorkflow) {\n if (mappedWorkflow?.diff) {\n writeFile(git.ciFilePath, mappedWorkflow.newWorkflow);\n log.success(messages.devinit.writeCiFile(`./${ciFileName}`));\n log.info(\n messages.devinit.ciBlockTip(blockId, currentEnv, currentProject)\n );\n } else {\n log.info(messages.devinit.ciFileNoChanges(`./${ciFileName}`));\n }\n checkpoint('CI file updated');\n }\n }\n\n // Echo Deployment API key to console, ask user to add secrets to repo\n log.warning(messages.devinit.addGitSecretsIntro());\n log.help(\n messages.devinit.addGitSecretsHelp(\n git,\n existingDeployKey?.id,\n existingDeployKey?.sharedSecret\n )\n );\n\n if (dryRun) {\n log.success(messages.devinit.dryRun());\n log.help(messages.devinit.noChanges());\n } else {\n log.success(messages.devinit.success());\n log.help(messages.devinit.startProjectTip());\n }\n }\n };\n\n ExecRequestHandler = async (blockIds: string[], overrideArgs?: string[]) => {\n // if no request handler exe\n // download it.\n\n // if update arg, redownload it\n\n const { log } = this;\n // const getPrefixOld = log.getPrefix;\n const exeHome = path.join(appRootDir, 'reqhan');\n const exe = 'Zengenti.Contensis.RequestHandler.LocalDevelopment';\n const exePath = path.join(exeHome, exe);\n const siteConfigPath = path.join(appRootDir, 'site_config.yaml');\n\n const siteConfig = await mapSiteConfigYaml(this);\n writeFile('site_config.yaml', stringifyYaml(siteConfig));\n\n const args = overrideArgs\n ? typeof overrideArgs?.[0] === 'string' &&\n overrideArgs[0].includes(' ', 2)\n ? overrideArgs[0].split(' ')\n : overrideArgs\n : []; // args could be [ '-c .\\\\site_config.yaml' ] or [ '-c', '.\\\\site_config.yaml' ]\n\n // Add required args\n if (!args.find(a => a === '-c')) args.push('-c', siteConfigPath);\n\n // const child = execFile(exePath, args);\n\n const child = spawn(exePath, args, { stdio: 'inherit' });\n\n // log.raw('');\n log.info(`Launching request handler...`);\n if (overrideArgs?.length)\n this.log.warning(\n `Spawning process with supplied args: ${JSON.stringify(\n child.spawnargs,\n null,\n 2\n )}`\n );\n\n let isRunning = false;\n\n // Log child output through event listeners\n child?.stdout?.on('data', data => {\n isRunning = true;\n log.raw(data);\n });\n\n child?.stderr?.on('data', data => {\n log.error(data);\n });\n\n child.on('spawn', () => {\n isRunning = true;\n log.help(\n `You may see a firewall popup requesting network access, it is safe to approve`\n );\n // log.getPrefix = () => Logger.infoText(`[rqh]`);\n });\n\n child.on('exit', code => {\n isRunning = false;\n\n log[code === 0 ? 'success' : 'warning'](\n `Request handler exited with code ${code}\\n`\n );\n });\n\n child.on('error', error => {\n isRunning = false;\n log.error(`Could not launch request handler due to error \\n${error}`);\n });\n\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n // keep the method running until we can return\n while (true === true) {\n if (!isRunning) {\n // log.getPrefix = getPrefixOld; // restore logger state\n return;\n }\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n };\n}\nexport const devCommand = (\n commandArgs: string[],\n outputOpts: OutputOptionsConstructorArg,\n contensisOpts: Partial<MigrateRequest> = {}\n) => {\n return new ContensisDev(['', '', ...commandArgs], outputOpts, contensisOpts);\n};\n\nexport default ContensisDev;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ContensisRole", "inquirer", "to", "path"]
|
|
7
7
|
}
|
package/dist/util/diff.js
CHANGED
|
@@ -54,18 +54,24 @@ const diffFileContent = (existingContent, newContent) => {
|
|
|
54
54
|
...diffRanges.map((d) => d.startLineNumber.toString().length)
|
|
55
55
|
);
|
|
56
56
|
const lnSpaces = Array(lnSpaceLength).join(" ");
|
|
57
|
+
let needsNewLine = false;
|
|
57
58
|
for (let i = 0; i < diffRanges.length; i++) {
|
|
58
59
|
const part = diffRanges[i];
|
|
59
60
|
if (part.added || part.removed) {
|
|
60
61
|
const colour = part.added ? "green" : part.removed ? "red" : "grey";
|
|
61
|
-
if (part.value !== "\n")
|
|
62
|
+
if (part.value !== "\n") {
|
|
63
|
+
if (needsNewLine)
|
|
64
|
+
output.push("\n### --");
|
|
62
65
|
output.push(
|
|
63
66
|
`
|
|
64
67
|
${part.value.split("\n").map(
|
|
65
68
|
(ln, idx) => ln.trim() !== "" ? `${part.startLineNumber ? part.startLineNumber + idx : lnSpaces}${part.added ? "+" : part.removed ? "-" : " "} ${import_chalk.default[colour](`${ln}`)}` : ln
|
|
66
69
|
).join("\n")}`
|
|
67
70
|
);
|
|
68
|
-
|
|
71
|
+
} else
|
|
72
|
+
needsNewLine = true;
|
|
73
|
+
} else
|
|
74
|
+
needsNewLine = true;
|
|
69
75
|
}
|
|
70
76
|
return output.join("");
|
|
71
77
|
};
|
package/dist/util/diff.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/util/diff.ts"],
|
|
4
|
-
"sourcesContent": ["import chalk from 'chalk';\nimport { Change, diffLines } from 'diff';\nimport { normaliseLineEndings } from './os';\n\nexport const diffLogStrings = (updates: string, previous: string) => {\n const lastFewLines = previous.split('\\n').slice(-10);\n const incomingLines = updates.split('\\n');\n\n // Find the line indices in the incoming lines\n // of the last few lines previously rendered\n const incomingLineIndices = [];\n for (const lastRenderedLine of lastFewLines) {\n if (lastRenderedLine.length > 10)\n incomingLineIndices.push(incomingLines.lastIndexOf(lastRenderedLine));\n }\n\n // Get the new lines from the next position on from the last of the already shown lines\n const differentFromPos = Math.max(...incomingLineIndices) + 1 || 0;\n // Return just the incoming lines from the position we matched\n return incomingLines.slice(differentFromPos).join('\\n');\n};\n\nexport const diffFileContent = (\n existingContent: string,\n newContent: string\n) => {\n const existingContentNormalised = normaliseLineEndings(existingContent, '\\n');\n const newContentNormalised = normaliseLineEndings(newContent, '\\n');\n\n const diff = diffLines(existingContentNormalised, newContentNormalised, {\n newlineIsToken: true,\n });\n const diffRanges = addDiffPositionInfo(diff);\n\n // Create formatted output for console\n const output: string[] = [];\n const lnSpaceLength = Math.max(\n ...diffRanges.map(d => d.startLineNumber.toString().length)\n );\n\n const lnSpaces = Array(lnSpaceLength).join(' ');\n\n for (let i = 0; i < diffRanges.length; i++) {\n const part = diffRanges[i];\n if (part.added || part.removed) {\n const colour = part.added ? 'green' : part.removed ? 'red' : 'grey';\n\n if (part.value !== '\\n')\n output.push(\n `\\n${part.value\n .split('\\n')\n .map((ln, idx) =>\n ln.trim() !== ''\n ? `${\n part.startLineNumber ? part.startLineNumber + idx : lnSpaces\n }${part.added ? '+' : part.removed ? '-' : ' '} ${chalk[\n colour\n ](`${ln}`)}`\n : ln\n )\n .join('\\n')}`\n );\n }
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,kBAAkC;AAClC,gBAAqC;AAE9B,MAAM,iBAAiB,CAAC,SAAiB,aAAqB;AACnE,QAAM,eAAe,SAAS,MAAM,IAAI,EAAE,MAAM,GAAG;AACnD,QAAM,gBAAgB,QAAQ,MAAM,IAAI;AAIxC,QAAM,sBAAsB,CAAC;AAC7B,aAAW,oBAAoB,cAAc;AAC3C,QAAI,iBAAiB,SAAS;AAC5B,0BAAoB,KAAK,cAAc,YAAY,gBAAgB,CAAC;AAAA,EACxE;AAGA,QAAM,mBAAmB,KAAK,IAAI,GAAG,mBAAmB,IAAI,KAAK;AAEjE,SAAO,cAAc,MAAM,gBAAgB,EAAE,KAAK,IAAI;AACxD;AAEO,MAAM,kBAAkB,CAC7B,iBACA,eACG;AACH,QAAM,gCAA4B,gCAAqB,iBAAiB,IAAI;AAC5E,QAAM,2BAAuB,gCAAqB,YAAY,IAAI;AAElE,QAAM,WAAO,uBAAU,2BAA2B,sBAAsB;AAAA,IACtE,gBAAgB;AAAA,EAClB,CAAC;AACD,QAAM,aAAa,oBAAoB,IAAI;AAG3C,QAAM,SAAmB,CAAC;AAC1B,QAAM,gBAAgB,KAAK;AAAA,IACzB,GAAG,WAAW,IAAI,OAAK,EAAE,gBAAgB,SAAS,EAAE,MAAM;AAAA,EAC5D;AAEA,QAAM,WAAW,MAAM,aAAa,EAAE,KAAK,GAAG;AAE9C,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,OAAO,WAAW;AACxB,QAAI,KAAK,SAAS,KAAK,SAAS;AAC9B,YAAM,SAAS,KAAK,QAAQ,UAAU,KAAK,UAAU,QAAQ;AAE7D,UAAI,KAAK,UAAU;
|
|
4
|
+
"sourcesContent": ["import chalk from 'chalk';\nimport { Change, diffLines } from 'diff';\nimport { normaliseLineEndings } from './os';\n\nexport const diffLogStrings = (updates: string, previous: string) => {\n const lastFewLines = previous.split('\\n').slice(-10);\n const incomingLines = updates.split('\\n');\n\n // Find the line indices in the incoming lines\n // of the last few lines previously rendered\n const incomingLineIndices = [];\n for (const lastRenderedLine of lastFewLines) {\n if (lastRenderedLine.length > 10)\n incomingLineIndices.push(incomingLines.lastIndexOf(lastRenderedLine));\n }\n\n // Get the new lines from the next position on from the last of the already shown lines\n const differentFromPos = Math.max(...incomingLineIndices) + 1 || 0;\n // Return just the incoming lines from the position we matched\n return incomingLines.slice(differentFromPos).join('\\n');\n};\n\nexport const diffFileContent = (\n existingContent: string,\n newContent: string\n) => {\n const existingContentNormalised = normaliseLineEndings(existingContent, '\\n');\n const newContentNormalised = normaliseLineEndings(newContent, '\\n');\n\n const diff = diffLines(existingContentNormalised, newContentNormalised, {\n newlineIsToken: true,\n });\n const diffRanges = addDiffPositionInfo(diff);\n\n // Create formatted output for console\n const output: string[] = [];\n const lnSpaceLength = Math.max(\n ...diffRanges.map(d => d.startLineNumber.toString().length)\n );\n\n const lnSpaces = Array(lnSpaceLength).join(' ');\n\n let needsNewLine = false;\n for (let i = 0; i < diffRanges.length; i++) {\n const part = diffRanges[i];\n if (part.added || part.removed) {\n const colour = part.added ? 'green' : part.removed ? 'red' : 'grey';\n\n if (part.value !== '\\n') {\n if (needsNewLine) output.push('\\n### --');\n output.push(\n `\\n${part.value\n .split('\\n')\n .map((ln, idx) =>\n ln.trim() !== ''\n ? `${\n part.startLineNumber ? part.startLineNumber + idx : lnSpaces\n }${part.added ? '+' : part.removed ? '-' : ' '} ${chalk[\n colour\n ](`${ln}`)}`\n : ln\n )\n .join('\\n')}`\n );\n } else needsNewLine = true;\n } else needsNewLine = true;\n }\n\n return output.join('');\n};\n\nconst addDiffPositionInfo = (diff: Change[]) => {\n const diffRanges: (Change & {\n startLineNumber: number;\n startColumn: number;\n endLineNumber: number;\n endColumn: number;\n })[] = [];\n\n let lineNumber = 0;\n let column = 0;\n for (let partIndex = 0; partIndex < diff.length; partIndex++) {\n const part = diff[partIndex];\n\n // // Skip any parts that aren't in `after`\n // if (part.removed === true) {\n // continue;\n // }\n\n const startLineNumber = lineNumber;\n const startColumn = column;\n\n // Split the part into lines. Loop throug these lines to find\n // the line no. and column at the end of this part.\n const substring = part.value;\n const lines = substring.split('\\n');\n lines.forEach((line, lineIndex) => {\n // The first `line` is actually just a continuation of the last line\n if (lineIndex === 0) {\n column += line.length;\n // All other lines come after a line break.\n } else if (lineIndex > 0) {\n lineNumber += 1;\n column = line.length;\n }\n });\n\n // Save a range for all of the parts with position info added\n if (part.added === true || part.removed === true) {\n diffRanges.push({\n startLineNumber: startLineNumber + 1,\n startColumn: startColumn,\n endLineNumber: lineNumber,\n endColumn: column,\n ...part,\n });\n }\n }\n return diffRanges;\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,kBAAkC;AAClC,gBAAqC;AAE9B,MAAM,iBAAiB,CAAC,SAAiB,aAAqB;AACnE,QAAM,eAAe,SAAS,MAAM,IAAI,EAAE,MAAM,GAAG;AACnD,QAAM,gBAAgB,QAAQ,MAAM,IAAI;AAIxC,QAAM,sBAAsB,CAAC;AAC7B,aAAW,oBAAoB,cAAc;AAC3C,QAAI,iBAAiB,SAAS;AAC5B,0BAAoB,KAAK,cAAc,YAAY,gBAAgB,CAAC;AAAA,EACxE;AAGA,QAAM,mBAAmB,KAAK,IAAI,GAAG,mBAAmB,IAAI,KAAK;AAEjE,SAAO,cAAc,MAAM,gBAAgB,EAAE,KAAK,IAAI;AACxD;AAEO,MAAM,kBAAkB,CAC7B,iBACA,eACG;AACH,QAAM,gCAA4B,gCAAqB,iBAAiB,IAAI;AAC5E,QAAM,2BAAuB,gCAAqB,YAAY,IAAI;AAElE,QAAM,WAAO,uBAAU,2BAA2B,sBAAsB;AAAA,IACtE,gBAAgB;AAAA,EAClB,CAAC;AACD,QAAM,aAAa,oBAAoB,IAAI;AAG3C,QAAM,SAAmB,CAAC;AAC1B,QAAM,gBAAgB,KAAK;AAAA,IACzB,GAAG,WAAW,IAAI,OAAK,EAAE,gBAAgB,SAAS,EAAE,MAAM;AAAA,EAC5D;AAEA,QAAM,WAAW,MAAM,aAAa,EAAE,KAAK,GAAG;AAE9C,MAAI,eAAe;AACnB,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,OAAO,WAAW;AACxB,QAAI,KAAK,SAAS,KAAK,SAAS;AAC9B,YAAM,SAAS,KAAK,QAAQ,UAAU,KAAK,UAAU,QAAQ;AAE7D,UAAI,KAAK,UAAU,MAAM;AACvB,YAAI;AAAc,iBAAO,KAAK,UAAU;AACxC,eAAO;AAAA,UACL;AAAA,EAAK,KAAK,MACP,MAAM,IAAI,EACV;AAAA,YAAI,CAAC,IAAI,QACR,GAAG,KAAK,MAAM,KACV,GACE,KAAK,kBAAkB,KAAK,kBAAkB,MAAM,WACnD,KAAK,QAAQ,MAAM,KAAK,UAAU,MAAM,OAAO,aAAAA,QAChD,QACA,GAAG,IAAI,MACT;AAAA,UACN,EACC,KAAK,IAAI;AAAA,QACd;AAAA,MACF;AAAO,uBAAe;AAAA,IACxB;AAAO,qBAAe;AAAA,EACxB;AAEA,SAAO,OAAO,KAAK,EAAE;AACvB;AAEA,MAAM,sBAAsB,CAAC,SAAmB;AAC9C,QAAM,aAKC,CAAC;AAER,MAAI,aAAa;AACjB,MAAI,SAAS;AACb,WAAS,YAAY,GAAG,YAAY,KAAK,QAAQ,aAAa;AAC5D,UAAM,OAAO,KAAK;AAOlB,UAAM,kBAAkB;AACxB,UAAM,cAAc;AAIpB,UAAM,YAAY,KAAK;AACvB,UAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,UAAM,QAAQ,CAAC,MAAM,cAAc;AAEjC,UAAI,cAAc,GAAG;AACnB,kBAAU,KAAK;AAAA,MAEjB,WAAW,YAAY,GAAG;AACxB,sBAAc;AACd,iBAAS,KAAK;AAAA,MAChB;AAAA,IACF,CAAC;AAGD,QAAI,KAAK,UAAU,QAAQ,KAAK,YAAY,MAAM;AAChD,iBAAW,KAAK;AAAA,QACd,iBAAiB,kBAAkB;AAAA,QACnC;AAAA,QACA,eAAe;AAAA,QACf,WAAW;AAAA,QACX,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;",
|
|
6
6
|
"names": ["chalk"]
|
|
7
7
|
}
|
package/dist/version.js
CHANGED
|
@@ -21,7 +21,7 @@ __export(version_exports, {
|
|
|
21
21
|
LIB_VERSION: () => LIB_VERSION
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(version_exports);
|
|
24
|
-
const LIB_VERSION = "1.0.0-beta.
|
|
24
|
+
const LIB_VERSION = "1.0.0-beta.95";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
LIB_VERSION
|
package/dist/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["export const LIB_VERSION = \"1.0.0-beta.
|
|
4
|
+
"sourcesContent": ["export const LIB_VERSION = \"1.0.0-beta.95\";\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contensis-cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.95",
|
|
4
4
|
"description": "A fully featured Contensis command line interface with a shell UI provides simple and intuitive ways to manage or profile your content in any NodeJS terminal.",
|
|
5
5
|
"repository": "https://github.com/contensis/node-cli",
|
|
6
6
|
"homepage": "https://github.com/contensis/node-cli/tree/main/packages/contensis-cli#readme",
|
|
@@ -456,8 +456,24 @@ We will ask you to add secrets/variables to your git repository to give your wor
|
|
|
456
456
|
`Add push-block job to CI file: ${Logger.highlightText(filename)}\n`,
|
|
457
457
|
ciMultipleChoices: () =>
|
|
458
458
|
`Multiple GitHub workflow files found\n${Logger.infoText(
|
|
459
|
-
`Tell us which GitHub workflow builds
|
|
459
|
+
`Tell us which GitHub workflow builds a container image after each push:`
|
|
460
460
|
)}`,
|
|
461
|
+
ciMultipleBuildJobChoices: () =>
|
|
462
|
+
`Multiple build jobs found in workflow\n${Logger.infoText(
|
|
463
|
+
`Choose the build job that produces a fresh container image to push to a block:`
|
|
464
|
+
)}`,
|
|
465
|
+
ciMultipleJobChoices: () =>
|
|
466
|
+
`Other jobs found in workflow\n${Logger.infoText(
|
|
467
|
+
`Choose the job that produces a fresh container image we can push to a block:`
|
|
468
|
+
)}`,
|
|
469
|
+
ciMultipleAppImageVarChoices: () =>
|
|
470
|
+
`Do one of these variables point to your tagged app image?\n${Logger.infoText(
|
|
471
|
+
`we have included a default choice - ensure your build image is tagged exactly the same as this`
|
|
472
|
+
)}`,
|
|
473
|
+
ciEnterOwnAppImagePrompt: () =>
|
|
474
|
+
`Tell us the registry uri your app image is tagged and pushed with (ā accept default) \n${Logger.infoText(
|
|
475
|
+
`Tip: GitHub context variables available\nhttps://docs.github.com/en/actions/learn-github-actions/variables#using-contexts-to-access-variable-values`
|
|
476
|
+
)}\n`,
|
|
461
477
|
confirm: () =>
|
|
462
478
|
`Confirm these details are correct so we can make changes to your project`,
|
|
463
479
|
accessTokenPrompt: () =>
|
|
@@ -479,6 +495,10 @@ We will ask you to add secrets/variables to your git repository to give your wor
|
|
|
479
495
|
`You should alter existing project code that connects a Contensis client to use the variables from this file`,
|
|
480
496
|
writeCiFile: (ciFilePath: string) =>
|
|
481
497
|
`Updated CI file ${Logger.standardText(winSlash(ciFilePath))}`,
|
|
498
|
+
ciFileNoChanges: (ciFilePath: string) =>
|
|
499
|
+
`No updates needed for CI file ${Logger.standardText(
|
|
500
|
+
winSlash(ciFilePath)
|
|
501
|
+
)}`,
|
|
482
502
|
ciBlockTip: (blockId: string, env: string, projectId: string) =>
|
|
483
503
|
`A job is included to deploy your built container image to ${Logger.standardText(
|
|
484
504
|
projectId
|
|
@@ -512,7 +532,7 @@ We will ask you to add secrets/variables to your git repository to give your wor
|
|
|
512
532
|
dryRun: () =>
|
|
513
533
|
`Contensis developer environment initialisation dry run completed`,
|
|
514
534
|
noChanges: () =>
|
|
515
|
-
`No changes were made to your project
|
|
535
|
+
`No changes were made to your project, run the command again without the --dry-run flag to update your project with these changes`,
|
|
516
536
|
startProjectTip: () =>
|
|
517
537
|
`Start up your project in the normal way for development`,
|
|
518
538
|
},
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
1
2
|
import { JSONPath, JSONPathOptions } from 'jsonpath-plus';
|
|
3
|
+
import {
|
|
4
|
+
GitHubActionPushBlockJob,
|
|
5
|
+
GitHubActionPushBlockJobStep,
|
|
6
|
+
} from '~/models/DevService';
|
|
2
7
|
import { readFile } from '~/providers/file-provider';
|
|
3
8
|
import ContensisDev from '~/services/ContensisDevService';
|
|
4
9
|
import { diffFileContent } from '~/util/diff';
|
|
@@ -13,17 +18,17 @@ type MappedWorkflowOutput = {
|
|
|
13
18
|
diff: string;
|
|
14
19
|
};
|
|
15
20
|
|
|
16
|
-
export const mapCIWorkflowContent = (
|
|
21
|
+
export const mapCIWorkflowContent = async (
|
|
17
22
|
cli: ContensisDev,
|
|
18
23
|
git: GitHelper
|
|
19
|
-
): MappedWorkflowOutput | undefined => {
|
|
24
|
+
): Promise<MappedWorkflowOutput | undefined> => {
|
|
20
25
|
// get existing workflow file
|
|
21
26
|
const workflowFile = readFile(git.ciFilePath);
|
|
22
27
|
if (!workflowFile) return undefined;
|
|
23
28
|
|
|
24
29
|
const blockId = git.name;
|
|
25
30
|
if (git.type === 'github') {
|
|
26
|
-
const addGitHubActionJobStep = {
|
|
31
|
+
const addGitHubActionJobStep: GitHubActionPushBlockJobStep = {
|
|
27
32
|
name: 'Push block to Contensis',
|
|
28
33
|
id: 'push-block',
|
|
29
34
|
uses: 'contensis/block-push@v1',
|
|
@@ -39,7 +44,7 @@ export const mapCIWorkflowContent = (
|
|
|
39
44
|
|
|
40
45
|
// parse yaml to js
|
|
41
46
|
const workflowDoc = parseYamlDocument(workflowFile);
|
|
42
|
-
const
|
|
47
|
+
const workflowJS = workflowDoc.toJS();
|
|
43
48
|
const setWorkflowElement = (path: string | any[], value: any) => {
|
|
44
49
|
const findPath =
|
|
45
50
|
typeof path === 'string' && path.includes('.')
|
|
@@ -56,26 +61,44 @@ export const mapCIWorkflowContent = (
|
|
|
56
61
|
}
|
|
57
62
|
};
|
|
58
63
|
const findExistingJobSteps = (
|
|
64
|
+
path: string,
|
|
59
65
|
resultType: JSONPathOptions['resultType']
|
|
60
66
|
) => {
|
|
61
|
-
// look for line in job
|
|
62
|
-
// jobs.x.steps[uses: contensis/block-push]
|
|
63
|
-
const path =
|
|
64
|
-
git.type === 'github'
|
|
65
|
-
? '$.jobs..steps.*[?(@property === "uses" && @.match(/^contensis\\/block-push/i))]^'
|
|
66
|
-
: // TODO: add jsonpath for gitlab file
|
|
67
|
-
'';
|
|
68
|
-
|
|
69
67
|
const existingJobStep = JSONPath({
|
|
70
68
|
path,
|
|
71
|
-
json:
|
|
69
|
+
json: workflowJS,
|
|
72
70
|
resultType: resultType,
|
|
73
71
|
});
|
|
74
72
|
|
|
75
73
|
return existingJobStep;
|
|
76
74
|
};
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
// look for line in job
|
|
77
|
+
// jobs.x.steps[uses: contensis/block-push]
|
|
78
|
+
const existingJobStep = findExistingJobSteps(
|
|
79
|
+
git.type === 'github'
|
|
80
|
+
? '$.jobs..steps.*[?(@property === "uses" && @.match(/^contensis\\/block-push/i))]^'
|
|
81
|
+
: // TODO: add jsonpath for gitlab file
|
|
82
|
+
'',
|
|
83
|
+
'all'
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const addAppImageUri = async () => {
|
|
87
|
+
// Look in document level "env" vars
|
|
88
|
+
const appImageUri = await determineAppImageUri(
|
|
89
|
+
cli,
|
|
90
|
+
Object.entries(workflowJS.env || {})
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
if (appImageUri.addVar)
|
|
94
|
+
setWorkflowElement(`env.${appImageUri.var}`, appImageUri.uri);
|
|
95
|
+
// workflowDoc.addIn(['env'], { [appImageUri.var]: appImageUri.uri });
|
|
96
|
+
|
|
97
|
+
if (appImageUri.var)
|
|
98
|
+
addGitHubActionJobStep.with[
|
|
99
|
+
'image-uri'
|
|
100
|
+
] = `\${{ env.${appImageUri.var} }}`;
|
|
101
|
+
};
|
|
79
102
|
|
|
80
103
|
// update job step
|
|
81
104
|
if (existingJobStep.length) {
|
|
@@ -101,6 +124,11 @@ export const mapCIWorkflowContent = (
|
|
|
101
124
|
setWorkflowElement(`${stepPath}.with.alias`, cli.currentEnv);
|
|
102
125
|
setWorkflowElement(`${stepPath}.with.project-id`, cli.currentProject);
|
|
103
126
|
setWorkflowElement(`${stepPath}.with.block-id`, blockId);
|
|
127
|
+
|
|
128
|
+
// This is likely not needed when updating an existing push-block job step
|
|
129
|
+
// we are assuming this is a forked/copied workflow with an already working image-uri reference
|
|
130
|
+
// await addAppImageUri();
|
|
131
|
+
|
|
104
132
|
setWorkflowElement(
|
|
105
133
|
`${stepPath}.with.client-id`,
|
|
106
134
|
'${{ secrets.CONTENSIS_CLIENT_ID }}'
|
|
@@ -111,20 +139,89 @@ export const mapCIWorkflowContent = (
|
|
|
111
139
|
);
|
|
112
140
|
} else {
|
|
113
141
|
// create job with push step
|
|
142
|
+
|
|
143
|
+
// is there already a job with a property name containing "build"?
|
|
144
|
+
const existingBuildJobStep = findExistingJobSteps(
|
|
145
|
+
git.type === 'github'
|
|
146
|
+
? '$.jobs[?(@property.match(/build/i))]'
|
|
147
|
+
: // TODO: add jsonpath for gitlab file
|
|
148
|
+
'',
|
|
149
|
+
'all'
|
|
150
|
+
) as JSONPathOptions[]; // This isn't the correct type for this object
|
|
151
|
+
|
|
152
|
+
let needs: string | undefined;
|
|
153
|
+
// There are multiple jobs called *build*
|
|
154
|
+
if (existingBuildJobStep.length > 1) {
|
|
155
|
+
// prompt which build job we should depend on before pushing the block
|
|
156
|
+
const choices = existingBuildJobStep.map(s => s.parentProperty);
|
|
157
|
+
choices.push(new inquirer.Separator() as any);
|
|
158
|
+
choices.push('none');
|
|
159
|
+
|
|
160
|
+
({ needs } = await inquirer.prompt([
|
|
161
|
+
{
|
|
162
|
+
type: 'list',
|
|
163
|
+
prefix: 'ā',
|
|
164
|
+
message: cli.messages.devinit.ciMultipleBuildJobChoices(),
|
|
165
|
+
name: 'needs',
|
|
166
|
+
choices,
|
|
167
|
+
default: choices.find(
|
|
168
|
+
s => typeof s === 'string' && s.includes('docker')
|
|
169
|
+
),
|
|
170
|
+
},
|
|
171
|
+
]));
|
|
172
|
+
cli.log.raw('');
|
|
173
|
+
} else if (existingBuildJobStep.length === 1)
|
|
174
|
+
// Exactly one job step found containing a property name of *build*
|
|
175
|
+
// we'll assume that is the one the push-block job depends on
|
|
176
|
+
needs = existingBuildJobStep[0].parentProperty;
|
|
177
|
+
|
|
178
|
+
if (existingBuildJobStep.length === 0 || needs === 'none') {
|
|
179
|
+
// No existing build step found or chosen, offer all job steps in prompt
|
|
180
|
+
const choices = Object.keys(workflowJS.jobs);
|
|
181
|
+
choices.push(new inquirer.Separator() as any);
|
|
182
|
+
choices.push('none');
|
|
183
|
+
|
|
184
|
+
({ needs } = await inquirer.prompt([
|
|
185
|
+
{
|
|
186
|
+
type: 'list',
|
|
187
|
+
prefix: 'ā',
|
|
188
|
+
message: cli.messages.devinit.ciMultipleJobChoices(),
|
|
189
|
+
name: 'needs',
|
|
190
|
+
choices,
|
|
191
|
+
default: choices.find(
|
|
192
|
+
j => typeof j === 'string' && j.includes('docker')
|
|
193
|
+
),
|
|
194
|
+
},
|
|
195
|
+
]));
|
|
196
|
+
if (needs === 'none') needs = undefined;
|
|
197
|
+
cli.log.raw('');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Does a series of checks and prompts to determine the correct image-uri
|
|
201
|
+
// for the app container build
|
|
202
|
+
await addAppImageUri();
|
|
203
|
+
|
|
204
|
+
const newJob: GitHubActionPushBlockJob = {
|
|
205
|
+
name: 'Deploy container image to Contensis',
|
|
206
|
+
'runs-on': 'ubuntu-latest',
|
|
207
|
+
needs,
|
|
208
|
+
steps: [addGitHubActionJobStep],
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Add the new "job" to the Yaml Document
|
|
114
212
|
workflowDoc.addIn(['jobs'], {
|
|
115
213
|
key: 'deploy',
|
|
116
|
-
value:
|
|
117
|
-
name: 'Push image to Contensis',
|
|
118
|
-
'runs-on': 'ubuntu-latest',
|
|
119
|
-
steps: [addGitHubActionJobStep],
|
|
120
|
-
},
|
|
214
|
+
value: newJob,
|
|
121
215
|
});
|
|
122
216
|
}
|
|
123
217
|
|
|
124
218
|
// Workflow validation provided by @action-validator/core package
|
|
125
219
|
const workflowIsValid = validateWorkflowYaml(workflowDoc.toString());
|
|
126
220
|
|
|
221
|
+
// We could expand validation to check for having a build step to wait for
|
|
222
|
+
// or if a valid image-uri attribute is set
|
|
127
223
|
if (workflowIsValid === true) {
|
|
224
|
+
cli.log.success(`GitHub workflow YAML is valid`);
|
|
128
225
|
cli.log.debug(
|
|
129
226
|
`New file content to write to ${git.ciFilePath}\n\n${workflowDoc}`
|
|
130
227
|
);
|
|
@@ -151,3 +248,89 @@ export const mapCIWorkflowContent = (
|
|
|
151
248
|
};
|
|
152
249
|
}
|
|
153
250
|
};
|
|
251
|
+
|
|
252
|
+
const determineAppImageUri = async (
|
|
253
|
+
cli: ContensisDev,
|
|
254
|
+
vars: [string, string][]
|
|
255
|
+
) => {
|
|
256
|
+
// Determine container image-uri via variables and/or prompts
|
|
257
|
+
|
|
258
|
+
// Find vars including the word "image"
|
|
259
|
+
const imageVars = vars.filter(([varname, value]) =>
|
|
260
|
+
varname.toLowerCase().includes('image')
|
|
261
|
+
);
|
|
262
|
+
// Find vars named "image" that include the word "app"
|
|
263
|
+
const appImageVars = imageVars.filter(
|
|
264
|
+
([varname, value]) =>
|
|
265
|
+
varname.toLowerCase().includes('app_') ||
|
|
266
|
+
varname.toLowerCase().includes('build_') ||
|
|
267
|
+
value?.toLowerCase().includes('/app')
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const appImageUriGuess = appImageVars?.[0];
|
|
271
|
+
|
|
272
|
+
let appImageUri: string | undefined;
|
|
273
|
+
let appImageVar: string | undefined;
|
|
274
|
+
|
|
275
|
+
if (appImageUriGuess) {
|
|
276
|
+
cli.log.success(
|
|
277
|
+
`Found variable ${cli.log.standardText(
|
|
278
|
+
appImageUriGuess[0]
|
|
279
|
+
)} we'll use for pulling the block image from: ${cli.log.infoText(
|
|
280
|
+
appImageUriGuess[1]
|
|
281
|
+
)}`
|
|
282
|
+
);
|
|
283
|
+
appImageVar = appImageUriGuess[0];
|
|
284
|
+
} else {
|
|
285
|
+
// Could not find a suitable var to use for block image-uri
|
|
286
|
+
// prompt for an app image uri
|
|
287
|
+
const choices = vars.map(v => v[0]);
|
|
288
|
+
const enterOwnMsg = 'enter my own / use default';
|
|
289
|
+
const defaultUri =
|
|
290
|
+
'ghcr.io/${{ github.repository }}/${{ github.ref_name }}/app:build-${{ github.run_number }}';
|
|
291
|
+
choices.push(new inquirer.Separator() as any);
|
|
292
|
+
choices.push(enterOwnMsg);
|
|
293
|
+
choices.push(defaultUri);
|
|
294
|
+
|
|
295
|
+
({ appImageVar, appImageUri } = await inquirer.prompt([
|
|
296
|
+
// First question determines if an existing env variable
|
|
297
|
+
// already containes the tagged app image uri
|
|
298
|
+
{
|
|
299
|
+
type: 'list',
|
|
300
|
+
prefix: 'š³',
|
|
301
|
+
message: cli.messages.devinit.ciMultipleAppImageVarChoices(),
|
|
302
|
+
name: 'appImageVar',
|
|
303
|
+
choices,
|
|
304
|
+
default: choices.find(
|
|
305
|
+
v => typeof v === 'string' && v.toLowerCase().includes('image')
|
|
306
|
+
),
|
|
307
|
+
},
|
|
308
|
+
// Subsequent prompt allows input of an image-uri if needed
|
|
309
|
+
{
|
|
310
|
+
type: 'input',
|
|
311
|
+
when(answers) {
|
|
312
|
+
return [enterOwnMsg, defaultUri].includes(answers.appImageVar);
|
|
313
|
+
},
|
|
314
|
+
prefix: `\n \nš`,
|
|
315
|
+
message: cli.messages.devinit.ciEnterOwnAppImagePrompt(),
|
|
316
|
+
name: 'appImageUri',
|
|
317
|
+
default: defaultUri,
|
|
318
|
+
},
|
|
319
|
+
]));
|
|
320
|
+
cli.log.raw('');
|
|
321
|
+
|
|
322
|
+
// this indicates a uri has been added and we will add a new var
|
|
323
|
+
// to the workflow to encourage users to update the docker tag part
|
|
324
|
+
// of their build workflow to use the same var as the push-block job/step
|
|
325
|
+
if ([enterOwnMsg, defaultUri].includes(appImageVar || ''))
|
|
326
|
+
appImageVar = undefined;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (appImageVar) appImageUri = `\${{ env.${appImageVar} }}`;
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
addVar: !appImageVar,
|
|
333
|
+
uri: appImageUri,
|
|
334
|
+
var: appImageVar || 'BUILD_IMAGE',
|
|
335
|
+
};
|
|
336
|
+
};
|
|
@@ -2,4 +2,25 @@ export type EnvContentsToAdd = {
|
|
|
2
2
|
ALIAS: string;
|
|
3
3
|
PROJECT: string;
|
|
4
4
|
ACCESS_TOKEN?: string;
|
|
5
|
-
}
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type GitHubActionPushBlockJobStep = {
|
|
8
|
+
name: string;
|
|
9
|
+
id: 'push-block';
|
|
10
|
+
uses: string;
|
|
11
|
+
with: {
|
|
12
|
+
'block-id': string;
|
|
13
|
+
alias: string;
|
|
14
|
+
'project-id': string;
|
|
15
|
+
'client-id': string;
|
|
16
|
+
'shared-secret': string;
|
|
17
|
+
'image-uri'?: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type GitHubActionPushBlockJob = {
|
|
22
|
+
name: string;
|
|
23
|
+
'runs-on': string;
|
|
24
|
+
needs?: string;
|
|
25
|
+
steps: GitHubActionPushBlockJobStep[];
|
|
26
|
+
};
|
|
@@ -21,7 +21,7 @@ import { mergeDotEnvFileContents } from '~/util/dotenv';
|
|
|
21
21
|
import { findByIdOrName } from '~/util/find';
|
|
22
22
|
import { GitHelper } from '~/util/git';
|
|
23
23
|
import { jsonFormatter } from '~/util/json.formatter';
|
|
24
|
-
import { normaliseLineEndings } from '~/util/os';
|
|
24
|
+
import { normaliseLineEndings, winSlash } from '~/util/os';
|
|
25
25
|
import { stringifyYaml } from '~/util/yaml';
|
|
26
26
|
|
|
27
27
|
class ContensisDev extends ContensisRole {
|
|
@@ -103,6 +103,7 @@ class ContensisDev extends ContensisRole {
|
|
|
103
103
|
({ ciFileName } = await inquirer.prompt([
|
|
104
104
|
{
|
|
105
105
|
type: 'list',
|
|
106
|
+
prefix: 'ā§°',
|
|
106
107
|
message: messages.devinit.ciMultipleChoices(),
|
|
107
108
|
name: 'ciFileName',
|
|
108
109
|
choices: workflowFiles,
|
|
@@ -116,7 +117,7 @@ class ContensisDev extends ContensisRole {
|
|
|
116
117
|
log.raw(log.infoText(messages.devinit.ciDetails(ciFileName)));
|
|
117
118
|
|
|
118
119
|
// Look at the workflow file content and make updates
|
|
119
|
-
const mappedWorkflow = mapCIWorkflowContent(this, git);
|
|
120
|
+
const mappedWorkflow = await mapCIWorkflowContent(this, git);
|
|
120
121
|
|
|
121
122
|
log.help(messages.devinit.ciIntro(git));
|
|
122
123
|
|
|
@@ -138,6 +139,7 @@ class ContensisDev extends ContensisRole {
|
|
|
138
139
|
const { accessToken }: { accessToken: string } = await inquirer.prompt([
|
|
139
140
|
{
|
|
140
141
|
type: 'input',
|
|
142
|
+
prefix: 'š”ļø',
|
|
141
143
|
message: messages.devinit.accessTokenPrompt(),
|
|
142
144
|
name: 'accessToken',
|
|
143
145
|
},
|
|
@@ -219,34 +221,41 @@ class ContensisDev extends ContensisRole {
|
|
|
219
221
|
|
|
220
222
|
if (dryRun) {
|
|
221
223
|
if (envDiff) {
|
|
222
|
-
log.info(`
|
|
224
|
+
log.info(`Updating .env file ${winSlash(envFilePath)}:\n${envDiff}`);
|
|
223
225
|
log.raw('');
|
|
224
226
|
}
|
|
225
227
|
checkpoint('skip .env file update (dry-run)');
|
|
226
228
|
} else {
|
|
227
|
-
if (envDiff) log.info(`updating .env file ${envFilePath}`);
|
|
229
|
+
if (envDiff) log.info(`updating .env file ${winSlash(envFilePath)}`);
|
|
228
230
|
writeFile(envFilePath, envFileLines.join('\n'));
|
|
229
231
|
checkpoint('.env file updated');
|
|
230
232
|
log.success(messages.devinit.writeEnvFile());
|
|
231
233
|
// log.help(messages.devinit.useEnvFileTip());
|
|
232
234
|
}
|
|
233
235
|
|
|
234
|
-
// Update CI file -- different for GH/GL
|
|
236
|
+
// Update CI file -- different for GH/GL
|
|
237
|
+
if (mappedWorkflow?.diff) {
|
|
238
|
+
log.info(
|
|
239
|
+
`Updating ${winSlash(ciFileName)} file:\n${mappedWorkflow.diff}`
|
|
240
|
+
);
|
|
241
|
+
log.raw('');
|
|
242
|
+
}
|
|
235
243
|
if (dryRun) {
|
|
236
|
-
if (mappedWorkflow?.diff) {
|
|
237
|
-
log.info(`updating${ciFileName} file: ${mappedWorkflow.diff}`);
|
|
238
|
-
log.raw('');
|
|
239
|
-
}
|
|
240
244
|
checkpoint('skip CI file update (dry-run)');
|
|
241
245
|
//log.object(ciFileLines);
|
|
242
246
|
} else {
|
|
243
|
-
if (mappedWorkflow?.
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
if (mappedWorkflow?.newWorkflow) {
|
|
248
|
+
if (mappedWorkflow?.diff) {
|
|
249
|
+
writeFile(git.ciFilePath, mappedWorkflow.newWorkflow);
|
|
250
|
+
log.success(messages.devinit.writeCiFile(`./${ciFileName}`));
|
|
251
|
+
log.info(
|
|
252
|
+
messages.devinit.ciBlockTip(blockId, currentEnv, currentProject)
|
|
253
|
+
);
|
|
254
|
+
} else {
|
|
255
|
+
log.info(messages.devinit.ciFileNoChanges(`./${ciFileName}`));
|
|
256
|
+
}
|
|
257
|
+
checkpoint('CI file updated');
|
|
258
|
+
}
|
|
250
259
|
}
|
|
251
260
|
|
|
252
261
|
// Echo Deployment API key to console, ask user to add secrets to repo
|