Skip to content

Commit 164c767

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

File tree

5 files changed

+188
-3
lines changed

5 files changed

+188
-3
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ events:
55
- all
66

77
tasks:
8+
- name: Github Label Canary Monitor
9+
call: github-label-canary-monitor@default
10+
args:
11+
metricName: AutomationApp_EventDataLake
812
- name: Github Events To S3 Operation
913
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",
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
// Arguments :
13+
// - metricName: (string) The name of the CloudWatch Metric you want to send data to.
14+
15+
import { Probot } from 'probot';
16+
import { CloudWatchClient, PutMetricDataCommand } from '@aws-sdk/client-cloudwatch';
17+
18+
export interface LabelCanaryMonitorParams {
19+
metricName: string;
20+
}
21+
22+
export default async function githubLabelCanaryMonitor(app: Probot, context: any, { metricName }: LabelCanaryMonitorParams): Promise<void> {
23+
// Removed validateResourceConfig to let this function listen on all repos, and filter for only the repos that are public.
24+
// This is done so when a new repo is made public, this app can automatically start processing its events.
25+
//
26+
// This is only for the s3 data lake specific case, everything else should still specify repos required to be listened in resource config.
27+
//
28+
// if (!(await validateResourceConfig(app, context, resource))) return;
29+
//
30+
const repoName = context.payload.repository?.name;
31+
if (context.payload.repository?.private === false) {
32+
// Handle canary event for monitoring purposes
33+
if (repoName === 'opensearch-metrics' && context.name === 'label' && context.payload.label?.name === 's3-data-lake-app-canary-label') {
34+
// Ignore if label was created
35+
if (context.payload.action === 'deleted') {
36+
try {
37+
const cloudWatchClient = new CloudWatchClient({ region: String(process.env.REGION) });
38+
const putMetricDataCommand = new PutMetricDataCommand({
39+
Namespace: 'GitHubLabelCanary',
40+
MetricData: [
41+
{
42+
MetricName: JSON.stringify(metricName),
43+
Value: 1,
44+
Unit: 'Count',
45+
},
46+
],
47+
});
48+
await cloudWatchClient.send(putMetricDataCommand);
49+
app.log.info('CloudWatch metric for monitoring published.');
50+
} catch (error) {
51+
app.log.error(`Error Publishing CloudWatch metric for monitoring : ${error}`);
52+
}
53+
}
54+
return; // In the future, add `exit` right here to prevent subsequent tasks from running
55+
}
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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, { LabelCanaryMonitorParams } 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+
let args: LabelCanaryMonitorParams;
21+
22+
beforeEach(() => {
23+
args = {
24+
metricName: 'testMetric',
25+
};
26+
27+
app = new Probot({ appId: 1, secret: 'test', privateKey: 'test' });
28+
app.log = {
29+
info: jest.fn(),
30+
error: jest.fn(),
31+
} as unknown as Logger;
32+
33+
context = {
34+
name: 'name',
35+
id: 'id',
36+
payload: {
37+
repository: {
38+
name: 'repo',
39+
owner: { login: 'org' },
40+
private: false,
41+
},
42+
},
43+
};
44+
45+
mockCloudWatchClient = {
46+
send: jest.fn(),
47+
};
48+
(CloudWatchClient as jest.Mock).mockImplementation(() => mockCloudWatchClient);
49+
});
50+
51+
afterEach(() => {
52+
jest.clearAllMocks();
53+
});
54+
55+
it('should publish CloudWatch metric if event is label canary', async () => {
56+
context = {
57+
name: 'label',
58+
id: 'id',
59+
payload: {
60+
action: 'deleted',
61+
label: {
62+
name: 's3-data-lake-app-canary-label',
63+
},
64+
repository: {
65+
name: 'opensearch-metrics',
66+
private: false,
67+
},
68+
},
69+
};
70+
71+
mockCloudWatchClient.send.mockResolvedValue({});
72+
73+
await githubLabelCanaryMonitor(app, context, args);
74+
75+
expect(mockCloudWatchClient.send).toHaveBeenCalledWith(expect.any(PutMetricDataCommand));
76+
expect(app.log.info).toHaveBeenCalledWith('CloudWatch metric for monitoring published.');
77+
});
78+
79+
it('should not publish CloudWatch metric if event is not label canary', async () => {
80+
context = {
81+
name: 'label',
82+
id: 'id',
83+
payload: {
84+
label: {
85+
name: 'normal-label',
86+
},
87+
repository: {
88+
name: 'opensearch-metrics',
89+
private: false,
90+
},
91+
},
92+
};
93+
94+
mockCloudWatchClient.send.mockResolvedValue({});
95+
96+
await githubLabelCanaryMonitor(app, context, args);
97+
98+
expect(mockCloudWatchClient.send).not.toHaveBeenCalledWith(expect.any(PutMetricDataCommand));
99+
expect(app.log.info).not.toHaveBeenCalledWith('CloudWatch metric for monitoring published.');
100+
});
101+
102+
it('should log an error if CloudWatch metric publishing fails', async () => {
103+
context = {
104+
name: 'label',
105+
id: 'id',
106+
payload: {
107+
action: 'deleted',
108+
label: {
109+
name: 's3-data-lake-app-canary-label',
110+
},
111+
repository: {
112+
name: 'opensearch-metrics',
113+
private: false,
114+
},
115+
},
116+
};
117+
118+
mockCloudWatchClient.send.mockRejectedValue(new Error('CloudWatch error'));
119+
120+
await githubLabelCanaryMonitor(app, context, args);
121+
122+
expect(app.log.error).toHaveBeenCalledWith('Error Publishing CloudWatch metric for monitoring : Error: CloudWatch error');
123+
});
124+
});

0 commit comments

Comments
 (0)