Skip to content

Repo sync #37109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/ghes-releases/lib/release-templates/release-steps-0.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ labels:
- skip FR board
- GHES {{ release-number }}
- ghes-release-automation
- rhythm of docs operations
---

This issue tracks Docs work for the GA release of GHES {{ release-number }}.
Expand All @@ -26,11 +27,11 @@ This issue tracks Docs work for the GA release of GHES {{ release-number }}.

## Instructions for triage

- [ ] In the Enterprise project, adjust the "Cycle" field to the cycle containing the target date.
- [ ] Add this issue to the [Rhythm of Docs: Operations](https://github.com/orgs/github/projects/20190) project.
- [ ] For assignee: if needed, add this issue to your persona team project for tracking purposes.

<br/>

```[tasklist]
# Tasks
- [ ] {{ release-steps-1-url }}
- [ ] {{ release-steps-2-url }}
Expand All @@ -43,7 +44,6 @@ This issue tracks Docs work for the GA release of GHES {{ release-number }}.
- [ ] After merging PR for RC, notify the API team in [#ecosystem-api](https://github.slack.com/archives/C1042T6MS) on Slack that they can now merge "Update OpenAPI 3.x Descriptions" PRs in [`github/rest-api-description`](https://github.com/github/rest-api-description/pulls), which you blocked as part of the issue for preparing OpenAPI assets.
- [ ] Notify the Docs Content first responder (`@TBD`) that they can now merge OpenAPI PRs.
- [ ] To close this issue, open a PR to complete [these steps](https://github.com/github/docs-content/issues/12972#issuecomment-1947981671).
```

## Resources

Expand Down
4 changes: 3 additions & 1 deletion src/ghes-releases/lib/release-templates/release-steps-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ labels:
- new-release
- priority-0
- skip FR board
- rhythm of docs operations
- GHES {{ release-number }}
---

## Instructions for triage

- [ ] In the Enterprise project, adjust the "Cycle" field to the cycle containing the target date.
- [ ] Add this issue to the [Rhythm of Docs: Operations](https://github.com/orgs/github/projects/20190) project.
- [ ] For assignee: if needed, add this issue to your persona team project for tracking purposes.

## Instructions for assignee

Expand Down
4 changes: 3 additions & 1 deletion src/ghes-releases/lib/release-templates/release-steps-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ labels:
- priority-0
- skip FR board
- GHES {{ release-number }}
- rhythm of docs operations
---

## Instructions for triage

- [ ] In the Enterprise project, adjust the "Cycle" field to the cycle **four weeks** before the target date.
- [ ] Add this issue to the [Rhythm of Docs: Operations](https://github.com/orgs/github/projects/20190) project.
- [ ] For assignee: if needed, add this issue to your persona team project for tracking purposes.

## Instructions for assignee

Expand Down
14 changes: 8 additions & 6 deletions src/ghes-releases/lib/release-templates/release-steps-5.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ labels:
- new-release
- priority-0
- skip FR board
- rhythm of docs operations
---

## Instructions for triage

- [ ] In the Enterprise focus area's project, adjust the "Cycle" field for this issue to the cycle four weeks before the target date.
- [ ] Add this issue to the [Rhythm of Docs: Operations](https://github.com/orgs/github/projects/20190) project.
- [ ] For assignee: if needed, add this issue to your persona team project for tracking purposes.

## Instructions for assignee

Expand Down Expand Up @@ -83,7 +85,7 @@ To prepare for publication, create a PR in `github/github` that publishes the sc

- [ ] Create a PR.

- [ ] Get the necessary reviews, but **do not deploy and merge the PR**. You'll merge this PR closer to the RC's release date, while Docs' repositories are frozen.
- [ ] Get the necessary reviews, but **do not deploy and merge the PR yet**. You'll merge this PR closer to the RC's release date.

<br/>
<a name="merge">
Expand All @@ -92,19 +94,19 @@ To prepare for publication, create a PR in `github/github` that publishes the sc

To trigger creation of an OpenAPI PR with the updated schema for the RC, merge your publication PR in `github/github`.

- [ ] On the Thursday after you begin the freeze of Docs' repositories per {{ release-steps-0-url }}, merge the publication PR you [prepared in `github/github`](#publication-preparation).
- [ ] 2-3 days before the RC release date, merge the publication PR you [prepared in `github/github`](#publication-preparation).

- [ ] In [#ecosystem-api](https://github.slack.com/archives/C1042T6MS) on Slack, update and then post the following message to notify the team of the upcoming release. Replace VERSION with the version we're releasing.
- [ ] In [#api-platform](https://github.slack.com/archives/C1042T6MS) on Slack, update and then post the following message to notify the team of the upcoming release. Replace VERSION with the version we're releasing.

> 👋 Hi from Docs! We have just marked `published` for the GHES VERSION release configuration to `true`. Please **do not** merge subsequent "Update OpenAPI 3.x Descriptions" PRs [in github/rest-api-description](https://github.com/github/rest-api-description/pulls) until further notice. Thanks!

- [ ] On the Friday during the freeze, locate the latest "Update OpenAPI 3.x Descriptions" PRs [in `github/rest-api-description`](https://github.com/github/rest-api-description/pulls).
- [ ] Locate the latest "Update OpenAPI 3.x Descriptions" PRs [in `github/rest-api-description`](https://github.com/github/rest-api-description/pulls).

- [ ] On each new PR, leave a review that requests changes with the following comment.

> This PR contains changes for the upcoming GHES RC. Please do not merge this or subsequent PRs until further notice in #ecosystem-api. Thanks!

- [ ] From now until after the freeze, all [existing "Update OpenAPI Description" PRs](https://github.com/github/docs-internal/labels/github-openapi-bot) in `github/docs-internal` can be closed.
- [ ] From now until the RC ships, all [existing "Update OpenAPI Description" PRs](https://github.com/github/docs-internal/labels/github-openapi-bot) in `github/docs-internal` can be closed.

To get the latest changes from the latest "Update OpenAPI 3.x Descriptions" PR in the `github/rest-api-description` repository into your PR to close {{ release-steps-1-url }}, you can use one of two methods.

Expand Down
46 changes: 33 additions & 13 deletions src/search/lib/ai-search-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Request, Response } from 'express'
import statsd from '@/observability/lib/statsd'
import got from 'got'
import { getHmacWithEpoch } from '@/search/lib/helpers/get-cse-copilot-auth'
import { getCSECopilotSource } from '#src/search/lib/helpers/cse-copilot-docs-versions.js'
import { getCSECopilotSource } from '@/search/lib/helpers/cse-copilot-docs-versions'

const memoryCache = new Map<string, Buffer>()

export const aiSearchProxy = async (req: Request, res: Response) => {
const { query, version, language } = req.body

const errors = []

// Validate request body
Expand Down Expand Up @@ -34,13 +36,25 @@ export const aiSearchProxy = async (req: Request, res: Response) => {
return
}

const diagnosticTags = [
`version:${version}`.slice(0, 200),
`language:${language}`.slice(0, 200),
`queryLength:${query.length}`.slice(0, 200),
]
statsd.increment('ai-search.call', 1, diagnosticTags)

// TODO: Caching here may cause an issue if the cache grows too large. Additionally, the cache will be inconsistent across pods
const cacheKey = `${query}:${version}:${language}`
if (memoryCache.has(cacheKey)) {
statsd.increment('ai-search.cache_hit', 1, diagnosticTags)
res.setHeader('Content-Type', 'application/x-ndjson')
res.send(memoryCache.get(cacheKey))
return
}

const startTime = Date.now()
let totalChars = 0

const body = {
chat_context: 'docs',
docs_source: docsSource,
Expand All @@ -57,22 +71,19 @@ export const aiSearchProxy = async (req: Request, res: Response) => {
},
})

const chunks: Buffer[] = []
stream.on('data', (chunk) => {
chunks.push(chunk)
// Listen for data events to count characters
stream.on('data', (chunk: Buffer | string) => {
// Ensure we have a string for proper character count
const dataStr = typeof chunk === 'string' ? chunk : chunk.toString()
totalChars += dataStr.length
})

// Handle the upstream response before piping
stream.on('response', (upstreamResponse) => {
// When cse-copilot returns a 204, it means the backend received the request
// but was unable to answer the question. So we return a 400 to the client to be handled.
if (upstreamResponse.statusCode === 204) {
return res
.status(400)
.json({ errors: [{ message: 'Sorry I am unable to answer this question.' }] })
} else if (upstreamResponse.statusCode !== 200) {
if (upstreamResponse.statusCode !== 200) {
const errorMessage = `Upstream server responded with status code ${upstreamResponse.statusCode}`
console.error(errorMessage)
statsd.increment('ai-search.stream_response_error', 1, diagnosticTags)
res.status(500).json({ errors: [{ message: errorMessage }] })
stream.destroy()
} else {
Expand All @@ -95,6 +106,8 @@ export const aiSearchProxy = async (req: Request, res: Response) => {
.json({ errors: [{ message: 'Sorry I am unable to answer this question.' }] })
}

statsd.increment('ai-search.stream_error', 1, diagnosticTags)

if (!res.headersSent) {
res.status(500).json({ errors: [{ message: 'Internal server error' }] })
} else {
Expand All @@ -106,12 +119,19 @@ export const aiSearchProxy = async (req: Request, res: Response) => {
}
})

// Ensure response ends when stream ends
// Calculate metrics on stream end
stream.on('end', () => {
memoryCache.set(cacheKey, Buffer.concat(chunks as Uint8Array[]))
const totalResponseTime = Date.now() - startTime // in ms
const charPerMsRatio = totalResponseTime > 0 ? totalChars / totalResponseTime : 0 // chars per ms

statsd.gauge('ai-search.total_response_time', totalResponseTime, diagnosticTags)
statsd.gauge('ai-search.response_chars_per_ms', charPerMsRatio, diagnosticTags)

statsd.increment('ai-search.success_stream_end', 1, diagnosticTags)
res.end()
})
} catch (error) {
statsd.increment('ai-search.route_error', 1, diagnosticTags)
console.error('Error posting /answers to cse-copilot:', error)
res.status(500).json({ errors: [{ message: 'Internal server error' }] })
}
Expand Down