You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: CI unit test failures across migrated external plugins
Summary
This PR fixes a series of CI failures discovered after migrating external CLI plugins into the monorepo. All failures were silent in CI because they either threw before tests ran, produced exit codes that masked the real error, or targeted wrong module instances due to the build/test environment mismatch.
Fixes
1. contentstack-apps-cli — CI crash: Region not configured at module load time
Problem:
Several test files (create.test.ts, deploy.test.ts, reinstall.test.ts, common-utils.test.ts, etc.) called configHandler.get("region") and getDeveloperHubUrl() at the top level — outside of any describe/it block. In CI, no region is pre-configured, so getDeveloperHubUrl() threw "Region not configured. Please set the region..." before a single test could register. This caused mocha to crash entirely.
Fix (test/helpers/init.js):
Added a mock NA region via configHandler.set() in the shared mocha init file. This file is required before any test file is loaded, ensuring the region is available at module-load time in CI without affecting real CLI configuration.
2. contentstack-apps-cli — 5 deploy tests failing in CI (exit code 5)
Problem: deploy.test.ts (and previously update.test.ts) used a try/catch pattern to load stubs from lib/ if that directory existed, falling back to src/ otherwise:
try{BaseCommandToStub=require("lib/base-command").BaseCommand;// succeeds in CI}catch{BaseCommandToStub=BaseCommand;// only used locally}
The CI workflow runs pnpm build before tests, so lib/always exists in CI. This meant stubs were applied to lib/ class instances. However, oclif's tsPath mechanism (activated by NODE_ENV=development in init.js) redirects all command loading from lib/ → src/ at runtime. The actual command ran against src/ module instances — completely different objects from those being stubbed — so stubs had no effect, real HTTP calls went out, and all 5 tests failed.
The exit code 5 matched the 5 failing tests (mocha exits with the number of failures), and the --reporter json flag in the test:unit:report:json script suppressed terminal output, hiding the actual errors.
Fix (deploy.test.ts and update.test.ts):
Removed the try/catch lib/ loading pattern entirely. Both files now import directly from src/ — the same module instances oclif loads via tsPath — making stubs work correctly regardless of whether lib/ exists.
// Before (broken in CI when lib/ is built)try{LibDeploy=require("lib/commands/app/deploy").default;}catch{LibDeploy=Deploy;}// After (always targets src/, matching what runCommand loads)constLibDeploy=Deploy;import*aslibCommonUtilsfrom"../../../../src/util/common-utils";import*aslibInquirerfrom"../../../../src/util/inquirer";
Also fixed two TypeScript type errors introduced by switching to typed imports:
selectProject stub changed from .resolves(null) to .resolves(undefined) (return type is LaunchProjectRes | undefined, not null)
Added missing developerHubAppUid: null to a mock LaunchProjectRes object
Problem: compare.test.ts mocked cli-ux for the open browser call, but the source (compare.ts) had already been migrated to use the standalone open package directly. The mock was targeting a package that was no longer imported, so the real open() call executed in tests.
Fix (compare.ts + compare.test.ts):
Updated the source to import from open and updated the test mock to match:
Problem:
The package used ESLint v8 with eslint-config-oclif v6. eslint-config-oclif v6 is ESM-only flat config — it cannot be loaded by ESLint v8's CommonJS require(). The posttest lint step failed immediately with a config resolution error.
Additionally, the old .eslintrc config bundled its own @typescript-eslint/eslint-plugin and eslint-plugin-unicorn versions, which conflicted with the versions brought in by eslint-config-oclif.
Fix (package.json + new eslint.config.mjs):
Upgraded to ESLint v9 (which supports flat config natively), removed the now-redundant standalone plugin packages, created a new eslint.config.mjs flat config file matching the pattern used by other packages in the monorepo, and updated the lint/posttest scripts to use the new flat config invocation.
5. contentstack-cli-cm-regex-validate — Source code refactored for ESLint v9 compliance
Problem:
With the upgraded ESLint v9 + flat config, the existing source files had violations the old config was silently allowing (import ordering, arrow function style, semicolons, spacing).
Fix (multiple src/ files):
Applied consistent formatting fixes across validate-regex.ts, generate-output.ts, interactive.ts, connect-stack.ts, process-stack.ts, and safe-regex.ts — import ordering, arrow functions, semicolon removal, object spacing — to satisfy the new lint rules. Also reordered static examples before static flags in the command class to match oclif convention.
6. contentstack-cli-tsgen — Integration tests running in the unit test workflow
Problem:
The unit-test.yml workflow ran npm run test for the tsgen plugin. The test script runs jest --testPathPattern=tests, which matches tests/integration/ — the only test directory. Integration tests throw at module load time if TOKEN_ALIAS env var is not set:
if(!tokenAlias){thrownewError("TOKEN_ALIAS environment variable is not set");}
TOKEN_ALIAS is a delivery token alias that must be registered in the csdx CLI config via csdx auth:tokens:add. The unit test workflow has no access to these secrets. A dedicated tsgen-integration-test.yml workflow already exists that properly sets up the CLI, registers the token, and provides TOKEN_ALIAS from GitHub Secrets.
Fix (unit-test.yml):
Removed the tsgen step from unit-test.yml entirely. Integration tests are already handled by the dedicated tsgen-integration-test.yml workflow on pull requests. Additionally updated tsgen-integration-test.yml to use npm run test (which runs all tests including integration) instead of test:integration to ensure the full test suite runs in the right environment.
7. Dependency updates across packages
Bumped minor/patch versions of shared dependencies to resolve lockfile conflicts introduced during the monorepo migration:
axios: ^1.15.0 → ^1.16.1 (apps-cli)
oclif: ^4.23.0 → ^4.23.8 (apps-cli, regex-validate, tsgen, and others)
Various @contentstack/* peer dependency alignments across contentstack-audit, contentstack-bootstrap, contentstack-clone, contentstack-export, contentstack-import, contentstack-migrate-rte, contentstack-migration, contentstack-query-export, contentstack-seed, contentstack-variants, and others
Updated pnpm-lock.yaml to reflect all of the above
Packages affected
Package
Change type
contentstack-apps-cli
Test infra fix (region mock, stub target, deploy tests)
contentstack-content-type
Source + test fix (cli-ux → open)
contentstack-cli-cm-regex-validate
ESLint v8→v9 upgrade, source lint fixes
contentstack-cli-tsgen
Removed from unit test workflow
.github/workflows/unit-test.yml
Removed tsgen step, corrected apps-cli script name
.github/workflows/tsgen-integration-test.yml
Fixed test script reference
Multiple packages
Dependency version bumps + lockfile update
Test plan
All steps in unit-test.yml pass in CI (no TOKEN_ALIAS, no built lib/ conflict)
tsgen-integration-test.yml runs correctly on PRs with secrets configured
contentstack-apps-cli: 61 unit tests pass (npm run test:unit:report)
contentstack-content-type: 76 unit tests pass (npm run test:unit)
contentstack-cli-cm-regex-validate: 22 unit tests pass + ESLint clean (npm run test:unit)
cs-raj
changed the title
Fix/external plugin migration
Fix external plugin migration pipeline issues
May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: CI unit test failures across migrated external plugins
Summary
This PR fixes a series of CI failures discovered after migrating external CLI plugins into the monorepo. All failures were silent in CI because they either threw before tests ran, produced exit codes that masked the real error, or targeted wrong module instances due to the build/test environment mismatch.
Fixes
1.
contentstack-apps-cli— CI crash:Region not configuredat module load timeProblem:
Several test files (
create.test.ts,deploy.test.ts,reinstall.test.ts,common-utils.test.ts, etc.) calledconfigHandler.get("region")andgetDeveloperHubUrl()at the top level — outside of anydescribe/itblock. In CI, no region is pre-configured, sogetDeveloperHubUrl()threw"Region not configured. Please set the region..."before a single test could register. This caused mocha to crash entirely.Fix (
test/helpers/init.js):Added a mock NA region via
configHandler.set()in the shared mocha init file. This file is required before any test file is loaded, ensuring the region is available at module-load time in CI without affecting real CLI configuration.2.
contentstack-apps-cli— 5 deploy tests failing in CI (exit code 5)Problem:
deploy.test.ts(and previouslyupdate.test.ts) used a try/catch pattern to load stubs fromlib/if that directory existed, falling back tosrc/otherwise:The CI workflow runs
pnpm buildbefore tests, solib/always exists in CI. This meant stubs were applied tolib/class instances. However, oclif'stsPathmechanism (activated byNODE_ENV=developmentininit.js) redirects all command loading fromlib/→src/at runtime. The actual command ran againstsrc/module instances — completely different objects from those being stubbed — so stubs had no effect, real HTTP calls went out, and all 5 tests failed.The exit code
5matched the 5 failing tests (mocha exits with the number of failures), and the--reporter jsonflag in thetest:unit:report:jsonscript suppressed terminal output, hiding the actual errors.Fix (
deploy.test.tsandupdate.test.ts):Removed the try/catch
lib/loading pattern entirely. Both files now import directly fromsrc/— the same module instances oclif loads via tsPath — making stubs work correctly regardless of whetherlib/exists.Also fixed two TypeScript type errors introduced by switching to typed imports:
selectProjectstub changed from.resolves(null)to.resolves(undefined)(return type isLaunchProjectRes | undefined, notnull)developerHubAppUid: nullto a mockLaunchProjectResobject3.
contentstack-content-type—Cannot find module 'cli-ux'Problem:
compare.test.tsmockedcli-uxfor theopenbrowser call, but the source (compare.ts) had already been migrated to use the standaloneopenpackage directly. The mock was targeting a package that was no longer imported, so the realopen()call executed in tests.Fix (
compare.ts+compare.test.ts):Updated the source to import from
openand updated the test mock to match:4.
contentstack-cli-cm-regex-validate— ESLint v8 +eslint-config-oclifv6 incompatibilityProblem:
The package used ESLint v8 with
eslint-config-oclifv6.eslint-config-oclifv6 is ESM-only flat config — it cannot be loaded by ESLint v8's CommonJSrequire(). Theposttestlint step failed immediately with a config resolution error.Additionally, the old
.eslintrcconfig bundled its own@typescript-eslint/eslint-pluginandeslint-plugin-unicornversions, which conflicted with the versions brought in byeslint-config-oclif.Fix (
package.json+ neweslint.config.mjs):Upgraded to ESLint v9 (which supports flat config natively), removed the now-redundant standalone plugin packages, created a new
eslint.config.mjsflat config file matching the pattern used by other packages in the monorepo, and updated the lint/posttest scripts to use the new flat config invocation.5.
contentstack-cli-cm-regex-validate— Source code refactored for ESLint v9 complianceProblem:
With the upgraded ESLint v9 + flat config, the existing source files had violations the old config was silently allowing (import ordering, arrow function style, semicolons, spacing).
Fix (multiple
src/files):Applied consistent formatting fixes across
validate-regex.ts,generate-output.ts,interactive.ts,connect-stack.ts,process-stack.ts, andsafe-regex.ts— import ordering, arrow functions, semicolon removal, object spacing — to satisfy the new lint rules. Also reorderedstatic examplesbeforestatic flagsin the command class to match oclif convention.6.
contentstack-cli-tsgen— Integration tests running in the unit test workflowProblem:
The
unit-test.ymlworkflow rannpm run testfor the tsgen plugin. Thetestscript runsjest --testPathPattern=tests, which matchestests/integration/— the only test directory. Integration tests throw at module load time ifTOKEN_ALIASenv var is not set:TOKEN_ALIASis a delivery token alias that must be registered in thecsdxCLI config viacsdx auth:tokens:add. The unit test workflow has no access to these secrets. A dedicatedtsgen-integration-test.ymlworkflow already exists that properly sets up the CLI, registers the token, and providesTOKEN_ALIASfrom GitHub Secrets.Fix (
unit-test.yml):Removed the tsgen step from
unit-test.ymlentirely. Integration tests are already handled by the dedicatedtsgen-integration-test.ymlworkflow on pull requests. Additionally updatedtsgen-integration-test.ymlto usenpm run test(which runs all tests including integration) instead oftest:integrationto ensure the full test suite runs in the right environment.7. Dependency updates across packages
Bumped minor/patch versions of shared dependencies to resolve lockfile conflicts introduced during the monorepo migration:
axios:^1.15.0→^1.16.1(apps-cli)oclif:^4.23.0→^4.23.8(apps-cli, regex-validate, tsgen, and others)@contentstack/*peer dependency alignments acrosscontentstack-audit,contentstack-bootstrap,contentstack-clone,contentstack-export,contentstack-import,contentstack-migrate-rte,contentstack-migration,contentstack-query-export,contentstack-seed,contentstack-variants, and otherspnpm-lock.yamlto reflect all of the abovePackages affected
contentstack-apps-clicontentstack-content-typecli-ux→open)contentstack-cli-cm-regex-validatecontentstack-cli-tsgen.github/workflows/unit-test.yml.github/workflows/tsgen-integration-test.ymlTest plan
unit-test.ymlpass in CI (noTOKEN_ALIAS, no builtlib/conflict)tsgen-integration-test.ymlruns correctly on PRs with secrets configuredcontentstack-apps-cli: 61 unit tests pass (npm run test:unit:report)contentstack-content-type: 76 unit tests pass (npm run test:unit)contentstack-cli-cm-regex-validate: 22 unit tests pass + ESLint clean (npm run test:unit)