-
Notifications
You must be signed in to change notification settings - Fork 377
Overlay: check query packs for compatibility #2993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
230fc32
to
d0d4112
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't feel to me that resolve packs is quite the right command (although it looks like it will work).It feels like we should run resolve queries
with --format startingpacks
to find the query packs we care about, and then just use those.
But I am also not fully sure of all the subtleties of either choice.
Thanks for the suggestion! When I first looked into the problem, I considered this approach but was unable to get it to work. While Prompted by your suggestion, I looked again. This time I noticed that (There is the slight complication that |
d0d4112
to
f1a0360
Compare
I updated the PR to use this approach to identify the query packs to check for overlay compatibility. Related changes:
The other commits remain the same as before. PTAL. |
f1a0360
to
119d629
Compare
The latest force push updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As always, thanks for taking on this work! I have added a few suggestions, questions, and points for discussion.
const output = await runCli(cmd, codeqlArgs, { noStreamStdout: true }); | ||
|
||
try { | ||
return JSON.parse(output) as string[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not specific to this PR: I see that we follow the same JSON.parse(output) as type
pattern throughout the implementation here, but that doesn't actually give us any guarantees that the result of JSON.parse
is compatible with the type
here. This may effectively delay an error until a later point. Where possible, we should probably check that the result actually what we expect (and not just valid JSON) as done in e.g. #2956.
I don't think this has to be addressed here, but we might want to look into improving this throughout in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acknowledged. I will leave it to you to decide if and when you want to perform that overall cleanup.
src/init.ts
Outdated
const suitePath = path.join( | ||
config.dbLocation, | ||
language, | ||
"temp", | ||
"config-queries.qls", | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is now at least the second place where we construct this path (after my changes in #2935) so we may want to add a utility function that constructs this path for a given config+language somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/init.ts
Outdated
for (const packDir of packDirs) { | ||
if ( | ||
!checkPackForOverlayCompatibility(packDir, codeQlOverlayVersion, logger) | ||
) { | ||
return false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: perhaps this could be nicer as something like:
if (packDirs.some((packDir) => !checkPackForOverlayCompatibility(packDir, codeQlOverlayVersion, logger))) {
return false;
}
You could potentially also chain something together with the outer loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/init.ts
Outdated
const qlpackPath = path.join(packDir, "qlpack.yml"); | ||
const qlpackContents = yaml.load( | ||
fs.readFileSync(qlpackPath, "utf8"), | ||
) as any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Copilot here - it would be good to have typings for (at least) the parts of the format that are used here.
This might also make the tests a little nicer since you can then have test objects of this type that you can serialise, rather than hard-coded strings.
|
||
const packInfoFileContents = JSON.parse( | ||
fs.readFileSync(packInfoPath, "utf8"), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with Copilot. It would be good to distinguish errors while reading/parsing JSON from other errors.
src/init.ts
Outdated
logger.warning( | ||
`The query pack at ${packDir} is not compatible with overlay analysis.`, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: This is very non-specific. How about "The query pack at ${packDir} does not contain the required overlayVersion
property."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioning the overlayVersion
property would make the message more specific, but it would not add any useful information.
Code Scanning users do not know what the overlayVersion
property is or what it does. It is an implementation detail used to indicate presence and compatibility of overlay support. If a customer files a support ticket asking about the overlayVersion
property being absent, our answer would be "that means your pack is not compatible with overlay analysis".
So I don't see how adding that detail would be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see Copilot agreed with my comment on this 😅
It might not be useful for users to know this implementation detail, but it would be helpful for us when troubleshooting issues related to this. It might be clear to you (and perhaps even me) what this error means since we know where in the code it is raised, but someone else might need to review the code to figure that out.
Just to be clear, I don't care whether you explicitly mention overlayVersion
in the error or not. But it would be good to have a message that points more clearly at there being something wrong with the file (for whatever reason) than a compatibility issue for an entirely unspecified reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/init.ts
Outdated
logger.warning( | ||
`The query pack at ${packDir} was compiled with ` + | ||
`overlay version ${packOverlayVersion}, but the CodeQL CLI ` + | ||
`supports only overlay version ${codeQlOverlayVersion}. The ` + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wording here suggests that codeQlOverlayVersion
is smaller than packOverlayVersion
, but the check just tests that they are not equal. Should the condition be different or the wording of the warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The !==
comparison is intended. If the pack overlay version is lower than the CLI overlay version, overlay analysis is not guaranteed to work. If the pack overlay version is higher than the CLI overlay version, overlay analysis is also not guaranteed to work.
We don't plan to ever reduce overlay versions with a new CodeQL CLI release, so the most common case would be the CLI having a higher overlay version that the pack. But I think the error message works both ways:
The query pack at ${packDir} was compiled with overlay version 6, but the CodeQL CLI supports only overlay version 4. The query pack needs to be recompiled to support overlay analysis.
and
The query pack at ${packDir} was compiled with overlay version 4, but the CodeQL CLI supports only overlay version 6. The query pack needs to be recompiled to support overlay analysis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. I think the real problem here is that "only" can be ambiguous and could either be interpreted as "the versions supported by this CLI go up to only version X right now and version Y is greater" or "the version X must be an exact match for Y". I had interpreted it as the former, while you meant the latter.
If you don't plan to support version mixing, then perhaps the wording could be improved to be less ambiguous. How about simply dropping the "only":
The query pack at ${packDir} was compiled with overlay version 6, but the CodeQL CLI supports overlay version 4. The query pack needs to be recompiled to support overlay analysis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -78,21 +78,40 @@ export async function runInit( | |||
apiDetails: GitHubApiCombinedDetails, | |||
logger: Logger, | |||
): Promise<TracerConfig | undefined> { | |||
fs.mkdirSync(config.dbLocation, { recursive: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting this for future reference: it doesn't look like dbLocation
is used by generateRegistries
, so moving this seems fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Furthermore, codeql database init
generally expects the database path to be non-existent and reports an error when the database path already exists. (There are some exceptions, such as when initializing an overlay database.) So I would be very surprised if generateRegistries()
writes anything into dbLocation
.
// To check custom query packs for compatibility with overlay analysis, we | ||
// need to first initialize the database cluster, which downloads the | ||
// user-specified custom query packs. But we also want to check custom query | ||
// pack compatibility first, because database cluster initialization depends | ||
// on the overlay database mode. The solution is to initialize the database | ||
// cluster first, check custom query pack compatibility, and if we need to | ||
// revert to `OverlayDatabaseMode.None`, re-initialize the database cluster | ||
// with the new overlay database mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like a good bit of effort in the last couple of commits here is spent on enabling this. I am sure you've already thought about this, but is there any way that we could change the overlay database mode for the database cluster after it has been initialised? Or alternatively, shuffle things around so that we can download the user-specified custom query packs?
I am trying to understand the design space here a bit better. I am also thinking about concurrent efforts we'll have to look into related to code quality, which might mean that we have to break up what happens when a database is initialised anyway. It might be that we can find a solution for both in one go depending on what timelines permit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I responded in more detail in the internal tracking issue, but the short answer is that neither of the suggested approach would be practical. Nonetheless thank you for the suggestions!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the responses. I am happy to keep this as-is since it shouldn't be a common occurrence, and responded to the internal issue with more detailed thoughts.
119d629
to
7ba8b26
Compare
7ba8b26
to
210aa6a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds query pack compatibility checking for overlay analysis in the CodeQL Action. The main purpose is to ensure that when overlay analysis is enabled, all query packs involved are compatible with the installed CodeQL CLI's overlay analysis support before proceeding.
- Introduces a new
checkPacksForOverlayCompatibility
function that validates query pack overlay compatibility - Refactors the
runInit
function intorunDatabaseInitCluster
and updates the overlay compatibility checking workflow - Updates the minimum CodeQL overlay version requirement from "2.20.5" to "2.22.3"
Reviewed Changes
Copilot reviewed 20 out of 29 changed files in this pull request and generated 2 comments.
Show a summary per file
File | Description |
---|---|
src/util.ts | Adds getGeneratedSuitePath helper function for query suite paths |
src/testing-utils.ts | Updates mock functions to support overlayVersion parameter |
src/overlay-database-utils.ts | Updates minimum CodeQL overlay version constant |
src/init.ts | Adds overlay compatibility checking logic and refactors database initialization |
src/init.test.ts | Adds comprehensive tests for overlay compatibility checking |
src/init-action.ts | Updates main initialization flow to handle overlay compatibility checks |
src/config-utils.test.ts | Updates test configuration to use new minimum overlay version |
src/codeql.ts | Adds overlayVersion to VersionInfo and resolveQueriesStartingPacks method |
src/analyze.ts | Uses new getGeneratedSuitePath helper function |
src/analyze.test.ts | Removes unused packDownload mock |
Comments suppressed due to low confidence (2)
src/init.ts:79
- [nitpick] The parameter order in
runDatabaseInitCluster
is inconsistent with the originalrunInit
function. Consider maintaining the same parameter order (codeql, config, sourceRoot, processName, then additional parameters) for better consistency and easier migration.
export async function runDatabaseInitCluster(
databaseInitEnvironment: Record<string, string | undefined>,
codeql: CodeQL,
config: configUtils.Config,
sourceRoot: string,
processName: string | undefined,
qlconfigFile: string | undefined,
logger: Logger,
): Promise<void> {
src/init.ts:138
- [nitpick] The interface
QlPack
is too generic and incomplete for representing aqlpack.yml
file structure. Consider renaming it toQlPackMetadata
orQlPackYaml
to be more specific about its purpose.
interface QlPack {
buildMetadata?: string;
}
src/init.ts
Outdated
const packOverlayVersion = packInfoFileContents.overlayVersion; | ||
if (typeof packOverlayVersion !== "number") { | ||
logger.warning( | ||
`The query pack at ${packDir} is not compatible with overlay analysis.`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message 'is not compatible with overlay analysis' is vague. Consider making it more specific, such as 'is missing the overlayVersion field in .packinfo' or 'has an invalid overlayVersion field in .packinfo' to help users understand exactly what's wrong.
`The query pack at ${packDir} is not compatible with overlay analysis.`, | |
`The query pack at ${packDir} has an invalid or missing overlayVersion field in .packinfo and is not compatible with overlay analysis.`, |
Copilot uses AI. Check for mistakes.
const qlpackContents = yaml.load( | ||
fs.readFileSync(qlpackPath, "utf8"), | ||
) as QlPack; | ||
if (!qlpackContents.buildMetadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code assumes qlpack.yml
exists and can be parsed as YAML, but doesn't handle the case where the file doesn't exist or contains invalid YAML. This could cause the function to throw an unhandled exception instead of logging a warning and returning false.
Copilot uses AI. Check for mistakes.
I responded to some of the comments, and will follow up on the remaining ones tomorrow. |
210aa6a
to
7a53966
Compare
I responded to all comments (responses to copilot-initiated comments might be visible only under the original copilot reviews). Also rebased the PR against current main to resolve merge conflicts. |
7a53966
to
f5b3a08
Compare
Another rebase to resolve merge conflicts. |
@mbg Friendly ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing my feedback from the last review, and sorry it took longer than I'd like to re-review.
This continues to look good, thank you! I've followed up to a few of your responses and added a couple of suggestions for potential improvements on test coverage.
I am generally happy with this and there isn't anything that's really blocking. Have a look over the comments and see if you want to change anything in light of them. I will be happy to approve this after you've had a look.
src/init.ts
Outdated
logger.warning( | ||
`The query pack at ${packDir} was compiled with ` + | ||
`overlay version ${packOverlayVersion}, but the CodeQL CLI ` + | ||
`supports only overlay version ${codeQlOverlayVersion}. The ` + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. I think the real problem here is that "only" can be ambiguous and could either be interpreted as "the versions supported by this CLI go up to only version X right now and version Y is greater" or "the version X must be an exact match for Y". I had interpreted it as the former, while you meant the latter.
If you don't plan to support version mixing, then perhaps the wording could be improved to be less ambiguous. How about simply dropping the "only":
The query pack at ${packDir} was compiled with overlay version 6, but the CodeQL CLI supports overlay version 4. The query pack needs to be recompiled to support overlay analysis.
src/init.ts
Outdated
logger.warning( | ||
`The query pack at ${packDir} is not compatible with overlay analysis.`, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see Copilot agreed with my comment on this 😅
It might not be useful for users to know this implementation detail, but it would be helpful for us when troubleshooting issues related to this. It might be clear to you (and perhaps even me) what this error means since we know where in the code it is raised, but someone else might need to review the code to figure that out.
Just to be clear, I don't care whether you explicitly mention overlayVersion
in the error or not. But it would be good to have a message that points more clearly at there being something wrong with the file (for whatever reason) than a compatibility issue for an entirely unspecified reason.
|
||
const packInfoFileContents = JSON.parse( | ||
fs.readFileSync(packInfoPath, "utf8"), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, I think it's probably fine. You're right that whatever errors come out of here are probably distinguishable based on the result of util.getErrorMessage(e)
in the existing catch
block.
src/init.ts
Outdated
logger.warning( | ||
`The query pack at ${packDir} ` + | ||
"does not have a .packinfo file. This pack is too old to support " + | ||
"overlay analysis.", | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your proposed change is good. Proposing a possible resolution, rather than suggesting a cause might allow most people to resolve this issue themselves if they run into it as well.
The main scenario I was thinking of is users who create their own query packs and (perhaps inadvertently) use an older CLI for that. That said, I am not sure whether users who create their own packs often bundle
them, so as you say this is probably not a likely issue.
src/config-utils.test.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR removes resolveQueries
and adds resolveQueriesStartingPacks
. For the corresponding tests, the ones for resolveQueries
are removed, but none are added for resolveQueriesStartingPacks
. Do you think it would make sense to add some?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not remove any resolveQueries
tests. What I removed was unnecessary resolveQueries
and packDownload
stubs in config loading tests. Those tests are still working the same way they used to: the removed resolveQueries
and packDownload
stubs has no effect on the tests because the tested code does not call either of those functions.
resolveQueriesStartingPacks
is just a wrapper that calls the corresponding CodeQL CLI subcommand, and I don't think tests for that function would add much value.
// To check custom query packs for compatibility with overlay analysis, we | ||
// need to first initialize the database cluster, which downloads the | ||
// user-specified custom query packs. But we also want to check custom query | ||
// pack compatibility first, because database cluster initialization depends | ||
// on the overlay database mode. The solution is to initialize the database | ||
// cluster first, check custom query pack compatibility, and if we need to | ||
// revert to `OverlayDatabaseMode.None`, re-initialize the database cluster | ||
// with the new overlay database mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the responses. I am happy to keep this as-is since it shouldn't be a common occurrence, and responded to the internal issue with more detailed thoughts.
cleanupDatabaseClusterDirectory(config, logger, { | ||
disableExistingDirectoryWarning: true, | ||
}); | ||
await runDatabaseInitCluster( | ||
databaseInitEnvironment, | ||
codeql, | ||
config, | ||
sourceRoot, | ||
"Runner.Worker.exe", | ||
qlconfigFile, | ||
logger, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it's worth adding a test that exercises this logic? I don't see anything wrong with things as they are, but it might be worthwhile to have to check that we don't break this sequence, especially since an error in cleanupDatabaseClusterDirectory
would be fatal. I don't feel strongly about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a new PR check to exercise this re-initialization logic.
f5b3a08
to
37f26d0
Compare
This commit inlines runInit(), so that it is easier to repeat the runDatabaseInitCluster() call when needed.
f17b8c2
to
a81656b
Compare
a81656b
to
2b2e27a
Compare
@mbg Thanks for your comments. I think I responded to them all. There has been a few force pushes to the PR branch, both to resolve merge conflicts and to iterate on the new database re-init PR check. The following link contains all the relevant changes since your last review: Edit: I updated the comparison link because I added a commit to support the |
2b2e27a
to
e471477
Compare
This PR updates the
init
action to prevent overlay analysis (or overlay-base database construction) when one of the query packs involved does not support overlay analysis with the installed CodeQL CLI.Merge / deployment checklist