Skip to content
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
74 changes: 67 additions & 7 deletions .github/workflows/publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,71 @@

1. `git checkout v8`
2. `git pull`
3. `git checkout -b hotfix/v<next-patch-release-version>`
4. Apply necessary hotfixes
5. `cd scripts && yarn release:version --deferred --release-type patch --verbose && cd .. && git add . && git commit -m "Bump deferred version"`
6. Add a new entry for the new version to the `CHANGELOG.md` file
7. Trigger canary release via dispatching the workflow for `publish-canary`
8. Test the canary release
3. Define which next patch version this release will be (last released version + patch e.g. 8.1.2 -> 8.1.3)
4. `git checkout -b hotfix/v<next-patch-release-version>`
5. Apply necessary hotfixes, finish the work and make a PR. Save that PR number to use later.
6. At the root of the repo, run a script to prepare for the new version
- `cd scripts && yarn release:version --deferred --release-type patch --verbose && cd .. && git add . && git commit -m "Bump deferred version"`
7. Manually add a new entry for the new version to the `CHANGELOG.md` file including the description of the change
8. Trigger canary release to test in real projects
1. Add the hotfix branch name as deployment branch here: https://github.com/storybookjs/storybook/settings/environments/1012979736/edit
2. Dispatch the `publish-canary` workflow and select the hotfix branch name and PR number: https://github.com/storybookjs/storybook/actions/workflows/publish.yml
3. Test the canary release (MealDrop has a [storybook/8.0.0](https://github.com/yannbf/mealdrop/tree/storybook/8.0.0) branch if you like to use for testing)
4. Remove the deployment branch name added in step 1
9. Merge `hotfix/v<next-patch-release-version>` into `v8`
10. Observe the `publish-normal` job
10. Observe the `publish-normal` job
11. Observe the generated release in GitHub releases page and make modifications to the release notes if necessary

## Known CI issues

Some CI failures are known and acceptable, so long as they do not impact the patch changes. Here's an overview of currently known and ignorable CI failures:

- UI Review: bench/react-vite-default-ts-test-build
- UI Review: bench/react-webpack-18-ts-test-build
- UI Review: storybook-ui

Additionally, certain jobs will fail with known and acceptable issues:

### Test Runner Production: Running Test Runner

103 failures:

```
Test suite failed to run

Failed to deserialize buffer as swc::config::Options
JSON: {"jsc":{"target":"es2023","transform":{"hidden":{"jest":true}}},"sourceMaps":"inline","module":{"type":"commonjs"},"filename":"/tmp/37b7a1ae084822841eff3e2d58b09cd9/addons-docs-docspage-error.test.js"}

Caused by:
unknown variant `es2023`, expected one of `es3`, `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021`, `es2022`, `esnext` at line 1 column 201
```

### Vitest integration: Running story tests in Vitest

```
⎯⎯⎯⎯⎯⎯⎯ Startup Error ⎯⎯⎯⎯⎯⎯⎯⎯
Error [ERR_REQUIRE_ESM]: require() of ES Module /tmp/storybook/sandbox/experimental-nextjs-vite-default-ts/node_modules/vite/dist/node/index.js from /tmp/storybook/sandbox/experimental-nextjs-vite-default-ts/node_modules/vitest/dist/config.cjs not supported.
Instead change the require of index.js in /tmp/storybook/sandbox/experimental-nextjs-vite-default-ts/node_modules/vitest/dist/config.cjs to a dynamic import() which is available in all CommonJS modules.
at _require.extensions.<computed> [as .js] (file:///tmp/storybook/sandbox/experimental-nextjs-vite-default-ts/node_modules/vite/dist/node/chunks/config.js:35920:9)
at Object.<anonymous> (/tmp/storybook/sandbox/experimental-nextjs-vite-default-ts/node_modules/vitest/dist/config.cjs:5:12)
at _require.extensions.<computed> [as .js] (file:///tmp/storybook/sandbox/experimental-nextjs-vite-default-ts/node_modules/vite/dist/node/chunks/config.js:35920:9) {
code: 'ERR_REQUIRE_ESM'
}
```

```
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 5 ⎯⎯⎯⎯⎯⎯⎯

FAIL storybook (chromium) template-stories/addons/docs/docspage/iframe.stories.ts > Basic

Test timed out in 5000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
❯ _test template-stories/addons/docs/docspage/iframe.stories.ts:16:7
```

### test-init-empty-npm-nextjs-ts: Storybook init from empty directory (NPM)

```
ERROR in main
Module not found: TypeError: Cannot read properties of undefined (reading 'tap')
```
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ tsconfig.vitest-temp.json
!/**/.yarn/versions
!/**/.yarn/patches
/**/.pnp.*
!/node_modules

# test-storybooks
test-storybooks/ember-cli/ember-output
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 8.6.18

- Add request validation
Comment thread
ghengeveld marked this conversation as resolved.

## 8.6.17

- Harden websocket connection
Expand Down
13 changes: 7 additions & 6 deletions code/builders/builder-vite/src/vite-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ export async function createViteServer(options: Options, devServer: Server) {

const commonCfg = await commonConfig(options, 'development');

const { allowedHosts } = await presets.apply('core', {});

const config: InlineConfig & { server: ServerOptions } = {
...commonCfg,
// Set up dev server
server: {
allowedHosts,
middlewareMode: true,
hmr: {
port: options.port,
Expand All @@ -29,14 +32,12 @@ export async function createViteServer(options: Options, devServer: Server) {
optimizeDeps: await getOptimizeDeps(commonCfg, options),
};

const ipRegex = /^(?:\d{1,3}\.){3}\d{1,3}$|^(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/;

// '0.0.0.0' binds to all interfaces, which is useful for Docker and other containerized environments
if (
!(config.server.allowedHosts as string[])?.length &&
options.host &&
!ipRegex.test(options.host)
options.host === '0.0.0.0' &&
(!allowedHosts || (Array.isArray(allowedHosts) && allowedHosts.length === 0))
) {
config.server.allowedHosts = [options.host.toLowerCase()];
config.server.allowedHosts = true;
Comment thread
ghengeveld marked this conversation as resolved.
}

const finalConfig = await presets.apply('viteFinal', config, options);
Expand Down
1 change: 1 addition & 0 deletions code/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@
"get-npm-tarball-url": "^2.0.3",
"glob": "^10.0.0",
"globby": "^14.0.1",
"host-validation-middleware": "^0.1.2",
"jiti": "^1.21.6",
"js-yaml": "^4.1.0",
"lazy-universal-dotenv": "^4.0.0",
Expand Down
18 changes: 16 additions & 2 deletions code/core/src/core-server/build-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { oneWayHash, telemetry } from '@storybook/core/telemetry';
import type { BuilderOptions, CLIOptions, LoadOptions, Options } from '@storybook/core/types';
import { global } from '@storybook/global';

import { deprecate } from '@storybook/core/node-logger';
import { deprecate, logger } from '@storybook/core/node-logger';
import { MissingBuilderError, NoStatsForViteDevError } from '@storybook/core/server-errors';

import prompts from 'prompts';
Expand Down Expand Up @@ -136,7 +136,20 @@ export async function buildDevStandalone(
isCritical: true,
});

const { renderer, builder, disableTelemetry } = await presets.apply('core', {});
const { allowedHosts, renderer, builder, disableTelemetry } = await presets.apply('core', {});

Comment thread
ghengeveld marked this conversation as resolved.
// '0.0.0.0' binds to all interfaces, which is useful for Docker and other containerized environments.
// By default we allow requests from all hosts in this case, but the user should be made aware of the risk.
if (
options.host === '0.0.0.0' &&
(!allowedHosts || (allowedHosts !== true && allowedHosts.length === 0))
) {
logger.warn(dedent`
--host is set to 0.0.0.0 but no allowedHosts are defined. Allowing all hosts.
To restrict allowed hosts, set core.allowedHosts in your main Storybook config.
See: https://storybook.js.org/docs/api/main-config/main-config-core
`);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

if (!builder) {
throw new MissingBuilderError();
Expand Down Expand Up @@ -251,6 +264,7 @@ export async function buildDevStandalone(
name,
address,
networkAddress,
allowedHosts,
managerTotalTime,
previewTotalTime,
});
Expand Down
27 changes: 21 additions & 6 deletions code/core/src/core-server/dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getManagerBuilder, getPreviewBuilder } from './utils/get-builders';
import { getCachingMiddleware } from './utils/get-caching-middleware';
import { getServerChannel } from './utils/get-server-channel';
import { getAccessControlMiddleware } from './utils/getAccessControlMiddleware';
import { getHostValidationMiddleware } from './utils/getHostValidationMiddleware';
import { getStoryIndexGenerator } from './utils/getStoryIndexGenerator';
import { getMiddleware } from './utils/middleware';
import { openInBrowser } from './utils/open-in-browser';
Expand All @@ -28,9 +29,20 @@ export async function storybookDevServer(options: Options) {

assert(core?.channelOptions?.wsToken, 'wsToken is required for securing the server channel');

const { port, host, initialPath } = options;
invariant(port, 'expected options to have a port');
const proto = options.https ? 'https' : 'http';
const { address, networkAddress } = getServerAddresses(port, host, proto, initialPath);

const serverChannel = await options.presets.apply(
'experimental_serverChannel',
getServerChannel(server, core.channelOptions.wsToken)
getServerChannel(server, {
token: core.channelOptions.wsToken,
host,
allowedHosts: core.allowedHosts,
localAddress: address,
networkAddress,
})
);

let indexError: Error | undefined;
Expand All @@ -47,16 +59,19 @@ export async function storybookDevServer(options: Options) {
options.extendServer(server);
}

app.use(
getHostValidationMiddleware({
host,
allowedHosts: core?.allowedHosts,
localAddress: address,
networkAddress,
})
);
app.use(getAccessControlMiddleware(core?.crossOriginIsolated ?? false));
app.use(getCachingMiddleware());

getMiddleware(options.configDir)(app);

const { port, host, initialPath } = options;
invariant(port, 'expected options to have a port');
const proto = options.https ? 'https' : 'http';
const { address, networkAddress } = getServerAddresses(port, host, proto, initialPath);

if (!core?.builder) {
throw new MissingBuilderError();
}
Expand Down
Loading