Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions extensions/ql-vscode/src/remote-queries/run-remote-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ async function findPackRoot(queryFile: string): Promise<string> {
while (!(await fs.pathExists(path.join(dir, 'qlpack.yml')))) {
dir = path.dirname(dir);
if (isFileSystemRoot(dir)) {
// there is no qlpack.yml in this direcory or any parent directory.
// there is no qlpack.yml in this directory or any parent directory.
// just use the query file's directory as the pack root.
return path.dirname(queryFile);
}
Expand Down Expand Up @@ -349,36 +349,44 @@ async function runRemoteQueriesApiRequest(
const eol = os.EOL;
const eol2 = os.EOL + os.EOL;

/**
* Returns "N repository" if N is one, "N repositories" otherwise.
*/
function pluralizeRepositories(numRepositories: number) {
return `${numRepositories} ${numRepositories === 1 ? 'repository' : 'repositories'}`;
}

// exported for testing only
export function parseResponse(owner: string, repo: string, response: QueriesResponse) {
const repositoriesQueried = response.repositories_queried;
const numRepositoriesQueried = repositoriesQueried.length;

const popupMessage = `Successfully scheduled runs on ${numRepositoriesQueried} repositories. [Click here to see the progress](https://github.com/${owner}/${repo}/actions/runs/${response.workflow_run_id}).`
const popupMessage = `Successfully scheduled runs on ${pluralizeRepositories(numRepositoriesQueried)}. [Click here to see the progress](https://github.com/${owner}/${repo}/actions/runs/${response.workflow_run_id}).`
+ (response.errors ? `${eol2}Some repositories could not be scheduled. See extension log for details.` : '');

let logMessage = `Successfully scheduled runs on ${numRepositoriesQueried} repositories. See https://github.com/${owner}/${repo}/actions/runs/${response.workflow_run_id}.`;
let logMessage = `Successfully scheduled runs on ${pluralizeRepositories(numRepositoriesQueried)}. See https://github.com/${owner}/${repo}/actions/runs/${response.workflow_run_id}.`;
logMessage += `${eol2}Repositories queried:${eol}${repositoriesQueried.join(', ')}`;
if (response.errors) {
const { invalid_repositories, repositories_without_database, private_repositories, cutoff_repositories, cutoff_repositories_count } = response.errors;
logMessage += `${eol2}Some repositories could not be scheduled.`;
if (invalid_repositories?.length) {
logMessage += `${eol2}${invalid_repositories.length} repositories were invalid and could not be found:${eol}${invalid_repositories.join(', ')}`;
logMessage += `${eol2}${pluralizeRepositories(invalid_repositories.length)} invalid and could not be found:${eol}${invalid_repositories.join(', ')}`;
}
if (repositories_without_database?.length) {
logMessage += `${eol2}${repositories_without_database.length} repositories did not have a CodeQL database available:${eol}${repositories_without_database.join(', ')}`;
logMessage += `${eol2}${pluralizeRepositories(repositories_without_database.length)} did not have a CodeQL database available:${eol}${repositories_without_database.join(', ')}`;
logMessage += `${eol}For each public repository that has not yet been added to the database service, we will try to create a database next time the store is updated.`;
}
if (private_repositories?.length) {
logMessage += `${eol2}${private_repositories.length} repositories are not public:${eol}${private_repositories.join(', ')}`;
logMessage += `${eol2}${pluralizeRepositories(private_repositories.length)} not public:${eol}${private_repositories.join(', ')}`;
logMessage += `${eol}When using a public controller repository, only public repositories can be queried.`;
}
if (cutoff_repositories_count) {
logMessage += `${eol2}${cutoff_repositories_count} repositories over the limit for a single request`;
logMessage += `${eol2}${pluralizeRepositories(cutoff_repositories_count)} over the limit for a single request`;
if (cutoff_repositories) {
logMessage += `:${eol}${cutoff_repositories.join(', ')}`;
if (cutoff_repositories_count !== cutoff_repositories.length) {
logMessage += `${eol}...${eol}And ${cutoff_repositories_count - cutoff_repositories.length} more repositrories.`;
const moreRepositories = cutoff_repositories_count - cutoff_repositories.length;
logMessage += `${eol}...${eol}And another ${pluralizeRepositories(moreRepositories)}.`;
}
} else {
logMessage += '.';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('run-remote-query', () => {
'',
'Some repositories could not be scheduled.',
'',
'2 repositories were invalid and could not be found:',
'2 repositories invalid and could not be found:',
'e/f, g/h'].join(os.EOL)
);
});
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('run-remote-query', () => {
'',
'Some repositories could not be scheduled.',
'',
'2 repositories are not public:',
'2 repositories not public:',
'e/f, g/h',
'When using a public controller repository, only public repositories can be queried.'].join(os.EOL)
);
Expand Down Expand Up @@ -181,13 +181,58 @@ describe('run-remote-query', () => {
'',
'Some repositories could not be scheduled.',
'',
'2 repositories were invalid and could not be found:',
'2 repositories invalid and could not be found:',
'e/f, g/h',
'',
'2 repositories did not have a CodeQL database available:',
'i/j, k/l',
'For each public repository that has not yet been added to the database service, we will try to create a database next time the store is updated.'].join(os.EOL)
);
});

it('should parse a response with one repo of each category, and not pluralize "repositories"', () => {
const result = parseResponse('org', 'name', {
workflow_run_id: 123,
repositories_queried: ['a/b'],
errors: {
private_repositories: ['e/f'],
cutoff_repositories: ['i/j'],
cutoff_repositories_count: 1,
invalid_repositories: ['m/n'],
repositories_without_database: ['q/r'],
}
});

expect(result.popupMessage).to.equal(
['Successfully scheduled runs on 1 repository. [Click here to see the progress](https://github.com/org/name/actions/runs/123).',
'',
'Some repositories could not be scheduled. See extension log for details.'].join(os.EOL)
);
expect(result.logMessage).to.equal(
[
'Successfully scheduled runs on 1 repository. See https://github.com/org/name/actions/runs/123.',
'',
'Repositories queried:',
'a/b',
'',
'Some repositories could not be scheduled.',
'',
'1 repository invalid and could not be found:',
'm/n',
'',
'1 repository did not have a CodeQL database available:',
'q/r',
'For each public repository that has not yet been added to the database service, we will try to create a database next time the store is updated.',
'',
'1 repository not public:',
'e/f',
'When using a public controller repository, only public repositories can be queried.',
'',
'1 repository over the limit for a single request:',
'i/j',
'Repositories were selected based on how recently they had been updated.',
].join(os.EOL)
);
});
});
});