@unisphere/nx 3.5.0 → 3.5.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"reorganize-applications-by-distribution-channel.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-0-0/reorganize-applications-by-distribution-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;EAQE;AAEF,OAAO,EACL,IAAI,EAML,MAAM,YAAY,CAAC;AAsmBpB;;GAEG;AACH,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAyE9D"}
1
+ {"version":3,"file":"reorganize-applications-by-distribution-channel.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-0-0/reorganize-applications-by-distribution-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;EAQE;AAEF,OAAO,EACL,IAAI,EAUL,MAAM,YAAY,CAAC;AAqvBpB;;GAEG;AACH,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE9D"}
@@ -11,27 +11,8 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.default = update;
13
13
  const devkit_1 = require("@nx/devkit");
14
- const generators_1 = require("@nx/workspace/generators");
15
- const child_process_1 = require("child_process");
16
14
  const fs_1 = require("fs");
17
15
  const path_1 = require("path");
18
- /**
19
- * Reset Nx cache to ensure fresh project graph
20
- * This is important before moving projects, as Nx caches project locations
21
- */
22
- function resetNxCache() {
23
- try {
24
- devkit_1.logger.info('Resetting Nx cache to ensure fresh project graph...');
25
- (0, child_process_1.execSync)('npx nx reset', {
26
- stdio: 'pipe',
27
- });
28
- devkit_1.logger.info('Nx cache reset successfully');
29
- }
30
- catch (error) {
31
- // Log but don't fail - cache reset is best effort
32
- devkit_1.logger.warn('Could not reset Nx cache (continuing anyway): ' + error);
33
- }
34
- }
35
16
  /**
36
17
  * Get the subdirectory based on distribution channel
37
18
  */
@@ -401,7 +382,142 @@ function updateRootPackageJsonScripts(tree, oldPath, newPath) {
401
382
  }
402
383
  }
403
384
  /**
404
- * Migrate a single application
385
+ * Move all files from one tree path to another.
386
+ * Recursively walks the source directory and copies each file to the destination,
387
+ * then deletes the source. This replaces moveGenerator's moveProjectFiles.
388
+ */
389
+ function moveFilesInTree(tree, fromPath, toPath) {
390
+ let movedCount = 0;
391
+ function walkAndMove(currentPath) {
392
+ const children = tree.children(currentPath);
393
+ for (const child of children) {
394
+ const childPath = `${currentPath}/${child}`;
395
+ if (tree.isFile(childPath)) {
396
+ const content = tree.read(childPath);
397
+ if (content) {
398
+ const relativePath = childPath.substring(fromPath.length + 1);
399
+ const newFilePath = `${toPath}/${relativePath}`;
400
+ tree.write(newFilePath, content);
401
+ movedCount++;
402
+ }
403
+ tree.delete(childPath);
404
+ }
405
+ else {
406
+ walkAndMove(childPath);
407
+ }
408
+ }
409
+ }
410
+ walkAndMove(fromPath);
411
+ // Delete the now-empty source directory
412
+ if (tree.exists(fromPath)) {
413
+ tree.delete(fromPath);
414
+ }
415
+ return movedCount;
416
+ }
417
+ /**
418
+ * Update project.json at the new location after moving files.
419
+ * Updates root, sourceRoot, $schema, and path references in target configurations.
420
+ */
421
+ function updateProjectJsonAfterMove(tree, oldPath, newPath) {
422
+ const projectJsonPath = `${newPath}/project.json`;
423
+ if (!tree.exists(projectJsonPath)) {
424
+ return;
425
+ }
426
+ const projectJson = (0, devkit_1.readJson)(tree, projectJsonPath);
427
+ // Update root
428
+ projectJson.root = newPath;
429
+ // Update sourceRoot
430
+ if (projectJson.sourceRoot) {
431
+ projectJson.sourceRoot = projectJson.sourceRoot.replace(oldPath, newPath);
432
+ }
433
+ // Update $schema relative path
434
+ if (projectJson['$schema']) {
435
+ projectJson['$schema'] = projectJson['$schema'].replace(/^(\.\.\/)+/, (match) => `../${match}`);
436
+ }
437
+ // Update path references in targets
438
+ if (projectJson.targets) {
439
+ const targetStr = JSON.stringify(projectJson.targets);
440
+ // Replace all occurrences of old path with new path in targets
441
+ const updatedTargetStr = targetStr.replace(new RegExp(oldPath.replace(/[/\\]/g, '[\\\\/]'), 'g'), newPath);
442
+ projectJson.targets = JSON.parse(updatedTargetStr);
443
+ }
444
+ (0, devkit_1.writeJson)(tree, projectJsonPath, projectJson);
445
+ }
446
+ /**
447
+ * Register the project at its new location in the Nx workspace.
448
+ * Removes old project configuration and adds new one.
449
+ */
450
+ function updateNxProjectRegistration(tree, oldProjectName, newProjectName, newPath) {
451
+ // Read the project configuration from the new project.json
452
+ const projectJsonPath = `${newPath}/project.json`;
453
+ if (!tree.exists(projectJsonPath)) {
454
+ devkit_1.logger.warn(` Cannot update Nx registration: project.json not found at ${projectJsonPath}`);
455
+ return;
456
+ }
457
+ const projectJson = (0, devkit_1.readJson)(tree, projectJsonPath);
458
+ // Remove old project registration
459
+ try {
460
+ (0, devkit_1.removeProjectConfiguration)(tree, oldProjectName);
461
+ devkit_1.logger.info(` Removed old Nx project registration: ${oldProjectName}`);
462
+ }
463
+ catch (e) {
464
+ // Project may not be registered yet (first run), ignore
465
+ devkit_1.logger.info(` Old Nx project registration not found (ok): ${oldProjectName}`);
466
+ }
467
+ // Build the new project configuration
468
+ const newConfig = {
469
+ ...projectJson,
470
+ name: newProjectName,
471
+ root: newPath,
472
+ };
473
+ // Register at new location
474
+ try {
475
+ (0, devkit_1.updateProjectConfiguration)(tree, newProjectName, newConfig);
476
+ devkit_1.logger.info(` Registered Nx project at new location: ${newProjectName}`);
477
+ }
478
+ catch (e) {
479
+ // If updateProjectConfiguration fails (project doesn't exist yet), write project.json directly
480
+ projectJson.name = newProjectName;
481
+ (0, devkit_1.writeJson)(tree, projectJsonPath, projectJson);
482
+ devkit_1.logger.info(` Updated project.json name to: ${newProjectName}`);
483
+ }
484
+ }
485
+ /**
486
+ * Update cross-project build target references.
487
+ * Scans all projects in the workspace for references to the old project name
488
+ * in their target configurations and updates them.
489
+ */
490
+ function updateCrossProjectReferences(tree, oldProjectName, newProjectName) {
491
+ if (oldProjectName === newProjectName) {
492
+ return; // No rename, no cross-references to update
493
+ }
494
+ const projects = (0, devkit_1.getProjects)(tree);
495
+ let updatedCount = 0;
496
+ for (const [name, config] of projects) {
497
+ if (!config.targets)
498
+ continue;
499
+ let configStr = JSON.stringify(config.targets);
500
+ // Match patterns like "old-project:build" or "old-project:build:production"
501
+ const pattern = new RegExp(`${oldProjectName.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}:`, 'g');
502
+ if (pattern.test(configStr)) {
503
+ configStr = configStr.replace(pattern, `${newProjectName}:`);
504
+ config.targets = JSON.parse(configStr);
505
+ (0, devkit_1.updateProjectConfiguration)(tree, name, config);
506
+ updatedCount++;
507
+ }
508
+ }
509
+ if (updatedCount > 0) {
510
+ devkit_1.logger.info(` Updated build target references in ${updatedCount} project(s)`);
511
+ }
512
+ }
513
+ /**
514
+ * Migrate a single application using manual tree operations.
515
+ *
516
+ * We bypass Nx's moveGenerator because it calls readAndCombineAllProjectConfigurations
517
+ * which uses the native WorkspaceContext (Rust addon) that caches stale file paths
518
+ * from the packages migration. The Rust addon's glob cache cannot be reliably reset
519
+ * from JavaScript. Manual tree operations avoid this entirely since Tree operates
520
+ * on an in-memory overlay on top of the filesystem.
405
521
  */
406
522
  async function migrateApplication(tree, target) {
407
523
  const { application: app, newPath, newNxProjectName } = target;
@@ -415,56 +531,40 @@ async function migrateApplication(tree, target) {
415
531
  devkit_1.logger.warn(` Source project.json not found at ${sourceProjectJson}, skipping`);
416
532
  return;
417
533
  }
418
- // Step 0: Clean node_modules from destination on disk if present.
419
- // npm install may create node_modules/ at the target path (e.g. for workspace
420
- // dependency resolution). tree.delete() only records a virtual deletion and
421
- // doesn't remove on-disk children, so moveGenerator's checkDestination
422
- // (which uses tree.children() -> readdirSync) would see node_modules and
423
- // throw "Path is not empty". We must remove it from the real filesystem.
424
- const destNodeModules = (0, path_1.join)(newPath, 'node_modules');
534
+ // Step 1: Clean node_modules from destination on disk if present.
535
+ const destNodeModules = (0, path_1.join)(tree.root, newPath, 'node_modules');
425
536
  if ((0, fs_1.existsSync)(destNodeModules)) {
426
- devkit_1.logger.info(` Removing leftover node_modules at destination: ${destNodeModules}`);
537
+ devkit_1.logger.info(` Removing leftover node_modules at destination`);
427
538
  (0, fs_1.rmSync)(destNodeModules, { recursive: true, force: true });
428
539
  }
429
- // Step 1: Use Nx moveGenerator for the heavy lifting
430
- try {
431
- await (0, generators_1.moveGenerator)(tree, {
432
- projectName: app.currentNxProjectName,
433
- destination: newPath,
434
- newProjectName: newNxProjectName,
435
- updateImportPath: false, // Applications are entry points, not libraries
436
- skipFormat: true,
437
- });
438
- devkit_1.logger.info(` Nx moved project successfully`);
439
- // Reset Nx cache after move to ensure fresh project graph for next operations
440
- // This is important because moveGenerator uses the project graph, and it can become stale
441
- resetNxCache();
442
- }
443
- catch (error) {
444
- devkit_1.logger.error(` Failed to move project with Nx: ${error}`);
445
- devkit_1.logger.error(` Source path: ${app.currentPath}`);
446
- devkit_1.logger.error(` Destination path: ${newPath}`);
447
- devkit_1.logger.error(` Project name: ${app.currentNxProjectName}`);
448
- throw error;
449
- }
450
- // Step 2: Update .unisphere configuration
540
+ // Step 2: Move all files from old path to new path in the tree
541
+ const movedCount = moveFilesInTree(tree, app.currentPath, newPath);
542
+ devkit_1.logger.info(` Moved ${movedCount} files from ${app.currentPath} to ${newPath}`);
543
+ // Step 3: Update project.json at new location (root, sourceRoot, targets)
544
+ updateProjectJsonAfterMove(tree, app.currentPath, newPath);
545
+ devkit_1.logger.info(` Updated project.json paths`);
546
+ // Step 4: Update Nx project registration (remove old, register new)
547
+ updateNxProjectRegistration(tree, app.currentNxProjectName, newNxProjectName, newPath);
548
+ // Step 5: Update cross-project build target references
549
+ updateCrossProjectReferences(tree, app.currentNxProjectName, newNxProjectName);
550
+ // Step 6: Update .unisphere configuration
451
551
  updateUnisphereSourceRoot(tree, app.name, newPath);
452
552
  devkit_1.logger.info(` Updated .unisphere sourceRoot`);
453
- // Step 3: Update package-lock.json
553
+ // Step 7: Update package-lock.json
454
554
  updatePackageLockPaths(tree, app.currentPath, newPath);
455
- // Step 4: Fix .eslintrc.json extends path
555
+ // Step 8: Fix .eslintrc.json extends path
456
556
  fixEslintConfigPath(tree, newPath);
457
- // Step 5: Fix tsconfig.json extends path
557
+ // Step 9: Fix tsconfig.json extends path
458
558
  fixTsconfigJsonPath(tree, newPath);
459
- // Step 6: Fix jest.config.ts paths
559
+ // Step 10: Fix jest.config.ts paths
460
560
  fixJestConfigPath(tree, newPath, newPath);
461
- // Step 7: Fix project.json paths
561
+ // Step 11: Fix project.json paths ($schema, sourceRoot)
462
562
  fixProjectJsonPath(tree, newPath, newPath);
463
- // Step 8: Fix webpack.config.js output path
563
+ // Step 12: Fix webpack.config.js output path
464
564
  fixWebpackConfigPath(tree, newPath, newPath);
465
- // Step 9: Update tsconfig.base.json paths
565
+ // Step 13: Update tsconfig.base.json paths
466
566
  updateTsConfigBasePaths(tree, app.currentPath, newPath);
467
- // Step 10: Update root package.json scripts
567
+ // Step 14: Update root package.json scripts
468
568
  updateRootPackageJsonScripts(tree, app.currentPath, newPath);
469
569
  }
470
570
  /**
@@ -476,9 +576,6 @@ async function update(tree) {
476
576
  devkit_1.logger.info('Reorganizing applications by distribution channel');
477
577
  devkit_1.logger.info('========================================');
478
578
  devkit_1.logger.info('');
479
- // Phase 0: Reset Nx cache to ensure fresh project graph
480
- resetNxCache();
481
- devkit_1.logger.info('');
482
579
  // Phase 1: Discover applications
483
580
  const applications = discoverApplications(tree);
484
581
  if (applications.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"reorganize-packages-by-distribution-channel.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-0-0/reorganize-packages-by-distribution-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,IAAI,EAML,MAAM,YAAY,CAAC;AA8qBpB;;GAEG;AACH,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA6E9D"}
1
+ {"version":3,"file":"reorganize-packages-by-distribution-channel.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-0-0/reorganize-packages-by-distribution-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,IAAI,EAML,MAAM,YAAY,CAAC;AA+rBpB;;GAEG;AACH,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAyH9D"}
@@ -20,27 +20,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  exports.default = update;
21
21
  const devkit_1 = require("@nx/devkit");
22
22
  const generators_1 = require("@nx/workspace/generators");
23
- const child_process_1 = require("child_process");
24
23
  const fs_1 = require("fs");
25
24
  const path_1 = require("path");
26
25
  const has_react_dependency_1 = require("../utils/has-react-dependency");
27
- /**
28
- * Reset Nx cache to ensure fresh project graph
29
- * This is important before moving projects, as Nx caches project locations
30
- */
31
- function resetNxCache() {
32
- try {
33
- devkit_1.logger.info('Resetting Nx cache to ensure fresh project graph...');
34
- (0, child_process_1.execSync)('npx nx reset', {
35
- stdio: 'pipe',
36
- });
37
- devkit_1.logger.info('Nx cache reset successfully');
38
- }
39
- catch (error) {
40
- // Log but don't fail - cache reset is best effort
41
- devkit_1.logger.warn('Could not reset Nx cache (continuing anyway): ' + error);
42
- }
43
- }
44
26
  /**
45
27
  * Check if a package name needs the "-react" suffix and return the new name.
46
28
  * Following the convention in validateReactNaming() from dependency-config.ts.
@@ -446,6 +428,10 @@ function verifyPackageJsonName(tree, packagePath, expectedName) {
446
428
  * Update tsconfig.base.json paths for the package.
447
429
  * This ensures paths are updated even if moveGenerator fails to do so
448
430
  * (e.g., due to stale project graph cache).
431
+ *
432
+ * Handles both:
433
+ * - Updating existing path mappings (when old path still exists)
434
+ * - Adding new path mappings (when old path was removed in cleanup phase)
449
435
  */
450
436
  function updateTsConfigBasePaths(tree, oldPath, newPath, oldImportPath, newImportPath) {
451
437
  if (!tree.exists('tsconfig.base.json')) {
@@ -456,6 +442,7 @@ function updateTsConfigBasePaths(tree, oldPath, newPath, oldImportPath, newImpor
456
442
  return;
457
443
  }
458
444
  let updated = false;
445
+ let foundOldPath = false;
459
446
  const newPaths = {};
460
447
  for (const [key, paths] of Object.entries(tsconfigBase.compilerOptions.paths)) {
461
448
  // Check if we need to rename the key (import path changed)
@@ -463,6 +450,7 @@ function updateTsConfigBasePaths(tree, oldPath, newPath, oldImportPath, newImpor
463
450
  if (key === oldImportPath || key === `${oldImportPath}/*`) {
464
451
  newKey = key === oldImportPath ? newImportPath : `${newImportPath}/*`;
465
452
  updated = true;
453
+ foundOldPath = true;
466
454
  }
467
455
  // Update the path values
468
456
  if (Array.isArray(paths)) {
@@ -479,10 +467,41 @@ function updateTsConfigBasePaths(tree, oldPath, newPath, oldImportPath, newImpor
479
467
  newPaths[newKey] = paths;
480
468
  }
481
469
  }
470
+ // Ensure old import path is removed and new one is added
471
+ if (!foundOldPath) {
472
+ // Old path mapping wasn't found during iteration, so explicitly remove it
473
+ // This handles the case where moveGenerator didn't properly update the mapping
474
+ if (oldImportPath !== newImportPath) {
475
+ // Delete old import path mapping if it exists
476
+ if (newPaths[oldImportPath]) {
477
+ devkit_1.logger.info(` Removing old tsconfig path mapping: "${oldImportPath}"`);
478
+ delete newPaths[oldImportPath];
479
+ updated = true;
480
+ }
481
+ // Also check for the wildcard version
482
+ if (newPaths[`${oldImportPath}/*`]) {
483
+ devkit_1.logger.info(` Removing old tsconfig path mapping: "${oldImportPath}/*"`);
484
+ delete newPaths[`${oldImportPath}/*`];
485
+ updated = true;
486
+ }
487
+ }
488
+ // Add new path mapping
489
+ devkit_1.logger.info(` Adding new tsconfig path mapping: "${newImportPath}" -> "${newPath}/src/index.ts"`);
490
+ newPaths[newImportPath] = [`${newPath}/src/index.ts`];
491
+ updated = true;
492
+ }
482
493
  if (updated) {
483
494
  tsconfigBase.compilerOptions.paths = newPaths;
484
495
  (0, devkit_1.writeJson)(tree, 'tsconfig.base.json', tsconfigBase);
485
- devkit_1.logger.info(` Updated tsconfig.base.json paths`);
496
+ // CRITICAL: Also write to disk immediately so subsequent migrations see the changes
497
+ // Nx's globWithWorkspaceContextSync reads from disk, not the Tree
498
+ try {
499
+ (0, fs_1.writeFileSync)('tsconfig.base.json', JSON.stringify(tsconfigBase, null, 2) + '\n', 'utf-8');
500
+ devkit_1.logger.info(` Updated tsconfig.base.json paths (written to disk)`);
501
+ }
502
+ catch (error) {
503
+ devkit_1.logger.warn(` Failed to write tsconfig.base.json to disk: ${error}`);
504
+ }
486
505
  }
487
506
  }
488
507
  /**
@@ -528,13 +547,10 @@ async function migratePackage(tree, target) {
528
547
  destination: newPath,
529
548
  newProjectName: newNxProjectName,
530
549
  importPath: newPackageJsonName,
531
- updateImportPath: true,
550
+ updateImportPath: true, // Let moveGenerator update tsconfig paths
532
551
  skipFormat: true,
533
552
  });
534
553
  devkit_1.logger.info(` Nx moved project successfully`);
535
- // Reset Nx cache after move to ensure fresh project graph for next operations
536
- // This is important because moveGenerator uses the project graph, and it can become stale
537
- resetNxCache();
538
554
  }
539
555
  catch (error) {
540
556
  devkit_1.logger.error(` Failed to move project with Nx: ${error}`);
@@ -582,9 +598,6 @@ async function update(tree) {
582
598
  devkit_1.logger.info('Reorganizing packages by distribution channel');
583
599
  devkit_1.logger.info('========================================');
584
600
  devkit_1.logger.info('');
585
- // Phase 0: Reset Nx cache to ensure fresh project graph
586
- resetNxCache();
587
- devkit_1.logger.info('');
588
601
  // Phase 1: Discover packages
589
602
  const packages = await discoverPackages(tree);
590
603
  if (packages.length === 0) {
@@ -632,6 +645,52 @@ async function update(tree) {
632
645
  }
633
646
  // Format all files at the end
634
647
  await (0, devkit_1.formatFiles)(tree);
648
+ // Phase 5: Physically clean up any remaining old package directories from disk
649
+ // After formatFiles(), moveGenerator should have deleted old directories from the Tree
650
+ // But we need to ensure they're also gone from disk before the next migration runs
651
+ devkit_1.logger.info('');
652
+ devkit_1.logger.info('Physically cleaning up old package directories from disk...');
653
+ const packagesDir = (0, path_1.join)(tree.root, 'unisphere', 'packages');
654
+ if ((0, fs_1.existsSync)(packagesDir)) {
655
+ const subdirs = (0, fs_1.readdirSync)(packagesDir, { withFileTypes: true })
656
+ .filter(dirent => dirent.isDirectory())
657
+ .map(dirent => dirent.name);
658
+ let removedCount = 0;
659
+ for (const subdir of subdirs) {
660
+ // Keep only the new subdirectories (local, kaltura-corp, unisphere, kaltura-ai)
661
+ // Delete everything else (old package directories that moveGenerator may have left)
662
+ if (!['local', 'kaltura-corp', 'unisphere', 'kaltura-ai'].includes(subdir)) {
663
+ const oldPackagePath = (0, path_1.join)(packagesDir, subdir);
664
+ devkit_1.logger.info(` Physically removing old package directory: ${oldPackagePath}`);
665
+ (0, fs_1.rmSync)(oldPackagePath, { recursive: true, force: true });
666
+ removedCount++;
667
+ }
668
+ }
669
+ if (removedCount > 0) {
670
+ devkit_1.logger.info(` Physically removed ${removedCount} old package director(ies) from disk`);
671
+ }
672
+ else {
673
+ devkit_1.logger.info(' No old package directories found on disk to remove');
674
+ }
675
+ }
676
+ // Phase 6: Reset Nx's workspace data and in-memory context
677
+ // The native WorkspaceContext (Rust addon) persists a file index in .nx/workspace-data/.
678
+ // Since we deleted directories in Phase 5, the persisted index is stale. Delete the persisted
679
+ // data AND reset the in-memory singleton so subsequent migrations (e.g., applications
680
+ // reorganization) get a fresh disk scan via globWithWorkspaceContextSync().
681
+ const workspaceDataDir = (0, path_1.join)(tree.root, '.nx', 'workspace-data');
682
+ if ((0, fs_1.existsSync)(workspaceDataDir)) {
683
+ (0, fs_1.rmSync)(workspaceDataDir, { recursive: true, force: true });
684
+ devkit_1.logger.info('Deleted .nx/workspace-data/ (stale persisted file index)');
685
+ }
686
+ try {
687
+ const { resetWorkspaceContext } = require('nx/src/utils/workspace-context');
688
+ resetWorkspaceContext();
689
+ devkit_1.logger.info('Reset in-memory workspace context');
690
+ }
691
+ catch (e) {
692
+ devkit_1.logger.warn('Could not reset workspace context: ' + e);
693
+ }
635
694
  devkit_1.logger.info('');
636
695
  devkit_1.logger.info('========================================');
637
696
  devkit_1.logger.info(`Successfully reorganized ${migrated} package(s)`);
@@ -0,0 +1,363 @@
1
+ name: Shared Deployment Jobs
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ check-elements:
8
+ runs-on:
9
+ - codebuild-ovp-unisphere-runner-${{ github.run_id }}-${{ github.run_attempt }}
10
+ - instance-size:small
11
+ outputs:
12
+ has_packages: ${{ steps.check.outputs.has_packages }}
13
+ has_runtimes: ${{ steps.check.outputs.has_runtimes }}
14
+ has_applications: ${{ steps.check.outputs.has_applications }}
15
+ steps:
16
+
17
+ - name: Checkout Repo
18
+ uses: actions/checkout@v4
19
+ with:
20
+ ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}
21
+ fetch-tags: true
22
+
23
+ - name: Check elements in .unisphere
24
+ id: check
25
+ run: |
26
+ if [ -f .unisphere ]; then
27
+ PACKAGES=$(jq -r '.elements.packages // {} | length' .unisphere)
28
+ RUNTIMES=$(jq -r '(.elements.runtimes // {} | length) + (.elements.workspace // {} | length) + (.elements.loader // {} | length)' .unisphere)
29
+ APPLICATIONS=$(jq -r '.elements.applications // {} | length' .unisphere)
30
+
31
+ if [ "$PACKAGES" -gt 0 ]; then
32
+ echo "has_packages=true" >> $GITHUB_OUTPUT
33
+ else
34
+ echo "has_packages=false" >> $GITHUB_OUTPUT
35
+ fi
36
+
37
+ if [ "$RUNTIMES" -gt 0 ]; then
38
+ echo "has_runtimes=true" >> $GITHUB_OUTPUT
39
+ else
40
+ echo "has_runtimes=false" >> $GITHUB_OUTPUT
41
+ fi
42
+
43
+ if [ "$APPLICATIONS" -gt 0 ]; then
44
+ echo "has_applications=true" >> $GITHUB_OUTPUT
45
+ else
46
+ echo "has_applications=false" >> $GITHUB_OUTPUT
47
+ fi
48
+ else
49
+ echo "has_packages=false" >> $GITHUB_OUTPUT
50
+ echo "has_runtimes=false" >> $GITHUB_OUTPUT
51
+ echo "has_applications=false" >> $GITHUB_OUTPUT
52
+ fi
53
+
54
+ prepare-runtimes:
55
+ runs-on:
56
+ - codebuild-ovp-unisphere-runner-${{ github.run_id }}-${{ github.run_attempt }}
57
+ - instance-size:medium
58
+
59
+ if: needs.check-elements.outputs.has_runtimes == 'true'
60
+ needs: check-elements
61
+ outputs:
62
+ unisphereElementsArtifactsFolder: ${{ steps.prepare-runtimes.outputs.artifactsRootFolder }}
63
+ hasArtifacts: ${{ steps.prepare-runtimes.outputs.hasArtifacts }}
64
+ commit_sha: ${{ steps.capture_commit_sha.outputs.commit_sha }}
65
+ steps:
66
+ - name: Cache npm
67
+ uses: actions/cache@v3
68
+ with:
69
+ path: ~/.npm
70
+ key: dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-${{ hashFiles('package-lock.json') }}
71
+ restore-keys: |
72
+ dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-
73
+
74
+ - name: Checkout Repo
75
+ uses: actions/checkout@v4
76
+ with:
77
+ ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}
78
+ fetch-tags: true
79
+ - name: Setup Node.js
80
+ uses: actions/setup-node@v4
81
+ with:
82
+ node-version-file: '.nvmrc'
83
+ - name: Clean workspace
84
+ run: git reset --hard HEAD
85
+ - name: Clean npm cache
86
+ run: npm cache clean --force
87
+
88
+ - name: Setup JFrog
89
+
90
+ uses: jfrog/setup-jfrog-cli@v4
91
+ id: setup-jfrog
92
+ env:
93
+ JF_URL: https://kalturaa.jfrog.io
94
+ with:
95
+ oidc-provider-name: ovp-github-oidc
96
+ - name: Install dependencies
97
+ run: npm ci --prefer-offline --include=optional --no-fund --verbose
98
+ env:
99
+ GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
100
+ KALTURA_JFROG_TOKEN: ${{ steps.setup-jfrog.outputs.oidc-token }}
101
+
102
+ - name: Prepare Unisphere Elements
103
+ id: prepare-runtimes
104
+ run: npx unisphere runtime publish prepare --verbose
105
+ - name: Capture Commit SHA
106
+ id: capture_commit_sha
107
+ run: echo "commit_sha=$(git rev-parse HEAD)" >> $GITHUB_ENV
108
+ - name: Set commit_sha as output
109
+ id: set_commit_sha
110
+ run: echo "commit_sha=${{ env.commit_sha }}" >> $GITHUB_OUTPUT
111
+ - uses: actions/upload-artifact@v4
112
+ id: upload-unisphere-elements-artifacts
113
+ with:
114
+ name: unisphere-elements
115
+ path: ${{ steps.prepare-runtimes.outputs.artifactsRootFolder }}
116
+ retention-days: 1
117
+
118
+ deploy-packages:
119
+ if: needs.check-elements.outputs.has_packages == 'true'
120
+ needs: check-elements
121
+ runs-on:
122
+ - codebuild-ovp-unisphere-runner-${{ github.run_id }}-${{ github.run_attempt }}
123
+ - instance-size:medium
124
+ steps:
125
+ - name: Cache npm
126
+ uses: actions/cache@v3
127
+ with:
128
+ path: ~/.npm
129
+ key: dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-${{ hashFiles('package-lock.json') }}
130
+ restore-keys: |
131
+ dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-
132
+
133
+ - name: Checkout Repo
134
+ uses: actions/checkout@v4
135
+ with:
136
+ ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}
137
+ fetch-tags: true
138
+ - name: Setup Node.js
139
+ uses: actions/setup-node@v4
140
+ with:
141
+ node-version-file: '.nvmrc'
142
+
143
+ - name: Setup JFrog
144
+
145
+ uses: jfrog/setup-jfrog-cli@v4
146
+ id: setup-jfrog
147
+ env:
148
+ JF_URL: https://kalturaa.jfrog.io
149
+ with:
150
+ oidc-provider-name: ovp-github-oidc
151
+
152
+ - name: Install dependencies
153
+
154
+ run: |
155
+ npm ci --prefer-offline --include=optional --no-fund --verbose
156
+
157
+ env:
158
+ GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
159
+ KALTURA_JFROG_TOKEN: ${{ steps.setup-jfrog.outputs.oidc-token }}
160
+
161
+ - name: Get NPM Token from AWS Secrets Manager
162
+ id: get-npm-token
163
+ run: |
164
+ NPM_TOKEN=$(aws secretsmanager get-secret-value --secret-id arn:aws:secretsmanager:eu-central-1:785328604905:secret:unisphere-secrets-um86Cs --query SecretString --output text | jq -r '."NPM_UNISPHERE_TOKEN"')
165
+ echo "NPM_TOKEN=$NPM_TOKEN" >> $GITHUB_ENV
166
+ # Debug token existence (safely)
167
+ echo "::debug::Token exists: $([ ! -z "$NPM_TOKEN" ] && echo 'true' || echo 'false')"
168
+ - name: Deploy to registry
169
+ run: npx unisphere package publish --verbose --jfrogToken ${{ steps.setup-jfrog.outputs.oidc-token }} --jfrogUser ${{ steps.setup-jfrog.outputs.oidc-user }} --npmToken ${{ env.NPM_TOKEN }} --branch "${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}"
170
+
171
+ deploy-runtimes:
172
+ if: needs.prepare-runtimes.outputs.hasArtifacts == 'true'
173
+ needs: prepare-runtimes
174
+ runs-on:
175
+ - codebuild-ovp-unisphere-runner-${{ github.run_id }}-${{ github.run_attempt }}
176
+ - instance-size:medium
177
+ strategy:
178
+ matrix:
179
+ envs_regions:
180
+ - { env: 'nvp1', region: 'us-east-1', accountid: '583352821080' }
181
+ - { env: 'frp2', region: 'eu-central-1', accountid: '082111255551' }
182
+ - { env: 'irp2', region: 'eu-west-1', accountid: '137576761235' }
183
+ - { env: 'nvq2', region: 'us-east-1', accountid: '383697330906' }
184
+ - { env: 'sgp2', region: 'ap-southeast-1', accountid: '882351240370' }
185
+ - { env: 'syp2', region: 'ap-southeast-2', accountid: '650755435642' }
186
+ - { env: 'cap2', region: 'ca-central-1', accountid: '948632009361' }
187
+ fail-fast: false
188
+
189
+ steps:
190
+ - name: Cache npm
191
+ uses: actions/cache@v3
192
+ with:
193
+ path: ~/.npm
194
+ key: dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-${{ hashFiles('package-lock.json') }}
195
+ restore-keys: |
196
+ dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-
197
+
198
+ - name: Check available disk space
199
+ run: df -h
200
+ - name: Checkout Repo at specific commit
201
+ uses: actions/checkout@v4
202
+ with:
203
+ ref: ${{ needs.prepare-runtimes.outputs.commit_sha }}
204
+ fetch-tags: true
205
+ - name: Setup Node.js
206
+ uses: actions/setup-node@v4
207
+ with:
208
+ node-version-file: '.nvmrc'
209
+
210
+ - name: Setup JFrog
211
+
212
+ uses: jfrog/setup-jfrog-cli@v4
213
+ id: setup-jfrog
214
+ env:
215
+ JF_URL: https://kalturaa.jfrog.io
216
+ with:
217
+ oidc-provider-name: ovp-github-oidc
218
+
219
+ - name: Install dependencies
220
+
221
+ run: npm ci --prefer-offline --include=optional --no-fund --verbose
222
+ env:
223
+ GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
224
+ KALTURA_JFROG_TOKEN: ${{ steps.setup-jfrog.outputs.oidc-token }}
225
+
226
+ - name: Download artifacts folder
227
+ uses: actions/download-artifact@v4
228
+ with:
229
+ name: unisphere-elements
230
+ path: ${{ needs.prepare-runtimes.outputs.unisphereElementsArtifactsFolder }}
231
+ - name: Sync S3 bucket
232
+ run: |
233
+ npx unisphere runtime publish execute \
234
+ --env ${{ matrix.envs_regions.env }} \
235
+ --aws-region '${{ matrix.envs_regions.region }}' \
236
+ --aws-arn 'arn:aws:iam::${{matrix.envs_regions.accountid }}:role/${{ matrix.envs_regions.env }}-unisphere-content-role' \
237
+ --artifacts-folder '${{ needs.prepare-runtimes.outputs.unisphereElementsArtifactsFolder }}' \
238
+ --verbose
239
+
240
+ prepare-applications:
241
+ if: always() && needs.check-elements.outputs.has_applications == 'true'
242
+ needs: [deploy-runtimes, check-elements]
243
+ runs-on:
244
+ - codebuild-ovp-unisphere-runner-${{ github.run_id }}-${{ github.run_attempt }}
245
+ - instance-size:medium
246
+ outputs:
247
+ unisphereApplicationsArtifactsFolder: ${{ steps.prepare-applications.outputs.artifactsRootFolder }}
248
+ hasArtifacts: ${{ steps.prepare-applications.outputs.hasArtifacts }}
249
+ commit_sha: ${{ steps.capture_commit_sha.outputs.commit_sha }}
250
+ steps:
251
+ - name: Cache npm
252
+ uses: actions/cache@v3
253
+ with:
254
+ path: ~/.npm
255
+ key: dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-${{ hashFiles('package-lock.json') }}
256
+ restore-keys: |
257
+ dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-
258
+
259
+ - name: Checkout Repo
260
+ uses: actions/checkout@v4
261
+ with:
262
+ ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}
263
+ fetch-tags: true
264
+ - name: Setup Node.js
265
+ uses: actions/setup-node@v4
266
+ with:
267
+ node-version-file: '.nvmrc'
268
+ - name: Clean workspace
269
+ run: git reset --hard HEAD
270
+ - name: Clean npm cache
271
+ run: npm cache clean --force
272
+ - name: Setup JFrog
273
+
274
+ uses: jfrog/setup-jfrog-cli@v4
275
+ id: setup-jfrog
276
+ env:
277
+ JF_URL: https://kalturaa.jfrog.io
278
+ with:
279
+ oidc-provider-name: ovp-github-oidc
280
+ - name: Install dependencies
281
+
282
+ run: npm ci --prefer-offline --include=optional --no-fund --verbose
283
+ env:
284
+ GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
285
+ KALTURA_JFROG_TOKEN: ${{ steps.setup-jfrog.outputs.oidc-token }}
286
+ - name: Prepare Unisphere Applications
287
+ id: prepare-applications
288
+ run: npx unisphere application publish prepare --verbose
289
+ - name: Capture Commit SHA
290
+ id: capture_commit_sha
291
+ run: echo "commit_sha=$(git rev-parse HEAD)" >> $GITHUB_ENV
292
+ - name: Set commit_sha as output
293
+ id: set_commit_sha
294
+ run: echo "commit_sha=${{ env.commit_sha }}" >> $GITHUB_OUTPUT
295
+ - uses: actions/upload-artifact@v4
296
+ id: upload-unisphere-applications-artifacts
297
+ with:
298
+ name: unisphere-applications
299
+ path: ${{ steps.prepare-applications.outputs.artifactsRootFolder }}
300
+ retention-days: 1
301
+
302
+ deploy-applications:
303
+ if: always() && needs.prepare-applications.outputs.hasArtifacts == 'true'
304
+ needs: [prepare-applications]
305
+ runs-on:
306
+ - codebuild-ovp-unisphere-runner-${{ github.run_id }}-${{ github.run_attempt }}
307
+ - instance-size:medium
308
+ strategy:
309
+ matrix:
310
+ envs_regions:
311
+ - { env: 'nvp1', region: 'us-east-1', accountid: '583352821080' }
312
+ - { env: 'frp2', region: 'eu-central-1', accountid: '082111255551' }
313
+ - { env: 'irp2', region: 'eu-west-1', accountid: '137576761235' }
314
+ - { env: 'nvq2', region: 'us-east-1', accountid: '383697330906' }
315
+ - { env: 'sgp2', region: 'ap-southeast-1', accountid: '882351240370' }
316
+ - { env: 'syp2', region: 'ap-southeast-2', accountid: '650755435642' }
317
+ - { env: 'cap2', region: 'ca-central-1', accountid: '948632009361' }
318
+ fail-fast: false
319
+ steps:
320
+ - name: Cache npm
321
+ uses: actions/cache@v3
322
+ with:
323
+ path: ~/.npm
324
+ key: dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-${{ hashFiles('package-lock.json') }}
325
+ restore-keys: |
326
+ dependencies-${{ runner.os }}-node-${{ hashFiles('.nvmrc') }}-
327
+
328
+ - name: Checkout Repo at specific commit
329
+ uses: actions/checkout@v4
330
+ with:
331
+ ref: ${{ needs.prepare-applications.outputs.commit_sha }}
332
+ fetch-tags: true
333
+ - name: Setup Node.js
334
+ uses: actions/setup-node@v4
335
+ with:
336
+ node-version-file: '.nvmrc'
337
+ - name: Setup JFrog
338
+
339
+ uses: jfrog/setup-jfrog-cli@v4
340
+ id: setup-jfrog
341
+ env:
342
+ JF_URL: https://kalturaa.jfrog.io
343
+ with:
344
+ oidc-provider-name: ovp-github-oidc
345
+ - name: Install dependencies
346
+
347
+ run: npm ci --prefer-offline --include=optional --no-fund --verbose
348
+ env:
349
+ GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
350
+ KALTURA_JFROG_TOKEN: ${{ steps.setup-jfrog.outputs.oidc-token }}
351
+ - name: Download artifacts folder
352
+ uses: actions/download-artifact@v4
353
+ with:
354
+ name: unisphere-applications
355
+ path: ${{ needs.prepare-applications.outputs.unisphereApplicationsArtifactsFolder }}
356
+ - name: Sync S3 bucket
357
+ run: |
358
+ npx unisphere application publish execute \
359
+ --env ${{ matrix.envs_regions.env }} \
360
+ --aws-region '${{ matrix.envs_regions.region }}' \
361
+ --aws-arn 'arn:aws:iam::${{matrix.envs_regions.accountid }}:role/${{ matrix.envs_regions.env }}-unisphere-content-role' \
362
+ --artifacts-folder '${{ needs.prepare-applications.outputs.unisphereApplicationsArtifactsFolder }}' \
363
+ --verbose
@@ -0,0 +1,3 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export default function update(tree: Tree): Promise<void>;
3
+ //# sourceMappingURL=update-publish-artifacts-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-publish-artifacts-workflow.d.ts","sourceRoot":"","sources":["../../../src/migrations/3-5-0/update-publish-artifacts-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAU,MAAM,YAAY,CAAC;AAI1C,wBAA8B,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC9D"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = update;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ async function update(tree) {
8
+ devkit_1.logger.info('🔄 Updating GitHub _publish-artifacts workflow for v3.5.0');
9
+ // Ensure .github/workflows directory exists
10
+ if (!tree.exists('.github')) {
11
+ tree.write('.github/.gitkeep', '');
12
+ devkit_1.logger.info('✅ Created .github directory');
13
+ }
14
+ if (!tree.exists('.github/workflows')) {
15
+ tree.write('.github/workflows/.gitkeep', '');
16
+ devkit_1.logger.info('✅ Created .github/workflows directory');
17
+ }
18
+ try {
19
+ // Update publishArtifacts.yml
20
+ const publishArtifactsWorkflowPath = '.github/workflows/_publish-artifacts.yml';
21
+ const publishArtifactsTemplatePath = (0, path_1.join)(__dirname, 'templates', '_publish-artifacts.template');
22
+ const publishArtifactsTemplateContent = (0, fs_1.readFileSync)(publishArtifactsTemplatePath, 'utf-8');
23
+ const publishArtifactsExists = tree.exists(publishArtifactsWorkflowPath);
24
+ tree.write(publishArtifactsWorkflowPath, publishArtifactsTemplateContent);
25
+ if (publishArtifactsExists) {
26
+ devkit_1.logger.info(`✅ Updated ${publishArtifactsWorkflowPath}`);
27
+ }
28
+ else {
29
+ devkit_1.logger.info(`✅ Created ${publishArtifactsWorkflowPath}`);
30
+ }
31
+ }
32
+ catch (error) {
33
+ devkit_1.logger.error(`❌ Failed to update GitHub publishArtifacts workflow: ${error?.message || 'Unknown error'}`);
34
+ throw error;
35
+ }
36
+ }
package/migrations.json CHANGED
@@ -298,6 +298,14 @@
298
298
  "cli": {
299
299
  "postUpdateMessage": "✅ .github/workflows/cicd.yml updated successfully"
300
300
  }
301
+ },
302
+ "3-5-0-update-publish-artifacts-workflow": {
303
+ "version": "3.5.0",
304
+ "description": "Updates .github/workflows/publish-artifacts.yml with JFrog OIDC setup and improved cache management",
305
+ "factory": "./dist/migrations/3-5-0/update-publish-artifacts-workflow.js",
306
+ "cli": {
307
+ "postUpdateMessage": "✅ .github/workflows/publish-artifacts.yml updated successfully"
308
+ }
301
309
  }
302
310
  },
303
311
  "packageJsonUpdates": {
@@ -453,6 +461,17 @@
453
461
  "alwaysAddToPackageJson": false
454
462
  }
455
463
  }
464
+ },
465
+ "3.5.1": {
466
+ "version": "3.5.1",
467
+ "cli": "nx",
468
+ "postUpdateMessage": "🎉 Migration to @unisphere/nx 3.5.1 completed successfully!",
469
+ "packages": {
470
+ "@unisphere/cli": {
471
+ "version": "2.6.0",
472
+ "alwaysAddToPackageJson": false
473
+ }
474
+ }
456
475
  }
457
476
  }
458
477
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unisphere/nx",
3
- "version": "3.5.0",
3
+ "version": "3.5.2",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",