Skip to content

Conversation

@robertbrignull
Copy link
Contributor

This PR adds a CLI interface to the rest of the actions. This should get us to a state where we have a working product, though it's very rough around the edges and there will be some tech debt cleanup to do.
(Currently depends on #159 but I'll rebase once that PR is merged)

This PR is currently quite rough and not very pretty, but I think it largely works. I've done a single manual test and was about to run the init and analyze actions on a javascript repository.

Problems I have with this current situation are:

  • Some methods have far too many arguments and they are all the same type so it's easy to get them mixed up. We should look into some way of doing named arguments, or packaging related args up into objects.
  • There's an awful hack of setting RUNNNER_TEMP so we can use the existing toolcache code. We shouldn't be doing this and should instead write our own implementation for use outside of actions.
  • The temp directory situation is still a bit awkward but we're discussing how to improve that.

@sampart, @joshhale, @chrisgavin, @jhutchings1

Merge / deployment checklist

  • Confirm this change is backwards compatible with existing workflows.
  • Confirm the readme has been updated if necessary.

@robertbrignull
Copy link
Contributor Author

Realised just after posting I've missed the bit with outputting the env vars to a file so you can source them. I'll do that tomorrow morning.

@robertbrignull
Copy link
Contributor Author

Added code to generate the env file and instructions for how to use it. Also had to inline a couple of files that we depended on just existing, because now we have to write them out to a temporary location ourselves prior to using them.

I've tested this on linux building some javascript code. Unfortunately it doesn't work for me tracing a compiled language as the tracer is not intercepting so it claims nothing has been built. I will investigate but I haven't been able to work out what's up yet.

@robertbrignull
Copy link
Contributor Author

robertbrignull commented Aug 26, 2020

Things still to do:

  • Work out why the environment vars aren't working to inject the tracer.
  • Inline inject-tracer.ps1 file
  • Check at start of autobuild/analze commands that env vars are set, to avoid wasting time and improve error message

@robertbrignull
Copy link
Contributor Author

I've managed to analyze a cpp project on linux now. Had some errors in the setting of env vars.

@sampart
Copy link
Contributor

sampart commented Aug 27, 2020

We should look into some way of doing named arguments, or packaging related args up into objects.

I like both of these approaches. You could also consider introducing some new types for things like pathString, urlString etc. These would simply be defined as string, but would allow nice type checking.

@robertbrignull
Copy link
Contributor Author

I like both of these approaches.

I just want to say that although I would like to do these too I am worried they will eat up a lot of time as we try to find better solutions. If it's acceptable then I would like to go for a correct implementation for now and look at improving it in later pull requests.

You could also consider introducing some new types for things like pathString, urlString etc. These would simply be defined as string, but would allow nice type checking.

Typescript unfortunately doesn't work that way. If you define new types like type pathString = string and type urlString = string then both are interchangeable and it won't be an error to pass one instead of the other.

@sampart
Copy link
Contributor

sampart commented Aug 27, 2020

If it's acceptable then I would like to go for a correct implementation for now and look at improving it in later pull requests.

Absolutely - don't add any more in this PR!

Typescript unfortunately doesn't work that way. If you define new types like type pathString = string and type urlString = string then both are interchangeable and it won't be an error to pass one instead of the other.

Oh, rubbish.

Copy link
Contributor

@sampart sampart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thakns for all you work here. A number of comments, but they're all small ones.

Do you think it would have been feasible to do this as 3 PRs, one for each of init, autobuild and analyze, or would the first one have had a lot of "baggage" that the others would need and so have been huge anyway?

src/codeql.ts Outdated
// e.g. our integration tests which use the Action code from the current checkout.
if (relativeScriptPath.startsWith("..") || path.isAbsolute(relativeScriptPath)) {
function getCodeQLActionRepository(mode: util.Mode): string {
if (mode === 'actions') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could avoid nesting here by using a guard clause. Start with

if (mode !== 'actions') {
  return CODEQL_DEFAULT_ACTION_REPOSITORY;
}

and then the rest of the code needn't be in a block.

This has the downside of introducing a ! condition, but the upsides of reducing nesting and also preventing the reader getting to the else and thinking "which condition does this relate to again?" (as I did)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's nicer code. The thing that held me back initially is that I'm not sure the unguarded-action-lib query will understand this, but really that just means we should improve the query.

}

// We have to download CodeQL manually because the toolcache doesn't support Accept headers.
// This can be removed once https://github.com/actions/toolkit/pull/530 is merged and released.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to remove this comment? The PR it mentions hasn't been merged yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really. I am worried we may not be able to go back to using the toolcache and may need to carry on implementing this ourselves even once that PR is eventually merged. However I'm not trying to change that assumption in this PR, so I'll revert this to add back the comment.

src/codeql.ts Outdated
mode: util.Mode,
logger: Logger): Promise<CodeQL> {

// Setting these two env vars makes the toolcache code safe to use,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Setting these two env vars makes the toolcache code safe to use,
// Setting these two env vars makes the toolcache code safe to use outside of actions,

You'll probably want to implement this change yourself (assuming you agree with it), though, so you can make the lines line up.

Without a change like this, it implies that the toolcache code is never safe to use!

src/codeql.ts Outdated
getTracerEnv: async function(databasePath: string) {
let envFile = path.resolve(databasePath, 'working', 'env.tmp');
// Write tracer-env.js to a temp location. When running in CLI mode we can't rely
// on this file existing so we have to create it ourselves.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does it come from in Actions land? It would be good to mention that here so that future developers can compare the file contents below with the canonical version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no difference in behaviour on actions, so I'll delete that bit of the comment about when running in CLI mode as it always applies.

What I meant is that currently we rely on there being a checkout of this repository present so we can reference arbitrary files in it. That's what we can't do when running in CLI mode.

util.getRequiredEnvParam('RUNNER_TEMP'),
util.getRequiredEnvParam('RUNNER_TOOL_CACHE'),
codeql);
analysisPaths.includeAndExcludeAnalysisPaths(config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't call this in initConfig (although you do call analysisPaths.printPathFiltersWarning(config, logger);). Should you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call has been moved to createdDBForScannedLanguages in analyze.ts as that's where the env vars are actually used. It's replaced here with printPathFiltersWarning so we still print the warning in the init step where it comes currently.

src/runner.ts Outdated
.option('--queries <queries>', 'Comma-separated list of additional queries to run. By default, this overrides the same setting in a configuration file.')
.option('--config-file <file>', 'Path to config file')
.option('--codeql-path <path>', 'Path to a copy of the CodeQL CLI executable to use. Otherwise downloads a copy.')
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use current working directory.')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use current working directory.')
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use a subdirectory of the current working directory.')

src/runner.ts Outdated
.command('autobuild')
.description('Attempts to automatically build code')
.option('--language <language>', 'The language to build. By default will try to detect the dominant language.')
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use current working directory.')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use current working directory.')
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use a subdirectory of the current working directory.')

} else {
language = determineAutobuildLanguage(config, logger);
}
if (language !== undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need an else here - a conditional after the call to determineAutobuildLanguage above - to print a warning if the language is undefined?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit convoluted but no, because determineAutobuildLanguage prints a message saying "None of the languages in this project require extra build steps" and then the intention is that we exit gracefully and successfully.

src/runner.ts Outdated
.option('--checkout-path <path>', 'Checkout path (default: current working directory)')
.option('--no-upload', 'Do not upload results after analysis', false)
.option('--output-dir <dir>', 'Directory to output SARIF files to. By default will use temp directory.')
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use current working directory.')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use current working directory.')
.option('--temp-dir <dir>', 'Directory to use for temporary files. By default will use a subdirectory of the current working directory.')

src/runner.ts Outdated
config,
logger);
} catch (e) {
logger.error('Upload failed');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.error('Upload failed');
logger.error('Analyze failed');

Copy link
Contributor

@sampart sampart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of typos

const config = await getConfig(getTempDir(cmd.tempDir), logger);
if (config === undefined) {
throw new Error("Config file could not be found at expected location. " +
"Was the 'init' command run with the same '--temp-dir' argument as this command.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Was the 'init' command run with the same '--temp-dir' argument as this command.");
"Was the 'init' command run with the same '--temp-dir' argument as this command?");

const config = await getConfig(getTempDir(cmd.tempDir), logger);
if (config === undefined) {
throw new Error("Config file could not be found at expected location. " +
"Was the 'init' command run with the same '--temp-dir' argument as this command.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Was the 'init' command run with the same '--temp-dir' argument as this command.");
"Was the 'init' command run with the same '--temp-dir' argument as this command?");

@robertbrignull
Copy link
Contributor Author

robertbrignull commented Aug 28, 2020

Bugs that have been discovered and need fixing:

  • It breaks if there's a space in the path (possibly only on windows)

Things to do:

  • Make it so autobuild adds all env vars internalls so you don't need to explicitly source them if using the autobuild command.

@robertbrignull
Copy link
Contributor Author

The issue with the spaces in the filepath was due to exec from @actions/exec "helpfully" splitting the command string on spaces. It implements escaping so we possibly could have wrapped our command in quotes, but that seems like a route for future problems. Instead I've replaced the uses with ToolRunner from @actions/exec/lib/toolrunner which is what exec uses internally and doesn't do the splitting.

@robertbrignull
Copy link
Contributor Author

I had the idea that in the case that people are able to use the autobuilder it would be nice if they didn't have to source the env explicitly. Doing this is largely fine, but it makes the check at the start of the analyze command a bit odd, so I've removed that for now. I'll test and see what the error message from CodeQL is like in the case that you forget to source the env.

@robertbrignull
Copy link
Contributor Author

Currently getting a weird error on windows. Not sure if it's something I've done wrong in the configuration or not

[command]"C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\codeql\codeql.exe" resolve queries cpp-code-scanning.qls --format=bylanguage
Warning: C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\codeql\.codeqlmanifest.json: Could not create real path
(eventual cause: AccessDeniedException "C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\codeql\.codeqlmanifest.json")
Warning: C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\codeql-go\.codeqlmanifest.json: Could not create real path
(eventual cause: AccessDeniedException "C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\codeql-...")
Warning: C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\ql\.codeqlmanifest.json: Could not create real path
(eventual cause: AccessDeniedException "C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\ql\.codeqlmanifest.json")
A fatal error occurred: cpp-code-scanning.qls is not a well-known query suite.
Init failed
Error: The process 'C:\Users\User\My Documents\codeql-runner-tools\CodeQL\0.0.0-20200826\x64\codeql\codeql.exe' failed with exit code 2
    at ExecState._setResult (C:\snapshot\dist\codeql-runner.js)
    at ExecState.CheckComplete (C:\snapshot\dist\codeql-runner.js)
    at ChildProcess.<anonymous> (C:\snapshot\dist\codeql-runner.js)
    at ChildProcess.emit (events.js:315:20)
    at maybeClose (internal/child_process.js:1021:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:286:5)

Possibly it's another problem with having a space in the path, as I specifically put the tools dir under My Documents to test this.

@robertbrignull
Copy link
Contributor Author

Although the work on the runner for 3rd party CI/CD is not yet finished (mostly unfinished on windows) I'm moderately confident this doesn't break anything on actions, so we should likely merge this now so we get the code in main. It won't go to v1 for another week so we'll get maximum amount of time for pasive testing.

@robertbrignull robertbrignull merged commit 68c6069 into main Sep 1, 2020
@robertbrignull robertbrignull deleted the runner_analyze branch September 1, 2020 14:01
@github-actions github-actions bot mentioned this pull request Sep 7, 2020
@greysteil
Copy link

@robertbrignull you merged this with outstanding code scanning results on it. What was your thinking on doing that rather than marking those results as won't fix / false positives (or, indeed, fixing them if they were accurate)?

@robertbrignull
Copy link
Contributor Author

you merged this with outstanding code scanning results on it. What was your thinking on doing that rather than marking those results as won't fix / false positives (or, indeed, fixing them if they were accurate)?

It was purely a matter of forgetfulness. I saw the restults and noted that none of them we're serious enough to block merging, but then forgot to follow up later. I'll go through the alerts now and see which can be closed or fixed.

@greysteil
Copy link

👍 just curious if there's anything we can learn from it as we polish the UI :octocat:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants