-
Notifications
You must be signed in to change notification settings - Fork 422
Add a CLI interface to the upload-sarif action #147
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
Conversation
|
I can't jump to file to see the significant files because there are too many in the PR, and I can't see, e.g. |
I'll reorganise so the node_modules changes are in a separate commit. That way you should be able to view it in the UI. |
|
I'm doing some testing and have found some bits I've missed, so I'm fixing those up and will push a new version shortly. |
3321083 to
34b3722
Compare
|
I've now tested this manually, which showed up a few bugs and odditites. I managed to upload to one of my testing repos with Unfortunately everything has become a bit more annoying since there are different upload endpoints for actions vs non-actions, so there's a bit of ugly code there to generate the right payload and upload it to the right place. I'm not sure what the best approach is to avoid duplicating too much code or keep it safe so we won't accidentally do the wrong thing in the wrong environment. |
|
@sampart would you be able to review this? You'll have to look at individual commits and ignore the one that's got all the node_modules and generated file changes in it. |
src/cli.ts
Outdated
| .requiredOption('--repository <repository>', 'Repository name') | ||
| .requiredOption('--commit <commit>', 'SHA of commit that was analyzed') | ||
| .requiredOption('--ref <ref>', 'Name of ref that was analyzed') | ||
| .requiredOption('--analysis-key <key>', 'Identifies the analysis, for use matching up equivalent analyses on different commits') |
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.
A bunch of these options are not used. That's a bug from changing definitions over time. I'll trim these down.
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've pushed a commit to remove all of these that aren't used in CLI mode. It makes the upload_lib.upload interface a bit silly though as lots of the parameters are nullable so the type system isn't giving us much.
Maybe we could do something better by passing all the options as a blob along the with mod actions/cli mode variable.
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 like the idea of passing as an object, so you effectively get named parameters 👍
package.json
Outdated
| "ts-loader": "8.0.2", | ||
| "typescript": "^3.7.5", | ||
| "webpack": "4.44.1", | ||
| "webpack-cli": "3.3.12" |
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.
| "ts-loader": "8.0.2", | |
| "typescript": "^3.7.5", | |
| "webpack": "4.44.1", | |
| "webpack-cli": "3.3.12" | |
| "ts-loader": "^8.0.2", | |
| "typescript": "^3.7.5", | |
| "webpack": "^4.44.1", | |
| "webpack-cli": "^3.3.12" |
package.json
Outdated
| "@actions/github": "^2.2.0", | ||
| "@actions/http-client": "^1.0.8", | ||
| "@actions/tool-cache": "^1.5.5", | ||
| "commander": "6.0.0", |
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.
| "commander": "6.0.0", | |
| "commander": "^6.0.0", |
Unless you've a reason to pin to specific versions, I would allow upgrades of minor versions. This will make it easier for people to upgrade in future - pinning to a specific version here is like saying "there's a reason we can't use a later version", IMHO.
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 you noted this doesn't make too much difference to use day-to-day as we're using package-lock.json to pin to specific versions anyway and the node_modules folder is checked into the repo. So yes I suppose it makes the intention slightly more clear when it comes to upgrading.
src/cli.ts
Outdated
| program | ||
| .command('upload') | ||
| .description('Uploads a SARIF file, or all SARIF files from a directory, to code scanning') | ||
| .requiredOption('--sarif-file <file>', 'SARIF file to upload') |
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.
| .requiredOption('--sarif-file <file>', 'SARIF file to upload') | |
| .requiredOption('--sarif-file <file>', 'SARIF file to upload; can also be a directory for uploading multiple') |
src/cli.ts
Outdated
| .requiredOption('--repository <repository>', 'Repository name') | ||
| .requiredOption('--commit <commit>', 'SHA of commit that was analyzed') | ||
| .requiredOption('--ref <ref>', 'Name of ref that was analyzed') | ||
| .requiredOption('--analysis-key <key>', 'Identifies the analysis, for use matching up equivalent analyses on different commits') |
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 like the idea of passing as an object, so you effectively get named parameters 👍
sampart
left a comment
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.
Nice work! It's particularly gratifying how small cli.ts is. A fair few comments, but nothing major.
| @@ -0,0 +1,26 @@ | |||
| import * as core from '@actions/core'; | |||
|
|
|||
| export interface 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.
I really like your approach here 🏅
src/upload-lib.ts
Outdated
| if (fs.lstatSync(input).isDirectory()) { | ||
| const sarifFiles = fs.readdirSync(input) | ||
| export async function upload( | ||
| sarifFile: 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.
How about calling this sarifPath, since it could be a file or a directory? I'm not particularly fussed about this, though, so happy to leave if you'd rather.
webpack.config.js
Outdated
| // We no not want to minimize our code. | ||
| minimize: 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.
| // We no not want to minimize our code. | |
| minimize: false | |
| }, | |
| // We do not want to minimize our code. | |
| minimize: 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.
You probably don't even need the comment:
| // We no not want to minimize our code. | |
| minimize: false | |
| }, | |
| minimize: false | |
| }, |
|
|
||
| const sentinelEnvVar = "CODEQL_UPLOAD_SARIF"; | ||
| if (process.env[sentinelEnvVar]) { | ||
| throw new Error("Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job"); |
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.
You're now allowing multiple uploads in a job. Is that okay? Another option might be to clear this env var every time the CLI launches?
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 spotting this. Removing this wasn't intentional.
It is worth pointing out the check won't work when running in CLI mode because we can't set env vars in the same way such that they are seen by subsequent processes. But it should be safe to leave in and it'll just only do something on actions.
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.
That's what I thought 👍
| "sarif": zipped_sarif, | ||
| "workflow_run_id": workflowRunID, | ||
| "checkout_uri": checkoutURI, | ||
| "environment": environment, |
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.
You don't have started_at anymore. Is that deliberate?
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. That also was not intentional.
src/upload-lib.ts
Outdated
| // Log some useful debug info about the info | ||
| const rawUploadSizeBytes = sarifPayload.length; | ||
| core.debug("Raw upload size: " + rawUploadSizeBytes + " bytes"); | ||
| console.debug("Raw upload size: " + rawUploadSizeBytes + " bytes"); |
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 you want logger.debug here and below.
|
Because I added my comments to the commit rather than the PR-level diff, some comments are showing as "outdated". I don't think they are all genuinely redundant, though (although some are), so mind you don't miss them 😉 |
|
I've added a simple workflow that builds and runs the CLI to upload an empty SARIF file. You can still run the CLI on actions, so I think this should be ok for making sure we don't accidentally break it too much. |
|
Ok, fixed the error handling so it actually now sets a non-zero exit code when there's an error, and fixed a typo in a filename. Good thing I made that typo otherwise might not have noticed the broken error handling. With the exit code I tried a few variations of re-throwing the error, or putting the try-catch around the call to |
swinton
left a comment
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.
👋 Hi, just added a few comments / suggestions around how an end-user would acquire this CLI 🙇
| "scripts": { | ||
| "build": "tsc", | ||
| "build-cli": "webpack --mode production", | ||
| "test": "ava src/** --serial --verbose", | ||
| "lint": "tslint -p . -c tslint.json 'src/**/*.ts'", | ||
| "removeNPMAbsolutePaths": "removeNPMAbsolutePaths . --force" |
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.
Suggestion: add a postinstall step that builds the CLI automatically after a successful npm install. This will make it easier for new users to acquire the CLI by reducing the number of installation steps.
E.g.
| "scripts": { | |
| "build": "tsc", | |
| "build-cli": "webpack --mode production", | |
| "test": "ava src/** --serial --verbose", | |
| "lint": "tslint -p . -c tslint.json 'src/**/*.ts'", | |
| "removeNPMAbsolutePaths": "removeNPMAbsolutePaths . --force" | |
| "scripts": { | |
| "build": "tsc", | |
| "build-cli": "webpack --mode production", | |
| "test": "ava src/** --serial --verbose", | |
| "lint": "tslint -p . -c tslint.json 'src/**/*.ts'", | |
| "removeNPMAbsolutePaths": "removeNPMAbsolutePaths . --force", | |
| "postinstall": "npm run-script build-cli" |
| "version": "0.0.0", | ||
| "private": true, | ||
| "description": "CodeQL action", | ||
| "scripts": { |
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.
Suggestion: add a bin property to package.json, which resolves to the new CLI being introduced. This will allow new users to run the CLI directly, e.g. via npx ....
| "scripts": { | |
| "bin": { | |
| "codeql-cli": "cli/code-scanning-cli.js" | |
| }, | |
| "scripts": { |
| output: { | ||
| filename: 'cli.js', | ||
| path: path.resolve(__dirname, 'cli'), | ||
| }, |
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.
Is is possible to make this output executable, so that it can be invoked directly from the command-line?
Sorry I forgot to do this. I still think it would be good, but perhaps better to delay to a separate PR so we can discuss it properly. It could be a pretty big change in direction. |
|
Thanks for the comments @swinton. How to distribute this is still largely an open question and not one we have to solve right now, so I think I'm going to merge this without any changes for now and we'll address it later. I've mentioned you on an issue for this so we can discuss there. |
This PR is a first attempt at adding a command lint interface to the codeql-action. This PR only deals with the
upload-sarifaction, and largely ignores the others except the minimum changes required to keep them working.The main things done here are:
src/cli.tswhich is the entrypoint to the CLI. I'm using the commander library here to do the CLI part, and it generates-hoptions and stuff like that. I'm open to other libraries instead if someone has a favourite that is better.build-clinpm script, that uses webpack to bundle thecli.tsfile and all its dependencies into a single file, that is output tocli/cli.js. This file is not checked into the repository as it isn't needed to run the action normally. I felt it therefore didn't belong in thelibdirectory, but I don't think theclidirectory name is great either. I'd be very open to suggestions here.logging.tswhich mostly just wraps the@actions/corepackage, and replaces it with stuff likeconsole.logwhen not on actions.core.getInput, or the environment, and pass it onwards to where it is needed. Hopefully this won't get too ugly.The diff looks huge because of
node_moduleschanges, but if you ignore those and other generated files, the actual churn is only about 300 lines.This code is largely untested in practice. I wanted to get the PR up soon so people could see what it looks like.
Merge / deployment checklist