Skip to content

Commit 9b0ac63

Browse files
authored
Merge branch 'main' into locfiles/a2c940ae-355a-487e-9a5e-d1830efdf26b
2 parents 471aefa + 5ba1b5f commit 9b0ac63

4 files changed

Lines changed: 33 additions & 29 deletions

File tree

src/client/power-pages/actions-hub/ActionsHubCommandHandlers.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { IOtherSiteInfo, IWebsiteDetails, WebsiteYaml } from '../../../common/se
2424
import { getActiveWebsites, getAllWebsites } from '../../../common/utilities/WebsiteUtil';
2525
import CurrentSiteContext from './CurrentSiteContext';
2626
import path from 'path';
27-
import { getWebsiteRecordId, hasWebsiteYaml, hasPowerPagesSiteFolder, getWebsiteYamlPath } from '../../../common/utilities/WorkspaceInfoFinderUtil';
27+
import { getWebsiteRecordId, hasWebsiteYaml, getWebsiteYamlPath } from '../../../common/utilities/WorkspaceInfoFinderUtil';
2828
import { isEdmEnvironment } from '../../../common/copilot/dataverseMetadata';
2929
import { IWebsiteInfo } from './models/IWebsiteInfo';
3030
import moment from 'moment';
@@ -575,10 +575,10 @@ export function findOtherSites(knownSiteIds: Set<string>, fsModule = fs, yamlMod
575575
for (const dir of directories) {
576576
let websiteYamlPath = getWebsiteYamlPath(dir);
577577
let hasWebsiteYamlFile = hasWebsiteYaml(dir);
578-
const hasPowerPagesSiteFolderExists = hasPowerPagesSiteFolder(dir);
578+
const powerPagesSiteFolderExists = fs.existsSync(dir)
579579
let workingDir = dir;
580580

581-
if (hasPowerPagesSiteFolderExists) {
581+
if (powerPagesSiteFolderExists) {
582582
workingDir = path.join(dir, POWERPAGES_SITE_FOLDER);
583583
websiteYamlPath = getWebsiteYamlPath(workingDir);
584584
hasWebsiteYamlFile = hasWebsiteYaml(workingDir);
@@ -599,7 +599,7 @@ export function findOtherSites(knownSiteIds: Set<string>, fsModule = fs, yamlMod
599599
name: websiteData?.adx_name || path.basename(dir), // Use folder name as fallback
600600
websiteId: websiteId,
601601
folderPath: dir,
602-
isCodeSite: hasPowerPagesSiteFolderExists
602+
isCodeSite: powerPagesSiteFolderExists
603603
});
604604
}
605605
} catch (error) {
@@ -958,11 +958,7 @@ export const runCodeQLScreening = async (siteTreeItem?: SiteTreeItem) => {
958958
return;
959959
}
960960

961-
if(!hasPowerPagesSiteFolder(sitePath)) {
962-
traceInfo(Constants.EventNames.ACTIONS_HUB_CODEQL_SCREENING_NOT_SUPPORTED, { methodName: runCodeQLScreening.name });
963-
await vscode.window.showErrorMessage(Constants.Strings.CODEQL_SCREENING_NOT_SUPPORTED);
964-
return;
965-
}
961+
const powerPagesSiteFolderExists = fs.existsSync(sitePath);
966962

967963
// Check if CodeQL extension is installed
968964
const codeQLExtension = vscode.extensions.getExtension(CODEQL_EXTENSION_ID);
@@ -976,7 +972,7 @@ export const runCodeQLScreening = async (siteTreeItem?: SiteTreeItem) => {
976972
);
977973

978974
if (install === Constants.Strings.INSTALL) {
979-
await vscode.commands.executeCommand('workbench.extensions.search', CODEQL_EXTENSION_ID);
975+
await vscode.commands.executeCommand('workbench.extensions.installExtension', CODEQL_EXTENSION_ID);
980976
traceInfo(Constants.EventNames.ACTIONS_HUB_CODEQL_SCREENING_EXTENSION_NOT_INSTALLED, { methodName: runCodeQLScreening.name });
981977
return;
982978
} else {
@@ -996,7 +992,7 @@ export const runCodeQLScreening = async (siteTreeItem?: SiteTreeItem) => {
996992
Constants.Strings.CODEQL_SCREENING_STARTED,
997993
async () => {
998994
// Use a custom method that allows specifying the database location
999-
await codeQLAction.executeCodeQLAnalysisWithCustomPath(sitePath, databaseLocation);
995+
await codeQLAction.executeCodeQLAnalysisWithCustomPath(sitePath, databaseLocation, powerPagesSiteFolderExists);
1000996
}
1001997
);
1002998

src/client/power-pages/actions-hub/actions/codeQLAction.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class CodeQLAction {
2121
this.outputChannel = vscode.window.createOutputChannel(Constants.Strings.CODEQL_ANALYSIS_CHANNEL_NAME);
2222
}
2323

24-
public async executeCodeQLAnalysisWithCustomPath(sitePath: string, databaseLocation: string): Promise<void> {
24+
public async executeCodeQLAnalysisWithCustomPath(sitePath: string, databaseLocation: string, powerPagesSiteFolderExists: boolean): Promise<void> {
2525
this.outputChannel.show();
2626
this.outputChannel.appendLine(vscode.l10n.t(Constants.Strings.CODEQL_ANALYSIS_STARTING, path.basename(sitePath)));
2727
this.outputChannel.appendLine(vscode.l10n.t(Constants.Strings.CODEQL_DATABASE_LOCATION, databaseLocation));
@@ -41,8 +41,8 @@ export class CodeQLAction {
4141
this.outputChannel.appendLine(Constants.Strings.CODEQL_RUNNING_ANALYSIS);
4242
const resultsPath = path.join(path.dirname(dbPath), 'results.sarif');
4343

44-
// Get the query suite from config or use default
45-
const querySuite = await this.getCodeQLQuerySuite(sitePath);
44+
// Get the query suite from config or use default - only check config if Power Pages folder exists
45+
const querySuite = await this.getCodeQLQuerySuite(sitePath, powerPagesSiteFolderExists);
4646

4747
try {
4848
// Use the correct syntax for JavaScript code scanning query suite
@@ -401,10 +401,17 @@ export class CodeQLAction {
401401
}
402402
}
403403

404-
private async getCodeQLQuerySuite(sitePath: string): Promise<string> {
405-
const configPath = path.join(sitePath, 'powerpages.config.json');
404+
private async getCodeQLQuerySuite(sitePath: string, powerPagesSiteFolderExists: boolean): Promise<string> {
406405
const defaultQuerySuite = 'codeql/javascript-queries:codeql-suites/javascript-security-and-quality.qls';
407406

407+
// Only check for config if Power Pages folder exists
408+
if (!powerPagesSiteFolderExists) {
409+
this.outputChannel.appendLine(vscode.l10n.t(Constants.Strings.CODEQL_USING_DEFAULT_QUERY, defaultQuerySuite));
410+
return defaultQuerySuite;
411+
}
412+
413+
const configPath = path.join(sitePath, 'powerpages.config.json');
414+
408415
try {
409416
if (fs.existsSync(configPath)) {
410417
this.outputChannel.appendLine(vscode.l10n.t(Constants.Strings.CODEQL_CONFIG_FILE_FOUND, configPath));

src/client/test/Integration/power-pages/actions-hub/ActionsHubCommandHandlers.test.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import * as WorkspaceInfoFinderUtil from "../../../../../common/utilities/Worksp
2929
import path from 'path';
3030
import { SiteVisibility } from '../../../../power-pages/actions-hub/models/SiteVisibility';
3131
import * as TelemetryHelper from '../../../../power-pages/actions-hub/TelemetryHelper';
32+
import { CODEQL_EXTENSION_ID } from '../../../../../common/constants';
33+
import { CodeQLAction } from '../../../../power-pages/actions-hub/actions/codeQLAction';
3234

3335
describe('ActionsHubCommandHandlers', () => {
3436
let sandbox: sinon.SinonSandbox;
@@ -1502,21 +1504,27 @@ describe('ActionsHubCommandHandlers', () => {
15021504
let mockShowWarningMessage: sinon.SinonStub;
15031505
let mockGetExtension: sinon.SinonStub;
15041506
let mockShowProgressNotification: sinon.SinonStub;
1507+
let mockExecuteCommand: sinon.SinonStub;
1508+
let mockCodeQLAction: sinon.SinonStubbedInstance<CodeQLAction>;
15051509
let mockSiteTreeItem: SiteTreeItem;
1506-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1507-
let mockHasPowerPagesSiteFolder: sinon.SinonStub;
15081510

15091511
beforeEach(() => {
15101512
mockShowErrorMessage = sandbox.stub(vscode.window, 'showErrorMessage');
15111513
mockShowWarningMessage = sandbox.stub(vscode.window, 'showWarningMessage');
15121514
mockGetExtension = sandbox.stub(vscode.extensions, 'getExtension');
1515+
mockExecuteCommand = sandbox.stub(vscode.commands, 'executeCommand');
15131516
mockShowProgressNotification = sandbox.stub(Utils, 'showProgressWithNotification').callsFake(async (title: string, task: (progress: vscode.Progress<{
15141517
message?: string;
15151518
increment?: number;
15161519
// eslint-disable-next-line @typescript-eslint/no-explicit-any
15171520
}>) => Promise<any>) => await task({} as unknown as vscode.Progress<{ message?: string; increment?: number }>));
15181521

1519-
mockHasPowerPagesSiteFolder = sandbox.stub(WorkspaceInfoFinderUtil, 'hasPowerPagesSiteFolder').returns(true);
1522+
// Mock CodeQLAction constructor and methods
1523+
mockCodeQLAction = {
1524+
executeCodeQLAnalysisWithCustomPath: sandbox.stub().resolves(),
1525+
dispose: sandbox.stub()
1526+
} as sinon.SinonStubbedInstance<CodeQLAction>;
1527+
sandbox.stub(CodeQLAction.prototype, 'executeCodeQLAnalysisWithCustomPath').callsFake(mockCodeQLAction.executeCodeQLAnalysisWithCustomPath);
15201528

15211529
mockSiteTreeItem = new SiteTreeItem({
15221530
name: "Test Site",
@@ -1540,12 +1548,13 @@ describe('ActionsHubCommandHandlers', () => {
15401548

15411549
await runCodeQLScreening(mockSiteTreeItem);
15421550

1543-
expect(mockGetExtension.calledWith('github.vscode-codeql')).to.be.true;
1551+
expect(mockGetExtension.calledWith(CODEQL_EXTENSION_ID)).to.be.true;
15441552
expect(mockShowWarningMessage.calledWith(
15451553
Constants.Strings.CODEQL_EXTENSION_NOT_INSTALLED,
15461554
Constants.Strings.INSTALL,
15471555
Constants.Strings.CANCEL
15481556
)).to.be.true;
1557+
expect(mockExecuteCommand.calledWith('workbench.extensions.installExtension', CODEQL_EXTENSION_ID)).to.be.true;
15491558
});
15501559

15511560
it('should show error when current site path not found', async () => {
@@ -1564,6 +1573,7 @@ describe('ActionsHubCommandHandlers', () => {
15641573
await runCodeQLScreening(mockSiteTreeItem);
15651574

15661575
expect(mockShowProgressNotification.calledWith(Constants.Strings.CODEQL_SCREENING_STARTED)).to.be.true;
1576+
expect(mockCodeQLAction.executeCodeQLAnalysisWithCustomPath.called).to.be.true;
15671577
});
15681578

15691579
it('should handle errors gracefully', async () => {

src/common/utilities/WorkspaceInfoFinderUtil.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,6 @@ export function hasWebsiteYaml(directoryPath: string): boolean {
109109
return fs.existsSync(websiteYamlPath);
110110
}
111111

112-
/**
113-
* Checks if a .powerpages-site folder exists in the specified directory
114-
* @param directoryPath The directory path to check
115-
* @returns True if .powerpages-site folder exists, false otherwise
116-
*/
117-
export function hasPowerPagesSiteFolder(directoryPath: string): boolean {
118-
return fs.existsSync(directoryPath);
119-
}
120-
121112
/**
122113
* Gets the path to the website.yml file in the specified directory
123114
* @param directoryPath The directory path

0 commit comments

Comments
 (0)