feat(v4): add core-next & cli-next packages with integration/E2E test…#15663
Draft
Alive-Fish wants to merge 48 commits intodevfrom
Draft
feat(v4): add core-next & cli-next packages with integration/E2E test…#15663Alive-Fish wants to merge 48 commits intodevfrom
Alive-Fish wants to merge 48 commits intodevfrom
Conversation
…s and CI workflows - Add core-next engine: operations, drivers, DA manifest, templates, lifecycle - Add cli-next CLI: Commander.js commands, action handlers, telemetry, auth - Add integration tests: 24 core-next + 62 cli-next - Add E2E tests: cli-syntax verification with scaffold tests - Add CI workflow (ci-next.yml): build, lint, format, unit+integration tests - Add E2E workflow (e2e-test-next.yml): matrix test execution with failure summary - Add instruction files, skills, and plans for v4 development
- Add esbuild.mjs config: single-file CJS bundle, node18 target, keepNames - Add bundle/package/prepack scripts to package.json - Lazy-load applicationinsights (require inside init, not top-level import) - Defer registerBuiltinDrivers() from startup to wrapHandlerWithContext() - Update cli.instructions.md and codebase.instructions.md with bundling docs Before: node cli.js --help took ~18.5s (unbundled tsc output) After: node cli.js --help takes ~490ms (esbuild bundle, 2.2MB prod)
…ame conflicts core-next: @microsoft/teamsfx-core -> @microsoft/teamsfx-core-next cli-next: @microsoft/m365agentstoolkit-cli -> @microsoft/m365agentstoolkit-cli-next Both packages shared names with their v3 counterparts (fx-core, cli), causing pnpm install to fail during CI setup.
- dev-test-next: fix .tests.ts -> .test.ts extensions, add 3 new E2E test suites (mcp-scaffold, auth-commands, add-capability), remove format-check references, update verification checklist - dev-workflow: reference lint-format skill in Phase 5 - lint-format: new skill documenting ESLint+Prettier pipeline architecture
lifecycle.test.ts dynamically generates tests from templateRegistry.list(), but the registry is empty until registerBuiltinTemplates() is called. Without this call, Mocha sees 0 test cases and passes vacuously in 4s. Also adds a guard that throws if the registry is still empty after initialization, preventing silent 0-test passes in the future.
Instead of running all 43 templates sequentially in one lifecycle.test.ts job (which would take hours), expand each template into its own matrix entry: lifecycle.test.ts::da/basic, lifecycle.test.ts::bot/echo, etc. The setup job reads templateRegistry to generate entries. The run step parses the :: separator and passes --grep to Mocha so each job only runs the matching template's language variants.
In CI, the test context was using the interactive CLI auth (createTokenProvider) which opens browser popups for MSAL login — this hangs indefinitely on headless CI runners. Add ciTokenProvider.ts with: - M365LoginCI: uses acquireTokenByUsernamePassword (MSAL ROPC flow) - AzureLoginCIUserPassword: uses UsernamePasswordCredential from @azure/identity testContext.ts now checks isCIMode() (CI_ENABLED=true) and uses the CI provider instead of the interactive one.
azure/login@v1 with OIDC (federated credentials) exports AZURE_TENANT_ID and AZURE_SUBSCRIPTION_ID to GITHUB_ENV, overriding the test-user values set at job level. This caused all 43 lifecycle tests to authenticate the test user against the DEVOPS tenant, which fails immediately. Add 'Restore test env vars' steps right after azure/login in both the setup and execute-case jobs to write the correct test secrets back to GITHUB_ENV.
…alidation, and optimization - Add 8 source files: types, constants, parser, utils, validator, filter, optimizer, index - Add RealSpecParserAdapter implementing SpecParserAdapter interface - Wire createSpecParserAdapter factory to return RealSpecParserAdapter - Export specParser module from core-next index - Add dependencies: swagger-parser, swagger2openapi, openapi-types
| // Copy path-level properties (servers, parameters, etc.) but not operations | ||
| newPaths[path] = { ...unresolvedSpec.paths![path] }; | ||
| for (const m of HTTPMethodsConst.AllOperationMethods) { | ||
| delete (newPaths[path] as Record<string, unknown>)[m]; |
| } | ||
| } | ||
|
|
||
| (newPaths[path] as Record<string, unknown>)[methodName] = ( |
Three root causes found and fixed: 1. C# scaffold EISDIR crash: Missing Mustache variables (NewProjectTypeName, NewProjectTypeExt, SolutionName, PlaceProjectFileInSolutionDir) in getTemplateReplaceMap caused C# template file paths to collapse to empty strings, resulting in EISDIR when writing to the project directory path. Fix: Add the missing variables to replaceMap.ts matching fx-core defaults. 2. Provision empty AZURE_RESOURCE_GROUP_NAME: Templates scaffold .env.dev with AZURE_RESOURCE_GROUP_NAME= (empty). The test checked for key presence (not empty value), so it never injected the actual RG name. Additionally, provisionOp's analyzeSteps treated empty strings as 'resolved', skipping ensureResourceGroup(). Fix: Use upsertEnvVar in the test to replace empty values, and check for empty strings in provisionOp. 3. Driver projectPath missing: teamsApp/zipAppPackage requires projectPath but YAML templates don't include it in the 'with' block. The lifecycle executor now auto-injects ctx.projectPath when the config lacks it. Also includes: - UUID validation for cached tenant IDs (cacheAccess.ts) - Stale cache cleanup in E2E setup.ts - Unit test fix for provisionOp portal link test
- executor.ts: temporarily sync envMap into process.env before each driver
call so drivers loading external files (ARM params, AAD manifests) can
resolve ${{VAR}} placeholders; cleaned up in finally block
- createDriver.ts: detect AtkError plain objects in wrapUnexpectedError()
and return them directly instead of wrapping with String() which produced
[object Object]
- aadApp/update.ts: resolve env placeholders in AAD manifest template
before JSON parsing; return UnresolvedManifestVars error if any remain
- openApi.ts: mark 3 OpenAPI templates (da/api-plugin-from-spec, ai-agent/rag-from-spec, me/from-spec) as testable: false since they require interactive apiSpecPath input - declarativeAgent.ts: mark da/graph-connector as testable: false since its template artifact lacks appPackage/manifest.json
- lifecycle.test.ts: always create env/ dir and .env.dev with required vars; detect lifecycle sections in YAML before provision/deploy to gracefully skip templates without those phases - cli-syntax.test.ts: replace nonexistent template names (tab dashboard, bot notification-express) with real registry entries (tab basic, cea basic)
- fx-core.instructions.md: document executor process.env sync, createDriver AtkError handling, aadApp/update env resolution - features.instructions.md: document testable flag and 4 testable:false templates - dev-test-next SKILL.md: add lifecycle-aware, env bootstrapping, and testable filtering design decisions - lifecycle-e2e plan: add 2026-04-13 log with 8 root cause fixes
…rivers and YAML Drivers output UPPER_CASE keys (e.g. TEAMS_APP_ID) while YAML writeToEnvironmentFile uses camelCase keys (e.g. teamsAppId). The executor now checks both conventions so env vars flow correctly between lifecycle steps.
- Fix scaffold lang mismatch for da/typespec, da/mcp-local - Check Azure-requiring drivers instead of section presence - Remove forced teamsApp validator without provision - Fix noSpuriousErrors rule to check per-operation - Reorder phases: detect lifecycle before RG creation
- render.ts: Fix Mustache eating ${{VAR}} placeholders by using NUL-byte
sentinels instead of literal {{VAR}} text tokens. Prevents re-parsing
on cache miss when templates contain section tags.
- createDriver.ts: Add missing success attribute and fix duration
metric name in driver-end telemetry event.
- extendToM365.ts: Handle case-insensitive scope enum values (personal
vs Personal) with normalizeAppScope() helper.
- declarativeAgent.ts: Mark da/typespec as testable: false until
typeSpec/compile driver is ported from fx-core.
- validateManifest: resolve manifestPath relative to ctx.projectPath (fixes ENOENT for csharp templates where cwd != projectPath) - engineAgent: add csharp template name override for function-calling (csharp.zip uses 'custom-copilot-weather-agent' not 'weather-agent') - declarativeAgent: mark da/api-plugin-oauth, da/mcp-remote, da/mcp-local as testable:false (infra/env prerequisites not available in CI) - lifecycle test: pass llmService='azure-openai' so Mustache conditionals for LLM client code render correctly (fixes 4 ts npm build failures) - lifecycle test: add collectUnresolvedParameterVars() to pre-populate dummy env vars for unresolved parameters.json placeholders (fixes rag-ai-search, bearer, teams-collaborator provision failures)
… fallback - Make baseUrl optional in oauth/register driver schema (matches fx-core behavior) - Add apiSpecPath support: extract server domains from OpenAPI spec when baseUrl absent - Re-enable da/api-plugin-oauth as testable (remove testable: false) - Improve extendToM365 error handling: surface Axios response body in error detail - Add unit tests for apiSpecPath domain extraction and missing baseUrl error
…ster and apiKey/register - oauth/register: output 'configurationId' instead of 'OAUTH2_CONFIGURATION_ID' so executor's outputs[yamlKey] lookup matches the writeToEnvironmentFile mapping - apiKey/register: output 'registrationId' instead of 'API_KEY_REGISTRATION_ID' for the same reason - The executor maps outputs[yamlKey] ?? outputs[envVarName]; these drivers' hardcoded keys matched neither side, silently dropping env vars
…dApp/update - oauth/register: output applicationIdUri from TDP response's resourceIdentifierUri for MicrosoftEntra identity provider (maps to AADAUTHCODE_APPLICATION_ID_URI) - aadApp/update: auto-generate AAD_APP_ACCESS_AS_USER_PERMISSION_ID UUID when the AAD manifest references it but no value exists in the environment - aadApp/update: include generated permission ID in driver outputs so the executor persists it to envMap/.env for subsequent runs
…or reporting - lifecycle.test.ts: only add teamsApp validator when YAML contains teamsApp/create, not for all templates with a provision lifecycle (connector/graph has provision but no teamsApp/create, so TEAMS_APP_ID is never set, causing validate to fail and trigger a flaky retry) - AzureArmClient: include armErr.details in DeployArmError message so CI logs show which specific resource(s) failed during ARM deployment
…Ms in createDriver
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
…s and CI workflows