Skip to content

fix(tag-from-scope), merge package.json props from the last snap #9207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .bitmap
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"api-reference": {
"name": "api-reference",
"scope": "teambit.api-reference",
"version": "1.0.411",
"version": "1.0.410",
"mainFile": "index.ts",
"rootDir": "scopes/api-reference/api-reference"
},
Expand Down
87 changes: 72 additions & 15 deletions scopes/component/isolator/isolator.main.runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ export type IsolateComponentsOptions = CreateGraphOptions & {
*/
populateArtifactsFrom?: ComponentID[];

/**
* relevant when populateArtifactsFrom is set.
* by default, it uses the package.json created in the previous snap as a base and make the necessary changes.
* if this is set to true, it will ignore the package.json from the previous snap.
*/
populateArtifactsIgnorePkgJson?: boolean;

/**
* Force specific host to get the component from.
*/
Expand Down Expand Up @@ -910,6 +917,13 @@ export class IsolatorMain {
const legacyComponents = [...legacyUnmodifiedComps, ...legacyModifiedComps];
if (legacyScope && unmodifiedComps.length) await importMultipleDistsArtifacts(legacyScope, legacyUnmodifiedComps);
const allIds = ComponentIdList.fromArray(legacyComponents.map((c) => c.id));
const getParentsComp = () => {
const artifactsFrom = opts?.populateArtifactsFrom;
if (!artifactsFrom) return undefined;
if (!legacyScope) throw new Error('populateArtifactsFrom is set but legacyScope is not defined');
return Promise.all(artifactsFrom.map((id) => legacyScope.getConsumerComponent(id)));
};
const populateArtifactsFromComps = await getParentsComp();
await Promise.all(
components.map(async (component) => {
const capsule = capsuleList.getCapsule(component.id);
Expand All @@ -918,7 +932,13 @@ export class IsolatorMain {
(await CapsuleList.capsuleUsePreviouslySavedDists(component)) || opts?.populateArtifactsFrom
? legacyScope
: undefined;
const dataToPersist = await this.populateComponentsFilesToWriteForCapsule(component, allIds, scope, opts);
const dataToPersist = await this.populateComponentsFilesToWriteForCapsule(
component,
allIds,
scope,
opts,
populateArtifactsFromComps
);
await dataToPersist.persistAllToCapsule(capsule, { keepExistingCapsule: true });
})
);
Expand Down Expand Up @@ -1128,11 +1148,12 @@ export class IsolatorMain {
return packageJson;
}

async populateComponentsFilesToWriteForCapsule(
private async populateComponentsFilesToWriteForCapsule(
component: Component,
ids: ComponentIdList,
legacyScope?: Scope,
opts?: IsolateComponentsOptions
opts?: IsolateComponentsOptions,
populateArtifactsFromComps?: ConsumerComponent[]
): Promise<DataToPersist> {
const legacyComp: ConsumerComponent = component.state._consumer;
const dataToPersist = new DataToPersist();
Expand All @@ -1153,12 +1174,55 @@ export class IsolatorMain {
await PackageJsonTransformer.applyTransformers(component, packageJson);
const valuesToMerge = legacyComp.overrides.componentOverridesPackageJsonData;
packageJson.mergePackageJsonObject(valuesToMerge);
if (populateArtifactsFromComps && !opts?.populateArtifactsIgnorePkgJson) {
const compParent = this.getCompForArtifacts(component, populateArtifactsFromComps);
this.mergePkgJsonFromLastBuild(compParent, packageJson);
}
dataToPersist.addFile(packageJson.toVinylFile());
const artifacts = await this.getArtifacts(component, legacyScope, opts?.populateArtifactsFrom);
const artifacts = await this.getArtifacts(component, legacyScope, populateArtifactsFromComps);
dataToPersist.addManyFiles(artifacts);
return dataToPersist;
}

private mergePkgJsonFromLastBuild(component: ConsumerComponent, packageJson: PackageJsonFile) {
const suffix = `for ${component.id.toString()}. to workaround this, use --ignore-last-pkg-json flag`;
const aspectsData = component.extensions.findExtension('teambit.pipelines/builder')?.data?.aspectsData;
if (!aspectsData) throw new Error(`getPkgJsonFromLastBuild, unable to find builder aspects data ${suffix}`);
const data = aspectsData?.find((aspectData) => aspectData.aspectId === 'teambit.pkg/pkg');
if (!data) throw new Error(`getPkgJsonFromLastBuild, unable to find pkg aspect data ${suffix}`);
const pkgJsonLastBuild = data?.data?.pkgJson;
if (!pkgJsonLastBuild) throw new Error(`getPkgJsonFromLastBuild, unable to find pkgJson of pkg aspect ${suffix}`);
const current = packageJson.packageJsonObject;
pkgJsonLastBuild.componentId = current.componentId;
pkgJsonLastBuild.version = current.version;
const mergeDeps = (currentDeps?: Record<string, string>, depsFromLastBuild?: Record<string, string>) => {
if (!depsFromLastBuild) return;
if (!currentDeps) return depsFromLastBuild;
Object.keys(depsFromLastBuild).forEach((depName) => {
if (!currentDeps[depName]) return;
depsFromLastBuild[depName] = currentDeps[depName];
});
return depsFromLastBuild;
};
pkgJsonLastBuild.dependencies = mergeDeps(current.dependencies, pkgJsonLastBuild.dependencies);
pkgJsonLastBuild.devDependencies = mergeDeps(current.devDependencies, pkgJsonLastBuild.devDependencies);
pkgJsonLastBuild.peerDependencies = mergeDeps(current.peerDependencies, pkgJsonLastBuild.peerDependencies);
packageJson.mergePackageJsonObject(pkgJsonLastBuild);
}

private getCompForArtifacts(
component: Component,
populateArtifactsFromComps: ConsumerComponent[]
): ConsumerComponent {
const compParent = populateArtifactsFromComps.find((comp) =>
comp.id.isEqual(component.id, { ignoreVersion: true })
);
if (!compParent) {
throw new Error(`isolator, unable to find where to populate the artifacts from for ${component.id.toString()}`);
}
return compParent;
}

private preparePackageJsonToWrite(
component: Component,
bitDir: string,
Expand Down Expand Up @@ -1208,28 +1272,21 @@ export class IsolatorMain {
private async getArtifacts(
component: Component,
legacyScope?: Scope,
populateArtifactsFrom?: ComponentID[]
populateArtifactsFromComps?: ConsumerComponent[]
): Promise<AbstractVinyl[]> {
const legacyComp: ConsumerComponent = component.state._consumer;
if (!legacyScope) {
if (populateArtifactsFrom) throw new Error(`unable to fetch from parent, the legacyScope was not provided`);
// when capsules are written via the workspace, do not write artifacts, they get created by
// build-pipeline. when capsules are written via the scope, we do need the dists.
return [];
}
if (legacyComp.buildStatus !== 'succeed' && !populateArtifactsFrom) {
if (legacyComp.buildStatus !== 'succeed' && !populateArtifactsFromComps) {
// this is important for "bit sign" when on lane to not go to the original scope
return [];
}
const artifactFilesToFetch = async () => {
if (populateArtifactsFrom) {
const found = populateArtifactsFrom.find((id) => id.isEqual(component.id, { ignoreVersion: true }));
if (!found) {
throw new Error(
`getArtifacts: unable to find where to populate the artifacts from for ${component.id.toString()}`
);
}
const compParent = await legacyScope.getConsumerComponent(found);
if (populateArtifactsFromComps) {
const compParent = this.getCompForArtifacts(component, populateArtifactsFromComps);
return getArtifactFilesExcludeExtension(compParent.extensions, 'teambit.pkg/pkg');
}
const extensionsNamesForArtifacts = ['teambit.compilation/compiler'];
Expand Down
2 changes: 2 additions & 0 deletions scopes/component/snapping/snapping.main.runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export class SnappingMain {
ignoreIssues?: string;
incrementBy?: number;
rebuildArtifacts?: boolean;
ignoreLastPkgJson?: boolean;
} & Partial<BasicTagParams>
): Promise<TagResults | null> {
if (this.workspace) {
Expand Down Expand Up @@ -340,6 +341,7 @@ if you're willing to lose the history from the head to the specified version, us
consumerComponents,
tagDataPerComp,
populateArtifactsFrom: shouldUsePopulateArtifactsFrom ? components.map((c) => c.id) : undefined,
populateArtifactsIgnorePkgJson: params.ignoreLastPkgJson,
copyLogFromPreviousSnap: true,
snapping: this,
builder: this.builder,
Expand Down
4 changes: 4 additions & 0 deletions scopes/component/snapping/tag-from-scope.cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ an example of the final data: '[{"componentId":"ci.remote2/comp-b","dependencies
options = [
['', 'push', 'export the updated objects to the original scopes once done'],
['', 'rebuild-artifacts', 'run the full build pipeline. do not use the saved artifacts from the last snap'],
['', 'ignore-last-pkg-json', 'ignore the package.json created by the last snap'],
...tagCmdOptions.filter((o) => !excludeOptions.includes(o[1])),
] as CommandOptions;
remoteOp = true; // In case a compiler / tester is not installed
Expand All @@ -49,6 +50,7 @@ an example of the final data: '[{"componentId":"ci.remote2/comp-b","dependencies
options: {
push?: boolean;
rebuildArtifacts?: boolean;
ignoreLastPkgJson?: boolean;
} & Partial<TagParams>
): Promise<string> {
const { releaseType, preReleaseId } = validateOptions(options);
Expand All @@ -64,6 +66,7 @@ an example of the final data: '[{"componentId":"ci.remote2/comp-b","dependencies
disableTagPipeline = false,
ignoreBuildErrors = false,
rebuildArtifacts,
ignoreLastPkgJson,
rebuildDepsGraph,
incrementBy = 1,
} = options;
Expand All @@ -85,6 +88,7 @@ an example of the final data: '[{"componentId":"ci.remote2/comp-b","dependencies
incrementBy,
version: ver,
rebuildArtifacts,
ignoreLastPkgJson,
};

const tagDataPerCompRaw = this.parseData(data);
Expand Down
4 changes: 3 additions & 1 deletion scopes/component/snapping/tag-model-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export async function tagModelComponent({
ids,
tagDataPerComp,
populateArtifactsFrom,
populateArtifactsIgnorePkgJson,
message,
editor,
exactVersion,
Expand Down Expand Up @@ -211,6 +212,7 @@ export async function tagModelComponent({
ids: ComponentIdList;
tagDataPerComp?: TagDataPerComp[];
populateArtifactsFrom?: ComponentID[];
populateArtifactsIgnorePkgJson?: boolean;
copyLogFromPreviousSnap?: boolean;
exactVersion?: string | null | undefined;
releaseType?: ReleaseType;
Expand Down Expand Up @@ -355,7 +357,7 @@ export async function tagModelComponent({
};
const skipTasksParsed = skipTasks ? skipTasks.split(',').map((t) => t.trim()) : undefined;
const seedersOnly = !workspace; // if tag from scope, build only the given components
const isolateOptions = { packageManagerConfigRootDir, seedersOnly };
const isolateOptions = { packageManagerConfigRootDir, seedersOnly, populateArtifactsIgnorePkgJson };
const builderOptions = { exitOnFirstFailedTask, skipTests, skipTasks: skipTasksParsed };

const componentsToBuild = allComponentsToTag.filter((c) => !c.isRemoved());
Expand Down
2 changes: 1 addition & 1 deletion scopes/lanes/merge-lanes/merge-lane.cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Component pattern format: ${COMPONENT_PATTERN_HELP}`,
[
'',
'include-deps',
'relevant for "--pattern" and "--workspace". merge also dependencies of the specified components',
'relevant for "pattern" and "--workspace". merge also dependencies of the specified components',
],
[
'',
Expand Down