Skip to content

Commit

Permalink
fix(storybook): handle defaultProject issues with projectBuildConfig …
Browse files Browse the repository at this point in the history
…flag (#8494)

* fix(storybook): better error logging for missing projectBuildConfig

* feat(storybook): migrator to add projectBuildConfig

* fix(storybook): set projectBuildConfig in storybook configuration generator

* fix(storybook): find the correct targets for build and storybook
  • Loading branch information
mandarini committed Jan 17, 2022
1 parent bf22b2b commit dcb839c
Show file tree
Hide file tree
Showing 12 changed files with 1,000 additions and 29 deletions.
6 changes: 6 additions & 0 deletions packages/storybook/migrations.json
Expand Up @@ -72,6 +72,12 @@
"cli": "nx",
"description": "Adjust Storybook tsconfig to add styled-jsx typings",
"factory": "./src/migrations/update-12-8-0/update-storybook-styled-jsx-typings"
},
"update-13.4.6": {
"version": "13.4.6-beta.1",
"cli": "nx",
"description": "Add projectBuildConfig option to project's Storybook config.",
"factory": "./src/migrations/update-13-4-6/set-project-build-config"
}
},
"packageJsonUpdates": {
Expand Down
Expand Up @@ -43,6 +43,7 @@ describe('Build storybook', () => {
options = {
uiFramework,
outputPath,
projectBuildConfig: 'proj',
config,
};

Expand Down
Expand Up @@ -35,6 +35,7 @@ describe('@nrwl/storybook:storybook', () => {
options = {
uiFramework: '@storybook/angular',
port: 4400,
projectBuildConfig: 'proj',
config: {
configFolder: storybookPath,
},
Expand Down
85 changes: 61 additions & 24 deletions packages/storybook/src/executors/utils.ts
Expand Up @@ -5,7 +5,10 @@ import {
parseTargetString,
readTargetOptions,
} from '@nrwl/devkit';
import { Workspaces } from '@nrwl/tao/src/shared/workspace';
import {
TargetConfiguration,
Workspaces,
} from '@nrwl/tao/src/shared/workspace';
import { checkAndCleanWithSemver } from '@nrwl/workspace/src/utilities/version-utils';
import 'dotenv/config';
import { existsSync, readFileSync } from 'fs';
Expand Down Expand Up @@ -205,31 +208,36 @@ export function resolveCommonStorybookOptionMapper(

storybookOptions.angularBrowserTarget = targetString;
} else {
// to preserve the backwards compatibility for our users Nx resolves the
// default project just as Storybook used to before

const ws = new Workspaces(context.root);
const defaultProjectName = ws.calculateDefaultProjectName(
context.cwd,
context.workspace
);

buildProjectName = defaultProjectName;

targetOptions = readTargetOptions(
{
project: defaultProjectName,
target: targetName,
configuration: '',
},
context
);

storybookOptions.angularBrowserTarget = normalizeTargetString(
defaultProjectName,
targetName
const { storybookBuildTarget, storybookTarget, buildTarget } =
findStorybookAndBuildTargets(
context?.workspace?.projects?.[context.projectName]?.targets
);

throw new Error(
`
No projectBuildConfig was provided.
To fix this, you can try one of the following options:
1. You can run the ${
context.targetName ? context.targetName : storybookTarget
} executor by providing the projectBuildConfig flag as follows:
nx ${context.targetName ? context.targetName : storybookTarget} ${
context.projectName
} --projectBuildConfig=${context.projectName}${
!buildTarget && storybookBuildTarget ? `:${storybookBuildTarget}` : ''
}
2. In your project configuration, under the "${
context.targetName ? context.targetName : storybookTarget
}" target options, you can
set the "projectBuildConfig" property to the name of the project of which you want to use
the build configuration for Storybook.
`
);
}

const project = context.workspace.projects[buildProjectName];

const angularDevkitCompatibleLogger = {
Expand Down Expand Up @@ -280,3 +288,32 @@ function isStorybookGTE6_4() {
'6.4.0-rc.1'
);
}

export function findStorybookAndBuildTargets(targets: {
[targetName: string]: TargetConfiguration;
}): {
storybookBuildTarget?: string;
storybookTarget?: string;
buildTarget?: string;
} {
const returnObject: {
storybookBuildTarget?: string;
storybookTarget?: string;
buildTarget?: string;
} = {};
Object.entries(targets).forEach(([target, targetConfig]) => {
if (targetConfig.executor === '@nrwl/storybook:storybook') {
returnObject.storybookTarget = target;
}
if (targetConfig.executor === '@nrwl/storybook:build') {
returnObject.storybookBuildTarget = target;
}
if (
targetConfig.executor === '@angular-devkit/build-angular:browser' ||
targetConfig.executor === '@nrwl/angular:ng-packagr-lite'
) {
returnObject.buildTarget = target;
}
});
return returnObject;
}
Expand Up @@ -136,7 +136,7 @@ describe('@nrwl/storybook:configuration', () => {
expect(tree.read('.storybook/main.js', 'utf-8')).toEqual(newContents);
});

it('should update workspace file', async () => {
it('should update workspace file for react libs', async () => {
await configurationGenerator(tree, {
name: 'test-ui-lib',
uiFramework: '@storybook/react',
Expand Down Expand Up @@ -169,6 +169,45 @@ describe('@nrwl/storybook:configuration', () => {
});
});

it('should update workspace file for angular libs', async () => {
// Setup a new lib
await libraryGenerator(tree, {
name: 'test-ui-lib-2',
standaloneConfig: false,
});
await configurationGenerator(tree, {
name: 'test-ui-lib-2',
uiFramework: '@storybook/angular',
standaloneConfig: false,
});
const project = readProjectConfiguration(tree, 'test-ui-lib-2');

expect(project.targets.storybook).toEqual({
executor: '@nrwl/storybook:storybook',
configurations: {
ci: {
quiet: true,
},
},
options: {
port: 4400,
projectBuildConfig: 'test-ui-lib-2:build-storybook',
uiFramework: '@storybook/angular',
config: {
configFolder: 'libs/test-ui-lib-2/.storybook',
},
},
});

expect(project.targets.lint).toEqual({
executor: '@nrwl/linter:eslint',
outputs: ['{options.outputFile}'],
options: {
lintFilePatterns: ['libs/test-ui-lib-2/**/*.ts'],
},
});
});

it('should update `tsconfig.lib.json` file', async () => {
await configurationGenerator(tree, {
name: 'test-ui-lib',
Expand Down
23 changes: 19 additions & 4 deletions packages/storybook/src/generators/configuration/configuration.ts
Expand Up @@ -26,10 +26,10 @@ import {
} from '../../utils/utilities';
import { cypressProjectGenerator } from '../cypress-project/cypress-project';
import { StorybookConfigureSchema } from './schema';
import { storybookVersion } from '../../utils/versions';
import { initGenerator } from '../init/init';
import { checkAndCleanWithSemver } from '@nrwl/workspace/src/utilities/version-utils';
import { gte } from 'semver';
import { findStorybookAndBuildTargets } from '../../executors/utils';

export async function configurationGenerator(
tree: Tree,
Expand All @@ -41,7 +41,9 @@ export async function configurationGenerator(

const workspaceStorybookVersion = getCurrentWorkspaceStorybookVersion(tree);

const { projectType } = readProjectConfiguration(tree, schema.name);
const { projectType, targets } = readProjectConfiguration(tree, schema.name);

const { buildTarget } = findStorybookAndBuildTargets(targets);

const initTask = await initGenerator(tree, {
uiFramework: schema.uiFramework,
Expand All @@ -59,7 +61,7 @@ export async function configurationGenerator(
configureTsProjectConfig(tree, schema);
configureTsSolutionConfig(tree, schema);
updateLintConfig(tree, schema);
addStorybookTask(tree, schema.name, schema.uiFramework);
addStorybookTask(tree, schema.name, schema.uiFramework, buildTarget);
if (schema.configureCypress) {
if (projectType !== 'application') {
const cypressTask = await cypressProjectGenerator(tree, {
Expand Down Expand Up @@ -300,7 +302,8 @@ function dedupe(arr: string[]) {
function addStorybookTask(
tree: Tree,
projectName: string,
uiFramework: string
uiFramework: string,
buildTargetForAngularProjects: string
) {
const projectConfig = readProjectConfiguration(tree, projectName);
projectConfig.targets['storybook'] = {
Expand All @@ -311,6 +314,12 @@ function addStorybookTask(
config: {
configFolder: `${projectConfig.root}/.storybook`,
},
projectBuildConfig:
uiFramework === '@storybook/angular'
? buildTargetForAngularProjects
? projectName
: `${projectName}:build-storybook`
: undefined,
},
configurations: {
ci: {
Expand All @@ -327,6 +336,12 @@ function addStorybookTask(
config: {
configFolder: `${projectConfig.root}/.storybook`,
},
projectBuildConfig:
uiFramework === '@storybook/angular'
? buildTargetForAngularProjects
? projectName
: `${projectName}:build-storybook`
: undefined,
},
configurations: {
ci: {
Expand Down

0 comments on commit dcb839c

Please sign in to comment.