@@ -5,7 +5,11 @@ import { performance } from "perf_hooks";
55import * as io from "@actions/io" ;
66import * as yaml from "js-yaml" ;
77
8- import { getTemporaryDirectory , PullRequestBranches } from "./actions-util" ;
8+ import {
9+ getTemporaryDirectory ,
10+ getRequiredInput ,
11+ PullRequestBranches ,
12+ } from "./actions-util" ;
913import * as analyses from "./analyses" ;
1014import { setupCppAutobuild } from "./autobuild" ;
1115import { type CodeQL } from "./codeql" ;
@@ -243,7 +247,12 @@ export async function setupDiffInformedQueryRun(
243247 `Calculating diff ranges for ${ branches . base } ...${ branches . head } ` ,
244248 ) ;
245249 const diffRanges = await getPullRequestEditedDiffRanges ( branches , logger ) ;
246- const packDir = writeDiffRangeDataExtensionPack ( logger , diffRanges ) ;
250+ const checkoutPath = getRequiredInput ( "checkout_path" ) ;
251+ const packDir = writeDiffRangeDataExtensionPack (
252+ logger ,
253+ diffRanges ,
254+ checkoutPath ,
255+ ) ;
247256 if ( packDir === undefined ) {
248257 logger . warning (
249258 "Cannot create diff range extension pack for diff-informed queries; " +
@@ -259,19 +268,61 @@ export async function setupDiffInformedQueryRun(
259268 ) ;
260269}
261270
271+ export function diffRangeExtensionPackContents (
272+ ranges : DiffThunkRange [ ] ,
273+ checkoutPath : string ,
274+ ) : string {
275+ const header = `
276+ extensions:
277+ - addsTo:
278+ pack: codeql/util
279+ extensible: restrictAlertsTo
280+ checkPresence: false
281+ data:
282+ ` ;
283+
284+ let data = ranges
285+ . map ( ( range ) => {
286+ // Diff-informed queries expect the file path to be absolute. CodeQL always
287+ // uses forward slashes as the path separator, so on Windows we need to
288+ // replace any backslashes with forward slashes.
289+ const filename = path
290+ . join ( checkoutPath , range . path )
291+ . replaceAll ( path . sep , "/" ) ;
292+
293+ // Using yaml.dump() with `forceQuotes: true` ensures that all special
294+ // characters are escaped, and that the path is always rendered as a
295+ // quoted string on a single line.
296+ return (
297+ ` - [${ yaml . dump ( filename , { forceQuotes : true } ) . trim ( ) } , ` +
298+ `${ range . startLine } , ${ range . endLine } ]\n`
299+ ) ;
300+ } )
301+ . join ( "" ) ;
302+ if ( ! data ) {
303+ // Ensure that the data extension is not empty, so that a pull request with
304+ // no edited lines would exclude (instead of accepting) all alerts.
305+ data = ' - ["", 0, 0]\n' ;
306+ }
307+
308+ return header + data ;
309+ }
310+
262311/**
263312 * Create an extension pack in the temporary directory that contains the file
264313 * line ranges that were added or modified in the pull request.
265314 *
266315 * @param logger
267316 * @param ranges The file line ranges, as returned by
268317 * `getPullRequestEditedDiffRanges`.
318+ * @param checkoutPath The path at which the repository was checked out.
269319 * @returns The absolute path of the directory containing the extension pack, or
270320 * `undefined` if no extension pack was created.
271321 */
272322function writeDiffRangeDataExtensionPack (
273323 logger : Logger ,
274324 ranges : DiffThunkRange [ ] | undefined ,
325+ checkoutPath : string ,
275326) : string | undefined {
276327 if ( ranges === undefined ) {
277328 return undefined ;
@@ -307,32 +358,10 @@ dataExtensions:
307358` ,
308359 ) ;
309360
310- const header = `
311- extensions:
312- - addsTo:
313- pack: codeql/util
314- extensible: restrictAlertsTo
315- checkPresence: false
316- data:
317- ` ;
318-
319- let data = ranges
320- . map (
321- ( range ) =>
322- // Using yaml.dump() with `forceQuotes: true` ensures that all special
323- // characters are escaped, and that the path is always rendered as a
324- // quoted string on a single line.
325- ` - [${ yaml . dump ( range . path , { forceQuotes : true } ) . trim ( ) } , ` +
326- `${ range . startLine } , ${ range . endLine } ]\n` ,
327- )
328- . join ( "" ) ;
329- if ( ! data ) {
330- // Ensure that the data extension is not empty, so that a pull request with
331- // no edited lines would exclude (instead of accepting) all alerts.
332- data = ' - ["", 0, 0]\n' ;
333- }
334-
335- const extensionContents = header + data ;
361+ const extensionContents = diffRangeExtensionPackContents (
362+ ranges ,
363+ checkoutPath ,
364+ ) ;
336365 const extensionFilePath = path . join ( diffRangeDir , "pr-diff-range.yml" ) ;
337366 fs . writeFileSync ( extensionFilePath , extensionContents ) ;
338367 logger . debug (
0 commit comments