Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5eadd06
chore: update core-aspect-env to 1.0.2 (#10507)
davidfirst Jul 20, 2026
c5f1e3a
bump teambit version to 2.0.29 [skip ci]
Jul 21, 2026
a633055
fix(ripple): show the real error in 'ripple errors' summary (#10509)
davidfirst Jul 21, 2026
5c951ed
bump teambit version to 2.0.30 [skip ci]
Jul 21, 2026
8c743c8
fix(minimal-mode): suppress all notifications, including apollo error…
luvkapur Jul 21, 2026
10f1434
bump teambit version to 2.0.31 [skip ci]
Jul 21, 2026
df7a823
experiment: remove former-core envs (node/react/aspect/env/mdx/readme…
davidfirst Jul 21, 2026
bd6145a
chore(deps): bump @teambit/typescript.typescript-compiler to 4.0.0 (#…
davidfirst Jul 21, 2026
7a52236
ci(e2e): refresh e2e timings manifest (#10494)
GiladShoham Jul 21, 2026
ebdfb2c
bump teambit version to 2.0.32 [skip ci]
Jul 21, 2026
c662cfe
docs: add release notes for v2.0.2, v2.0.11, and v2.0.26 (#10512)
davidfirst Jul 21, 2026
ed00ff2
chore(types): decouple root type-check from env-source ambient module…
davidfirst Jul 22, 2026
a457f94
chore(types): decouple root type-check from env-source ambient module…
davidfirst Jul 22, 2026
833fca6
fix(dependency-resolver): resolve source-removed legacy core envs fro…
davidfirst Jul 22, 2026
9344b31
bump teambit version to 2.0.33 [skip ci]
Jul 22, 2026
4ae5289
chore(diag): temporary legacy-core-env resolution logging + custom-re…
davidfirst Jul 22, 2026
e6136e0
chore(deps): drop non-env source dependencies on former-core envs (#1…
davidfirst Jul 22, 2026
94a9d3c
chore(diag): trace env load pipeline (requireables + batch harmony.lo…
davidfirst Jul 22, 2026
8b3d1c2
bump teambit version to 2.0.34 [skip ci]
Jul 22, 2026
a58aa2d
fix(aspect-loader): don't drop requested env on resolution collisions…
davidfirst Jul 22, 2026
af7f30b
fix(workspace): skip dep detection in node-env fixtures; match abs-pa…
davidfirst Jul 22, 2026
2cef557
fix(preview): load ESM-only mdx options with a native import in pre-b…
davidfirst Jul 22, 2026
d10ffc7
fix(dependency-resolver): baseline md/mdx import detection when the m…
davidfirst Jul 22, 2026
bee89d1
fix(dependency-resolver): skip code fences, inline code and comments …
davidfirst Jul 22, 2026
354eea7
fix(bit): recover require() of ESM files when a test hook hijacked th…
davidfirst Jul 22, 2026
ee4be74
chore: remove temporary env-load diagnostics
davidfirst Jul 22, 2026
664af60
Merge remote-tracking branch 'origin/master' into experiment/remove-e…
davidfirst Jul 22, 2026
ce9fc61
chore: reconcile lockfile after master merge (env sources removed)
davidfirst Jul 22, 2026
7934cf4
fix(envs): bump node-babel-mocha env to 1.0.3, revert hook-require es…
davidfirst Jul 22, 2026
d8c3d33
fix(builder): restore require extension hooks after each build task
davidfirst Jul 22, 2026
b501f6f
ci(e2e): restore branch-measured e2e timings lost in master merge
davidfirst Jul 22, 2026
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
467 changes: 340 additions & 127 deletions .bitmap

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// @ts-nocheck
// the e2e runs inside the bit repo, where core-aspect types (e.g. @teambit/react) resolve to the
// repo sources while the env tree in the capsule brings the published packages. the types are
// structurally identical but nominally different - skip checking.
import { MainRuntime } from '@teambit/cli';
import { ReactAspect, ReactMain } from '@teambit/react';
import { EnvsAspect, EnvsMain } from '@teambit/envs';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// @bit-no-check
// @ts-nocheck
// the e2e runs inside the bit repo, where core-aspect types (e.g. @teambit/envs) resolve to the
// repo sources while the env tree in the capsule brings the published packages. the types are
// structurally identical but nominally different - skip checking.
import { EnvsMain, EnvsAspect } from '@teambit/envs';
import { NodeMain, NodeAspect } from '@teambit/node';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// @bit-no-check
// @ts-nocheck
// the e2e runs inside the bit repo, where core-aspect types (e.g. @teambit/envs) resolve to the
// repo sources while the env tree in the capsule brings the published packages. the types are
// structurally identical but nominally different - skip checking.
import { EnvsMain, EnvsAspect } from '@teambit/envs';
import { NodeMain, NodeAspect } from '@teambit/node';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// @bit-no-check
// @ts-nocheck
// the e2e runs inside the bit repo, where core-aspect types (e.g. @teambit/envs) resolve to the
// repo sources while the env tree in the capsule brings the published packages. the types are
// structurally identical but nominally different - skip checking.
import { EnvsMain, EnvsAspect } from '@teambit/envs';
import { NodeMain, NodeAspect } from '@teambit/node';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @bit-no-check
// @ts-nocheck
// the e2e runs inside the bit repo, where core-aspect types (e.g. @teambit/envs) resolve to the
// repo sources while the env tree in the capsule brings the published packages. the types are
Expand Down
142,890 changes: 95,385 additions & 47,505 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

34 changes: 18 additions & 16 deletions releases-docs/guideline.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@ This document provides guidelines for writing consistent and effective release n

## File Structure

Each release note file follows this structure:

```
title: v{VERSION}
tag: v{VERSION}
draft: false
prerelease: false
immutable: false
author: {AUTHOR_GITHUB_USERNAME}
created: {ISO_DATE}
published: {ISO_DATE}
url: https://github.com/teambit/bit/releases/tag/v{VERSION}
--

{RELEASE_CONTENT}
```
Release-note files in `releases-docs/releases/` contain **section content only** — they start directly with the release content's first heading, with no metadata header (see `v2.0.0.md` and later). This is the current convention and matches the `generate-release-notes` skill, which instructs saving the release content without any metadata header. For the heading level to use, see [Section Headers](#section-headers) below (`###` preferred; `##` also acceptable, as in `v2.0.0.md`).

> **Legacy metadata header (optional):** Some older release files (e.g. `v1.10.0.md`) begin with a metadata block followed by a `--` separator. It is no longer required, and new files should omit it:
>
> ```
> title: v{VERSION}
> tag: v{VERSION}
> draft: false
> prerelease: false
> immutable: false
> author: {AUTHOR_GITHUB_USERNAME}
> created: {ISO_DATE}
> published: {ISO_DATE}
> url: https://github.com/teambit/bit/releases/tag/v{VERSION}
> --
>
> {RELEASE_CONTENT}
> ```

## Section Order

Expand Down
12 changes: 12 additions & 0 deletions releases-docs/releases/v2.0.11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### New Features

- **`bit import --write-to-empty-dir`** — instead of failing when the target directory is occupied, `bit import` writes the component into the next available empty directory (e.g. `renderers/class` → `renderers/class_1`). Aimed at non-interactive clients like the IDE plugin that can't prompt for `--override`; without the flag, behavior is unchanged (#10471)

### Improvements

- **Core environments on TypeScript 6** — `core-aspect-env`, `node-babel-mocha`, and `node-typescript-mocha` updated to their TS6 releases (`1.0.0`), and `@teambit/typescript.typescript-compiler` to `^3.0.0`. The new toolchain compiles with TypeScript 6.0.3, pins the ambient `@types` the mocha envs need (TS6 no longer auto-includes `node_modules/@types`), and publishes dist-pointing `exports`. Also bumps `@teambit/harmony` to `0.4.12` and migrates remaining components off the legacy core envs (#10473, #10466, #10463, #10470)

### Bug Fixes

- Fix an issue where `bit ci pr --keep-lane` crashed the snap with `ExternalEnvWithoutVersion` (or kept the stale env) instead of propagating env migrations made on main to the PR lane with their version (#10469)
- Fix an issue where `bit ci pr --keep-lane` on fresh runners silently no-op'd the config sync from main (`… was not found on the filesystem`) instead of landing the 3-way merge, because each component's common-ancestor object wasn't pre-fetched (#10464)
3 changes: 3 additions & 0 deletions releases-docs/releases/v2.0.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Bug Fixes

- Fix an issue where the Workspace UI version-history didn't reflect staged (not-yet-snapped) range deprecations — the per-version deprecation marker only showed up after a tag/snap, unlike `bit log` (#10461)
23 changes: 23 additions & 0 deletions releases-docs/releases/v2.0.26.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Improvements

- Add `--auto-tag-increment` to `bit snap`/`bit tag` to control the version bump level applied to auto-tagged dependents (#10496)
- Add a git-style pager to `bit diff` and `bit log` for easier navigation of long output (#10472)
- Correct typos and grammar in various user-facing text (#10498)

### Bug Fixes

- Fix an issue where a component was not recognized as an env by its `.bit-env` plugin file (#10500)
- Fix an issue where `componentMap` `fullName` collisions across scopes broke component previews (#10497)
- Fix an issue where `bit init` didn't validate the default-scope name before creating the workspace (#10495)
- Fix an issue where envs' core-aspect phantom dependencies weren't resolved during `bit install` bootstrap (#10492)
- Fix an issue where switching to `main` didn't fetch the latest state from the original scope (#10493)
- Fix an issue where the isolator isolated published-tag dependency-only cycles unnecessarily (#10488)
- Fix an issue where concurrent exports could cause a lost update by making the export `clientId` collision-safe (#10458)

### Internal

- Update `typescript-compiler` to 3.0.2 (#10499)
- Resolve aspects/envs from `node_modules` instead of capsules (#10478)
- Update node babel/mocha envs (#10477, #10476)
- Migrate remaining components from the react v17 env to react 19 (#10483)
- E2E/CI stability and coverage improvements (#10489, #10484, #10474)
33 changes: 26 additions & 7 deletions scopes/cloud/ripple/ripple.main.runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,34 @@ export class RippleMain {

/**
* extract the error section from container log messages.
* looks for common error patterns in the build output.
* looks for common error markers in the build output and returns from the *earliest* one
* to the end, so the whole error block is shown starting at where it began.
*/
extractErrorsFromLog(messages: string[]): string[] {
const patterns = ['errors were found', 'Failed task', 'threw an error', 'Error:', 'FAIL'];
for (const pattern of patterns) {
const idx = messages.findIndex((m) => stripAnsi(m).includes(pattern));
if (idx >= 0) {
return messages.slice(idx);
}
// markers that denote the start of a real error section. most are matched
// case-insensitively; the named-Error marker is intentionally case-sensitive so it
// catches "TypeError:" / "ReferenceError:" at line start or after whitespace without
// matching serialized props such as "isUserError: true" (a common tail of a stringified
// error object) — matching that would slice from the very end and drop the real error
// printed above it.
const markers: RegExp[] = [
/errors were found/i,
/failed task/i,
/threw an error/i,
/responded with the following error/i,
/unable to find object/i,
/\berror:/i,
/(^|\s)[A-Z]\w*Error:/,
/\bfail\b/i,
];
// pick the earliest line matching any marker (not the first marker in the list) so an
// incidental late match can't truncate the error that appeared earlier in the log.
const startIdx = messages.findIndex((m) => {
const clean = stripAnsi(m);
return markers.some((re) => re.test(clean));
});
if (startIdx >= 0) {
return messages.slice(startIdx);
}
// last resort: grab the last 30 lines if the log has content
if (messages.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
import { ExtensionDataList } from '@teambit/legacy.extension-data';
import { componentIdToPackageName } from '@teambit/pkg.modules.component-package-name';
import { DetectorHook } from './detector-hook';
import { MarkdownImportDetector } from './markdown-import-detector';
import type { ProxyConfig, NetworkConfig } from '@teambit/scope.network';
import { Http } from '@teambit/scope.network';
import type { Dependency as LegacyDependency } from '@teambit/legacy.consumer-component';
Expand Down Expand Up @@ -559,8 +560,15 @@ export class DependencyResolverMain {
const pkgName = this.getPackageName(component);
const rootComponentsRelativePath = relative(options.workspacePath, options.rootComponentsPath);
const getRelativeRootComponentDir = getRootComponentDir.bind(null, rootComponentsRelativePath ?? '');
// install names a legacy core env's root dir by its VERSIONLESS id (calculateEnvId returns the
// versionless id for these envs), so the pinned external package sits in .bit_roots/<versionless>.
// resolve it the same way even when the env is not in the workspace (i.e. its source was removed);
// otherwise the versioned lookup misses and we fall back to <root>/node_modules/<pkg>, which was
// the now-deleted source-component dir -> "Cannot find module".
const useVersionlessSelfRoot =
options.isInWorkspace || this.envs.isLegacyCoreEnv(component.id.toStringWithoutVersion());
const selfRootDir = getRelativeRootComponentDir(
options.isInWorkspace ? component.id.toStringWithoutVersion() : component.id.toString()
useVersionlessSelfRoot ? component.id.toStringWithoutVersion() : component.id.toString()
);
// the returned paths are relative to the workspace root, so anchor all the existence checks
// to the workspace path rather than relying on process.cwd
Expand Down Expand Up @@ -1917,6 +1925,9 @@ as an alternative, you can use "+" to keep the same version installed in the wor

const envJsoncDetector = envs.getEnvJsoncDetector();
dependencyResolver.registerDetector(envJsoncDetector);
// baseline md/mdx import detection. the mdx aspect (no longer a core aspect) registers a
// compile-based detector for these extensions when loaded, which takes precedence.
dependencyResolver.registerDetector(new MarkdownImportDetector());

componentAspect.registerShowFragments([
new DependenciesFragment(dependencyResolver),
Expand Down
17 changes: 10 additions & 7 deletions scopes/dependencies/dependency-resolver/detector-hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,29 @@ export interface DependencyDetector {
* @param file
*/
dependencyLookup?(file: DependencyContext): string;

/**
* a fallback detector is used only when no regular detector supports the file. it lets core
* aspects provide a baseline detection (e.g. regex-based imports extraction for md/mdx) while a
* loaded aspect with a full parser for the same extension takes precedence.
*/
isFallback?: boolean;
}

export class DetectorHook {
static hooks: DependencyDetector[] = [];

isSupported(ext: string, filename: string): boolean {
return !!DetectorHook.hooks.find((hook) => {
return hook.isSupported({
ext,
filename,
});
});
return !!this.getDetector(ext, filename);
}

getDetector(ext: string, filename: string): DependencyDetector | undefined {
return DetectorHook.hooks.find((hook) => {
const supported = DetectorHook.hooks.filter((hook) => {
return hook.isSupported({
ext,
filename,
});
});
return supported.find((hook) => !hook.isFallback) ?? supported[0];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { DependencyDetector, FileContext } from './detector-hook';

/**
* Regex pattern for matching import statements in md/mdx files.
*
* Matches two import patterns in an alternation (both require a line to start with the `import`
* keyword, as MDX only treats block-level statements as ESM):
* - `[type] <specifiers> from "module"` - default (x), named ({x}), namespace (* as x) or mixed
* specifiers, module path captured in group 1.
* - `"module"` - side-effect only imports, module path captured in group 2.
*/
const IMPORT_STATEMENT_REGEX =
/^import\s+(?:(?:type\s+)?(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)(?:\s*,\s*\{[^}]*\}|\s*,\s*\w+)?\s+from\s+['"]([^'"]+)['"]|['"]([^'"]+)['"])/gm;

/**
* imports shown inside fenced code blocks, inline code spans or comments are documentation
* examples, not real ESM imports - MDX doesn't execute them, so they must not become
* dependencies (a usage example importing the component's own package would otherwise produce a
* self-import issue).
*/
function stripNonEsmContent(source: string): string {
return source
.replace(/```[\s\S]*?```/g, '')
.replace(/~~~[\s\S]*?~~~/g, '')
.replace(/`[^`\n]*`/g, '')
.replace(/<!--[\s\S]*?-->/g, '')
.replace(/\{\/\*[\s\S]*?\*\/\}/g, '');
}

export function detectMarkdownImports(source: string): string[] {
const strippedSource = stripNonEsmContent(source);
const modules: string[] = [];
let match: RegExpExecArray | null;
IMPORT_STATEMENT_REGEX.lastIndex = 0;
while ((match = IMPORT_STATEMENT_REGEX.exec(strippedSource)) !== null) {
const moduleName = match[1] || match[2];
if (moduleName) modules.push(moduleName);
}
return modules;
}

/**
* baseline import detection for md/mdx files (e.g. component docs importing other components).
* historically this detection was provided by the mdx aspect, which was a core aspect and thus
* always loaded. now that it is a regular env, md/mdx imports must still be detected even when no
* component in the workspace loads the mdx aspect - otherwise docs dependencies silently drop
* from the model and break e.g. the preview bundling in capsules. registered as a fallback so the
* mdx aspect's compile-based detector takes precedence whenever it is loaded.
*/
export class MarkdownImportDetector implements DependencyDetector {
isFallback = true;

isSupported(context: FileContext): boolean {
return context.ext === '.md' || context.ext === '.mdx';
}

detect(source: string): string[] {
return detectMarkdownImports(source);
}
}
5 changes: 0 additions & 5 deletions scopes/envs/env/env.aspect.ts

This file was deleted.

7 changes: 0 additions & 7 deletions scopes/envs/env/env.composition.tsx

This file was deleted.

4 changes: 0 additions & 4 deletions scopes/envs/env/env.docs.mdx

This file was deleted.

64 changes: 0 additions & 64 deletions scopes/envs/env/env.env.ts

This file was deleted.

Loading