UNPKG

@saucelabs/visual

Version:

JS client bindings for Sauce Labs Visual

172 lines (165 loc) 6.47 kB
#!/usr/bin/env node import { VisualApiRegion, displayStatusTable, getApi } from "./chunk-JCFCNGGA.js"; import "./chunk-3IT7HMR5.js"; // src/cli.ts import { Command as Command3, program as program3 } from "commander"; import chalk from "chalk"; // src/cli/build.ts import { Command, Option as Option2, program as program2 } from "commander"; // src/cli/common-options.ts import { program, Option } from "commander"; var regionParser = (input, _previous) => { if (!input) { return VisualApiRegion.fromName("us-west-1"); } try { return VisualApiRegion.fromName(input); } catch (e) { program.error(String(e)); } }; var regionOption = new Option( "-r, --region <region>", "The Sauce Labs region. Options: us-west-1, eu-central-1" ).default(VisualApiRegion.fromName("us-west-1"), "us-west-1").argParser(regionParser); // src/cli/build.ts var hasBuildIdOrCustomId = (args) => { if (args.buildId && args.customId) { program2.error( "Error: only one of --build-id or --custom-id can be specified" ); } if (!args.buildId && !args.customId) { program2.error("Error: --build-id or --custom-id needs to be specified"); } }; function apiFromOptions(opts) { return getApi({ region: opts.region, user: process.env.SAUCE_USERNAME, key: process.env.SAUCE_ACCESS_KEY }); } var buildIdOption = new Option2("-b, --build-id <build-id>"); var customIdOption = new Option2("-c, --custom-id <custom-id>"); var SUCCESS_STATUS = ["APPROVED" /* Approved */, "EQUAL" /* Equal */]; var getBuildResults = async (api, { buildId, customId }) => { const getBuild = async () => { if (customId) return api.buildWithDiffsByCustomId(customId); if (buildId) return api.buildWithDiffs(buildId); return null; }; const build = await getBuild(); if (!build) { throw new Error(`no build with matching criteria has been found`); } return build.diffs.nodes.map((d) => d.status).reduce((r, s) => { r[s] = (r[s] ?? 0) + 1; return r; }, {}); }; var buildStatusCommand = async (_, cmd) => { const options2 = cmd.optsWithGlobals(); hasBuildIdOrCustomId(options2); const visualApi = apiFromOptions(options2); const status = await getBuildResults(visualApi, options2); displayStatusTable(options2.buildId || options2.customId || "", status); const failures = Object.entries(status).filter(([state]) => !SUCCESS_STATUS.includes(state)).map(([_2, count]) => count).reduce((prev, cur) => prev + cur, 0); process.exit(failures ? 1 : 0); }; var statusCommand = () => new Command().name("status").description("Fetches status from a Sauce Visual build").addOption(regionOption).addOption(buildIdOption).addOption(customIdOption).action(buildStatusCommand); var buildCreate = async (_, cmd) => { const options2 = cmd.optsWithGlobals(); const visualApi = apiFromOptions(options2); const build = await visualApi.createBuild({ name: options2.name, branch: options2.branch, customId: options2.customId, project: options2.project, defaultBranch: options2.defaultBranch }); console.info(`Build ${build.id} created`); if (options2.url === true) { console.info(`URL: ${build.url}`); } }; var buildCreateCommand = () => new Command().name("create").description("Creates a Sauce Visual build").addOption(regionOption).requiredOption("-n, --name <name>").addOption(customIdOption).option("--branch <branch>").option("--default-branch <defaultBranch>").option("-p, --project <project>").option("-u, --url", "display build URL after creation").action(buildCreate); var buildFinish = async (_, cmd) => { const options2 = cmd.optsWithGlobals(); hasBuildIdOrCustomId(options2); const visualApi = apiFromOptions(options2); let { buildId } = options2; const { customId } = options2; if (!buildId && customId) { const build = await visualApi.buildByCustomId(customId); if (!build) { program2.error(`customId '${customId}' does not resolve to a build`); } buildId = build.id; } await visualApi.finishBuild({ uuid: buildId }); }; var buildFinishCommand = () => new Command().name("finish").description("Finishes a Sauce Visual build").addOption(regionOption).addOption(buildIdOption).addOption(customIdOption).action(buildFinish); var options = { hidden: false, isDefault: false }; var command = () => new Command().name("build").description("Interacts with a Sauce Visual build").addCommand(statusCommand()).addCommand(buildCreateCommand()).addCommand(buildFinishCommand()); // src/cli/baselines.ts import { Command as Command2 } from "commander"; function apiFromOptions2(opts) { return getApi({ region: opts.region, user: process.env.SAUCE_USERNAME, key: process.env.SAUCE_ACCESS_KEY }); } async function baselineMergeCommand(_, cmd) { const options2 = cmd.optsWithGlobals(); const visualApi = apiFromOptions2(options2); const result = await visualApi.mergeBaselines({ projectName: options2.project, sourceBranch: options2.sourceBranch, targetBranch: options2.targetBranch }); console.log(`Merged baselines: ${result.baselines?.length}`); } var mergeCommand = () => new Command2().name("merge").description("Merge baselines from a source branch into a target branch").addOption(regionOption).requiredOption("-p, --project <project>", "Project name").requiredOption( "-s, --source-branch <branch>", "Branch from which to copy the baselines" ).requiredOption( "-t, --target-branch <branch>", "Branch into which to copy the baselines" ).action(baselineMergeCommand); var baselinesOptions = {}; var baselinesCommand = () => new Command2().name("baselines").description("Interacts with Sauce Visual baselines").addCommand(mergeCommand()); // src/cli.ts var defaultCommand = new Command3().name("default").addOption(buildIdOption).addOption(customIdOption).action(async (...args) => { console.warn( chalk.bold( chalk.redBright( `This command is deprecated. Please use "visual build status" instead of "visual"` ) ) ); await buildStatusCommand(...args); }); program3.name("visual").description("Interacts with Sauce Visual"); program3.addOption(regionOption); program3.addCommand(defaultCommand, { isDefault: true, hidden: true }); program3.addCommand(command(), options); program3.addCommand(baselinesCommand(), baselinesOptions); (async function() { try { program3.parse(); } catch (e) { console.error(`${e}`); process.exit(1); } })();