From 2ace90dca1805b66c48a9d2fffe926d33a6b4335 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Wed, 25 Jun 2025 11:35:49 -0700 Subject: [PATCH 1/5] Fix expired content flagging by including warnings in weekly lint reports (#56303) --- .../lint-entire-content-data-markdown.yml | 6 +++--- src/content-linter/scripts/post-lints.js | 16 +++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint-entire-content-data-markdown.yml b/.github/workflows/lint-entire-content-data-markdown.yml index e95e2314481e..ee97eb16cca3 100644 --- a/.github/workflows/lint-entire-content-data-markdown.yml +++ b/.github/workflows/lint-entire-content-data-markdown.yml @@ -1,6 +1,6 @@ name: 'Lint entire content and data markdown files' -# **What it does**: Lints our content markdown weekly to ensure the content matches the specified styleguide. If errors exists, it opens a PR for the Docs content team to review. +# **What it does**: Lints our content markdown weekly to ensure the content matches the specified styleguide. If errors or warnings exist, it opens an issue for the Docs content team to review. # **Why we have it**: Extra precaution to run linter on the entire content/data directories. # **Who does it impact**: Docs content. @@ -32,7 +32,7 @@ jobs: id: linting-content-data timeout-minutes: 10 continue-on-error: true - run: npm run lint-content -- --errors-only --paths content data --output-file /tmp/error-lints.json + run: npm run lint-content -- --paths content data --output-file /tmp/lint-results.json - name: Open issue in docs-content if: ${{ always() && steps.linting-content-data.outcome == 'failure' }} @@ -41,7 +41,7 @@ jobs: REPORT_AUTHOR: docs-bot REPORT_LABEL: broken content markdown report REPORT_REPOSITORY: github/docs-content - run: npm run post-lints -- --path /tmp/error-lints.json + run: npm run post-lints -- --path /tmp/lint-results.json - uses: ./.github/actions/slack-alert if: ${{ failure() && github.event_name != 'workflow_dispatch' }} diff --git a/src/content-linter/scripts/post-lints.js b/src/content-linter/scripts/post-lints.js index f1e91243e584..7ec81c7bf30e 100644 --- a/src/content-linter/scripts/post-lints.js +++ b/src/content-linter/scripts/post-lints.js @@ -12,7 +12,7 @@ import { createReportIssue, linkReports } from '#src/workflows/issue-report.js' // the entire content and data directories based on our // markdownlint.js rules. // -// If errors are found, it will open up a new issue in the +// If errors or warnings are found, it will open up a new issue in the // docs-content repo with the label "broken content markdown report". // // The Content FR will go through the issue and update the content and @@ -21,10 +21,12 @@ import { createReportIssue, linkReports } from '#src/workflows/issue-report.js' // [end-readme] program - .description('Opens an issue for Content FR with the errors from the weekly content/data linter.') + .description( + 'Opens an issue for Content FR with the errors and warnings from the weekly content/data linter.', + ) .option( '-p, --path ', - 'provide a path to the errors output json file that will be in the issue body', + 'provide a path to the errors and warnings output json file that will be in the issue body', ) .parse(process.argv) @@ -32,7 +34,7 @@ const { path } = program.opts() main() async function main() { - const errors = fs.readFileSync(`${path}`, 'utf8') + const lintResults = fs.readFileSync(`${path}`, 'utf8') const core = coreLib const { REPORT_REPOSITORY, REPORT_AUTHOR, REPORT_LABEL } = process.env @@ -41,10 +43,10 @@ async function main() { // or open an issue report, you might get cryptic error messages from Octokit. getEnvInputs(['GITHUB_TOKEN']) - core.info(`Creating issue for errors...`) + core.info(`Creating issue for errors and warnings...`) let reportBody = 'The following files have markdown lint warnings/errors:\n\n' - for (const [file, flaws] of Object.entries(JSON.parse(errors))) { + for (const [file, flaws] of Object.entries(JSON.parse(lintResults))) { reportBody += `File: \`${file}\`:\n` reportBody += `\`\`\`json\n${JSON.stringify(flaws, null, 2)}\n\`\`\`\n` } @@ -52,7 +54,7 @@ async function main() { const reportProps = { core, octokit, - reportTitle: `Error(s) in content markdown file(s)`, + reportTitle: `Error(s) and warning(s) in content markdown file(s)`, reportBody, reportRepository: REPORT_REPOSITORY, reportLabel: REPORT_LABEL, From 6a94c3c0e10ca44ef6bd653713c79e2412fc35dd Mon Sep 17 00:00:00 2001 From: Sophie <29382425+sophietheking@users.noreply.github.com> Date: Wed, 25 Jun 2025 21:06:15 +0200 Subject: [PATCH 2/5] Claude Sonnet 4 and Opus 4 are generally available in Copilot (#56256) --- .../choosing-the-right-ai-model-for-your-task.md | 4 ++-- .../ai-models/supported-ai-models-in-copilot.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/content/copilot/using-github-copilot/ai-models/choosing-the-right-ai-model-for-your-task.md b/content/copilot/using-github-copilot/ai-models/choosing-the-right-ai-model-for-your-task.md index 49583c121720..f7a26018d3c0 100644 --- a/content/copilot/using-github-copilot/ai-models/choosing-the-right-ai-model-for-your-task.md +++ b/content/copilot/using-github-copilot/ai-models/choosing-the-right-ai-model-for-your-task.md @@ -27,10 +27,10 @@ Use this table to find a suitable model quickly, see more detail in the sections | {% data variables.copilot.copilot_o3 %} | Deep reasoning and debugging | Multi-step problem solving and architecture-level code analysis | Reasoning | | {% data variables.copilot.copilot_o3_mini %} | Fast help with simple or repetitive tasks | Quick responses for code snippets, explanations, and prototyping | Lower latency | | {% data variables.copilot.copilot_o4_mini %} | Fast help with simple or repetitive tasks | Fast, reliable answers to lightweight coding questions | Lower latency | -| {% data variables.copilot.copilot_claude_opus %} | Deep reasoning and debugging | Advanced agentic workflows over large codebases, long-horizon projects | Reasoning | +| {% data variables.copilot.copilot_claude_opus %} | Deep reasoning and debugging | Complex problem-solving challenges, sophisticated reasoning | Reasoning, vision | | {% data variables.copilot.copilot_claude_sonnet_35 %} | Fast help with simple or repetitive tasks | Quick responses for code, syntax, and documentation | Agent mode | | {% data variables.copilot.copilot_claude_sonnet_37 %} | Deep reasoning and debugging | Structured reasoning across large, complex codebases | Agent mode | -| {% data variables.copilot.copilot_claude_sonnet_40 %} | Deep reasoning and debugging | High-performance code review, bug fixes, and efficient research workflows | Agent mode | +| {% data variables.copilot.copilot_claude_sonnet_40 %} | Deep reasoning and debugging | Performance and practicality, perfectly balanced for coding workflows | Agent mode, vision | | {% data variables.copilot.copilot_gemini_25_pro %} | Deep reasoning and debugging | Complex code generation, debugging, and research workflows | Reasoning | | {% data variables.copilot.copilot_gemini_flash %} | Working with visuals (diagrams, screenshots) | Real-time responses and visual reasoning for UI and diagram-based tasks | Visual | diff --git a/content/copilot/using-github-copilot/ai-models/supported-ai-models-in-copilot.md b/content/copilot/using-github-copilot/ai-models/supported-ai-models-in-copilot.md index 482181483892..a70171a9713b 100644 --- a/content/copilot/using-github-copilot/ai-models/supported-ai-models-in-copilot.md +++ b/content/copilot/using-github-copilot/ai-models/supported-ai-models-in-copilot.md @@ -40,11 +40,11 @@ This table lists the AI models available in {% data variables.product.prodname_c | {% data variables.copilot.copilot_o3 %} | OpenAI | {% data variables.release-phases.public_preview_caps %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o3_mini %} | OpenAI | GA | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o4_mini %} | OpenAI | {% data variables.release-phases.public_preview_caps %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_opus %} | Anthropic | {% data variables.release-phases.public_preview_caps %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_opus %} | Anthropic | GA | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_35 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_37 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_37 %} Thinking | Anthropic | GA | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_sonnet_40 %} | Anthropic | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_sonnet_40 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_gemini_25_pro %} | Google | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_gemini_flash %} | Google | GA | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | @@ -65,11 +65,11 @@ The following table shows which models are available in each client. | {% data variables.copilot.copilot_o3 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o3_mini %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o4_mini %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_opus %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | +| {% data variables.copilot.copilot_claude_opus %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_35 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_37 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} |{% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_37 %} Thinking | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_sonnet_40 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | +| {% data variables.copilot.copilot_claude_sonnet_40 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_gemini_25_pro %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_gemini_flash %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | From 17d76464776c2f11e3b84adc899b86b1ddbdae02 Mon Sep 17 00:00:00 2001 From: Evan Bonsignori Date: Wed, 25 Jun 2025 13:53:04 -0700 Subject: [PATCH 3/5] allow pressing enter on AI Search before loading is complete (#56310) --- src/search/components/input/SearchOverlay.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/search/components/input/SearchOverlay.tsx b/src/search/components/input/SearchOverlay.tsx index addde4a74341..c2e4d2e6d202 100644 --- a/src/search/components/input/SearchOverlay.tsx +++ b/src/search/components/input/SearchOverlay.tsx @@ -481,9 +481,6 @@ export function SearchOverlay({ } } } else if (event.key === 'Enter') { - if (searchLoading) { - return - } event.preventDefault() let pressedGroupKey = SEARCH_OVERLAY_EVENT_GROUP let pressedGroupId = searchEventGroupId From d5eeb85d2e3824da726582c0674d741693a6f738 Mon Sep 17 00:00:00 2001 From: Evan Bonsignori Date: Wed, 25 Jun 2025 13:59:35 -0700 Subject: [PATCH 4/5] fix local development proxy to docs.github.com for Copilot Search (#56311) --- src/frame/middleware/api.ts | 12 +--- .../middleware/ai-search-local-proxy.ts | 70 +++++++++++++++++++ 2 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 src/search/middleware/ai-search-local-proxy.ts diff --git a/src/frame/middleware/api.ts b/src/frame/middleware/api.ts index b3fc7278fd1c..4d2ec8394f14 100644 --- a/src/frame/middleware/api.ts +++ b/src/frame/middleware/api.ts @@ -4,6 +4,7 @@ import { createProxyMiddleware } from 'http-proxy-middleware' import events from '@/events/middleware.js' import anchorRedirect from '@/rest/api/anchor-redirect.js' import aiSearch from '@/search/middleware/ai-search' +import aiSearchLocalProxy from '@/search/middleware/ai-search-local-proxy' import search from '@/search/middleware/search-routes.js' import pageList from '@/article-api/middleware/pagelist' import article from '@/article-api/middleware/article' @@ -31,16 +32,7 @@ if (process.env.CSE_COPILOT_ENDPOINT || process.env.NODE_ENV === 'test') { console.log( 'Proxying AI Search requests to docs.github.com. To use the cse-copilot endpoint, set the CSE_COPILOT_ENDPOINT environment variable.', ) - router.use( - '/ai-search', - createProxyMiddleware({ - target: 'https://docs.github.com', - changeOrigin: true, - pathRewrite: function (path, req: ExtendedRequest) { - return req.originalUrl - }, - }), - ) + router.use(aiSearchLocalProxy) } if (process.env.ELASTICSEARCH_URL) { router.use('/search', search) diff --git a/src/search/middleware/ai-search-local-proxy.ts b/src/search/middleware/ai-search-local-proxy.ts new file mode 100644 index 000000000000..327ffa991072 --- /dev/null +++ b/src/search/middleware/ai-search-local-proxy.ts @@ -0,0 +1,70 @@ +// When in local development we want to proxy to the ai-search route at docs.github.com + +import { Router, Request, Response, NextFunction } from 'express' +import got from 'got' +import { pipeline } from 'node:stream' + +const router = Router() + +const hopByHop = new Set([ + 'connection', + 'keep-alive', + 'proxy-authenticate', + 'proxy-authorization', + 'te', + 'trailers', + 'transfer-encoding', + 'upgrade', +]) + +function filterRequestHeaders(src: Request['headers']) { + const out: Record = {} + for (const [key, value] of Object.entries(src)) { + if (!value) continue + const k = key.toLowerCase() + if (hopByHop.has(k) || k === 'cookie' || k === 'host') continue + out[key] = value + } + out['accept'] = 'application/x-ndjson' + out['content-type'] = 'application/json' + return out +} + +router.post('/ai-search/v1', async (req: Request, res: Response, next: NextFunction) => { + try { + const upstream = got.stream.post('https://docs.github.com/api/ai-search/v1', { + headers: filterRequestHeaders(req.headers), + body: JSON.stringify(req.body ?? {}), + decompress: false, + throwHttpErrors: false, + retry: { limit: 0 }, + }) + + upstream.on('response', (uRes) => { + res.status(uRes.statusCode || 500) + + for (const [k, v] of Object.entries(uRes.headers)) { + if (!v) continue + const key = k.toLowerCase() + // Never forward hop-by-hop; got already handles chunked → strip content-length + if (hopByHop.has(key) || key === 'content-length') continue + res.setHeader(k, v as string) + } + res.flushHeaders?.() + }) + + pipeline(upstream, res, (err) => { + if (err) { + console.error('[ai-search proxy] pipeline error:', err) + if (!res.headersSent) res.status(502).end('Bad Gateway') + } + }) + + upstream.on('error', (err) => console.error('[ai-search proxy] upstream error:', err)) + } catch (err) { + console.error('[ai-search proxy] request failed:', err) + next(err) + } +}) + +export default router From 78d90c403bccb2d039ef2854ddedf7298898e119 Mon Sep 17 00:00:00 2001 From: Steve-Glass <84886334+Steve-Glass@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:07:15 -0400 Subject: [PATCH 5/5] Update Actions custom repository roles (#56250) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jacob Wallraff --- data/reusables/organizations/additional-permissions.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/data/reusables/organizations/additional-permissions.md b/data/reusables/organizations/additional-permissions.md index a25e13f98399..78f8e087cff0 100644 --- a/data/reusables/organizations/additional-permissions.md +++ b/data/reusables/organizations/additional-permissions.md @@ -58,3 +58,12 @@ For more information, see [AUTOTITLE](/discussions). * Dismiss or reopen {% data variables.product.prodname_dependabot_alerts %} * View {% data variables.product.prodname_secret_scanning %} results * Dismiss or reopen {% data variables.product.prodname_secret_scanning %} results + +### Actions + +* Manage {% data variables.product.prodname_actions %} general settings +* Manage runners +* Manage secrets +* Manage variables +* Manage environments (including environment secrets and variables) +