storybook-chromatic
Version:
Visual Testing for Storybook
132 lines (107 loc) • 3.39 kB
JavaScript
import { spawn } from 'cross-spawn';
import pkgUp from 'pkg-up';
import { readFile, writeFile } from 'jsonfile';
import dedent from 'ts-dedent';
import chalk from 'chalk';
const remainingFlags = process.argv.slice(2);
const targets = ['storybook-chromatic', 'storybook-chroma'];
const exec = (args, { pipe } = {}) => {
return new Promise((res, rej) => {
let output = '';
const child = spawn('npm', args);
const streamHandler = d => {
output += d.toString();
};
child.on('exit', code => {
if (code === 0) {
res(output);
} else {
rej(new Error(`${args.join(' ')} exited with code: ${code}`));
}
});
if (pipe) {
child.stdin.pipe(process.stdin);
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
} else {
child.stdout.on('data', streamHandler);
child.stderr.on('data', streamHandler);
}
});
};
const packageJson = {
async read() {
return pkgUp(__dirname).then(l => readFile(l));
},
async write(json) {
return pkgUp(__dirname).then(l => writeFile(l, json, { spaces: 2 }));
},
};
const publishAs = async name => {
const initial = await packageJson.read();
try {
const temp = { ...initial, name };
await packageJson.write(temp);
await exec(['publish', ...remainingFlags], { pipe: true });
} catch (e) {
//
} finally {
await packageJson.write(initial);
}
};
const check = {
async publishable(name, version) {
const text = await exec(['info', name, '--json', '--silent']);
const json = JSON.parse(text);
const { versions } = json.data ? json.data : json;
return !versions.find(v => v === version);
},
async allowed(name) {
const user = (await exec(['whoami', '--silent'])).trim();
const owners = JSON.parse(
await exec(['access', 'ls-collaborators', name, '--json', '--silent'])
);
return !!Object.entries(owners).find(
([useName, permissions]) => useName.match(user) && permissions.includes('write')
);
},
};
const getUnpublishable = async list => {
const { version } = await packageJson.read();
return (
await Promise.all(
list.map(async name => {
const versionOk = await check.publishable(name, version);
const ownershipOk = await check.allowed(name);
if (versionOk && ownershipOk) {
return false;
}
return { name, reason: versionOk ? 'ownership' : 'version' };
})
)
).reduce((acc, item) => acc.concat(item || []), []);
};
const run = async list => {
const unpublishable = await getUnpublishable(list);
if (unpublishable.length === 0) {
targets.reduce(async (acc, item) => {
await acc;
await publishAs(item);
}, Promise.resolve());
} else {
console.log(dedent`
${chalk.red('These packages cannot be published:')}
${unpublishable
.map(
({ name, reason }) =>
`${chalk.blue(name)} could not be published because of a ${chalk.bold(reason)} problem`
)
.join('\n')}
You may lack the required permissions on npm OR the version you're trying to publish already exists,
Upgrade the version or ask permission from current owners
`);
process.exitCode = 1;
}
};
run(targets).catch(e => process.exit(process.exitCode || 1));