Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions fluidBuild.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const releaseGroupPackageJsonGlobs = [
"tools/markdown-magic/package.json",
];

const skipCjsChecks = process.env.SKIP_CJS_CHECKS === "true";
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skipCjsChecks is derived via a strict process.env.SKIP_CJS_CHECKS === "true" check. In Azure Pipelines, boolean variables commonly come through as "True"/"False" (capitalized), so PR builds may not actually enable the skip behavior. Consider normalizing (e.g. case-insensitive) and/or accepting "1" to make the gate reliable.

Suggested change
const skipCjsChecks = process.env.SKIP_CJS_CHECKS === "true";
const skipCjsChecks =
typeof process.env.SKIP_CJS_CHECKS === "string" &&
(process.env.SKIP_CJS_CHECKS.toLowerCase() === "true" || process.env.SKIP_CJS_CHECKS === "1");

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an issue — the pipeline variable uses ${{ lower(eq(variables['Build.Reason'], 'PullRequest')) }} in include-vars.yml, which outputs lowercase "true" / "false". The === "true" check matches correctly.


/**
* The settings in this file configure the Fluid build tools, such as fluid-build and flub. Some settings apply to the
* whole repo, while others apply only to the client release group.
Expand Down Expand Up @@ -90,11 +92,17 @@ module.exports = {
// Generic build:test script should be replaced by :esm or :cjs specific versions.
// "tsc" would be nice to eliminate from here, but plenty of packages still focus
// on CommonJS.
"build:test": ["typetests:gen", "tsc", "api-extractor:commonjs", "api-extractor:esnext"],
"build:test:cjs": ["typetests:gen", "tsc", "api-extractor:commonjs"],
"build:test": skipCjsChecks
? ["typetests:gen", "tsc", "api-extractor:esnext"]
: ["typetests:gen", "tsc", "api-extractor:commonjs", "api-extractor:esnext"],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid duplication of the portions which are the same, as it could introduce surprising issues in the future if they diverge.

Suggested change
"build:test": skipCjsChecks
? ["typetests:gen", "tsc", "api-extractor:esnext"]
: ["typetests:gen", "tsc", "api-extractor:commonjs", "api-extractor:esnext"],
"build:test": ["typetests:gen", "tsc", "api-extractor:esnext", ...(skipCjsChecks ? [] : ["api-extractor:commonjs"])]

This same pattern should be applied to the cases below as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — applied the spread pattern to all three conditional arrays (build:test, build:test:cjs, api).

"build:test:cjs": skipCjsChecks
? ["typetests:gen", "tsc"]
: ["typetests:gen", "tsc", "api-extractor:commonjs"],
"build:test:esm": ["typetests:gen", "build:esnext", "api-extractor:esnext"],
"api": {
dependsOn: ["api-extractor:commonjs", "api-extractor:esnext"],
dependsOn: skipCjsChecks
? ["api-extractor:esnext"]
: ["api-extractor:commonjs", "api-extractor:esnext"],
script: false,
},
"api-extractor:commonjs": ["tsc"],
Expand Down Expand Up @@ -126,12 +134,29 @@ module.exports = {
script: true,
},
"depcruise": [],
"check:exports": ["api"],
// When skipping CJS checks, skip check:exports entirely. The package's concurrently
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes this PR do a lot more disabling that it claims in its description. It seems like you encountered some cases where our build does a poor job with its dependencies and trying to build subsets of what's normally build doesn't work. Its issues like this which is why my previous attempt to speed up our build have failed. I think we really need to correct the dependencies in the build so that its possible to add a minimal build script and just run that without breaking random stuff.

Anyway, I don't think we can consider this PR to be just disabling CJS checks if we disable all checks as a workaround for our build having bad dependencies and being unable to just disable cjs stuff.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. The PR description says "skip CJS api-extractor checks" but the actual scope is broader — check:exports and check:are-the-types-wrong are also fully disabled as a cascade effect, because they can't run without the CJS type rollups that api-extractor produces.

This is a real limitation. The build dependency graph doesn't let us cleanly remove just the CJS api-extractor step without breaking downstream checks that assume its output exists.

I'll update the PR description to accurately reflect the full scope of what's being skipped.

// script would fail because CJS entry points aren't generated, and forcing
// check:exports:bundle-release-tags to run individually surfaces pre-existing
// api-extractor lint errors in packages that have disabled check:exports via
// "echo skip". All export checks are deferred to main CI.
"check:exports": skipCjsChecks
? {
dependsOn: [],
script: false,
}
: ["api"],
Comment on lines +148 to +153
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really not correct. You might be able to alter api some of the time, but I can't think of a time when check:exports should depend on nothing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — disabling check:exports entirely was a workaround for the build dependency graph not allowing us to cleanly skip just the CJS subtasks. It's too blunt. The better path is separating validation into a parallel job so nothing gets dropped.

"check:exports:bundle-release-tags": ["build:esnext"],
// The package's local 'api-extractor-lint.json' may use the entrypoint from either CJS or ESM,
// therefore we need to require both before running api-extractor.
"check:release-tags": ["tsc", "build:esnext"],
"check:are-the-types-wrong": ["tsc", "build:esnext", "api"],
// attw packs the package and checks CJS+ESM type resolution. With CJS entry
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do not use api-extractor to generate our entry points (we have our own custom tools for that).

If disabling API extractor is breaking attw, then I think you might have disabled more than intended.

Also, if disabling attw is intended, then we should document that in the PR description as that is rather significant.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right that api-extractor doesn't generate entry points. The issue is that attw packs the package and validates CJS+ESM type resolution. When api-extractor:commonjs is skipped, the CJS .d.ts rollup files that attw expects to find are missing — so it fails. The entry points themselves (generated by custom tools) are still there, but the type rollups that api-extractor produces for CJS are not.

That said, your broader point stands — disabling attw is a significant omission that should be called out in the PR description. I'll update it.

// points missing, it fails. Defer to main CI where api generates both.
"check:are-the-types-wrong": skipCjsChecks
? {
dependsOn: [],
script: false,
}
: ["tsc", "build:esnext", "api"],
"check:format": {
dependencies: [],
script: true,
Expand Down
4 changes: 3 additions & 1 deletion tools/pipelines/build-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@ extends:
- { name: "ci:test:jest", jobName: "JestTest" }
- { name: "ci:test:realsvc:tinylicious", jobName: "RealsvcTinyliciousTest" }
- { name: "ci:test:stress:tinylicious", jobName: "StressTinyliciousTest" }
- { name: "ci:check:are-the-types-wrong", jobName: "AreTheTypesWrong" }
# attw checks CJS+ESM type resolution; skip on PRs where CJS api-extractor is skipped
- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
- { name: "ci:check:are-the-types-wrong", jobName: "AreTheTypesWrong" }
Comment on lines +224 to +225
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should always be checked. You can craft an alternate check for each package that ignores CJS.
But we should gate main on ESM being correct.
We just had a PR today that needs a correction caught by these checks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point — we shouldn't be dropping ESM validation on PRs, especially since it catches real issues. The right approach is CraigMacomber's suggestion: move these checks to a separate parallel validation job rather than disabling them. I'll close this PR in favor of that approach.

coverageTests:
- { name: "ci:test:mocha", jobName: "MochaTest" }
- { name: "ci:test:realsvc:local", jobName: "RealsvcLocalTest" }
Expand Down
4 changes: 4 additions & 0 deletions tools/pipelines/templates/include-build-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ steps:
# a transitive dependency of browserslist. Without this, the warning fires once
# per package during builds, producing 100+ identical warnings in build logs.
BASELINE_BROWSER_MAPPING_IGNORE_OLD_DATA: 1
# Skip CJS api-extractor checks on PR builds to reduce build time.
# CJS output is byte-for-byte identical to ESM; full CJS checks run on main/release CI.
SKIP_CJS_CHECKS: $(skipCjsChecks)
inputs:
command: 'custom'
workingDir: $(Pipeline.Workspace)/${{ parameters.buildDirectory }}
Expand All @@ -42,6 +45,7 @@ steps:
env:
# Suppress baseline-browser-mapping staleness warnings during lint as well.
BASELINE_BROWSER_MAPPING_IGNORE_OLD_DATA: 1
SKIP_CJS_CHECKS: $(skipCjsChecks)
inputs:
command: 'custom'
workingDir: $(Pipeline.Workspace)/${{ parameters.buildDirectory }}
Expand Down
4 changes: 4 additions & 0 deletions tools/pipelines/templates/include-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ variables:
value: ${{ ne(variables['Build.Reason'], 'PullRequest') }}
readonly: true

- name: skipCjsChecks
value: ${{ lower(eq(variables['Build.Reason'], 'PullRequest')) }}
readonly: true

- template: /tools/pipelines/templates/include-vars-telemetry-generator.yml@self

# The way 1ES pipeline templates determine the default branch of a repository only works for repos hosted in ADO.
Expand Down
Loading