@docupace/pipeline 1.0.92 โ 1.0.94
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 +1 -1
- package/src/next/config.js +9 -0
- package/src/next/deploy.js +172 -19
package/package.json
CHANGED
package/src/next/config.js
CHANGED
|
@@ -47,6 +47,15 @@ export const appInfo = {
|
|
|
47
47
|
'graphqlServer.standardConfigRemoteBranch',
|
|
48
48
|
],
|
|
49
49
|
},
|
|
50
|
+
'compliance-edge-graphql-server': {
|
|
51
|
+
repositoryName: 'compliance-edge-graphql-server',
|
|
52
|
+
imageName: 'compliance-edge-graphql-server',
|
|
53
|
+
deployAttributes: [
|
|
54
|
+
'image.tag',
|
|
55
|
+
'graphqlServer.siteConfigRemoteBranch',
|
|
56
|
+
'graphqlServer.standardConfigRemoteBranch',
|
|
57
|
+
],
|
|
58
|
+
},
|
|
50
59
|
cc: {
|
|
51
60
|
repositoryName: 'docupace-ui-main',
|
|
52
61
|
imageName: 'cc-ui-app',
|
package/src/next/deploy.js
CHANGED
|
@@ -70,7 +70,7 @@ async function updateAndCommitConnectVersion(
|
|
|
70
70
|
|
|
71
71
|
console.log('๐งน Cleaning up...');
|
|
72
72
|
await $`rm -rf ${connectDeployPath}`;
|
|
73
|
-
console.log('
|
|
73
|
+
console.log('Cleanup complete.');
|
|
74
74
|
} catch (error) {
|
|
75
75
|
console.error('Error updating Connect version:', error);
|
|
76
76
|
throw error;
|
|
@@ -183,13 +183,19 @@ function getAppTypesFromRepo(env, site) {
|
|
|
183
183
|
export async function readDeployConfig(application, env, site, name) {
|
|
184
184
|
const { deployConfigFilePath } = getConfigPath(application, env, site, name);
|
|
185
185
|
|
|
186
|
-
let deployConfig;
|
|
186
|
+
let deployConfig = null;
|
|
187
187
|
try {
|
|
188
188
|
deployConfig = yaml.load(fs.readFileSync(deployConfigFilePath, 'utf8'));
|
|
189
189
|
console.log(`YAML file loaded from: ${deployConfigFilePath}`);
|
|
190
190
|
} catch (error) {
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
if (error.code === 'ENOENT') {
|
|
192
|
+
console.log(
|
|
193
|
+
`โ ๏ธ No version found for ${application} in ${env}/${site} (${deployConfigFilePath} does not exist), skipping`,
|
|
194
|
+
);
|
|
195
|
+
} else {
|
|
196
|
+
console.error(`Error reading YAML file: ${error.message}`);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
return { deployConfig, deployConfigFilePath };
|
|
@@ -240,7 +246,7 @@ export async function pushDeployConfig(repoPath, commitMessage) {
|
|
|
240
246
|
await $`cd ${repoPath} && git status --porcelain`
|
|
241
247
|
).stdout.trim();
|
|
242
248
|
if (!status) {
|
|
243
|
-
console.log('
|
|
249
|
+
console.log('No changes to commit. Exiting.');
|
|
244
250
|
await $`rm -rf ${repoPath}`;
|
|
245
251
|
console.log('๐งน Cleanup complete.');
|
|
246
252
|
return;
|
|
@@ -265,17 +271,17 @@ export async function pushDeployConfig(repoPath, commitMessage) {
|
|
|
265
271
|
await $`cd ${repoPath} && git add .`;
|
|
266
272
|
await $`cd ${repoPath} && git commit -m ${commitMessage}`;
|
|
267
273
|
await $`cd ${repoPath} && git push`;
|
|
268
|
-
console.log('
|
|
274
|
+
console.log('Changes pushed to the remote repository.');
|
|
269
275
|
|
|
270
276
|
console.log('๐งน Cleaning up...');
|
|
271
277
|
await $`rm -rf ${repoPath}`;
|
|
272
|
-
console.log('
|
|
278
|
+
console.log('Cleanup complete.');
|
|
273
279
|
}
|
|
274
280
|
|
|
275
281
|
function writeDeployConfig(deployConfigFilePath, deployConfig) {
|
|
276
282
|
try {
|
|
277
283
|
fs.writeFileSync(deployConfigFilePath, yaml.dump(deployConfig), 'utf8');
|
|
278
|
-
console.log(
|
|
284
|
+
console.log(`Updated YAML file saved at: ${deployConfigFilePath}`);
|
|
279
285
|
} catch (error) {
|
|
280
286
|
console.error(`โ Error writing YAML file: ${error.message}`);
|
|
281
287
|
process.exit(1);
|
|
@@ -506,6 +512,10 @@ export async function deployApp(
|
|
|
506
512
|
'values',
|
|
507
513
|
);
|
|
508
514
|
|
|
515
|
+
if (!fromDeployConfig) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
|
|
509
519
|
if (fromEnv !== toEnv) {
|
|
510
520
|
await copy2(
|
|
511
521
|
appDetails.repositoryName,
|
|
@@ -522,6 +532,10 @@ export async function deployApp(
|
|
|
522
532
|
deployConfigFilePath: toDeployConfigFilePath,
|
|
523
533
|
} = await readDeployConfig(application, toEnv, toSite, 'values');
|
|
524
534
|
|
|
535
|
+
if (!toDeployConfig) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
|
|
525
539
|
// Update target configuration using attributes specified in appInfo
|
|
526
540
|
for (const attribute of appDetails.deployAttributes) {
|
|
527
541
|
const sourceValue = lodash.get(fromDeployConfig, attribute);
|
|
@@ -582,23 +596,40 @@ async function updateAutoDeployVersion(
|
|
|
582
596
|
oldVersion,
|
|
583
597
|
newVersion,
|
|
584
598
|
) {
|
|
599
|
+
console.log(
|
|
600
|
+
`Info: Checking auto-deploy version update for ${toEnv}/${toSite}: ${oldVersion} โ ${newVersion}`,
|
|
601
|
+
);
|
|
602
|
+
|
|
585
603
|
const oldMajorMinor = extractMajorMinor(oldVersion);
|
|
586
604
|
const newMajorMinor = extractMajorMinor(newVersion);
|
|
587
605
|
|
|
588
|
-
if (!oldMajorMinor || !newMajorMinor
|
|
606
|
+
if (!oldMajorMinor || !newMajorMinor) {
|
|
607
|
+
console.log(
|
|
608
|
+
`Info: Could not parse major.minor from versions (old: ${oldVersion}, new: ${newVersion}), skipping auto-deploy update`,
|
|
609
|
+
);
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (oldMajorMinor === newMajorMinor) {
|
|
614
|
+
console.log(
|
|
615
|
+
`Info: Major.minor version unchanged (${newMajorMinor}), skipping auto-deploy update`,
|
|
616
|
+
);
|
|
589
617
|
return false;
|
|
590
618
|
}
|
|
591
619
|
|
|
592
620
|
if (newVersion.toLowerCase().includes('alpha') || newVersion.includes('-')) {
|
|
621
|
+
console.log(
|
|
622
|
+
`Info: New version (${newVersion}) is a pre-release, skipping auto-deploy update`,
|
|
623
|
+
);
|
|
593
624
|
return false;
|
|
594
625
|
}
|
|
595
626
|
|
|
596
|
-
const { repoPath } = getRepoLocalPath(
|
|
597
|
-
const autoDeployConfigPath = path.join(
|
|
627
|
+
const { repoPath: devRepoPath } = getRepoLocalPath('dev');
|
|
628
|
+
const autoDeployConfigPath = path.join(devRepoPath, autoDeployConfigName);
|
|
598
629
|
|
|
599
630
|
if (!fs.existsSync(autoDeployConfigPath)) {
|
|
600
631
|
console.log(
|
|
601
|
-
`Info: ${autoDeployConfigName} not found in
|
|
632
|
+
`Info: ${autoDeployConfigName} not found in gitops-dev, skipping auto-deploy update`,
|
|
602
633
|
);
|
|
603
634
|
return false;
|
|
604
635
|
}
|
|
@@ -639,6 +670,112 @@ async function updateAutoDeployVersion(
|
|
|
639
670
|
return true;
|
|
640
671
|
}
|
|
641
672
|
|
|
673
|
+
/**
|
|
674
|
+
* Validate that all deployed components have internally consistent versions and
|
|
675
|
+
* share the same major.minor across the board before a git commit.
|
|
676
|
+
*
|
|
677
|
+
* Per-app checks:
|
|
678
|
+
* - image.tag major.minor == app.yaml revision major.minor
|
|
679
|
+
* (handles both plain "v1.21.3" and prefixed "enterprise-ui-app@1.21.6" revisions)
|
|
680
|
+
* - graphql-server additionally: image.tag major.minor == standardConfigRemoteBranch major.minor
|
|
681
|
+
*
|
|
682
|
+
* Cross-app check:
|
|
683
|
+
* - all deployed components must share the same major.minor
|
|
684
|
+
*
|
|
685
|
+
* @param {string} env
|
|
686
|
+
* @param {string} site
|
|
687
|
+
* @param {object} deployedApps - appInfoLocal map of { appName: appDetails }
|
|
688
|
+
* @throws {Error} if any version mismatch is detected
|
|
689
|
+
*/
|
|
690
|
+
async function validateDeployVersionConsistency(env, site, deployedApps) {
|
|
691
|
+
console.log(
|
|
692
|
+
`Validating version consistency for all components in ${env}/${site}...`,
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
const mismatches = [];
|
|
696
|
+
const appVersions = [];
|
|
697
|
+
|
|
698
|
+
for (const [application] of Object.entries(deployedApps)) {
|
|
699
|
+
const { deployConfigFilePath: valuesPath } = getConfigPath(
|
|
700
|
+
application,
|
|
701
|
+
env,
|
|
702
|
+
site,
|
|
703
|
+
'values',
|
|
704
|
+
);
|
|
705
|
+
const { deployConfigFilePath: appPath } = getConfigPath(
|
|
706
|
+
application,
|
|
707
|
+
env,
|
|
708
|
+
site,
|
|
709
|
+
'app',
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
if (!fs.existsSync(valuesPath) || !fs.existsSync(appPath)) {
|
|
713
|
+
console.log(
|
|
714
|
+
`โ ๏ธ Skipping version consistency check for ${application}: config files missing in ${env}/${site}`,
|
|
715
|
+
);
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const valuesConfig = yaml.load(fs.readFileSync(valuesPath, 'utf8'));
|
|
720
|
+
const appConfig = yaml.load(fs.readFileSync(appPath, 'utf8'));
|
|
721
|
+
|
|
722
|
+
const imageTag = valuesConfig?.image?.tag;
|
|
723
|
+
const revision = appConfig?.revision;
|
|
724
|
+
|
|
725
|
+
// Extract bare version from revision (e.g. "enterprise-ui-app@1.21.6" โ "1.21.6")
|
|
726
|
+
const revisionVersion = revision?.includes('@')
|
|
727
|
+
? revision.split('@')[1]
|
|
728
|
+
: revision;
|
|
729
|
+
|
|
730
|
+
const imageMajorMinor = extractMajorMinor(imageTag);
|
|
731
|
+
const revisionMajorMinor = extractMajorMinor(revisionVersion);
|
|
732
|
+
|
|
733
|
+
if (imageMajorMinor && revisionMajorMinor) {
|
|
734
|
+
if (imageMajorMinor !== revisionMajorMinor) {
|
|
735
|
+
mismatches.push(
|
|
736
|
+
`${application}: image.tag (${imageTag}) does not match app.yaml revision (${revision}) on major.minor`,
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (application === 'graphql-server') {
|
|
742
|
+
const standardConfigBranch =
|
|
743
|
+
valuesConfig?.graphqlServer?.standardConfigRemoteBranch;
|
|
744
|
+
const standardConfigMajorMinor = extractMajorMinor(standardConfigBranch);
|
|
745
|
+
if (imageMajorMinor && standardConfigMajorMinor) {
|
|
746
|
+
if (imageMajorMinor !== standardConfigMajorMinor) {
|
|
747
|
+
mismatches.push(
|
|
748
|
+
`graphql-server: image.tag (${imageTag}) does not match graphqlServer.standardConfigRemoteBranch (${standardConfigBranch}) on major.minor`,
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
if (imageMajorMinor) {
|
|
755
|
+
appVersions.push({ application, imageTag, majorMinor: imageMajorMinor });
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const uniqueMajorMinors = [...new Set(appVersions.map((a) => a.majorMinor))];
|
|
760
|
+
if (uniqueMajorMinors.length > 1) {
|
|
761
|
+
const versionList = appVersions
|
|
762
|
+
.map((a) => `${a.application} (${a.imageTag})`)
|
|
763
|
+
.join(', ');
|
|
764
|
+
mismatches.push(
|
|
765
|
+
`cross-app: components are on different major.minor versions: ${versionList}`,
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
if (mismatches.length > 0) {
|
|
770
|
+
throw new Error(
|
|
771
|
+
`โ Version consistency validation failed for ${env}/${site}:\n${mismatches.map((m) => ` - ${m}`).join('\n')}`,
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
console.log(
|
|
776
|
+
`โ
Version consistency validated for ${env}/${site}: all ${appVersions.length} component(s) aligned on ${uniqueMajorMinors[0] ?? 'n/a'}`,
|
|
777
|
+
);
|
|
778
|
+
}
|
|
642
779
|
export async function deployFromSite(
|
|
643
780
|
fromEnv,
|
|
644
781
|
fromSite,
|
|
@@ -789,9 +926,14 @@ export async function deployFromSite(
|
|
|
789
926
|
const toRepoPath =
|
|
790
927
|
toEnv === fromEnv ? fromRepoPath : await cloneEnvRepository(toEnv);
|
|
791
928
|
|
|
929
|
+
// Ensure gitops-dev is cloned for auto-deploy version checking
|
|
930
|
+
if (fromEnv !== 'dev' && toEnv !== 'dev') {
|
|
931
|
+
await cloneEnvRepository('dev');
|
|
932
|
+
}
|
|
933
|
+
|
|
792
934
|
// Initialize a flag to track changes
|
|
793
935
|
let changesMade = false;
|
|
794
|
-
const applications =
|
|
936
|
+
const applications = getAppTypesFromRepo(fromEnv, fromSite);
|
|
795
937
|
console.log(applications);
|
|
796
938
|
// Iterate over applications in appInfo
|
|
797
939
|
|
|
@@ -844,8 +986,10 @@ export async function deployFromSite(
|
|
|
844
986
|
toSite,
|
|
845
987
|
'values',
|
|
846
988
|
);
|
|
847
|
-
|
|
848
|
-
|
|
989
|
+
if (fromConfig && toConfig) {
|
|
990
|
+
newVersion = fromConfig.image?.tag;
|
|
991
|
+
oldVersion = toConfig.image?.tag;
|
|
992
|
+
}
|
|
849
993
|
}
|
|
850
994
|
|
|
851
995
|
let cm = await deployApp(
|
|
@@ -861,7 +1005,15 @@ export async function deployFromSite(
|
|
|
861
1005
|
}
|
|
862
1006
|
}
|
|
863
1007
|
|
|
864
|
-
if (oldVersion
|
|
1008
|
+
if (!oldVersion || !newVersion) {
|
|
1009
|
+
console.log(
|
|
1010
|
+
`Info: Could not determine versions for auto-deploy check (old: ${oldVersion}, new: ${newVersion})`,
|
|
1011
|
+
);
|
|
1012
|
+
} else if (oldVersion === newVersion) {
|
|
1013
|
+
console.log(
|
|
1014
|
+
`Info: Version unchanged (${newVersion}), skipping auto-deploy update`,
|
|
1015
|
+
);
|
|
1016
|
+
} else {
|
|
865
1017
|
const autoDeployUpdated = await updateAutoDeployVersion(
|
|
866
1018
|
fromEnv,
|
|
867
1019
|
toEnv,
|
|
@@ -871,7 +1023,7 @@ export async function deployFromSite(
|
|
|
871
1023
|
);
|
|
872
1024
|
if (autoDeployUpdated) {
|
|
873
1025
|
console.log(
|
|
874
|
-
`Info: auto-deploy.yaml updated for ${toEnv}/${toSite}
|
|
1026
|
+
`Info: auto-deploy.yaml updated for ${toEnv}/${toSite}: ${oldVersion} โ ${newVersion}`,
|
|
875
1027
|
);
|
|
876
1028
|
changesMade = true;
|
|
877
1029
|
}
|
|
@@ -879,12 +1031,13 @@ export async function deployFromSite(
|
|
|
879
1031
|
|
|
880
1032
|
// Push all changes if any updates were made
|
|
881
1033
|
if (changesMade) {
|
|
1034
|
+
await validateDeployVersionConsistency(toEnv, toSite, appInfoLocal);
|
|
882
1035
|
await pushDeployConfig(
|
|
883
1036
|
toRepoPath,
|
|
884
1037
|
`Updated deployment configurations from ${fromEnv}/${fromSite} to ${toEnv}/${toSite}`,
|
|
885
1038
|
);
|
|
886
|
-
console.log('
|
|
1039
|
+
console.log('All configurations updated and pushed successfully.');
|
|
887
1040
|
} else {
|
|
888
|
-
console.log('
|
|
1041
|
+
console.log('No changes detected. Nothing to push.');
|
|
889
1042
|
}
|
|
890
1043
|
}
|