Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ inputs:
description: 'Maximum number of concurrent trigger executions'
required: false
default: '5'
action-ref:
description: 'The action ref that produced this run, surfaced in the findings output harness field'
required: false
default: ${{ github.action_ref }}

outputs:
findings-count:
Expand Down Expand Up @@ -90,4 +94,5 @@ runs:
INPUT_REQUEST_CHANGES: ${{ inputs.request-changes }}
INPUT_FAIL_CHECK: ${{ inputs.fail-check }}
INPUT_PARALLEL: ${{ inputs.parallel }}
INPUT_ACTION_REF: ${{ inputs.action-ref }}
run: node ${{ github.action_path }}/dist/action/index.js
13 changes: 13 additions & 0 deletions packages/warden/src/action/inputs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,19 @@ describe('parseActionInputs', () => {
expect(() => parseActionInputs()).toThrow('Invalid mode "later"');
});
});

describe('actionRef', () => {
it('parses action-ref when provided', () => {
process.env['INPUT_ACTION_REF'] = 'getsentry/warden@v1';
const inputs = parseActionInputs();
expect(inputs.actionRef).toBe('getsentry/warden@v1');
});

it('is undefined when not provided', () => {
const inputs = parseActionInputs();
expect(inputs.actionRef).toBeUndefined();
});
});
});

describe('setupAuthEnv', () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/warden/src/action/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export interface ActionInputs {
failCheck?: boolean;
/** Max concurrent trigger executions */
parallel: number;
/** The action ref that produced this run, surfaced in the findings output harness field */
actionRef?: string;
}

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -127,6 +129,7 @@ export function parseActionInputs(): ActionInputs {
requestChanges,
failCheck,
parallel: Number.isNaN(parallelParsed) ? DEFAULT_CONCURRENCY : parallelParsed,
actionRef: getInput('action-ref') || undefined,
};
}

Expand Down
13 changes: 11 additions & 2 deletions packages/warden/src/action/reporting/outcomes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type FindingOutcome =

export type DedupeSource = 'warden' | 'external';
export type DedupeMatchType = 'hash' | 'semantic';
export type SkippedReason = 'max_findings' | 'duplicate_in_batch' | 'no_inline_location';
export type SkippedReason = 'max_findings' | 'duplicate_in_batch' | 'no_inline_location' | 'review_not_posted';
export type ResolvedReason = 'fix_evaluation' | 'stale_check';

export const DedupeDetailSchema = z.object({
Expand All @@ -21,6 +21,8 @@ export const DedupeDetailSchema = z.object({
existingCommentId: z.number().int().positive().optional(),
existingThreadId: z.string().optional(),
existingResolved: z.boolean().optional(),
/** Skills already attributed to the matched comment, parsed from its attribution footer. */
existingSkills: z.array(z.string()).optional(),
actor: z.string().optional(),
});

Expand All @@ -29,6 +31,8 @@ export type DedupeDetail = z.infer<typeof DedupeDetailSchema>;
interface BaseFindingObservation {
finding: Finding;
skill?: string;
/** skillExecutionId of the trigger execution that produced this observation. */
skillExecutionId?: string;
}

export interface PostedFindingObservation extends BaseFindingObservation {
Expand Down Expand Up @@ -66,29 +70,34 @@ export const FindingObservationSchema = z.discriminatedUnion('outcome', [
outcome: z.literal('posted'),
finding: FindingSchema,
skill: z.string().optional(),
skillExecutionId: z.string().optional(),
}),
z.object({
outcome: z.literal('deduped'),
finding: FindingSchema,
skill: z.string().optional(),
skillExecutionId: z.string().optional(),
dedupe: DedupeDetailSchema,
}),
z.object({
outcome: z.literal('skipped'),
finding: FindingSchema,
skill: z.string().optional(),
skippedReason: z.enum(['max_findings', 'duplicate_in_batch', 'no_inline_location']),
skillExecutionId: z.string().optional(),
skippedReason: z.enum(['max_findings', 'duplicate_in_batch', 'no_inline_location', 'review_not_posted']),
}),
z.object({
outcome: z.literal('resolved'),
finding: FindingSchema,
skill: z.string().optional(),
skillExecutionId: z.string().optional(),
resolvedReason: z.enum(['fix_evaluation', 'stale_check']),
}),
z.object({
outcome: z.literal('failed'),
finding: FindingSchema,
skill: z.string().optional(),
skillExecutionId: z.string().optional(),
}),
]);

Expand Down
Loading