Skip to content

Commit

Permalink
Merge branch 'next' into 286-update-apis
Browse files Browse the repository at this point in the history
  • Loading branch information
ghengeveld committed Mar 11, 2021
2 parents ae2dcb4 + 4edc95e commit d4bded9
Show file tree
Hide file tree
Showing 19 changed files with 155 additions and 86 deletions.
28 changes: 17 additions & 11 deletions README.md
Expand Up @@ -42,32 +42,36 @@ Before publishing, make sure you've done the following:
- Committed and pushed everything
- Decide on the proper semver bump (major/minor/patch)

#### Doing a `dev` or `rc` release
#### Doing a `canary` or `next` release

We have two types of pre-releases: `dev` and `rc`. `dev` releases are intended for development purposes and should not be used in production, as they may only work against a staging or dev environment. `rc` releases should be valid, working releases that can potentially be used by early adopters of new features, for example to handle a support request.
We have two types of pre-releases: `canary` and `next`. `canary` releases are intended for development purposes and should not be used in production, as they may only work against a staging or dev environment. `next` releases should be valid, working releases that can potentially be used by early adopters of new features, for example to handle a support request.

For the first `dev` (or `rc`) release, bump the version like so (depending on the semver bump):
> As a consumer, **you should not specify a tag** (e.g. `chromatic@next`) in your package dependencies, but rather a specific version number (e.g. `chromatic@5.6.2-next.0`). Otherwise you'll end up with a broken build when we remove or update the tag.
For the first `canary` (or `next`) release, bump the version like so (depending on the semver bump):

```sh
npm version <premajor|preminor|prepatch> --preid dev
npm version <premajor|preminor|prepatch> --preid canary
```

For consecutive `dev` releases on the same version:
For consecutive `canary` releases on the same version:

```sh
npm version prerelease --preid=dev
npm version prerelease --preid=canary
```

Then push and publish:

```sh
git push --follow-tags
npm publish --tag dev
npm publish --tag canary
```

Make sure to replace `dev` with `rc` if appropriate.
Make sure to replace `canary` with `next` if appropriate.

#### Doing a `latest` release

#### Doing a final release
A final release is automatically tagged `latest` by npm.

```sh
npm version <major|minor|patch>
Expand All @@ -76,8 +80,10 @@ npm publish
yarn publish-action
```

And finally, remove the `dev` and/or `rc` tag, if any:
And finally, remove the `canary` and/or `next` tag, if any:

```
npm dist-tag rm chromatic dev
npm dist-tag rm chromatic canary
```

This ensures we can safely do a new `canary` or `next` release later, without anyone getting an unexpected update.
82 changes: 57 additions & 25 deletions action.yml
@@ -1,55 +1,87 @@
name: Publish to Chromatic
author: Chroma Software, Inc.
description: "Publish your Storybook to Chromatic and run visual regression tests"
description: 'Publish your Storybook to Chromatic and run visual regression tests'
branding:
icon: "aperture"
color: "orange"
icon: 'aperture'
color: 'orange'

inputs:
token:
description: "Your github token"
description: 'Your github token'
required: true
projectToken:
description: "Your chromatic project token"
description: 'Your chromatic project token'
required: true
workingDir:
description: "Working directory for the package.json file"
description: 'Working directory for the package.json file'
required: false
appCode:
description: "Deprecated, please use projectToken instead"
description: 'Deprecated, please use projectToken instead'
required: false
buildScriptName:
description: "The npm script that builds your Storybook [build-storybook]"
description: 'The npm script that builds your Storybook [build-storybook]'
required: false
scriptName:
description: "The npm script that starts your Storybook [storybook]"
description: 'The npm script that starts your Storybook [storybook]'
required: false
exec:
description: "Alternatively, a full command to run to start your storybook"
description: 'Alternatively, a full command to run to start your storybook'
required: false
skip:
description: "Skip Chromatic tests, but mark the commit as passing"
description: 'Skip Chromatic tests, but mark the commit as passing'
required: false
doNotStart:
description: "Do not attempt to start or build; use if your Storybook is already running"
description: 'Do not attempt to start or build; use if your Storybook is already running'
required: false
storybookBuildDir:
description: "Provide a directory with your built storybook; use if you have already built your storybook"
description: 'Provide a directory with your built storybook; use if you have already built your storybook'
required: false
storybookCa:
description: "Use if Storybook is running on https (auto detected from -s, if set)"
description: 'Use if Storybook is running on https (auto detected from -s, if set)'
required: false
storybookCert:
description: "Use if Storybook is running on https (auto detected from -s, if set)"
description: 'Use if Storybook is running on https (auto detected from -s, if set)'
required: false
storybookHttps:
description: "Use if Storybook is running on https (auto detected from -s, if set)"
description: 'Use if Storybook is running on https (auto detected from -s, if set)'
required: false
storybookKey:
description: "Use if Storybook is running on https (auto detected from -s, if set)"
description: 'Use if Storybook is running on https (auto detected from -s, if set)'
required: false
storybookPort:
description: "What port is your Storybook running on (auto detected from -s, if set)"
description: 'What port is your Storybook running on (auto detected from -s, if set)'
required: false
storybookUrl:
description: "Storybook is already running at (external) url (implies -S)"
description: 'Storybook is already running at (external) url (implies -S)'
required: false
preserveMissing:
description: "Pass the baselines forward and treat all missing stories as “preserved” without re-capturing them"
description: 'Pass the baselines forward and treat all missing stories as “preserved” without re-capturing them'
required: false
autoAcceptChanges:
description: "Automatically accept all changes in chromatic: boolean or branchname"
description: 'Automatically accept all changes in chromatic: boolean or branchname'
required: false
allowConsoleErrors:
description: "Do not exit when runtime errors occur in storybook"
description: 'Do not exit when runtime errors occur in storybook'
required: false
exitZeroOnChanges:
description: "Positive exit of action even when there are changes: boolean or branchname"
description: 'Positive exit of action even when there are changes: boolean or branchname'
required: false
exitOnceUploaded:
description: "Exit with 0 once the built version has been sent to chromatic: boolean or branchname"
description: 'Exit with 0 once the built version has been sent to chromatic: boolean or branchname'
required: false
ignoreLastBuildOnBranch:
description: "Do not use the last build on this branch as a baseline if it is no longer in history (i.e. branch was rebased)"
description: 'Do not use the last build on this branch as a baseline if it is no longer in history (i.e. branch was rebased)'
required: false

outputs:
url:
description: 'An alias for the build URL (e.g. https://www.chromatic.com/build?appId=<app id goes here>&number=<build number>)'
buildUrl:
description: 'The build URL (e.g. https://www.chromatic.com/build?appId=<app id goes here>&number=<build number>)'
storybookUrl:
description: 'The Storybook preview URL for your current branch / Pull Request (e.g. https://<app id goes here>-<branch hash>.chromatic.com/)'
code:
description: 'The exit code for the current run of the Chromatic CLI'

runs:
main: action/register.js
Expand Down
9 changes: 9 additions & 0 deletions action/README.md
Expand Up @@ -68,6 +68,15 @@ We suggest you use a secret to hide the project token:

You can to configure secrets in the repository settings (`/<owner>/<repository>/settings/secrets`). However if you need to be able to run this action on pull requests from forks, because those can't access your secret.

### Outputs

| Name | Type | Description |
| -------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `url` | string | An alias for the build URL (e.g. `https://www.chromatic.com/build?appId=<app id goes here>&number=<build number>)` |
| `buildUrl` | string | The build URL (e.g. `https://www.chromatic.com/build?appId=<app id goes here>&number=<build number>`) |
| `storybookUrl` | string | The Storybook preview URL for your current branch / Pull Request (e.g. `https://<app id goes here>-<branch hash>.chromatic.com/`) |
| `code` | string | The exit code for the current run of the Chromatic CLI |

## Checkout depth

Version 2 of the `actions/checkout` action will only checkout a single commit without history by default. Chromatic needs the full git history in order to track changes over time. Set `fetch-depth: 0` to enable this. See [actions/checkout](https://github.com/actions/checkout#readme) for details.
Expand Down
2 changes: 1 addition & 1 deletion action/main.js
Expand Up @@ -128,7 +128,7 @@ function runChromatic(options) {
url: (_a = ctx.build) === null || _a === void 0 ? void 0 : _a.webUrl,
code: ctx.exitCode,
buildUrl: (_b = ctx.build) === null || _b === void 0 ? void 0 : _b.webUrl,
storybookUrl: (_c = ctx.build) === null || _c === void 0 ? void 0 : _c.isolatorUrl
storybookUrl: (_c = ctx.build) === null || _c === void 0 ? void 0 : _c.cachedUrl
}];
}
});
Expand Down
2 changes: 1 addition & 1 deletion action/main.ts
Expand Up @@ -81,7 +81,7 @@ async function runChromatic(options): Promise<Output> {
url: ctx.build?.webUrl,
code: ctx.exitCode,
buildUrl: ctx.build?.webUrl,
storybookUrl: ctx.build?.isolatorUrl,
storybookUrl: ctx.build?.cachedUrl,
};
}

Expand Down
7 changes: 7 additions & 0 deletions bin/git/getCommitAndBranch.js
Expand Up @@ -6,6 +6,7 @@ import missingTravisInfo from '../ui/messages/errors/missingTravisInfo';
import travisInternalBuild from '../ui/messages/warnings/travisInternalBuild';
import { getBranch, getCommit, hasPreviousCommit } from './git';

const ORIGIN_PREFIX_REGEXP = /^origin\//;
const notHead = (branch) => (branch && branch !== 'HEAD' ? branch : false);

export async function getCommitAndBranch({ branchName, patchBaseRef, ci, log } = {}) {
Expand Down Expand Up @@ -85,6 +86,12 @@ export async function getCommitAndBranch({ branchName, patchBaseRef, ci, log } =
!!process.env.REPOSITORY_URL || // https://www.netlify.com/docs/continuous-deployment/
!!process.env.GITHUB_REPOSITORY;

// Strip off any `origin/` prefix that's added sometimes.
if (!branchName && !isFromEnvVariable && ORIGIN_PREFIX_REGEXP.test(branch)) {
log.warn(`Ignoring 'origin/' prefix in branch name.`);
branch = branch.replace(ORIGIN_PREFIX_REGEXP, '');
}

log.debug(
`git info: ${JSON.stringify({
commit,
Expand Down
2 changes: 1 addition & 1 deletion bin/lib/getEnv.js
Expand Up @@ -2,7 +2,7 @@
const {
CHROMATIC_SERVER_PORT = 3004,
CHROMATIC_INDEX_URL = 'https://index.chromatic.com',
CHROMATIC_TUNNEL_URL = 'https://tunnel.chromatic.com',
CHROMATIC_TUNNEL_URL = 'https://tunnel.chromaticqa.com',
CHROMATIC_CREATE_TUNNEL = 'true',
CHROMATIC_RETRIES = 5,
CHROMATIC_POLL_INTERVAL = 1000,
Expand Down
1 change: 1 addition & 0 deletions bin/lib/getStorybookInfo.js
Expand Up @@ -5,6 +5,7 @@ import fs from 'fs-extra';
const viewLayers = [
'react',
'vue',
'vue3',
'angular',
'html',
'web-components',
Expand Down
23 changes: 12 additions & 11 deletions bin/main.test.js
Expand Up @@ -127,17 +127,18 @@ fs.statSync = jest.fn((path) => {
});

jest.mock('./git/git', () => ({
hasPreviousCommit: () => true,
getCommit: () => ({
commit: 'commit',
committedAt: 1234,
committerEmail: 'test@test.com',
committerName: 'tester',
}),
getBranch: () => 'branch',
getBaselineCommits: () => ['baseline'],
getSlug: () => 'user/repo',
getVersion: () => '2.24.1',
hasPreviousCommit: () => Promise.resolve(true),
getCommit: () =>
Promise.resolve({
commit: 'commit',
committedAt: 1234,
committerEmail: 'test@test.com',
committerName: 'tester',
}),
getBranch: () => Promise.resolve('branch'),
getBaselineCommits: () => Promise.resolve(['baseline']),
getSlug: () => Promise.resolve('user/repo'),
getVersion: () => Promise.resolve('2.24.1'),
}));

jest.mock('./lib/startStorybook');
Expand Down
2 changes: 1 addition & 1 deletion bin/tasks/build.js
Expand Up @@ -27,7 +27,7 @@ export const setSpawnParams = (ctx) => {
// Based on https://github.com/mysticatea/npm-run-all/blob/52eaf86242ba408dedd015f53ca7ca368f25a026/lib/run-task.js#L156-L174
const npmExecPath = process.env.npm_execpath;
const isJsPath = typeof npmExecPath === 'string' && /\.m?js/.test(path.extname(npmExecPath));
const isYarn = npmExecPath && path.basename(npmExecPath) === 'yarn.js';
const isYarn = npmExecPath && /^yarn(\.js)?$/.test(path.basename(npmExecPath));
ctx.spawnParams = {
command: (isJsPath ? process.execPath : npmExecPath) || 'npm',
clientArgs: isJsPath ? [npmExecPath, 'run'] : ['run', '--silent'],
Expand Down
11 changes: 11 additions & 0 deletions bin/tasks/build.test.js
Expand Up @@ -41,6 +41,17 @@ describe('setSpawnParams', () => {
scriptArgs: ['build:storybook', '--', '--output-dir', './source-dir/'],
});
});

it('supports yarn', async () => {
process.env.npm_execpath = '/path/to/yarn';
const ctx = { sourceDir: './source-dir/', options: { buildScriptName: 'build:storybook' } };
await setSpawnParams(ctx);
expect(ctx.spawnParams).toEqual({
command: '/path/to/yarn',
clientArgs: ['run', '--silent'],
scriptArgs: ['build:storybook', '--output-dir', './source-dir/'],
});
});
});

describe('buildStorybook', () => {
Expand Down
6 changes: 4 additions & 2 deletions bin/tasks/gitInfo.js
Expand Up @@ -21,10 +21,12 @@ const TesterSkipBuildMutation = `
export const setGitInfo = async (ctx, task) => {
const { branchName, patchBaseRef, fromCI: ci } = ctx.options;
ctx.git = await getCommitAndBranch({ branchName, patchBaseRef, ci, log: ctx.log });
ctx.git.slug = ctx.git.slug || (await getSlug());
ctx.git.version = await getVersion();
if (!ctx.git.slug) {
ctx.git.slug = await getSlug().catch((e) => ctx.log.warn('Failed to retrieve slug', e));
}

if (ctx.options.ownerName) {
if (ctx.git.slug && ctx.options.ownerName) {
ctx.git.slug = ctx.git.slug.replace(/[^/]+/, ctx.options.ownerName);
}

Expand Down
16 changes: 8 additions & 8 deletions bin/tasks/gitInfo.test.js
Expand Up @@ -9,10 +9,10 @@ const log = { debug: jest.fn() };

describe('setGitInfo', () => {
it('sets the git info on context', async () => {
getCommitAndBranch.mockReturnValue({ commit: '123asdf', branch: 'something' });
getBaselineCommits.mockReturnValue(['asd2344']);
getVersion.mockReturnValue('Git v1.0.0');
getSlug.mockReturnValue('user/repo');
getCommitAndBranch.mockResolvedValue({ commit: '123asdf', branch: 'something' });
getBaselineCommits.mockResolvedValue(['asd2344']);
getVersion.mockResolvedValue('Git v1.0.0');
getSlug.mockResolvedValue('user/repo');
const ctx = { log, options: {} };
await setGitInfo(ctx, {});
expect(ctx.git).toMatchObject({
Expand All @@ -25,10 +25,10 @@ describe('setGitInfo', () => {
});

it('supports overriding the owner name in the slug', async () => {
getCommitAndBranch.mockReturnValue({ commit: '123asdf', branch: 'something' });
getBaselineCommits.mockReturnValue(['asd2344']);
getVersion.mockReturnValue('Git v1.0.0');
getSlug.mockReturnValue('user/repo');
getCommitAndBranch.mockResolvedValue({ commit: '123asdf', branch: 'something' });
getBaselineCommits.mockResolvedValue(['asd2344']);
getVersion.mockResolvedValue('Git v1.0.0');
getSlug.mockResolvedValue('user/repo');
const ctx = { log, options: { ownerName: 'org' } };
await setGitInfo(ctx, {});
expect(ctx.git).toMatchObject({
Expand Down
8 changes: 4 additions & 4 deletions bin/tasks/tunnel.test.js
Expand Up @@ -10,19 +10,19 @@ const log = { debug: jest.fn() };

describe('createTunnel', () => {
it('opens the tunnel and sets the isolatorUrl on context', async () => {
openTunnel.mockReturnValue({ url: 'https://tunnel.chromatic.com' });
openTunnel.mockReturnValue({ url: 'https://tunnel.chromaticqa.com' });

const ctx = { log, isolatorUrl: 'http://localhost:9001', options: {} };
await createTunnel(ctx);

expect(openTunnel).toHaveBeenCalledWith({ log, port: '9001', https: undefined });
expect(ctx.isolatorUrl).toBe('https://tunnel.chromatic.com/');
expect(ctx.isolatorUrl).toBe('https://tunnel.chromaticqa.com/');
});
});

describe('testConnection', () => {
it('tries to fetch the isolatorUrl', async () => {
testConnection({ isolatorUrl: 'https://tunnel.chromatic.com' });
expect(fetch).toHaveBeenCalledWith('https://tunnel.chromatic.com');
testConnection({ isolatorUrl: 'https://tunnel.chromaticqa.com' });
expect(fetch).toHaveBeenCalledWith('https://tunnel.chromaticqa.com');
});
});
2 changes: 1 addition & 1 deletion bin/tasks/verify.test.js
Expand Up @@ -28,7 +28,7 @@ describe('createBuild', () => {
git: { version: 'whatever', matchesBranch: () => false },
pkg: { version: '1.0.0' },
storybook: { version: '2.0.0', viewLayer: 'react', addons: [] },
isolatorUrl: 'https://tunnel.chromatic.com/',
isolatorUrl: 'https://tunnel.chromaticqa.com/',
};

it('creates a build on the index and puts it on context', async () => {
Expand Down
2 changes: 1 addition & 1 deletion bin/ui/messages/errors/fatalError.stories.js
Expand Up @@ -36,7 +36,7 @@ const context = {
number: 1400,
webUrl: 'https://www.chromatic.com/build?appId=5d67dc0374b2e300209c41e7&number=1400',
},
isolatorUrl: 'https://pfkaemtlit.tunnel.chromatic.com/iframe.html',
isolatorUrl: 'https://pfkaemtlit.tunnel.chromaticqa.com/iframe.html',
cachedUrl: 'https://5d67dc0374b2e300209c41e7-pfkaemtlit.chromatic.com/iframe.html',
};

Expand Down
4 changes: 2 additions & 2 deletions bin/ui/tasks/tunnel.stories.js
Expand Up @@ -6,8 +6,8 @@ export default {
decorators: [(storyFn) => task(storyFn())],
};

const CHROMATIC_TUNNEL_URL = 'https://tunnel.chromatic.com';
const cachedUrl = 'https://fdeulpymiq.tunnel.chromatic.com/iframe.html';
const CHROMATIC_TUNNEL_URL = 'https://tunnel.chromaticqa.com';
const cachedUrl = 'https://fdeulpymiq.tunnel.chromaticqa.com/iframe.html';

export const Initial = () => initial;

Expand Down

0 comments on commit d4bded9

Please sign in to comment.