Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/next' into fix/remove-nodeenv-de…
Browse files Browse the repository at this point in the history
…velopment
  • Loading branch information
tmeasday committed Apr 8, 2020
2 parents a66131f + dff9a8d commit cea5c89
Show file tree
Hide file tree
Showing 27 changed files with 2,350 additions and 1,894 deletions.
3 changes: 1 addition & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
# If you need an app_code for local testing, we'll give you one for free:
# [email protected]

CHROMATIC_APP_CODE=<place app_code here>
CHROMATIC_PROJECT_TOKEN=<place app_code here>

# CHROMATIC_INDEX_URL=https://www.chromaticqa.com
# CHROMATIC_TUNNEL_URL=http://tunnel.chromaticqa.com

2 changes: 1 addition & 1 deletion .github/workflows/chromatic-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ jobs:
env:
DEBUG: chromatic-cli
with:
appCode: ${{ secrets.CHROMATIC_APP_CODE }}
projectToken: gcaw1ai2dgo
token: ${{ secrets.GITHUB_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/chromatic-manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
- name: run chromatic
run: yarn chromatic
env:
CHROMATIC_APP_CODE: ${{ secrets.CHROMATIC_APP_CODE }}
CHROMATIC_PROJECT_TOKEN: gcaw1ai2dgo
2 changes: 1 addition & 1 deletion .github/workflows/chromatic-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
- name: run chromatic
run: yarn chromatic
env:
CHROMATIC_APP_CODE: ${{ secrets.CHROMATIC_APP_CODE }}
CHROMATIC_PROJECT_TOKEN: gcaw1ai2dgo
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 3.5.2 - 2020-02-18

- FIX version of JSDOM to 16.1 as 16.2 includes a conflicting custom element support https://github.com/chromaui/chromatic-cli/issues/95

# 3.5.1 - 2020-02-06

- FIX setting the `fromCI` flag from our github action https://github.com/chromaui/action/issues/14

# 3.5.0 - 2020-01-28

- CHANGE so the CLI stop on storybook runtime errors https://github.com/chromaui/chromatic-cli/issues/75
Expand All @@ -7,6 +15,19 @@
- IMPROVE readability of the error when storybook runtime throws an error https://github.com/chromaui/chromatic-cli/issues/73
- FIX `Intl.PluralRules.supportedLocalesOf is not a function` error https://github.com/chromaui/chromatic-cli/issues/76

# 3.4.0 - 2019-12-25

- FIX pubish script

# 3.3.0 - 2019-12-25

- IMPROVE logging when git fails
- FIX script for windows
- ADD `--exit-once-uploaded` flag
- FIX escape chararacters in error messages

# 3.2.0 failed upload to npm

# 3.1.0 - 2019-11-04

- ADD jsdom shim for SVG elements
Expand Down Expand Up @@ -241,4 +262,4 @@
# 0.7.3 - 2017-12-09

- We now upload your application bundle to our tunnel server directly from the package.
This means that on slower uplinks, we no need to set arbitrary timeouts in our server process; instead we simply will not start your Chromatic build until we've verified the bundle has uploaded successfully.
This means that on slower uplinks, we no need to set arbitrary timeouts in our server process; instead we simply will not start your Chromatic build until we've verified the bundle has uploaded successfully.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ Do not run this based on a github pull_request event. If you do, the commit and
### Main options

```
--app-code="<your app code>"
--project-token="<your token>"
```

You can also use the environment variable: `CHROMATIC_APP_CODE`
You can also use the environment variable: `CHROMATIC_PROJECT_TOKEN`

### Storybook options

Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ steps:
node ./scripts/rename.js storybook-chromatic
displayName: 'yarn install and build'
- script: |
yarn chromatic --appCode="gcaw1ai2dgo"
yarn chromatic --project-token="gcaw1ai2dgo"
displayName: 'run chromatic'
14 changes: 7 additions & 7 deletions bin/__tests__/parseArgv.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { parseArgv } from '../main';

jest.mock('../constants', () => ({
CHROMATIC_CREATE_TUNNEL: true,
CHROMATIC_APP_CODE: 'env-code',
CHROMATIC_PROJECT_TOKEN: 'env-code',
}));

jest.mock('jsonfile', () => ({
Expand All @@ -18,12 +18,12 @@ jest.mock('jsonfile', () => ({
}),
}));

process.env.CHROMATIC_APP_CODE = 'test';
process.env.CHROMATIC_PROJECT_TOKEN = 'test';

describe('await parseArgv', () => {
it('sets reasonable defaults', async () => {
expect(await parseArgv(['--app-code', 'cli-code'])).toMatchObject({
appCode: 'cli-code',
expect(await parseArgv(['--project-token', 'cli-code'])).toMatchObject({
projectToken: 'cli-code',
buildScriptName: 'build-storybook',
noStart: true,
fromCI: false,
Expand All @@ -33,13 +33,13 @@ describe('await parseArgv', () => {
interactive: true,
verbose: false,
createTunnel: true,
originalArgv: ['--app-code', 'cli-code'],
originalArgv: ['--project-token', 'cli-code'],
});
});

it('picks up app-code from environment', async () => {
it('picks up project-token from environment', async () => {
expect(await parseArgv([])).toMatchObject({
appCode: 'env-code',
projectToken: 'env-code',
});
});

Expand Down
25 changes: 22 additions & 3 deletions bin/__tests__/tester.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ const defaultOutput = {
specCount: 1,
};

let mockBuildFeatures;
beforeEach(() => {
mockBuildFeatures = {
features: { uiTests: true, uiReview: true },
wasLimited: false,
};
});

jest.mock('node-fetch', () => async (url, { body } = {}) => ({
ok: true,
json: async () => {
Expand All @@ -38,9 +46,12 @@ jest.mock('node-fetch', () => async (url, { body } = {}) => ({
specCount: 1,
componentCount: 1,
webUrl: 'http://test.com',
...mockBuildFeatures,
app: {
account: {
features: { diffs: true },
billingUrl: 'https://foo.bar',
exceededThreshold: false,
paymentRequired: false,
},
},
},
Expand Down Expand Up @@ -119,10 +130,10 @@ afterEach(() => {
});

const defaultOptions = {
appCode: 'code',
projectToken: 'code',
scriptName: 'storybook',
url: 'http://localhost:1337/iframe.html',
originalArgv: ['node', 'chromatic', 'test', '--appCode', 'code'],
originalArgv: ['node', 'chromatic', '--project-token', 'code'],
};

it('runs in simple situations', async () => {
Expand Down Expand Up @@ -190,6 +201,14 @@ it('returns 0 when stopped after the build has been sent to chromatic', async ()
).toEqual({ exitCode: 0, exitUrl: 'http://test.com' });
});

it('returns 0 when the build is publish only', async () => {
mockBuildFeatures = {
features: { uiTests: false, uiReview: false },
wasLimited: false,
};
expect(await runTest(defaultOptions)).toEqual({ exitCode: 0, exitUrl: 'http://test.com' });
});

it('detects CI environments successfully', async () => {
// Standard CI
process.env = { CI: 'true', DISABLE_LOGGING: 'true' };
Expand Down
7 changes: 5 additions & 2 deletions bin/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ const STORYBOOK_CLI_FLAGS_BY_VERSION = {
'--loglevel': '5.1.0',
};

const CHROMATIC_APP_CODE = process.env.CHROMATIC_APP_CODE || process.env.CHROMA_APP_CODE;
const CHROMATIC_PROJECT_TOKEN =
process.env.CHROMATIC_PROJECT_TOKEN ||
process.env.CHROMATIC_APP_CODE || // backwards compatibility
process.env.CHROMA_APP_CODE; // backwards compatibility

export {
CHROMATIC_SERVER_PORT,
CHROMATIC_INDEX_URL,
CHROMATIC_TUNNEL_URL,
CHROMATIC_CREATE_TUNNEL,
CHROMATIC_APP_CODE,
CHROMATIC_PROJECT_TOKEN,
CHROMATIC_RETRIES,
CHROMATIC_POLL_INTERVAL,
CHROMATIC_TIMEOUT,
Expand Down
10 changes: 7 additions & 3 deletions bin/git/getCommitAndBranch.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ const notHead = b => {
return b;
};

export async function getCommitAndBranch({ inputFromCI } = {}) {
export async function getCommitAndBranch({ patchBaseRef, inputFromCI } = {}) {
// eslint-disable-next-line prefer-const
let { commit, committedAt, committerEmail, committerName } = await getCommit();
let branch = await getBranch();
let branch = patchBaseRef || (await getBranch());

const {
TRAVIS_EVENT_TYPE,
Expand Down Expand Up @@ -96,7 +96,11 @@ export async function getCommitAndBranch({ inputFromCI } = {}) {
'HEAD';
}
// REPOSITORY_URL is for netlify: https://www.netlify.com/docs/continuous-deployment/
const fromCI = inputFromCI || !!process.env.CI || !!process.env.REPOSITORY_URL;
const fromCI =
!!inputFromCI ||
!!process.env.CI ||
!!process.env.REPOSITORY_URL ||
!!process.env.GITHUB_REPOSITORY;
debug(
`git info: ${JSON.stringify({
commit,
Expand Down
102 changes: 100 additions & 2 deletions bin/git/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { execSync } from 'child_process';
import setupDebug from 'debug';
import gql from 'fake-tag';
import dedent from 'ts-dedent';

import log from '../lib/log';
import { EOL } from 'os';

const debug = setupDebug('chromatic-cli:git');

Expand Down Expand Up @@ -252,3 +251,102 @@ export async function getBaselineCommits(client, { branch, ignoreLastBuildOnBran
// For any pair A,B of builds, there is no point in using B if it is an ancestor of A.
return [...extraBaselineCommits, ...(await maximallyDescendentCommits(commitsWithBuilds))];
}

/**
* Returns a boolean indicating whether the workspace is up-to-date (neither ahead nor behind) with
* the remote.
*/
export async function isUpToDate() {
execGitCommand(`git remote update`);
const localCommit = await execGitCommand('git rev-parse HEAD');
const remoteCommit = await execGitCommand('git rev-parse @{u}');
if (!localCommit) {
throw new Error('Failed to retrieve last local commit hash');
}
if (!remoteCommit) {
throw new Error('Failed to retrieve last remote commit hash');
}
return localCommit === remoteCommit;
}

/**
* Returns a boolean indicating whether the workspace is clean (no changes, no untracked files).
*/
export async function isClean() {
const status = await execGitCommand('git status --porcelain');
return status === '';
}

/**
* Returns the "Your branch is behind by n commits (pull to update)" part of the git status message,
* omitting any of the other stuff that may be in there. Note we expect the workspace to be clean.
*/
export async function getUpdateMessage() {
const status = await execGitCommand('git status');
return status
.split(EOL + EOL)[0] // drop the 'nothing to commit' part
.split(EOL)
.filter(line => !line.startsWith('On branch')) // drop the 'On branch x' part
.join(EOL)
.trim();
}

/**
* Returns the git merge base between two branches, which is the best common ancestor between the
* last commit on either branch. The "best" is defined by not having any descendants which are a
* common ancestor themselves. Consider this example:
*
* - A - M <= master
* \ /
* B <= develop
* \
* C <= feature
*
* The merge base between master and feature is B, because it's the best common ancestor of C and M.
* A is a common ancestor too, but it isn't the "best" one because it's an ancestor of B.
*
* It's also possible to have a situation with two merge bases, where there isn't one "best" option:
*
* - A - M <= master
* \ /
* x (not a commit)
* / \
* - B - N <= develop
*
* Here, both A and B are the best common ancestor between master and develop. Neither one is the
* single "best" option because they aren't ancestors of each other. In this case we try to pick the
* one on the base branch, but if that fails we just pick the first one and hope it works out.
* Luckily this is an uncommon scenario.
*
* @param {string} headRef Name of the head branch
* @param {string} baseRef Name of the base branch
*/
export async function findMergeBase(headRef, baseRef) {
const result = await execGitCommand(`git merge-base --all ${headRef} ${baseRef}`);
const mergeBases = result.split(EOL).filter(Boolean);
if (mergeBases.length === 0) return undefined;
if (mergeBases.length === 1) return mergeBases[0];

// If we find multiple merge bases, look for one on the base branch.
// If we don't find a merge base on the base branch, just return the first one.
const branchNames = await Promise.all(
mergeBases.map(async sha => {
const name = await execGitCommand(`git name-rev --name-only --exclude="tags/*" ${sha}`);
return name.replace(/~[0-9]+$/, ''); // Drop the potential suffix
})
);
const baseRefIndex = branchNames.findIndex(branch => branch === baseRef);
return mergeBases[baseRefIndex] || mergeBases[0];
}

export async function checkout(ref) {
return execGitCommand(`git checkout ${ref}`);
}

export async function checkoutPrevious() {
return execGitCommand(`git checkout -`);
}

export async function discardChanges() {
return execGitCommand(`git reset --hard`);
}
15 changes: 10 additions & 5 deletions bin/io/gql-queries.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const TesterCreateAppTokenMutation = `
mutation TesterCreateAppTokenMutation($appCode: String!) {
createAppToken(code: $appCode)
mutation TesterCreateAppTokenMutation($projectToken: String!) {
createAppToken(code: $projectToken)
}
`;

Expand All @@ -13,11 +13,16 @@ export const TesterCreateBuildMutation = `
snapshotCount
componentCount
webUrl
features {
uiTests
uiReview
}
wasLimited
app {
account {
features {
diffs
}
exceededThreshold
paymentRequired
billingUrl
}
}
}
Expand Down
Loading

0 comments on commit cea5c89

Please sign in to comment.