@docupace/pipeline 1.0.5-alpha.1 → 1.0.5-alpha.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.5-alpha.1",
3
+ "version": "1.0.5-alpha.12",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -15,6 +15,7 @@
15
15
  "license": "ISC",
16
16
  "dependencies": {
17
17
  "@changesets/cli": "^2.27.10",
18
+ "axios": "^1.7.9",
18
19
  "commander": "^12.1.0",
19
20
  "dotenv": "^16.4.7",
20
21
  "js-yaml": "^4.1.0",
@@ -31,5 +32,9 @@
31
32
  "eslint-plugin-prettier": "^5.2.1",
32
33
  "globals": "^15.14.0",
33
34
  "prettier": "^3.4.2"
35
+ },
36
+ "scripts": {
37
+ "test-deploy-core": "dp-next-cli deploy-core dev template",
38
+ "test-deploy-from-site": "dp-next-cli deploy-from-site --from-env dev --to-env dev --from-site financialdev --to-site template"
34
39
  }
35
40
  }
@@ -0,0 +1,59 @@
1
+ import groovy.json.JsonSlurper
2
+
3
+ import hudson.model.*;
4
+
5
+ def build = Thread.currentThread().executable
6
+ def params = build.getEnvironment(listener)
7
+
8
+ def site = params.get('site')
9
+ def server = "jboss7"
10
+ def environment = params.get('environment')
11
+
12
+ def buildFile=new File("D:\\Docupace\\CustomFolders\\" + environment + "\\" + site + "\\" + server + "\\buildApp.properties")
13
+
14
+ List<String> jboss7controllerResult = []
15
+
16
+ def controllersReport = new File("D:\\Docupace\\controllers_report.json")
17
+ def inputJSON = new JsonSlurper().parseText(controllersReport.text)
18
+ def props = new Properties()
19
+ buildFile.withInputStream { stream -> props.load(stream) }
20
+ def webRootContext = props["web.root.context"]
21
+ if (webRootContext == null || webRootContext =="core") webRootContext = props["docupace.config.client.id"].toLowerCase()
22
+
23
+ webRootContext = webRootContext.replaceFirst('_sso','')
24
+ def map = inputJSON.'content'
25
+
26
+ def Boolean enabled
27
+
28
+ map.each {k,v ->
29
+ v.each{vk, vv -> if (vk == webRootContext ) {
30
+ enabled = false
31
+ if(vv.deploymentsProperty.size()>0) enabled = vv.deploymentsProperty[0].isEnabled
32
+ if (enabled) jboss7controllerResult.push(k)
33
+ else jboss7controllerResult << k
34
+ }
35
+ }
36
+ }
37
+
38
+ if (jboss7controllerResult.size()>0) {
39
+ if (environment == 'preprod') {
40
+ jboss7controllerResult.remove("dev-corjbdc10.corp.docupace.com")
41
+ jboss7controllerResult.remove("usdoc-s-jbdc1.corp.docupace.com")
42
+ }
43
+ if (environment == 'dev') {
44
+ jboss7controllerResult.remove("qa-corjbdc10.corp.docupace.com")
45
+ jboss7controllerResult.remove("qa-corjbdc20.corp.docupace.com")
46
+ jboss7controllerResult.remove("usdoc-s-jbdc2.corp.docupace.com")
47
+ }
48
+ }
49
+
50
+ println jboss7controllerResult[0]
51
+
52
+ env.jboss7controller = jboss7controllerResult[0]
53
+
54
+ def serverGroup = inputJSON.'content'."${jboss7controller}"."${webRootContext}".'serverGroup'
55
+
56
+ println serverGroup
57
+
58
+ params.put("serverGroup", serverGroup)
59
+
package/src/next/cli.js CHANGED
@@ -4,7 +4,7 @@ import { Command } from 'commander';
4
4
  import { pull } from './pull.js';
5
5
  import { sonar } from './sonar.js';
6
6
  import { publish } from './publish.js';
7
- import {deploy, deployFromSite} from './deploy.js';
7
+ import { deployFromSite } from './deploy.js';
8
8
  import { deployTemplate } from './deploy.js';
9
9
  import { copy } from './copy.js';
10
10
  import dotenv from 'dotenv';
@@ -15,6 +15,8 @@ const program = new Command();
15
15
 
16
16
  // GIT SHA computation
17
17
  import { $ } from 'zx';
18
+ import { deployCore } from './jenkins.js';
19
+ import { runPipeline } from './pipline.js';
18
20
  const GIT_SHA = (await $`git log --pretty=format:'%h' -n 1`).stdout.trim();
19
21
 
20
22
  program
@@ -57,6 +59,26 @@ program
57
59
  await deployTemplate(site);
58
60
  });
59
61
 
62
+ program
63
+ .command('deploy-core <env> <site>')
64
+ .description('Deploy Core')
65
+ .option('-l, --liquibase <liquibase>', 'Application name', 'true')
66
+ .action(async (env, site, liquibase) => {
67
+ await deployCore(env, site, liquibase);
68
+ });
69
+
70
+ program
71
+ .command('deploy-core-pipeline <env> <site>')
72
+ .description('Deploy Core')
73
+ .option('-l, --liquibase <liquibase>', 'Application name', 'true')
74
+ .action(async (env, site, liquibase) => {
75
+ await runPipeline('site-deploy', 'deploy-core', {
76
+ ENV: env,
77
+ SITE: site,
78
+ LIQUIBASE: liquibase,
79
+ });
80
+ });
81
+
60
82
  program
61
83
  .command('copy')
62
84
  .description('Copy a Docker image between registries')
@@ -35,7 +35,14 @@ export const getBitbucketInfo = () => {
35
35
  return {
36
36
  username: process.env.BITBUCKET_USERNAME,
37
37
  password: process.env.BITBUCKET_APP_PASSWORD,
38
+ workspace: 'dp-cloud',
38
39
  };
39
40
  };
40
41
 
42
+ export const getRepUrl = (repoName) => {
43
+ const { username, password, workspace } = getBitbucketInfo();
44
+ const repoUrl = `https://${username}:${password}@bitbucket.org/${workspace}/${repoName}.git`;
45
+ return repoUrl;
46
+ }
47
+
41
48
  export const jfRegistryUrl = 'registry.paperout.com';
package/src/next/copy.js CHANGED
@@ -20,7 +20,6 @@ export async function copy(application, fromEnv, toEnv, tag) {
20
20
  );
21
21
 
22
22
  // Login to source registry
23
- await $`export DOCKER_HOST=""`;
24
23
  await $`echo ${envInfo[fromEnv].jfrog.password} | docker login --username ${envInfo[fromEnv].jfrog.username} --password-stdin ${jfRegistryUrl}`;
25
24
  await $`docker pull ${fromFullImageName}`;
26
25
  await $`docker tag ${fromFullImageName} ${toFullImageName}`;
@@ -3,11 +3,9 @@ import path from 'path';
3
3
  import yaml from 'js-yaml';
4
4
  import { $ } from 'zx';
5
5
  import lodash from 'lodash';
6
- import { appInfo, getBitbucketInfo } from './config.js';
6
+ import {appInfo, getBitbucketInfo, getRepUrl} from './config.js';
7
7
  import { copy } from './copy.js';
8
8
 
9
- const GITOPS_BRANCH = 'master';
10
-
11
9
  /**
12
10
  * Clone the repository, read the YAML file, and return the parsed data and file paths.
13
11
  * @param {string} application - The application name.
@@ -23,8 +21,7 @@ function getRepoLocalPath(env) {
23
21
 
24
22
  async function cloneEnvRepository(env) {
25
23
  const { repoPath, repoName } = getRepoLocalPath(env);
26
- const { username, password } = getBitbucketInfo();
27
- const repoUrl = `https://${username}:${password}@bitbucket.org/dp-cloud/${repoName}.git`;
24
+ const repoUrl = getRepUrl(repoName);
28
25
  console.log(`Cloning repository: ${repoName}`);
29
26
  await $`git clone ${repoUrl}`;
30
27
  console.log(`Repository cloned to: ${repoPath}`);
@@ -109,8 +106,8 @@ export async function pushDeployConfig(repoPath, commitMessage) {
109
106
  console.log('📌 Committing changes to the repository...');
110
107
  await $`cd ${repoPath} && git config user.email "gitops@docupace.com"`;
111
108
  await $`cd ${repoPath} && git add .`;
112
- await $`cd ${repoPath} && git commit -m "${commitMessage}"`;
113
- await $`cd ${repoPath} && git push origin ${GITOPS_BRANCH}`;
109
+ await $`cd ${repoPath} && git commit -m ${commitMessage}`;
110
+ await $`cd ${repoPath} && git push`;
114
111
  console.log('✅ Changes pushed to the remote repository.');
115
112
 
116
113
  console.log('🧹 Cleaning up...');
@@ -0,0 +1,87 @@
1
+ import axios from 'axios';
2
+
3
+ const JENKINS_URL = 'http://devops.corp.docupace.com';
4
+ const JOB_NAME = 'auto-deploy-site';
5
+ const USERNAME = process.env.CORE_JENKINS_USERNAME;
6
+ const API_TOKEN = process.env.CORE_JENKINS_API_TOKEN;
7
+
8
+ export async function deployCore(env, site, liquibase) {
9
+ const parameters = {
10
+ environment: env,
11
+ site: site,
12
+ runLiquibase: liquibase,
13
+ };
14
+
15
+ try {
16
+ // Trigger the job
17
+ console.log('Triggering Jenkins job...');
18
+ const buildResponse = await axios.post(
19
+ `${JENKINS_URL}/job/${JOB_NAME}/buildWithParameters`,
20
+ new URLSearchParams(parameters),
21
+ {
22
+ auth: { username: USERNAME, password: API_TOKEN },
23
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
24
+ validateStatus: (status) => status === 201 || status === 302, // Accept 201 and 302 as valid statuses
25
+ },
26
+ );
27
+
28
+ const queueUrl = buildResponse.headers.location;
29
+ console.log(`Job queued at: ${queueUrl}`);
30
+
31
+ // Poll queue for executable URL
32
+ let jobUrl = null;
33
+ while (!jobUrl) {
34
+ const queueResponse = await axios.get(`${queueUrl}api/json`, {
35
+ auth: { username: USERNAME, password: API_TOKEN },
36
+ });
37
+ jobUrl = queueResponse.data.executable?.url || null;
38
+
39
+ if (!jobUrl) {
40
+ console.log('Waiting for job to start...');
41
+ await new Promise((resolve) => setTimeout(resolve, 5000));
42
+ }
43
+ }
44
+
45
+ jobUrl = jobUrl.replaceAll('https', 'http');
46
+
47
+ console.log(`Job started at: ${jobUrl}`);
48
+
49
+ // Stream console output
50
+ const consoleUrl = `${jobUrl}consoleText`;
51
+ let lastSize = 0;
52
+
53
+ console.log('Streaming job output...');
54
+ while (true) {
55
+ const consoleResponse = await axios.get(consoleUrl, {
56
+ auth: { username: USERNAME, password: API_TOKEN },
57
+ responseType: 'text',
58
+ });
59
+
60
+ const consoleText = consoleResponse.data;
61
+ const newOutput = consoleText.slice(lastSize);
62
+ process.stdout.write(newOutput); // Write new output to console
63
+ lastSize = consoleText.length;
64
+
65
+ // Check job status
66
+ const jobResponse = await axios.get(`${jobUrl}api/json`, {
67
+ auth: { username: USERNAME, password: API_TOKEN },
68
+ });
69
+ const result = jobResponse.data.result;
70
+
71
+ if (result) {
72
+ console.log(`\nJob completed with result: ${result}`);
73
+ if (result === 'SUCCESS') {
74
+ process.exit(0);
75
+ } else {
76
+ process.exit(1);
77
+ }
78
+ }
79
+
80
+ // Wait before polling again
81
+ await new Promise((resolve) => setTimeout(resolve, 5000));
82
+ }
83
+ } catch (error) {
84
+ console.error('Error:', error.message);
85
+ process.exit(1);
86
+ }
87
+ }
@@ -0,0 +1,101 @@
1
+ import axios from 'axios';
2
+ import { getBitbucketInfo } from './config.js';
3
+
4
+ const BITBUCKET_BASE_URL = 'https://api.bitbucket.org/2.0';
5
+
6
+ async function triggerPipelineByName(
7
+ repository,
8
+ pipelineName,
9
+ branch,
10
+ variables,
11
+ ) {
12
+ const { username, password, workspace } = getBitbucketInfo();
13
+ const url = `${BITBUCKET_BASE_URL}/repositories/${workspace}/${repository}/pipelines/`;
14
+ const auth = {
15
+ username: username,
16
+ password: password,
17
+ };
18
+
19
+ const payload = {
20
+ target: {
21
+ ref_type: 'branch',
22
+ ref_name: branch,
23
+ selector: {
24
+ type: 'custom',
25
+ pattern: pipelineName,
26
+ },
27
+ },
28
+ variables: Object.entries(variables).map(([key, value]) => ({
29
+ key,
30
+ value,
31
+ secured: false, // Set to true if the variable should be secure
32
+ })),
33
+ };
34
+
35
+ try {
36
+ const response = await axios.post(url, payload, { auth });
37
+ return response.data;
38
+ } catch (error) {
39
+ console.error(
40
+ 'Error triggering custom pipeline:',
41
+ error.response?.data || error.message,
42
+ );
43
+ throw error;
44
+ }
45
+ }
46
+
47
+ async function getPipelineStatus(repository, pipelineUUID) {
48
+ const { username, password, workspace } = getBitbucketInfo();
49
+ const url = `${BITBUCKET_BASE_URL}/repositories/${workspace}/${repository}/pipelines/${pipelineUUID}`;
50
+ const auth = {
51
+ username: username,
52
+ password: password,
53
+ };
54
+
55
+ try {
56
+ const response = await axios.get(url, { auth });
57
+ return response.data.state.name;
58
+ } catch (error) {
59
+ console.error(
60
+ 'Error fetching pipeline status:',
61
+ error.response?.data || error.message,
62
+ );
63
+ throw error;
64
+ }
65
+ }
66
+
67
+ export async function runPipeline(repository, pipelineName, branch, variables) {
68
+ try {
69
+ console.log(
70
+ `Triggering custom pipeline: ${pipelineName} for branch: ${branch}...`,
71
+ );
72
+ const pipeline = await triggerPipelineByName(
73
+ repository,
74
+ pipelineName,
75
+ branch,
76
+ variables,
77
+ );
78
+ const pipelineUUID = pipeline.uuid;
79
+
80
+ console.log(`Pipeline triggered with UUID: ${pipelineUUID}`);
81
+ let status = '';
82
+ do {
83
+ console.log('Checking pipeline status...');
84
+ await new Promise((resolve) => setTimeout(resolve, 10000)); // Wait 10 seconds
85
+ status = await getPipelineStatus(repository, pipelineUUID);
86
+ console.log(`Pipeline status: ${status}`);
87
+ } while (['IN_PROGRESS', 'PENDING', 'RUNNING'].includes(status));
88
+
89
+ console.log(`Pipeline completed with status: ${status}`);
90
+ } catch (error) {
91
+ console.error('Error monitoring pipeline:', error.message);
92
+ }
93
+ }
94
+
95
+ // Example: Trigger and monitor a custom pipeline
96
+ const variables = {
97
+ ENV: 'production',
98
+ DEPLOY_VERSION: 'v1.2.3',
99
+ };
100
+
101
+ runPipeline('site-deploy', 'deploy-to-production', 'main', variables);