Skip to content

Commit 0c2522b

Browse files
committed
Add mock files for mssql and applicationinsights***
***Update template.json to include app settings for app insights*** ***Update README.md with testing instructions
1 parent 80c3937 commit 0c2522b

File tree

5 files changed

+109
-78
lines changed

5 files changed

+109
-78
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,27 @@ npm start
5858

5959
As a first time execution probot will prompt you for creating a new GitHub App or connect it with an existing App. As you complete the requested information, a .env file will get created in your local source code and all the private information regarding your GitHub App will be automatically written there. If you need guidance on how to configure your first GitHub App, please review this guide https://probot.github.io/docs/development/#configuring-a-github-app.
6060

61-
You will also need to provide the DATABASE_CONNECTION_STRING in your env file.
61+
**Be careful!** If a webhook_URL variable is created, please delete it before deploying on your environment. This should only be used for testing purposes.
62+
63+
You will also need to provide the DATABASE_CONNECTION_STRING in your env file. Be sure to use your ODBC Connection String.
6264

6365
Optionally if you'll be also using Application Ingishts please provide the value for APPLICATIONINSIGHTS_CONNECTION_STRING. You can search for this in your Azure Portal, going to the resource group you've created previously. Select the resource of type Application Insights and copy the Connection String in the Essentials section of the Overview page.
6466

6567
Optionally if you'll be also using Languange detection API please provide the value for LANGUAGE_API_ENDPOINT, LANGUAGE_API_KEY. You can search for this in your Azure Portal, going to the resource group you've created previously. Select the resource of type Language and go to Keys and Endpoint. Copy one of the keys and corresponding endpoint.
6668

69+
To test your code, please run the following. You should see the 3 test cases pass.
70+
71+
```sh
72+
npm run test
73+
```
74+
6775
### Step 3. Deploy your App!
6876

6977
For a quick deployment you could open your Visual Studio Code and open the cloned project. Make sure you have the Azure Tools extension installed. If not, please install it https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-node-azure-pack
7078

7179
Once you have the extension sign in to Azure with your credentials go to your Explorer view and right click in the file directory to select the option "Deploy to web app". Select the subscription in which you've created the resources in step 1. Select the name you chose for the App Service created in step 1.
7280

73-
Finally go to your GitHub App and update your webhook URL to reflect your App Service URL.
81+
Finally go to your GitHub App and update your webhook URL to reflect your App Service URL. Do not append "/probot".
7482

7583

7684
### Step 4. Test your App!

__mocks__/applicationinsights.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
setup: jest.fn().mockReturnThis(),
3+
start: jest.fn().mockReturnThis(),
4+
defaultClient: {
5+
trackEvent: jest.fn(),
6+
trackDependency: jest.fn(),
7+
trackException: jest.fn(),
8+
},
9+
};

__mocks__/mssql.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
connect: jest.fn(),
3+
query: jest.fn().mockResolvedValue({ recordset: [] }),
4+
close: jest.fn()
5+
};

deployment/template.json

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@
367367
"location": "[variables('resourceGroup_location')]",
368368
"dependsOn": [
369369
"[resourceId('Microsoft.Web/serverfarms', parameters('serverfarms_ASP_name'))]",
370-
"[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworks_vnet_name'), 'AppServiceSnet')]"
370+
"[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworks_vnet_name'), 'AppServiceSnet')]",
371+
"[resourceId('microsoft.insights/components', parameters('components_insight_name'))]"
371372
],
372373
"kind": "app,linux",
373374
"properties": {
@@ -376,7 +377,13 @@
376377
"siteConfig": {
377378
"numberOfWorkers": 1,
378379
"linuxFxVersion": "NODE|18-lts",
379-
"alwaysOn": true
380+
"alwaysOn": true,
381+
"appSettings": [
382+
{
383+
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
384+
"value": "[reference(resourceId('microsoft.insights/components', parameters('components_insight_name'))).InstrumentationKey]"
385+
}
386+
]
380387
},
381388
"httpsOnly": true,
382389
"redundancyMode": "None",
@@ -398,5 +405,11 @@
398405
"isSwift": true
399406
}
400407
}
401-
]
408+
],
409+
"outputs": {
410+
"appInsightsInstrumentationKey": {
411+
"type": "string",
412+
"value": "[reference(resourceId('microsoft.insights/components', parameters('components_insight_name'))).InstrumentationKey]"
413+
}
414+
}
402415
}

index.js

Lines changed: 69 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,21 @@ module.exports = (app) => {
2323
let appInsights = new AppInsights();
2424

2525
app.on("pull_request.closed", async (context) => {
26-
appInsights.trackEvent({
27-
name: "Pull Request Close Payload",
28-
properties: context.payload,
29-
});
26+
3027
let pr_number = context.payload.pull_request.number;
28+
let pr_author = context.payload.pull_request.user.login;
29+
let organization_name = context.payload.repository.owner.login;
3130
let pr_body = context.payload.pull_request.body;
3231
let detectedLanguage = "en";
33-
let pr_author = context.payload.pull_request.user.login;
34-
let organization_name = context.payload.repository.owner.login
32+
33+
appInsights.trackEvent({
34+
name: "Pull Request Close Payload",
35+
properties: {
36+
pr_number: pr_number,
37+
pr_author: pr_author,
38+
39+
},
40+
});
3541

3642
// check language for pr_body
3743
if (LANGUAGE_API_ENDPOINT && LANGUAGE_API_KEY) {
@@ -48,7 +54,7 @@ module.exports = (app) => {
4854
target: "API:Language Detection",
4955
name: "detect pull request description language",
5056
duration: duration,
51-
resultCode: 0,
57+
resultCode: 200,
5258
success: true,
5359
dependencyTypeName: "HTTP",
5460
});
@@ -99,7 +105,9 @@ module.exports = (app) => {
99105
if (context.payload.issue.title.startsWith("Copilot Usage - PR#")) {
100106
appInsights.trackEvent({
101107
name: "Issue Edited Payload",
102-
properties: context.payload,
108+
properties: {
109+
issue_number: context.payload.issue.number
110+
},
103111
});
104112
await GetSurveyData(context);
105113
}
@@ -109,7 +117,10 @@ module.exports = (app) => {
109117
if (context.payload.issue.title.startsWith("Copilot Usage - PR#")) {
110118
appInsights.trackEvent({
111119
name: "Issue Comment Created Payload",
112-
properties: context.payload,
120+
properties: {
121+
issue_number: context.payload.issue.number,
122+
comment: context.payload.comment,
123+
},
113124
});
114125
await GetSurveyData(context);
115126
}
@@ -144,30 +155,30 @@ module.exports = (app) => {
144155
// if there's a comment, insert it into the DB regardless of whether the user answered the survey or not
145156
if (comment) {
146157
let startTime = Date.now();
147-
let query = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, null, comment);
158+
let insertResult = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, null, comment);
148159
let duration = Date.now() - startTime;
149160
appInsights.trackDependency({
150161
target: "DB:copilotUsage",
151162
name: "insert when comment is present",
152-
data: query,
163+
data: insertResult.query,
153164
duration: duration,
154-
resultCode: 0,
155-
success: true,
165+
resultCode: insertResult.status ? 200 : 500,
166+
success: insertResult.status,
156167
dependencyTypeName: "SQL",
157168
});
158169
}
159170

160171
if (isCopilotUsed) {
161172
let startTime = Date.now();
162-
let query = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, null, comment);
173+
let insertResult = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, null, comment);
163174
let duration = Date.now() - startTime;
164175
appInsights.trackDependency({
165176
target: "DB:copilotUsage",
166177
name: "insert when Yes is selected",
167-
data: query,
178+
data: insertResult.query,
168179
duration: duration,
169-
resultCode: 0,
170-
success: true,
180+
resultCode: insertResult.status ? 200 : 500,
181+
success: insertResult.status,
171182
dependencyTypeName: "SQL",
172183
});
173184

@@ -186,15 +197,15 @@ module.exports = (app) => {
186197
if (pctSelected) {
187198
//if percentage is selected, insert into DB
188199
let startTime = Date.now();
189-
let query = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, pctValue, null, comment);
200+
let insertResult = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, pctValue, null, comment);
190201
let duration = Date.now() - startTime;
191202
appInsights.trackDependency({
192203
target: "DB:copilotUsage",
193204
name: "insert when pct is selected",
194-
data: query,
205+
data: insertResult.query,
195206
duration: duration,
196-
resultCode: 0,
197-
success: true,
207+
resultCode: insertResult.status ? 200 : 500,
208+
success: insertResult.status,
198209
dependencyTypeName: "SQL",
199210
});
200211
}
@@ -224,15 +235,15 @@ module.exports = (app) => {
224235
if (freqSelected) {
225236
//if frequency is selected, insert into DB
226237
let startTime = Date.now();
227-
let query = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, freqValue, comment);
238+
let insertResult = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, freqValue, comment);
228239
let duration = Date.now() - startTime;
229240
appInsights.trackDependency({
230241
target: "DB:copilotUsage",
231242
name: "insert when freq is selected",
232-
data: query,
243+
data: insertResult.query,
233244
duration: duration,
234-
resultCode: 0,
235-
success: true,
245+
resultCode: insertResult.status ? 200 : 500,
246+
success: insertResult.status,
236247
dependencyTypeName: "SQL",
237248
});
238249
}
@@ -262,15 +273,15 @@ module.exports = (app) => {
262273
})
263274
) {
264275
let startTime = Date.now();
265-
let query = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, null, comment);
276+
let insertResult = await insertIntoDB(context, issue_id, pr_number, isCopilotUsed, null, null, comment);
266277
let duration = Date.now() - startTime;
267278
appInsights.trackDependency({
268279
target: "DB:copilotUsage",
269280
name: "insert when No is selected",
270-
data: query,
281+
data: insertResult.query,
271282
duration: duration,
272-
resultCode: 0,
273-
success: true,
283+
resultCode: insertResult.status ? 200 : 500,
284+
success: insertResult.status,
274285
dependencyTypeName: "SQL",
275286
});
276287

@@ -301,7 +312,11 @@ module.exports = (app) => {
301312
freqValue,
302313
comment
303314
) {
315+
304316
let conn = null;
317+
let query = null;
318+
let status = true;
319+
305320
try {
306321
conn = await sql.connect(DATABASE_CONNECTION_STRING);
307322

@@ -316,18 +331,18 @@ module.exports = (app) => {
316331
// Create table if it doesn't exist
317332
await sql.query`
318333
CREATE TABLE SurveyResults (
319-
record_ID int IDENTITY(1,1),
320-
enterprise_name varchar(50),
321-
organization_name varchar(50),
322-
repository_name varchar(50),
323-
issue_id int,
324-
issue_number varchar(20),
325-
PR_number varchar(20),
326-
assignee_name varchar(50),
334+
record_ID INT IDENTITY(1,1),
335+
enterprise_name VARCHAR(50),
336+
organization_name VARCHAR(50),
337+
repository_name VARCHAR(50),
338+
issue_id BIGINT,
339+
issue_number INT,
340+
PR_number INT,
341+
assignee_name VARCHAR(50),
327342
is_copilot_used BIT,
328-
saving_percentage varchar(25),
329-
usage_frequency varchar(50),
330-
comment varchar(255),
343+
saving_percentage VARCHAR(25),
344+
usage_frequency VARCHAR(50),
345+
comment VARCHAR(255),
331346
created_at DATETIME,
332347
completed_at DATETIME
333348
);
@@ -372,7 +387,6 @@ module.exports = (app) => {
372387
// update existing record
373388
let update_result = await sql.query(update_query);
374389
app.log.info(update_result);
375-
return update_query;
376390
} else {
377391
// check if dynamic values are present in context.payload
378392
let enterprise_name = null;
@@ -409,7 +423,7 @@ module.exports = (app) => {
409423
${context.payload.issue.number},
410424
${pr_number},
411425
'${assignee_name}',
412-
'${isCopilotUsed}',
426+
'${isCopilotUsed}',
413427
'${pctValue}',
414428
'${freqValue}',
415429
'${comment}',
@@ -418,65 +432,47 @@ module.exports = (app) => {
418432
)`;
419433
let insert_result = await sql.query(insert_query);
420434
app.log.info(insert_result);
421-
return insert_query;
422435
}
423436
} catch (err) {
424437
app.log.error(err);
425438
appInsights.trackException({ exception: err });
439+
status = false;
426440
} finally {
427441
if (conn) {
428442
conn.close();
429443
}
444+
return {
445+
query: query,
446+
status: status
447+
};
448+
}
430449
}
431-
}
432-
433-
// For more information on building apps:
434-
// https://probot.github.io/docs/
435-
436-
// To get your app running against GitHub, see:
437-
// https://probot.github.io/docs/development/
438-
};
450+
};
439451

440452
// Define class for app insights. If no instrumentation key is provided, then no app insights will be used.
441453
class AppInsights {
442454
constructor() {
443-
if (process.env.APPINSIGHTS_INSTRUMENTATIONKEY) {
455+
if (process.env.APPLICATIONINSIGHTS_CONNECTION_STRING) {
444456
this.appInsights = require("applicationinsights");
445457
this.appInsights.setup().start();
446458
this.appIClient = this.appInsights.defaultClient;
447459
} else {
448460
this.appIClient = null;
449461
}
450462
}
451-
trackEvent(name, properties) {
463+
trackEvent(event) {
452464
if (this.appIClient) {
453-
this.appIClient.trackEvent({ name: name, properties: properties });
465+
this.appIClient.trackEvent(event);
454466
}
455467
}
456-
trackDependency(
457-
target,
458-
name,
459-
data,
460-
duration,
461-
resultCode,
462-
success,
463-
dependencyTypeName
464-
) {
468+
trackDependency( dependency ) {
465469
if (this.appIClient) {
466-
this.appIClient.trackDependency({
467-
target: target,
468-
name: name,
469-
data: data,
470-
duration: duration,
471-
resultCode: resultCode,
472-
success: success,
473-
dependencyTypeName: dependencyTypeName,
474-
});
470+
this.appIClient.trackDependency(dependency);
475471
}
476472
}
477473
trackException(exception) {
478474
if (this.appIClient) {
479-
this.appIClient.trackException({ exception: exception });
475+
this.appIClient.trackException(exception);
480476
}
481477
}
482478
}

0 commit comments

Comments
 (0)