Skip to content

Commit

Permalink
Merge branch 'master' into integration-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
David Verdeguer committed May 12, 2020
2 parents f17ebc8 + c0d9de1 commit 1477a43
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 7 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ env:

to `github/codeql-action/analyze`.

### If you do not use a vendor directory
#### If you do not use a vendor directory

Dependencies on public repositories should just work. If you have dependencies on private repositories, one option is to use `git config` and a [personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) to authenticate when downloading dependencies. Add a section like

Expand All @@ -168,3 +168,7 @@ dotnet build /p:UseSharedCompilation=false
```

Version 3 does not require the additional flag.

### Analysing Go together with other languages on `macos-latest`

When running on macos it is currently not possible to analyze Go in conjunction with any of Java, C/C++, or C#. Each language can still be analyzed separately.
3 changes: 2 additions & 1 deletion lib/external-queries.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/shared-environment.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/upload-lib.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions lib/util.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions queries/undeclared-action-input.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @name Undeclared action input
* @description Code tries to use an input parameter that is not defined for this action.
Perhaps this code is shared by multiple actions.
* @kind problem
* @problem.severity error
* @id javascript/codeql-action/undeclared-action-input
*/

import javascript

class ActionDeclaration extends File {
ActionDeclaration() {
getRelativePath().matches("%/action.yml")
}

string getName() {
result = getRelativePath().regexpCapture("(.*)/action.yml", 1)
}

YAMLDocument getRootNode() {
result.getFile() = this
}

string getAnInput() {
result = getRootNode().(YAMLMapping).lookup("inputs").(YAMLMapping).getKey(_).(YAMLString).getValue()
}

FunctionDeclStmt getEntrypoint() {
result.getFile().getRelativePath() = getRootNode().
(YAMLMapping).lookup("runs").
(YAMLMapping).lookup("main").
(YAMLString).getValue().regexpReplaceAll("\\.\\./lib/(.*)\\.js", "src/$1.ts") and
result.getName() = "run"
}
}

Expr getAFunctionChildExpr(Function f) {
result.getContainer() = f
}

/*
* Result is a function that is called from the body of the given function `f`
*/
Function calledBy(Function f) {
result = getAFunctionChildExpr(f).(InvokeExpr).getResolvedCallee()
or
result.getEnclosingContainer() = f // assume outer function causes inner function to be called
}

class GetInputMethodCallExpr extends MethodCallExpr {
GetInputMethodCallExpr() {
getMethodName() = "getInput"
}

string getInputName() {
result = getArgument(0).(StringLiteral).getValue()
}
}

from ActionDeclaration action, GetInputMethodCallExpr getInputCall, string inputName
where getAFunctionChildExpr(calledBy*(action.getEntrypoint())) = getInputCall and
inputName = getInputCall.getInputName() and
not inputName = action.getAnInput()
select getInputCall, "The $@ input is not defined for the $@ action", inputName, inputName, action, action.getName()
12 changes: 8 additions & 4 deletions src/external-queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ import * as path from "path";

import * as configUtils from "./config-utils";
import * as externalQueries from "./external-queries";
import * as util from "./util";

test("checkoutExternalQueries", async () => {
let config = new configUtils.Config();
config.externalQueries = [
new configUtils.ExternalQuery("github/codeql-go", "df4c6869212341b601005567381944ed90906b6b"),
];
await externalQueries.checkoutExternalQueries(config);

let destination = process.env["RUNNER_WORKSPACE"] || "/tmp/codeql-action/";
// COPYRIGHT file existed in df4c6869212341b601005567381944ed90906b6b but not in master
expect(fs.existsSync(path.join(destination, "github", "codeql-go", "COPYRIGHT"))).toBeTruthy();
await util.withTmpDir(async tmpDir => {
process.env["RUNNER_WORKSPACE"] = tmpDir;
await externalQueries.checkoutExternalQueries(config);

// COPYRIGHT file existed in df4c6869212341b601005567381944ed90906b6b but not in master
expect(fs.existsSync(path.join(tmpDir, "github", "codeql-go", "COPYRIGHT"))).toBeTruthy();
});
});
3 changes: 2 additions & 1 deletion src/external-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import * as fs from 'fs';
import * as path from 'path';

import * as configUtils from './config-utils';
import * as util from './util';

export async function checkoutExternalQueries(config: configUtils.Config) {
const folder = process.env['RUNNER_WORKSPACE'] || '/tmp/codeql-action';
const folder = util.getRequiredEnvParam('RUNNER_WORKSPACE');

for (const externalQuery of config.externalQueries) {
core.info('Checking out ' + externalQuery.repository);
Expand Down
1 change: 1 addition & 0 deletions src/shared-environment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const CODEQL_ACTION_CMD = 'CODEQL_ACTION_CMD';
export const CODEQL_ACTION_DATABASE_DIR = 'CODEQL_ACTION_DATABASE_DIR';
export const CODEQL_ACTION_LANGUAGES = 'CODEQL_ACTION_LANGUAGES';
export const CODEQL_ACTION_ANALYSIS_KEY = 'CODEQL_ACTION_ANALYSIS_KEY';
export const ODASA_TRACER_CONFIGURATION = 'ODASA_TRACER_CONFIGURATION';
export const CODEQL_ACTION_SCANNED_LANGUAGES = 'CODEQL_ACTION_SCANNED_LANGUAGES';
export const CODEQL_ACTION_TRACED_LANGUAGES = 'CODEQL_ACTION_TRACED_LANGUAGES';
Expand Down
2 changes: 2 additions & 0 deletions src/upload-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ async function uploadFiles(sarifFiles: string[]): Promise<boolean> {
const commitOid = util.getRequiredEnvParam('GITHUB_SHA');
const workflowRunIDStr = util.getRequiredEnvParam('GITHUB_RUN_ID');
const ref = util.getRequiredEnvParam('GITHUB_REF'); // it's in the form "refs/heads/master"
const analysisKey = await util.getAnalysisKey();
const analysisName = util.getRequiredEnvParam('GITHUB_WORKFLOW');
const startedAt = process.env[sharedEnv.CODEQL_ACTION_STARTED_AT];

Expand Down Expand Up @@ -173,6 +174,7 @@ async function uploadFiles(sarifFiles: string[]): Promise<boolean> {
const payload = JSON.stringify({
"commit_oid": commitOid,
"ref": ref,
"analysis_key": analysisKey,
"analysis_name": analysisName,
"sarif": zipped_sarif,
"workflow_run_id": workflowRunID,
Expand Down
58 changes: 58 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as http from '@actions/http-client';
import * as auth from '@actions/http-client/auth';
import * as octokit from '@octokit/rest';
import consoleLogLevel from 'console-log-level';
import * as fs from "fs";
import * as os from 'os';
import * as path from 'path';

import * as sharedEnv from './shared-environment';
Expand Down Expand Up @@ -150,6 +152,54 @@ export async function getLanguages(): Promise<string[]> {
return languages;
}

/**
* Get the path of the currently executing workflow.
*/
async function getWorkflowPath(): Promise<string> {
const repo_nwo = getRequiredEnvParam('GITHUB_REPOSITORY').split("/");
const owner = repo_nwo[0];
const repo = repo_nwo[1];
const run_id = getRequiredEnvParam('GITHUB_RUN_ID');

const ok = new octokit.Octokit({
auth: core.getInput('token'),
userAgent: "CodeQL Action",
log: consoleLogLevel({ level: 'debug' })
});

const runsResponse = await ok.request('GET /repos/:owner/:repo/actions/runs/:run_id', {
owner,
repo,
run_id
});
const workflowUrl = runsResponse.data.workflow_url;

const workflowResponse = await ok.request('GET ' + workflowUrl);

return workflowResponse.data.path;
}

/**
* Get the analysis key paramter for the current job.
*
* This will combine the workflow path and current job name.
* Computing this the first time requires making requests to
* the github API, but after that the result will be cached.
*/
export async function getAnalysisKey(): Promise<string> {
let analysisKey = process.env[sharedEnv.CODEQL_ACTION_ANALYSIS_KEY];
if (analysisKey !== undefined) {
return analysisKey;
}

const workflowPath = await getWorkflowPath();
const jobName = getRequiredEnvParam('GITHUB_JOB');

analysisKey = workflowPath + ':' + jobName;
core.exportVariable(sharedEnv.CODEQL_ACTION_ANALYSIS_KEY, analysisKey);
return analysisKey;
}

interface StatusReport {
"workflow_run_id": number;
"workflow_name": string;
Expand Down Expand Up @@ -313,3 +363,11 @@ export function getToolNames(sarifContents: string): string[] {

return Object.keys(toolNames);
}

// Creates a random temporary directory, runs the given body, and then deletes the directory.
// Mostly intended for use within tests.
export async function withTmpDir(body: (tmpDir: string) => Promise<void>) {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codeql-action-'));
await body(tmpDir);
fs.rmdirSync(tmpDir, { recursive: true });
}

0 comments on commit 1477a43

Please sign in to comment.