Skip to content
This repository was archived by the owner on Sep 1, 2022. It is now read-only.

Commit dd6c8eb

Browse files
author
Sam Lanning
authored
Merge pull request #1 from github/additional-workflows
Additional workflows
2 parents 2997847 + 4cc80c6 commit dd6c8eb

File tree

2 files changed

+140
-19
lines changed

2 files changed

+140
-19
lines changed

codeql-learninglab-check/package/src/index.ts

Lines changed: 139 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -103,32 +103,153 @@ function isConfig(config: any): config is Config {
103103
commit_sha: event.after
104104
});
105105

106-
// Calculate which file paths have changed in this push
107-
const {stdout: filesChangedRaw} = await execFile('git', ['diff', '--name-only', `${event.before}..${event.after}`]);
108-
const queriesChanged = new Set(filesChangedRaw.split('\n')
109-
.map(s => s.trim())
110-
.filter(s => s.endsWith('.ql')));
111-
console.log(`${pluralize(queriesChanged.size, 'query')} updated in this push`);
112-
comment += `${pluralize(queriesChanged.size, 'query')} changed `
113-
comment += `[between \`${event.before.substr(0, 7)}\` and \`${event.after.substr(0, 7)}\`]`
114-
comment += `(${event.repository.html_url}/compare/${event.before}...${event.after}) after push to \`${event.ref}\``;
115-
if (queriesChanged.size > 0) {
116-
comment += ':\n';
117-
for (const query of queriesChanged) {
118-
console.log(`- ${query}`);
119-
const exists = await access(query, fs.constants.R_OK).then(() => true, () => false);
120-
comment += `* \`${query}\`${exists ? '' : ' *(deleted)*'}\n`;
106+
/**
107+
* File paths changed by the user (if we're not just running all queries)
108+
*
109+
* This is used to reduce the number of queries we need to run to only those
110+
* that currently interest the user.
111+
*/
112+
const queriesChanged = new Set<string>();
113+
let unableToGetChangedQueries = false;
114+
115+
if (RUN_ALL) {
116+
117+
/*
118+
* There are a few different ways in which we may determine which queries
119+
* are currently interesting to the user, in decreasing usefulness:
120+
*
121+
* 1. If the user just pushed to a branch that currently has an open pull
122+
* request, the interesting queries are those that are changed in the pull
123+
* request (and not just those changed in the most recent push).
124+
* 2. If there's no active pull request, then what's probably most
125+
* interesting are the queries that have changed in the last push (i.e.
126+
* between the previous head and the new head)
127+
* 3. If that's not possible (e.g. the push could have created the branch for
128+
* the first time, and so there is no "previous ref"), then comparing this
129+
* branch to the default branch of a repo will probably give the most
130+
* accurate results.
131+
* 4. Finally, if all else fails (e.g. the push was the initial push to the
132+
* default branch of the repo), then we should just run every query we
133+
* recognize (as if RUN_ALL was true). We do this by setting
134+
* unableToGetChangedQueries to true.
135+
*/
136+
137+
/**
138+
* The output from a successful call to `git diff --name-only`
139+
*/
140+
let diff: {
141+
baseSha: string;
142+
filesChangedRaw: string;
143+
} | null = null;
144+
145+
// Try (1) - find any PR associated with the branch of this push
146+
147+
// Get branch name
148+
// This is expected to fail if e.g. the push was to a tag not a branch
149+
const branch = /^refs\/heads\/(.*)$/.exec(event.ref)?.[1];
150+
151+
if (branch) {
152+
try {
153+
const pulls = await api.pulls.list({
154+
owner: event.repository.owner.login,
155+
repo: event.repository.name,
156+
head: `${event.repository.owner.login}:${branch}`
157+
});
158+
if (pulls && pulls.data.length > 0) {
159+
// Just use first PR
160+
const pr = pulls.data[0];
161+
const baseBranch = pr.base.ref;
162+
// Ensure we have the commits from that ref
163+
await execFile('git', ['fetch', 'origin', baseBranch]);
164+
diff = {
165+
baseSha: baseBranch,
166+
filesChangedRaw: (await execFile(
167+
'git', ['diff', '--name-only', `origin/${baseBranch}..${event.after}`]
168+
)).stdout
169+
}
170+
} else {
171+
console.log('No pull requests associated with the current push');
172+
}
173+
} catch (err) {
174+
console.warn(err);
175+
console.log(`Failed to use PRs to calculate changed files branch ${branch}.`);
176+
}
177+
} else {
178+
console.log(
179+
'Push was not for a branch, calculating changed files differently'
180+
);
181+
}
182+
183+
// Try (2) - see what files have changed in the last push
184+
185+
if (!diff) {
186+
try {
187+
const result = await execFile(
188+
'git', ['diff', '--name-only', `${event.before}..${event.after}`]
189+
);
190+
if (result)
191+
diff = {
192+
baseSha: event.before,
193+
filesChangedRaw: result.stdout
194+
};
195+
} catch (err) {
196+
console.warn(err);
197+
console.log('Failed to get diff for push');
198+
}
199+
}
200+
201+
// Try (3) - see how the current HEAD differs from the default branch
202+
203+
if (!diff) {
204+
try {
205+
const defaultBranchSha = await (await execFile(
206+
'git', ['rev-parse', 'refs/remotes/origin/HEAD']
207+
)).stdout.trim();
208+
const result = await execFile(
209+
'git', ['diff', '--name-only', `${defaultBranchSha}..${event.after}`]
210+
);
211+
if (result)
212+
diff = {
213+
baseSha: defaultBranchSha,
214+
filesChangedRaw: result.stdout
215+
}
216+
} catch (err) {
217+
console.warn(err);
218+
console.log('Failed to diff against default branch');
219+
}
220+
}
221+
222+
if (!diff) {
223+
unableToGetChangedQueries = true;
224+
} else {
225+
// We have successfully obtained the diff for this push
226+
diff.filesChangedRaw.split('\n')
227+
.map(s => s.trim())
228+
.filter(s => s.endsWith('.ql'))
229+
.forEach(s => queriesChanged.add(s));
230+
console.log(`${pluralize(queriesChanged.size, 'query')} updated in this push`);
231+
comment += `${pluralize(queriesChanged.size, 'query')} changed `
232+
comment += `[between \`${diff.baseSha.substr(0, 7)}\` and \`${event.after.substr(0, 7)}\`]`
233+
comment += `(${event.repository.html_url}/compare/${diff.baseSha}...${event.after}) after push to \`${event.ref}\``;
234+
if (queriesChanged.size > 0) {
235+
comment += ':\n';
236+
for (const query of queriesChanged) {
237+
console.log(`- ${query}`);
238+
const exists = await access(query, fs.constants.R_OK).then(() => true, () => false);
239+
comment += `* \`${query}\`${exists ? '' : ' *(deleted)*'}\n`;
240+
}
241+
} else {
242+
comment += '\n';
243+
}
121244
}
122-
} else {
123-
comment += '\n';
124245
}
125246

126247
// Work out which queries to run, based on config and changed & existing queries
127248
const queriesToRun: string[] = [];
128249
for (const query of Object.keys(config.expectedResults)) {
129250
const exists = await access(query, fs.constants.R_OK).then(() => true, () => false);
130251
// Run the query if either it's changed, or runAll is true
131-
if (exists && (RUN_ALL || queriesChanged.has(query))) {
252+
if (exists && (RUN_ALL || unableToGetChangedQueries || queriesChanged.has(query))) {
132253
queriesToRun.push(query);
133254
}
134255
}

codeql-learninglab-check/publish.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ set -x
55

66
docker login docker.pkg.github.com -u github-actions -p ${GITHUB_TOKEN}
77

8-
IMAGE_VERSION=v0.0.1
8+
IMAGE_VERSION=v0.0.2
99
IMAGE_TAG=docker.pkg.github.com/github/codeql-learninglab-actions/codeql-learninglab-check:${IMAGE_VERSION}
1010

1111
if docker pull $IMAGE_TAG; then

0 commit comments

Comments
 (0)