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
3 changes: 0 additions & 3 deletions src/commander/uploadPdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ command
.name('upload-pdf')
.description('Upload PDFs for visual comparison')
.argument('<directory>', 'Path of the directory containing PDFs')
.option('-c --config <filepath>', 'Config file path; the same file used by exec, thresholds read from the top level or a pdf block')
.option('--fetch-results [filename]', 'Fetch results and optionally specify an output file, e.g., <filename>.json')
.option('--buildName <string>', 'Specify the build name')
.option('--markBaseline', 'Mark this build baseline')
.option('--pdfNames <string>', 'Specify PDF names for the upload')
.option('--approvalThreshold <number>', 'Mismatch % at or below which every PDF in this upload is auto-approved (0-100); per-PDF overrides go in the config file under pdf.thresholds')
.option('--rejectionThreshold <number>', 'Mismatch % at or above which every PDF in this upload is auto-rejected (0-100); per-PDF overrides go in the config file under pdf.thresholds')
.option('--sync', 'Wait for the uploaded PDFs to be compared and return the results')
.action(async function(directory, _, command) {
const options = command.optsWithGlobals();
Expand Down
21 changes: 1 addition & 20 deletions src/lib/ctx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ export default (options: Record<string, string>): Context => {
try {
if (options.config) {
config = JSON.parse(fs.readFileSync(options.config, 'utf-8'));
// the schema now also accepts a pdf-only file, so keep every other command on the rule
// it had before: no web or mobile block means nothing to run
if (options.commandType !== constants.COMMAND_TYPE_UPLOAD_PDF && !config.web && !config.mobile) {
throw new Error('Invalid config; must have either web or mobile config');
}
// TODO: Mask sensitive data of config file
// logger.debug(`Config file ${options.config} loaded: ${JSON.stringify(config, null, 2)}`);

Expand Down Expand Up @@ -293,13 +288,6 @@ export default (options: Record<string, string>): Context => {
userName: options.userName || '',
accessKey: options.accessKey || '',
pdfNames: options.pdfNames || '',
// flag > pdf block > project. The top-level approvalThreshold/rejectionThreshold are the
// web values and are never read for pdf. Kept as strings so an explicit 0 is sent rather
// than dropped; the backend does the range/band validation
approvalThreshold: firstThreshold(options.approvalThreshold, (config as any).pdf?.approvalThreshold),
rejectionThreshold: firstThreshold(options.rejectionThreshold, (config as any).pdf?.rejectionThreshold),
// per-pdf overrides come only from the config file; there is no flag for them
pdfThresholds: (config as any).pdf?.thresholds ?? {},
sync: options.sync ? true : false
},
cliVersion: version,
Expand All @@ -325,11 +313,4 @@ export default (options: Record<string, string>): Context => {
logFileUUID: logFileUUID,
logFilePath: logFilePath
}
}
// first source that actually set a value; a numeric 0 from config is a value, an empty flag is not
function firstThreshold(...sources: any[]): string {
for (const s of sources) {
if (s !== undefined && s !== null && s !== '') return String(s);
}
return '';
}
}
6 changes: 1 addition & 5 deletions src/lib/httpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ export default class httpClient {
}
}

async uploadPdf(ctx: Context, form: FormData, buildName?: string, pdfNames?: string, snapshotUuids?: string, thresholds?: Record<string, { approval?: number; rejection?: number }>): Promise<any> {
async uploadPdf(ctx: Context, form: FormData, buildName?: string, pdfNames?: string, snapshotUuids?: string): Promise<any> {
form.append('projectToken', this.projectToken);
if (ctx.build.name !== undefined && ctx.build.name !== '') {
form.append('buildName', buildName);
Expand All @@ -831,10 +831,6 @@ export default class httpClient {
if (snapshotUuids && snapshotUuids !== '') {
form.append('snapshotUuids', snapshotUuids);
}
// already resolved per pdf by the task; only the final map goes over, never the raw flags
if (thresholds && Object.keys(thresholds).length > 0) {
form.append('thresholds', JSON.stringify(thresholds));
}

if (ctx.git?.branch) form.append('branch', ctx.git.branch);
if (ctx.git?.commitId) form.append('commitId', ctx.git.commitId);
Expand Down
36 changes: 0 additions & 36 deletions src/lib/pdfThresholds.ts

This file was deleted.

45 changes: 1 addition & 44 deletions src/lib/schemaValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,54 +389,11 @@ const ConfigSchema = {
showRenderErrors: {
type: "boolean",
errorMessage: "Invalid config; showRenderErrors must be true/false"
},
pdf: {
type: "object",
properties: {
approvalThreshold: {
type: "number",
minimum: 0,
maximum: 100,
errorMessage: "Invalid config; pdf.approvalThreshold must be a number between 0 and 100"
},
rejectionThreshold: {
type: "number",
minimum: 0,
maximum: 100,
errorMessage: "Invalid config; pdf.rejectionThreshold must be a number between 0 and 100"
},
thresholds: {
type: "object",
additionalProperties: {
type: "object",
properties: {
approval: {
type: "number",
minimum: 0,
maximum: 100,
errorMessage: "Invalid config; pdf.thresholds.<name>.approval must be a number between 0 and 100"
},
rejection: {
type: "number",
minimum: 0,
maximum: 100,
errorMessage: "Invalid config; pdf.thresholds.<name>.rejection must be a number between 0 and 100"
}
},
additionalProperties: false,
errorMessage: "Invalid config; each pdf.thresholds entry may only have approval and rejection"
},
errorMessage: "Invalid config; pdf.thresholds must be an object keyed by PDF name"
}
},
additionalProperties: false,
errorMessage: "Invalid config; pdf may only contain approvalThreshold, rejectionThreshold and thresholds"
}
},
anyOf: [
{ required: ["web"] },
{ required: ["mobile"] },
{ required: ["pdf"] }
{ required: ["mobile"] }
],
additionalProperties: false
}
Expand Down
12 changes: 1 addition & 11 deletions src/tasks/uploadPdfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import path from 'path';
import fs from 'fs';
import FormData from 'form-data';
import { randomUUID } from 'node:crypto';
import { resolvePdfThresholds } from '../lib/pdfThresholds.js';

export default (ctx: Context): ListrTask<Context, ListrRendererFactory, ListrRendererFactory> => {
return {
Expand Down Expand Up @@ -56,15 +55,6 @@ async function uploadPdfs(ctx: Context, pdfPath: string): Promise<void> {
const providedNames = pdfNames ? pdfNames.split(',').map(name => name.trim()) : [];
const documentNames = uploadedFileNames.map((fileName, index) => providedNames[index] ?? fileName);

// resolved per pdf here, as the web path does per snapshot, so the backend gets one final
// value per file: config pdf.thresholds entry, else the build-level value (flag > pdf block > top-level)
const thresholds = resolvePdfThresholds(
documentNames,
ctx.options.pdfThresholds ?? {},
ctx.options.approvalThreshold,
ctx.options.rejectionThreshold
);

let snapshotUuids = '';
if (ctx.options.sync) {
const syncTargets = documentNames.map(name => ({ name, uuid: randomUUID() as string }));
Expand All @@ -77,7 +67,7 @@ async function uploadPdfs(ctx: Context, pdfPath: string): Promise<void> {
}

try {
const response = await ctx.client.uploadPdf(ctx, formData, buildName, pdfNames, snapshotUuids, thresholds);
const response = await ctx.client.uploadPdf(ctx, formData, buildName, pdfNames, snapshotUuids);
if (response && response.buildId) {
ctx.build.id = response.buildId;
ctx.log.debug(`PDF upload successful. Build ID: ${ctx.build.id}`);
Expand Down
3 changes: 0 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ export interface Context {
gitURL?: string,
showRenderErrors?: boolean,
pdfNames?: string,
approvalThreshold?: string,
rejectionThreshold?: string,
pdfThresholds?: Record<string, { approval?: number; rejection?: number }>,
sync?: boolean,
userName?: string,
accessKey?: string
Expand Down