Skip to content

Commit 63093f5

Browse files
committed
Added check to events-to-s3 for label canary
Signed-off-by: Brandon Shien <bshien@amazon.com>
1 parent 3b1ecd9 commit 63093f5

File tree

6 files changed

+179
-7
lines changed

6 files changed

+179
-7
lines changed

configs/operations/github-events-to-s3.yml

+2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ events:
55
- all
66

77
tasks:
8+
- name: Github Label Canary Monitor
9+
call: github-label-canary-monitor@default
810
- name: Github Events To S3 Operation
911
call: github-events-to-s3@default

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "opensearch-automation-app",
3-
"version": "0.3.5",
3+
"version": "0.3.6",
44
"description": "An Automation App that handles all your GitHub Repository Activities",
55
"author": "Peter Zhu",
66
"homepage": "https://github.com/opensearch-project/automation-app",
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* The OpenSearch Contributors require contributions made to
6+
* this file be licensed under the Apache-2.0 license or a
7+
* compatible open source license.
8+
*/
9+
10+
// Name : githubLabelCanaryMonitor
11+
// Description : Handle canary event by sending CloudWatch Metrics for monitoring purposes
12+
13+
import { Probot } from 'probot';
14+
import { CloudWatchClient, PutMetricDataCommand } from '@aws-sdk/client-cloudwatch';
15+
16+
export default async function githubLabelCanaryMonitor(app: Probot, context: any): Promise<void> {
17+
// Removed validateResourceConfig to let this function listen on all repos, and filter for only the repos that are public.
18+
// This is done so when a new repo is made public, this app can automatically start processing its events.
19+
//
20+
// This is only for the s3 data lake specific case, everything else should still specify repos required to be listened in resource config.
21+
//
22+
// if (!(await validateResourceConfig(app, context, resource))) return;
23+
//
24+
const repoName = context.payload.repository?.name;
25+
if (context.payload.repository?.private === false) {
26+
// Handle canary event for monitoring purposes
27+
if (repoName === 'opensearch-metrics' && context.name === 'label' && context.payload.label?.name === 's3-data-lake-app-canary-label') {
28+
// Ignore if label was created
29+
if (context.payload.action === 'deleted') {
30+
try {
31+
const cloudWatchClient = new CloudWatchClient({ region: String(process.env.REGION) });
32+
const putMetricDataCommand = new PutMetricDataCommand({
33+
Namespace: 'GitHubLabelCanary',
34+
MetricData: [
35+
{
36+
MetricName: 'AutomationApp_EventDataLake',
37+
Value: 1,
38+
Unit: 'Count',
39+
},
40+
],
41+
});
42+
await cloudWatchClient.send(putMetricDataCommand);
43+
app.log.info('CloudWatch metric for monitoring published.');
44+
} catch (error) {
45+
app.log.error(`Error Publishing CloudWatch metric for monitoring : ${error}`);
46+
}
47+
}
48+
// In the future, add `exit` right here to prevent subsequent tasks from running
49+
}
50+
}
51+
}

src/utility/opensearch/opensearch-client.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ export class OpensearchClient {
4141
...AwsSigv4Signer({
4242
region: this._region,
4343
getCredentials: () => Promise.resolve({
44-
accessKeyId: credentials.AccessKeyId!,
45-
secretAccessKey: credentials.SecretAccessKey!,
46-
sessionToken: credentials.SessionToken!,
47-
}),
44+
accessKeyId: credentials.AccessKeyId!,
45+
secretAccessKey: credentials.SecretAccessKey!,
46+
sessionToken: credentials.SessionToken!,
47+
}),
4848
}),
4949
node: this._openSearchUrl,
5050
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* The OpenSearch Contributors require contributions made to
6+
* this file be licensed under the Apache-2.0 license or a
7+
* compatible open source license.
8+
*/
9+
10+
import { Logger, Probot } from 'probot';
11+
import githubLabelCanaryMonitor from '../../src/call/github-label-canary-monitor';
12+
import { CloudWatchClient, PutMetricDataCommand } from '@aws-sdk/client-cloudwatch';
13+
14+
jest.mock('@aws-sdk/client-cloudwatch');
15+
16+
describe('githubEventsToS3', () => {
17+
let app: Probot;
18+
let context: any;
19+
let mockCloudWatchClient: any;
20+
21+
beforeEach(() => {
22+
app = new Probot({ appId: 1, secret: 'test', privateKey: 'test' });
23+
app.log = {
24+
info: jest.fn(),
25+
error: jest.fn(),
26+
} as unknown as Logger;
27+
28+
context = {
29+
name: 'name',
30+
id: 'id',
31+
payload: {
32+
repository: {
33+
name: 'repo',
34+
owner: { login: 'org' },
35+
private: false,
36+
},
37+
},
38+
};
39+
40+
mockCloudWatchClient = {
41+
send: jest.fn(),
42+
};
43+
(CloudWatchClient as jest.Mock).mockImplementation(() => mockCloudWatchClient);
44+
});
45+
46+
afterEach(() => {
47+
jest.clearAllMocks();
48+
});
49+
50+
it('should publish CloudWatch metric if event is label canary', async () => {
51+
context = {
52+
name: 'label',
53+
id: 'id',
54+
payload: {
55+
action: 'deleted',
56+
label: {
57+
name: 's3-data-lake-app-canary-label',
58+
},
59+
repository: {
60+
name: 'opensearch-metrics',
61+
private: false,
62+
},
63+
},
64+
};
65+
66+
mockCloudWatchClient.send.mockResolvedValue({});
67+
68+
await githubLabelCanaryMonitor(app, context);
69+
70+
expect(mockCloudWatchClient.send).toHaveBeenCalledWith(expect.any(PutMetricDataCommand));
71+
expect(app.log.info).toHaveBeenCalledWith('CloudWatch metric for monitoring published.');
72+
});
73+
74+
it('should not publish CloudWatch metric if event is not label canary', async () => {
75+
context = {
76+
name: 'label',
77+
id: 'id',
78+
payload: {
79+
label: {
80+
name: 'normal-label',
81+
},
82+
repository: {
83+
name: 'opensearch-metrics',
84+
private: false,
85+
},
86+
},
87+
};
88+
89+
mockCloudWatchClient.send.mockResolvedValue({});
90+
91+
await githubLabelCanaryMonitor(app, context);
92+
93+
expect(mockCloudWatchClient.send).not.toHaveBeenCalledWith(expect.any(PutMetricDataCommand));
94+
expect(app.log.info).not.toHaveBeenCalledWith('CloudWatch metric for monitoring published.');
95+
});
96+
97+
it('should log an error if CloudWatch metric publishing fails', async () => {
98+
context = {
99+
name: 'label',
100+
id: 'id',
101+
payload: {
102+
action: 'deleted',
103+
label: {
104+
name: 's3-data-lake-app-canary-label',
105+
},
106+
repository: {
107+
name: 'opensearch-metrics',
108+
private: false,
109+
},
110+
},
111+
};
112+
113+
mockCloudWatchClient.send.mockRejectedValue(new Error('CloudWatch error'));
114+
115+
await githubLabelCanaryMonitor(app, context);
116+
117+
expect(app.log.error).toHaveBeenCalledWith('Error Publishing CloudWatch metric for monitoring : Error: CloudWatch error');
118+
});
119+
});

0 commit comments

Comments
 (0)