Skip to content

Commit d8b8eb5

Browse files
committed
feat: add slack notify support
1 parent b4e7d4f commit d8b8eb5

File tree

10 files changed

+162
-5
lines changed

10 files changed

+162
-5
lines changed

.github/actions/deploy/deploy.mjs

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ const {
1818
COPILOT_OPENAI_API_KEY,
1919
COPILOT_FAL_API_KEY,
2020
COPILOT_UNSPLASH_API_KEY,
21+
SLACK_BOT_TOKEN,
22+
RELEASE_SLACK_CHNNEL_ID,
2123
MAILER_SENDER,
2224
MAILER_USER,
2325
MAILER_PASSWORD,
@@ -148,6 +150,8 @@ const createHelmCommand = ({ isDryRun }) => {
148150
`--set-string graphql.app.copilot.openai.key="${COPILOT_OPENAI_API_KEY}"`,
149151
`--set-string graphql.app.copilot.fal.key="${COPILOT_FAL_API_KEY}"`,
150152
`--set-string graphql.app.copilot.unsplash.key="${COPILOT_UNSPLASH_API_KEY}"`,
153+
`--set-string graphql.app.copilot.slack.botToken="${SLACK_BOT_TOKEN}"`,
154+
`--set-string graphql.app.copilot.slack.channelId="${RELEASE_SLACK_CHNNEL_ID}"`,
151155
`--set-string graphql.app.mailer.sender="${MAILER_SENDER}"`,
152156
`--set-string graphql.app.mailer.user="${MAILER_USER}"`,
153157
`--set-string graphql.app.mailer.password="${MAILER_PASSWORD}"`,

.github/helm/affine/charts/graphql/templates/copilot-secret.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ data:
88
openaiSecret: {{ .Values.app.copilot.openai.key | b64enc }}
99
falSecret: {{ .Values.app.copilot.fal.key | b64enc }}
1010
unsplashSecret: {{ .Values.app.copilot.unsplash.key | b64enc }}
11+
slackBotToken: {{ .Values.app.copilot.slack.botToken | b64enc }}
12+
slackChannelId: {{ .Values.app.copilot.slack.channelId | b64enc }}
1113
{{- end }}

.github/helm/affine/charts/graphql/templates/copilot-test.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ spec:
2121
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
2222
command: ["yarn", "test:copilot:e2e:cron"]
2323
env:
24+
- name: AFFINE_ENV
25+
value: "{{ .Release.Namespace }}"
26+
- name: SLACK_BOT_TOKEN
27+
valueFrom:
28+
secretKeyRef:
29+
name: "{{ .Values.app.copilot.secretName }}"
30+
key: slackBotToken
31+
- name: CHANNEL_ID
32+
valueFrom:
33+
secretKeyRef:
34+
name: "{{ .Values.app.copilot.secretName }}"
35+
key: slackChannelId
2436
- name: COPILOT_E2E_ENDPOINT
2537
value: "http://{{ include "graphql.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:3000"
2638
- name: DATABASE_PASSWORD

.github/workflows/deploy.yml

+3
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ jobs:
101101
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
102102
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
103103
COPILOT_UNSPLASH_API_KEY: ${{ secrets.COPILOT_UNSPLASH_API_KEY }}
104+
# used for slack notifications
105+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
106+
RELEASE_SLACK_CHNNEL_ID: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
104107
METRICS_CUSTOMER_IO_TOKEN: ${{ secrets.METRICS_CUSTOMER_IO_TOKEN }}
105108
MAILER_SENDER: ${{ secrets.OAUTH_EMAIL_SENDER }}
106109
MAILER_USER: ${{ secrets.OAUTH_EMAIL_LOGIN }}

packages/backend/native/index.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,3 @@ export declare function mergeUpdatesInApplyWay(updates: Array<Buffer>): Buffer
1919
export declare function mintChallengeResponse(resource: string, bits?: number | undefined | null): Promise<string>
2020

2121
export declare function verifyChallengeResponse(response: string, bits: number, resource: string): Promise<boolean>
22-

packages/backend/server/package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"test:coverage": "c8 ava --concurrency 1 --serial",
1818
"test:copilot:e2e:coverage": "c8 ava --timeout=5m \"tests/**/copilot-*.e2e.ts\"",
1919
"test:copilot:spec:coverage": "c8 ava --timeout=5m \"tests/**/copilot-*.spec.ts\"",
20-
"test:copilot:e2e:cron": "ava --config \"tests/ava.docker.config.js\" \"tests/**/copilot-*.e2e.ts\"",
20+
"test:copilot:e2e:cron": "node ./scripts/copilot-cron-test.js",
2121
"postinstall": "prisma generate",
2222
"data-migration": "node --loader ts-node/esm/transpile-only.mjs ./src/data/index.ts",
2323
"predeploy": "yarn prisma migrate deploy && node --import ./scripts/register.js ./dist/data/index.js run",
@@ -60,6 +60,7 @@
6060
"@opentelemetry/semantic-conventions": "^1.25.0",
6161
"@prisma/client": "^5.15.0",
6262
"@prisma/instrumentation": "^5.15.0",
63+
"@slack/web-api": "^7.3.4",
6364
"@socket.io/redis-adapter": "^8.3.0",
6465
"ava": "^6.1.2",
6566
"cookie-parser": "^1.4.6",
@@ -73,8 +74,10 @@
7374
"html-validate": "^8.20.1",
7475
"ioredis": "^5.3.2",
7576
"is-mobile": "^5.0.0",
77+
"jsx-slack": "^6.1.1",
7678
"keyv": "^5.0.0",
7779
"lodash-es": "^4.17.21",
80+
"marked": "^15.0.0",
7881
"mixpanel": "^0.18.0",
7982
"mustache": "^4.2.0",
8083
"nanoid": "^5.0.7",
@@ -91,6 +94,7 @@
9194
"socket.io": "^4.7.5",
9295
"stripe": "^17.0.0",
9396
"supertest": "^7.0.0",
97+
"tap-parser": "^18.0.0",
9498
"ts-node": "^10.9.2",
9599
"typescript": "^5.6.3",
96100
"yjs": "patch:yjs@npm%3A13.6.18#~/.yarn/patches/yjs-npm-13.6.18-ad0d5f7c43.patch",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// start process
2+
3+
import { spawn } from 'node:child_process';
4+
5+
import { WebClient } from '@slack/web-api';
6+
import { jsxslack } from 'jsx-slack';
7+
import { marked, Renderer } from 'marked';
8+
import { Parser } from 'tap-parser';
9+
10+
async function runTest() {
11+
const tester = new Promise(resolve => {
12+
const test = spawn(
13+
'npx',
14+
[
15+
'ava',
16+
'--config',
17+
'tests/ava.docker.config.js',
18+
'tests/**/copilot-*.e2e.ts',
19+
'--tap',
20+
],
21+
{ env: { ...process.env, NODE_NO_WARNINGS: 1 } }
22+
);
23+
24+
const parser = new Parser();
25+
test.stdout.pipe(parser);
26+
27+
test.on('close', _ => {
28+
const failures = parser?.failures.filter(f => !!f.fullname);
29+
const report = [
30+
`Test finished with ${parser.results.pass} passed, ${parser.results.fail} failed, ${parser.results.skip} skipped.`,
31+
failures?.length > 0
32+
? `Failed tests: \n\n${failures.map(failure => `- ${failure.fullname}`).join('\n')}`
33+
: '',
34+
];
35+
resolve(report.join('\n\n'));
36+
});
37+
});
38+
39+
try {
40+
return await tester;
41+
} catch (e) {
42+
return e.message;
43+
}
44+
}
45+
46+
function render(markdown) {
47+
const rendered = marked(markdown, {
48+
renderer: new (class CustomRenderer extends Renderer {
49+
heading({ tokens }) {
50+
return `
51+
<Fragment>
52+
<Section><b>${tokens[0].text}</b></Section>
53+
<Divider />
54+
</Fragment>`;
55+
}
56+
57+
paragraph({ tokens }) {
58+
return `<Section><p>${tokens[0].text}</b></Section>`;
59+
}
60+
61+
list(token) {
62+
return `<Section>${super.list(token)}</Section>`;
63+
}
64+
65+
hr() {
66+
return `<Divider />`;
67+
}
68+
})(),
69+
});
70+
return jsxslack([`<Blocks>${rendered}</Blocks>`]);
71+
}
72+
73+
async function main() {
74+
const { CHANNEL_ID, SLACK_BOT_TOKEN, AFFINE_ENV } = process.env;
75+
76+
const report = await runTest();
77+
const blocks = render(
78+
[`# AFFiNE Copilot Test ${AFFINE_ENV} Env Test Result`, report].join('\n\n')
79+
);
80+
const { ok } = await new WebClient(SLACK_BOT_TOKEN).chat.postMessage({
81+
channel: CHANNEL_ID,
82+
text: `AFFiNE Copilot Test ${AFFINE_ENV} Env Test Result`,
83+
blocks,
84+
});
85+
86+
console.assert(ok, 'Failed to send a message to Slack');
87+
}
88+
89+
await main();

packages/frontend/native/index.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,3 @@ export declare enum ValidationResult {
6666
}
6767

6868
export declare function verifyChallengeResponse(response: string, bits: number, resource: string): Promise<boolean>
69-

packages/frontend/native/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// prettier-ignore
22
/* eslint-disable */
3+
// @ts-nocheck
34
/* auto-generated by NAPI-RS */
45

5-
const { readFileSync } = require('fs')
6+
const { createRequire } = require('node:module')
7+
require = createRequire(__filename)
68

9+
const { readFileSync } = require('node:fs')
710
let nativeBinding = null
811
const loadErrors = []
912

yarn.lock

+43-1
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,7 @@ __metadata:
793793
"@opentelemetry/semantic-conventions": "npm:^1.25.0"
794794
"@prisma/client": "npm:^5.15.0"
795795
"@prisma/instrumentation": "npm:^5.15.0"
796+
"@slack/web-api": "npm:^7.3.4"
796797
"@socket.io/redis-adapter": "npm:^8.3.0"
797798
"@types/cookie-parser": "npm:^1.4.7"
798799
"@types/express": "npm:^4.17.21"
@@ -819,8 +820,10 @@ __metadata:
819820
html-validate: "npm:^8.20.1"
820821
ioredis: "npm:^5.3.2"
821822
is-mobile: "npm:^5.0.0"
823+
jsx-slack: "npm:^6.1.1"
822824
keyv: "npm:^5.0.0"
823825
lodash-es: "npm:^4.17.21"
826+
marked: "npm:^15.0.0"
824827
mixpanel: "npm:^0.18.0"
825828
mustache: "npm:^4.2.0"
826829
nanoid: "npm:^5.0.7"
@@ -839,6 +842,7 @@ __metadata:
839842
socket.io: "npm:^4.7.5"
840843
stripe: "npm:^17.0.0"
841844
supertest: "npm:^7.0.0"
845+
tap-parser: "npm:^18.0.0"
842846
ts-node: "npm:^10.9.2"
843847
typescript: "npm:^5.6.3"
844848
yjs: "patch:yjs@npm%3A13.6.18#~/.yarn/patches/yjs-npm-13.6.18-ad0d5f7c43.patch"
@@ -20044,6 +20048,13 @@ __metadata:
2004420048
languageName: node
2004520049
linkType: hard
2004620050

20051+
"events-to-array@npm:^2.0.3":
20052+
version: 2.0.3
20053+
resolution: "events-to-array@npm:2.0.3"
20054+
checksum: 10/d392eb0013013c3dfa66710a017902760edb2a588f6b1a3f1c92219563ba1c24bcb99c48e3754423a3538ebfd70318c3536d30bfd80c00e7fec77fdd088540d0
20055+
languageName: node
20056+
linkType: hard
20057+
2004720058
"events@npm:^3.2.0":
2004820059
version: 3.3.0
2004920060
resolution: "events@npm:3.3.0"
@@ -31267,6 +31278,28 @@ __metadata:
3126731278
languageName: node
3126831279
linkType: hard
3126931280

31281+
"tap-parser@npm:^18.0.0":
31282+
version: 18.0.0
31283+
resolution: "tap-parser@npm:18.0.0"
31284+
dependencies:
31285+
events-to-array: "npm:^2.0.3"
31286+
tap-yaml: "npm:4.0.0"
31287+
bin:
31288+
tap-parser: bin/cmd.cjs
31289+
checksum: 10/6e13dc475bfdc880307cc935b9917d43255f7e2b0902d171b7f51b41b029aae9dce5b8683aa48170bb720819b3551d793663c0a11f0660ef78d4a0fe87228ad0
31290+
languageName: node
31291+
linkType: hard
31292+
31293+
"tap-yaml@npm:4.0.0":
31294+
version: 4.0.0
31295+
resolution: "tap-yaml@npm:4.0.0"
31296+
dependencies:
31297+
yaml: "npm:^2.4.1"
31298+
yaml-types: "npm:^0.4.0"
31299+
checksum: 10/21d3a27328aa419bb90249357689446488351d350a4ba56c5b1afce9dfe33f60db49014170ea7d16eb90381d3f9f31b59d9637bda632e55167f33c834eb02171
31300+
languageName: node
31301+
linkType: hard
31302+
3127031303
"tapable@npm:^2.0.0, tapable@npm:^2.1.1, tapable@npm:^2.2.0, tapable@npm:^2.2.1":
3127131304
version: 2.2.1
3127231305
resolution: "tapable@npm:2.2.1"
@@ -33501,14 +33534,23 @@ __metadata:
3350133534
languageName: node
3350233535
linkType: hard
3350333536

33537+
"yaml-types@npm:^0.4.0":
33538+
version: 0.4.0
33539+
resolution: "yaml-types@npm:0.4.0"
33540+
peerDependencies:
33541+
yaml: ^2.3.0
33542+
checksum: 10/8a3cd3a0420d5d09981e3e1add46d7482336531e3bdc02192d26caa915c7d0795ad28dd8766e357234d6bfa3a2bd986687f967079e47aecfd4b191250f041cec
33543+
languageName: node
33544+
linkType: hard
33545+
3350433546
"yaml@npm:^1.10.0":
3350533547
version: 1.10.2
3350633548
resolution: "yaml@npm:1.10.2"
3350733549
checksum: 10/e088b37b4d4885b70b50c9fa1b7e54bd2e27f5c87205f9deaffd1fb293ab263d9c964feadb9817a7b129a5bf30a06582cb08750f810568ecc14f3cdbabb79cb3
3350833550
languageName: node
3350933551
linkType: hard
3351033552

33511-
"yaml@npm:^2.3.1, yaml@npm:^2.3.4, yaml@npm:^2.5.1":
33553+
"yaml@npm:^2.3.1, yaml@npm:^2.3.4, yaml@npm:^2.4.1, yaml@npm:^2.5.1":
3351233554
version: 2.6.0
3351333555
resolution: "yaml@npm:2.6.0"
3351433556
bin:

0 commit comments

Comments
 (0)