Skip to content

Commit bd29682

Browse files
shuyangligithub-actions[bot]TensorZero-Experimental-CI-Bot[bot]
authored
Allow mapping PRs to episode-level metrics (#29)
* Add clickhouse methods for PR - episode mapping * TEMP: feedback * Configure episode-level feedback metric * Remove duplicate episode mapping function * chore: automated fix for PR #29 (#30) Co-authored-by: TensorZero-Experimental-CI-Bot[bot] <hello@tensorzero.com> * Lint --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: TensorZero-Experimental-CI-Bot[bot] <hello@tensorzero.com>
1 parent 45104be commit bd29682

File tree

13 files changed

+139
-7
lines changed

13 files changed

+139
-7
lines changed

.github/workflows/ci-failure-diagnosis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
with:
6868
token: ${{ secrets.GITHUB_TOKEN }}
6969
tensorzero-base-url: http://localhost:3000
70+
# TODO: Remove when agent creates PRs
7071
tensorzero-diff-patched-successfully-metric-name: tensorzero_github_ci_bot_diff_patched_successfully
7172
output-artifacts-dir: debug-logs
7273
clickhouse-url: ${{ secrets.CI_BOT_CLICKHOUSE_URL }}

.github/workflows/provide-pull-request-feedback.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
uses: tensorzero/experimental-ci-bot/create-pr-feedback@main
4444
with:
4545
tensorzero-base-url: http://localhost:3000
46+
# TODO: Switch to tensorzero_github_ci_bot_agent_pr_merged for episode-level feedback when agent creates PRs
4647
tensorzero-pr-merged-metric-name: tensorzero_github_ci_bot_pr_merged
4748
clickhouse-url: ${{ secrets.CI_BOT_CLICKHOUSE_URL }}
4849
clickhouse-table: GitHubBotPullRequestToInferenceMap

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,5 @@ alongside source when behavior changes.
5252

5353
## IMPORTANT RULES
5454

55-
Before submitting a PR, run `npm run bundle` to update the javascript bundles.
55+
Before submitting a PR, run `npm run bundle` to update the JavaScript bundles.
5656
Otherwise, CI will fail.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ CREATE TABLE GitHubBotPullRequestToInferenceMap
3838
(
3939
pull_request_id UInt128,
4040
inference_id String,
41+
episode_id String,
4142
created_at DateTime DEFAULT now(),
4243
original_pull_request_url String
4344
)

dist/create-pr-feedback/index.js

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/create-pr-feedback/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/generate-pr-patch/index.js

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/generate-pr-patch/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/clickhouseClient.test.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
type ClickHouseClientLike,
55
type ClickHouseConfig,
66
createPullRequestToInferenceRecord,
7-
getPullRequestToInferenceRecords
7+
getPullRequestToInferenceRecords,
8+
getPullRequestToEpisodeRecords
89
} from './clickhouseClient.js'
910

1011
const defaultConfig: ClickHouseConfig = {
@@ -31,6 +32,7 @@ describe('clickhouseClient', () => {
3132
await createPullRequestToInferenceRecord(
3233
{
3334
inferenceId: 'abc-123',
35+
episodeId: 'episode-123',
3436
pullRequestId: 42,
3537
originalPullRequestUrl: 'https://github.com/org/repo/pull/42'
3638
},
@@ -42,6 +44,7 @@ describe('clickhouseClient', () => {
4244
table: 'tensorzero.inference_records',
4345
values: [
4446
{
47+
episode_id: 'episode-123',
4548
pull_request_id: 42,
4649
inference_id: 'abc-123',
4750
original_pull_request_url: 'https://github.com/org/repo/pull/42'
@@ -86,6 +89,7 @@ describe('clickhouseClient', () => {
8689
createPullRequestToInferenceRecord(
8790
{
8891
inferenceId: 'abc',
92+
episodeId: 'episode-123',
8993
pullRequestId: 1,
9094
originalPullRequestUrl: 'https://example.com/pr/1'
9195
},
@@ -99,6 +103,7 @@ describe('clickhouseClient', () => {
99103
createPullRequestToInferenceRecord(
100104
{
101105
inferenceId: 'abc',
106+
episodeId: 'episode-123',
102107
pullRequestId: 1,
103108
originalPullRequestUrl: 'https://example.com/pr/1'
104109
},
@@ -114,6 +119,7 @@ describe('clickhouseClient', () => {
114119
createPullRequestToInferenceRecord(
115120
{
116121
inferenceId: 'abc',
122+
episodeId: 'episode-123',
117123
pullRequestId: 1,
118124
originalPullRequestUrl: 'https://example.com/pr/1'
119125
},
@@ -124,4 +130,43 @@ describe('clickhouseClient', () => {
124130

125131
expect(client.close).not.toHaveBeenCalled()
126132
})
133+
134+
it('queries episode records with parameter binding', async () => {
135+
const expectedRecords = [
136+
{
137+
episode_id: 'episode-789',
138+
pull_request_id: 55,
139+
created_at: '2024-02-01T00:00:00Z',
140+
original_pull_request_url: 'https://github.com/org/repo/pull/55'
141+
}
142+
]
143+
const jsonMock = jest
144+
.fn<() => Promise<unknown>>()
145+
.mockResolvedValue(expectedRecords)
146+
// @ts-expect-error(Mock type is inaccurate)
147+
client.query.mockResolvedValueOnce({ json: jsonMock })
148+
149+
const records = await getPullRequestToEpisodeRecords(55, defaultConfig, {
150+
client
151+
})
152+
153+
expect(client.query).toHaveBeenCalledWith({
154+
query:
155+
'SELECT episode_id, pull_request_id, created_at, original_pull_request_url FROM tensorzero.inference_records WHERE pull_request_id = {pullRequestId:UInt64}',
156+
query_params: { pullRequestId: 55 },
157+
format: 'JSONEachRow'
158+
})
159+
expect(jsonMock).toHaveBeenCalledTimes(1)
160+
expect(records).toEqual(expectedRecords)
161+
})
162+
163+
it('propagates query failures for episode records without closing the client', async () => {
164+
client.query.mockRejectedValueOnce(new Error('query failed'))
165+
166+
await expect(
167+
getPullRequestToEpisodeRecords(123, defaultConfig, { client })
168+
).rejects.toThrow('query failed')
169+
170+
expect(client.close).not.toHaveBeenCalled()
171+
})
127172
})

src/clickhouseClient.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface ClickHouseConfig {
1616

1717
export interface CreatePullRequestToInferenceRequest {
1818
inferenceId: string
19+
episodeId: string
1920
pullRequestId: number
2021
originalPullRequestUrl: string
2122
}
@@ -27,6 +28,13 @@ export interface PullRequestToInferenceRecord {
2728
original_pull_request_url: string
2829
}
2930

31+
export interface PullRequestToEpisodeRecord {
32+
episode_id: string
33+
pull_request_id: number
34+
created_at: string
35+
original_pull_request_url: string
36+
}
37+
3038
const CLICKHOUSE_TABLE_NAME_REGEX = /^[a-zA-Z0-9_.]+$/
3139

3240
function assertValidTableName(table: string): void {
@@ -103,6 +111,7 @@ export async function createPullRequestToInferenceRecord(
103111
{
104112
pull_request_id: request.pullRequestId,
105113
inference_id: request.inferenceId,
114+
episode_id: request.episodeId,
106115
original_pull_request_url: request.originalPullRequestUrl
107116
}
108117
],
@@ -140,3 +149,29 @@ export async function getPullRequestToInferenceRecords(
140149
}
141150
return records
142151
}
152+
153+
// Returns all episode records for a given pull request.
154+
export async function getPullRequestToEpisodeRecords(
155+
pullRequestId: number,
156+
config: ClickHouseConfig,
157+
dependencies?: ClickHouseDependencies
158+
): Promise<PullRequestToEpisodeRecord[]> {
159+
const { client, table, shouldClose } = createTensorZeroClickHouseClient(
160+
config,
161+
dependencies
162+
)
163+
let records: PullRequestToEpisodeRecord[] = []
164+
try {
165+
const response = await client.query({
166+
query: `SELECT episode_id, pull_request_id, created_at, original_pull_request_url FROM ${table} WHERE pull_request_id = {pullRequestId:UInt64}`,
167+
query_params: { pullRequestId },
168+
format: 'JSONEachRow'
169+
})
170+
records = await response.json()
171+
} finally {
172+
if (shouldClose) {
173+
await client.close()
174+
}
175+
}
176+
return records
177+
}

0 commit comments

Comments
 (0)