diff --git a/.github/workflows/enterprise-dates.yml b/.github/workflows/enterprise-dates.yml index f12bf24642d6..047618db6539 100644 --- a/.github/workflows/enterprise-dates.yml +++ b/.github/workflows/enterprise-dates.yml @@ -32,7 +32,7 @@ jobs: app-id: ${{ secrets.DOCS_BOT_APP_ID }} private-key: ${{ secrets.DOCS_BOT_APP_PRIVATE_KEY }} owner: github - repositories: docs-internal,docs-engineering + repositories: docs-internal,docs-engineering,enterprise-releases - uses: ./.github/actions/node-npm-setup diff --git a/.github/workflows/enterprise-release-issue.yml b/.github/workflows/enterprise-release-issue.yml index 4b9f59498cb2..5b95ca5864d8 100644 --- a/.github/workflows/enterprise-release-issue.yml +++ b/.github/workflows/enterprise-release-issue.yml @@ -27,7 +27,7 @@ jobs: app-id: ${{ secrets.DOCS_BOT_APP_ID }} private-key: ${{ secrets.DOCS_BOT_APP_PRIVATE_KEY }} owner: github - repositories: docs-content,docs-engineering + repositories: docs-content,docs-engineering,enterprise-releases - uses: ./.github/actions/node-npm-setup diff --git a/.github/workflows/link-check-external.yml b/.github/workflows/link-check-external.yml index 3c9877844c6c..a8440699ae87 100644 --- a/.github/workflows/link-check-external.yml +++ b/.github/workflows/link-check-external.yml @@ -61,15 +61,6 @@ jobs: run: | if [ -f "artifacts/external-link-report.md" ]; then echo "has_report=true" >> $GITHUB_OUTPUT - # Prepend disclaimer banner - tmp=$(mktemp) - { - echo "> [!NOTE]" - echo "> **No action needed right now.** The link checker is being actively worked on and may produce false positives. You can safely ignore this report for now. We'll let you know when it's reliable." - echo "" - cat "artifacts/external-link-report.md" - } > "$tmp" - mv "$tmp" "artifacts/external-link-report.md" else echo "has_report=false" >> $GITHUB_OUTPUT echo "No broken link report generated - all links valid!" diff --git a/.github/workflows/link-check-github-github.yml b/.github/workflows/link-check-github-github.yml index fcbc1c11f1ee..b48532edd83e 100644 --- a/.github/workflows/link-check-github-github.yml +++ b/.github/workflows/link-check-github-github.yml @@ -55,6 +55,9 @@ jobs: curl --retry-connrefused --retry 5 -I http://localhost:4000/ - name: Run broken github/github link check + env: + # Needs a token with access to github/github; the app token is scoped to it above + GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} run: | npm run check-github-github-links -- broken_github_github_links.md diff --git a/.github/workflows/link-check-internal.yml b/.github/workflows/link-check-internal.yml index aedda28a08ea..1d8a394e6bae 100644 --- a/.github/workflows/link-check-internal.yml +++ b/.github/workflows/link-check-internal.yml @@ -248,9 +248,6 @@ jobs: # Combine all markdown reports echo "# Internal Links Report" > combined-report.md echo "" >> combined-report.md - echo "> [!NOTE]" >> combined-report.md - echo "> **No action needed right now.** The link checker is being actively worked on and may produce false positives. You can safely ignore this report for now. We'll let you know when it's reliable." >> combined-report.md - echo "" >> combined-report.md echo "Generated: $(date -u +'%Y-%m-%d %H:%M UTC')" >> combined-report.md echo "[Action run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> combined-report.md echo "" >> combined-report.md diff --git a/.github/workflows/link-check-on-pr.yml b/.github/workflows/link-check-on-pr.yml index 904596143a8f..6d77c5627e6a 100644 --- a/.github/workflows/link-check-on-pr.yml +++ b/.github/workflows/link-check-on-pr.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: # merge_group: pull_request: - types: [labeled, opened, synchronize, reopened] + types: [opened, synchronize, reopened] permissions: contents: read @@ -24,9 +24,7 @@ jobs: check-links: name: Check links runs-on: ubuntu-latest - if: | - (github.repository == 'github/docs-internal' || github.repository == 'github/docs') && - (github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'check-links')) + if: github.repository == 'github/docs-internal' || github.repository == 'github/docs' steps: - name: Checkout uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 @@ -61,12 +59,14 @@ jobs: - name: Check links in changed files if: steps.changed-files.outputs.any_changed == 'true' + # Work in progress: never fail the PR. The comment is informational only. + continue-on-error: true env: FILES_CHANGED: ${{ steps.changed-files.outputs.all_changed_files }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ACTION_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} SHOULD_COMMENT: ${{ secrets.DOCS_BOT_APP_ID != '' }} - FAIL_ON_FLAW: true + FAIL_ON_FLAW: false ENABLED_LANGUAGES: en run: npm run check-links-pr diff --git a/Dockerfile b/Dockerfile index b31271ee0caf..a593f03633b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ # --------------------------------------------------------------- # To update the sha: # https://github.com/github/gh-base-image/pkgs/container/gh-base-image%2Fgh-base-noble -FROM ghcr.io/github/gh-base-image/gh-base-noble:20260625-083609-gedf42de01@sha256:bf0a2f43957531d73dcb2abceabf2228560f1f67d14e23f5bb0c0ccbabd77dee AS base +FROM ghcr.io/github/gh-base-image/gh-base-noble:20260630-205522-g4a33dc6bb@sha256:2b8edd7da1718e2e9c25b98fd31dae58e57e756ef19842eac212255765cf4ada AS base # Install curl for Node install and determining the early access branch # Install git for cloning docs-early-access & translations repos diff --git a/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png b/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png index 9263455a5ac2..f2f0500a9d3e 100644 Binary files a/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png and b/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png differ diff --git a/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png b/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png index 6fe2706dff63..0c7b17986298 100644 Binary files a/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png and b/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png differ diff --git a/assets/images/help/copilot/copilot-sdk/setup-azure-managed-identity-diagram-0.png b/assets/images/help/copilot/copilot-sdk/setup-azure-managed-identity-diagram-0.png index 5123a687db31..44d0054435a4 100644 Binary files a/assets/images/help/copilot/copilot-sdk/setup-azure-managed-identity-diagram-0.png and b/assets/images/help/copilot/copilot-sdk/setup-azure-managed-identity-diagram-0.png differ diff --git a/assets/images/help/copilot/copilot-sdk/setup-choosing-a-setup-path-diagram-0.png b/assets/images/help/copilot/copilot-sdk/setup-choosing-a-setup-path-diagram-0.png index 8d1ed7b19f4c..ec49fe30e3e5 100644 Binary files a/assets/images/help/copilot/copilot-sdk/setup-choosing-a-setup-path-diagram-0.png and b/assets/images/help/copilot/copilot-sdk/setup-choosing-a-setup-path-diagram-0.png differ diff --git a/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-0.png b/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-0.png index a20cb534ffcc..9b6bb90c3292 100644 Binary files a/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-0.png and b/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-0.png differ diff --git a/content/actions/reference/workflows-and-actions/workflow-syntax.md b/content/actions/reference/workflows-and-actions/workflow-syntax.md index 5ca629d02b49..dc693471414b 100644 --- a/content/actions/reference/workflows-and-actions/workflow-syntax.md +++ b/content/actions/reference/workflows-and-actions/workflow-syntax.md @@ -915,6 +915,9 @@ Outputs and environment changes from a background step are only available after Use `background` when you need fine-grained control: starting a long-running process (like a server or database) that stays up while later steps run, referencing a specific step with [`wait`](#jobsjob_idstepswait) or [`cancel`](#jobsjob_idstepscancel), or interleaving background work with other steps. If you instead have a self-contained group of steps that should all finish before the job continues, [`parallel`](#jobsjob_idstepsparallel) is a more convenient shorthand. +> [!NOTE] +> You cannot use `background` on steps inside a composite action. A composite action can itself run as a background step, but it cannot declare background steps internally. + ### Example: Running a step in the background ```yaml @@ -937,6 +940,9 @@ Pauses the job until one or more background steps complete. A `wait` step perfor After a `wait` step completes, the outputs of the referenced background steps become available to subsequent steps. If a referenced background step failed, the `wait` step fails too. +> [!NOTE] +> A `wait` step always runs and does not support the [`if`](#jobsjob_idstepsif) conditional. + ### Example: Waiting for specific background steps ```yaml @@ -967,6 +973,9 @@ Pauses the job until all active background steps complete. This is useful when s The `wait-all` keyword takes no arguments. +> [!NOTE] +> A `wait-all` step always runs and does not support the [`if`](#jobsjob_idstepsif) conditional. + ### Example: Waiting for all background steps ```yaml @@ -992,6 +1001,9 @@ steps: Gracefully terminates a running background step. The runner sends the step's process a termination signal (`SIGTERM`) so it can clean up, and forcibly stops it (`SIGKILL`) if it does not exit within a short grace period. The `cancel` keyword targets a single background step by its `id`. +> [!NOTE] +> A `cancel` step always runs and does not support the [`if`](#jobsjob_idstepsif) conditional. + ### Example: Canceling a background step ```yaml @@ -1016,6 +1028,9 @@ Use `parallel` when you have a self-contained group of steps that should all fin Each step in the group is subject to the same 10-step concurrency limit as other background steps. +> [!NOTE] +> You cannot use `parallel` inside a composite action. + ### Example: Running steps in parallel ```yaml diff --git a/content/copilot/concepts/billing/usage-based-billing-for-individuals.md b/content/copilot/concepts/billing/usage-based-billing-for-individuals.md index 540f1f705719..43cd02e2e6fb 100644 --- a/content/copilot/concepts/billing/usage-based-billing-for-individuals.md +++ b/content/copilot/concepts/billing/usage-based-billing-for-individuals.md @@ -49,6 +49,8 @@ Each paid plan includes the following: Your base credits are used first. If you go beyond your base credits, the flex allotment is applied automatically at the same rates across your IDE, {% data variables.product.prodname_dotcom_the_website %}, and {% data variables.copilot.copilot_cli_short %}. No additional setup is required. Your usage dashboard shows your available allowance and what you've used. +Included {% data variables.product.prodname_ai_credits_short %} do not carry over between months. Unused credits are forfeited, and your allowance resets to the full monthly amount at 00:00:00 UTC on the first day of each calendar month. This reset date is fixed and does not change based on your subscription billing date. See [AUTOTITLE](/billing/concepts/billing-cycles#billing-cycles-for-metered-products). + ### {% data variables.product.prodname_ai_credits %} allowance by plan The following table shows what's included with each paid plan. diff --git a/content/copilot/concepts/billing/usage-based-billing-for-organizations-and-enterprises.md b/content/copilot/concepts/billing/usage-based-billing-for-organizations-and-enterprises.md index 152d4de0053c..4e959cd0d3c4 100644 --- a/content/copilot/concepts/billing/usage-based-billing-for-organizations-and-enterprises.md +++ b/content/copilot/concepts/billing/usage-based-billing-for-organizations-and-enterprises.md @@ -40,6 +40,8 @@ A user's included {% data variables.product.prodname_ai_credits_short %} are poo Adding licenses mid-cycle increases the pool immediately. Removing licenses mid-cycle doesn't shrink the pool: the decrease is reflected at the start of the next billing cycle. +Included {% data variables.product.prodname_ai_credits_short %} do not carry over between months. Unused credits are forfeited, and the pool resets to the full monthly amount at 00:00:00 UTC on the first day of each calendar month. This reset date is fixed and does not change based on when licenses are added, removed, or billed. See [AUTOTITLE](/billing/concepts/billing-cycles#billing-cycles-for-metered-products). + ### Promotional amounts for existing customers diff --git a/content/copilot/concepts/context/repository-indexing.md b/content/copilot/concepts/context/repository-indexing.md index 0991e421347f..8c742a100dca 100644 --- a/content/copilot/concepts/context/repository-indexing.md +++ b/content/copilot/concepts/context/repository-indexing.md @@ -47,9 +47,9 @@ Once an index has been created for a repository, it can be used by: > [!TIP] There is no limit to how many repositories you can index. -## Semantic indexing for non-GitHub repositories +## Semantic indexing for non-{% data variables.product.github %} repositories -{% data variables.product.prodname_copilot_short %} in {% data variables.product.prodname_vscode %} can use semantic indexing for workspace files from repositories hosted outside {% data variables.product.github %}, such as GitLab and local repositories. +{% data variables.product.prodname_copilot_short %} in {% data variables.product.prodname_vscode %} can use semantic indexing for workspace files from repositories hosted outside {% data variables.product.github %}, such as GitLab and local repositories. This feature uploads your data to {% data variables.product.github %} to make it searchable. This feature is controlled by policy and is disabled by default. For organizations and enterprises with {% data variables.copilot.copilot_business_short %} or {% data variables.copilot.copilot_enterprise_short %}, an enterprise owner or organization owner must explicitly set the `Semantic indexing for non-GitHub repositories` policy to **Enabled** before members can use it. If the policy remains **Unconfigured**, the feature stays unavailable. See: diff --git a/content/copilot/how-tos/copilot-cli/customize-copilot/add-skills.md b/content/copilot/how-tos/copilot-cli/customize-copilot/add-skills.md index 3a13ac0bbb05..fd865d8c002a 100644 --- a/content/copilot/how-tos/copilot-cli/customize-copilot/add-skills.md +++ b/content/copilot/how-tos/copilot-cli/customize-copilot/add-skills.md @@ -53,6 +53,8 @@ Use the /frontend-design skill to create a responsive navigation bar in React. * **Remove skills:** to remove a skill that you have added directly—not via a plugin—use the command `/skills remove SKILL-DIRECTORY`. To remove skills added as part of a plugin you must manage the plugin itself. Use the `info` subcommand to find out which plugin a skill came from. +The `/skills` commands above run inside an interactive session. The same list, add, and remove operations are also available from the terminal command line by using the `copilot skill` subcommand. This is useful for scripting or for setting up skills before you start a session. For example, run `copilot skill list` to list your skills, or `copilot skill add ` to add one. For the full set of subcommands for {% data variables.copilot.copilot_cli_short %}, see [AUTOTITLE](/copilot/reference/copilot-cli-reference/cli-command-reference). + {% data reusables.copilot.skills-compared %} To learn more about how skills differ from other customization features, see [AUTOTITLE](/copilot/concepts/agents/copilot-cli/comparing-cli-features). diff --git a/content/copilot/how-tos/copilot-sdk/auth/byok.md b/content/copilot/how-tos/copilot-sdk/auth/byok.md index 9a37fb8202ab..a24aa9f1cf69 100644 --- a/content/copilot/how-tos/copilot-sdk/auth/byok.md +++ b/content/copilot/how-tos/copilot-sdk/auth/byok.md @@ -413,7 +413,7 @@ func main() { Name: "My Custom Model", Capabilities: copilot.ModelCapabilities{ Supports: copilot.ModelSupports{Vision: false, ReasoningEffort: false}, - Limits: copilot.ModelLimits{MaxContextWindowTokens: 128000}, + Limits: copilot.ModelLimits{MaxContextWindowTokens: copilot.Int(128000)}, }, }, }, nil @@ -479,7 +479,7 @@ When using BYOK, be aware of these limitations: ### Identity limitations -BYOK authentication uses **static credentials only**. +BYOK authentication uses **static credentials only**. You must use an API key or static bearer token that you manage yourself. diff --git a/content/copilot/how-tos/copilot-sdk/features/cloud-sessions.md b/content/copilot/how-tos/copilot-sdk/features/cloud-sessions.md index fe36d3c6f2d0..522537546bde 100644 --- a/content/copilot/how-tos/copilot-sdk/features/cloud-sessions.md +++ b/content/copilot/how-tos/copilot-sdk/features/cloud-sessions.md @@ -2,8 +2,10 @@ title: Cloud sessions shortTitle: Cloud Sessions intro: >- - Run Copilot sessions on GitHub-hosted compute through Mission Control instead - of local CLI sessions. + Cloud sessions run Copilot work on GitHub-hosted compute through Mission + Control. Use them when your app should create a session that executes remotely + instead of starting a local Copilot CLI session on the user's machine or your + server. versions: fpt: '*' ghec: '*' diff --git a/content/copilot/how-tos/copilot-sdk/features/custom-agents.md b/content/copilot/how-tos/copilot-sdk/features/custom-agents.md index d93076614715..87b42f8122d5 100644 --- a/content/copilot/how-tos/copilot-sdk/features/custom-agents.md +++ b/content/copilot/how-tos/copilot-sdk/features/custom-agents.md @@ -3,7 +3,8 @@ title: Custom agents and sub-agent orchestration shortTitle: Custom Agents intro: >- Define specialized agents with scoped tools and prompts, then let Copilot - orchestrate them as sub-agents within a single session. + orchestrate them as sub-agents within a single session. For dispatching + multiple sub-agents in parallel, see [AUTOTITLE](/copilot/how-tos/copilot-sdk/features/fleet-mode). versions: fpt: '*' ghec: '*' diff --git a/content/copilot/how-tos/copilot-sdk/features/fleet-mode.md b/content/copilot/how-tos/copilot-sdk/features/fleet-mode.md index 817959982f40..0605fd9dfedc 100644 --- a/content/copilot/how-tos/copilot-sdk/features/fleet-mode.md +++ b/content/copilot/how-tos/copilot-sdk/features/fleet-mode.md @@ -2,8 +2,13 @@ title: Fleet mode shortTitle: Fleet Mode intro: >- - Use fleet mode to split work across multiple sub-agents and combine their - results in one parent session. + Fleet mode is Copilot's parallel orchestration pattern for work that can be + split across independent sub-agents. In the runtime research notes, fleet mode + is described as "the runtime's built-in pattern for dispatching multiple + sub-agents in parallel via the `task` tool, with SQL todos as the shared + coordination state." Use it when one parent session should coordinate several + workers, collect their results, and continue the conversation with the + combined context. versions: fpt: '*' ghec: '*' @@ -59,7 +64,7 @@ if (result.started) { {% codetab python %} ```python -from copilot.generated.rpc import FleetStartRequest +from copilot.rpc import FleetStartRequest result = await session.rpc.fleet.start( FleetStartRequest( @@ -151,7 +156,7 @@ if (result.Started) {% codetab rust %} ```rust -use github_copilot_sdk::generated::api_types::FleetStartRequest; +use github_copilot_sdk::rpc::FleetStartRequest; let result = session .rpc() diff --git a/content/copilot/how-tos/copilot-sdk/features/image-input.md b/content/copilot/how-tos/copilot-sdk/features/image-input.md index 5f95fc5db566..db4f625e9edd 100644 --- a/content/copilot/how-tos/copilot-sdk/features/image-input.md +++ b/content/copilot/how-tos/copilot-sdk/features/image-input.md @@ -326,7 +326,7 @@ func main() { Prompt: "Describe what you see in this image", Attachments: []copilot.Attachment{ &copilot.AttachmentBlob{ - Data: base64ImageData, + Data: &base64ImageData, MIMEType: mimeType, DisplayName: &displayName, }, @@ -342,7 +342,7 @@ session.Send(ctx, copilot.MessageOptions{ Prompt: "Describe what you see in this image", Attachments: []copilot.Attachment{ &copilot.AttachmentBlob{ - Data: base64ImageData, // base64-encoded string + Data: &base64ImageData, // base64-encoded string MIMEType: mimeType, DisplayName: &displayName, }, diff --git a/content/copilot/how-tos/copilot-sdk/features/mcp.md b/content/copilot/how-tos/copilot-sdk/features/mcp.md index 94f126e367c4..a6abc3d437e8 100644 --- a/content/copilot/how-tos/copilot-sdk/features/mcp.md +++ b/content/copilot/how-tos/copilot-sdk/features/mcp.md @@ -135,7 +135,7 @@ func main() { "my-local-server": copilot.MCPStdioServerConfig{ Command: "node", Args: []string{"./mcp-server.js"}, - Tools: &[]string{"*"}, + Tools: []string{"*"}, }, }, }) diff --git a/content/copilot/how-tos/copilot-sdk/features/plugin-directories.md b/content/copilot/how-tos/copilot-sdk/features/plugin-directories.md index f66586d55a10..2aa5601d537b 100644 --- a/content/copilot/how-tos/copilot-sdk/features/plugin-directories.md +++ b/content/copilot/how-tos/copilot-sdk/features/plugin-directories.md @@ -2,8 +2,11 @@ title: Plugin directories shortTitle: Plugin Directories intro: >- - Use plugin directories to load skills, hooks, MCP servers, custom agents, and - LSP settings from a single manifest. + A **plugin** is a directory that bundles SDK extensions — skills, hooks, MCP + servers, custom agents, and LSP configuration — behind a single manifest. + Pointing the SDK at a plugin directory loads everything the plugin + contributes, so you can ship reusable capability packs without writing + per-extension wiring in every host application. versions: fpt: '*' ghec: '*' diff --git a/content/copilot/how-tos/copilot-sdk/features/streaming-events.md b/content/copilot/how-tos/copilot-sdk/features/streaming-events.md index 202b768e05a6..e597af9e50f9 100644 --- a/content/copilot/how-tos/copilot-sdk/features/streaming-events.md +++ b/content/copilot/how-tos/copilot-sdk/features/streaming-events.md @@ -65,7 +65,7 @@ session.on("assistant.message_delta", (event) => { ```python from copilot import CopilotClient -from copilot.generated.session_events import SessionEventType +from copilot.session_events import SessionEventType client = CopilotClient() @@ -79,7 +79,7 @@ def handle(event): ``` ```python -from copilot.generated.session_events import SessionEventType +from copilot.session_events import SessionEventType def handle(event): if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA: diff --git a/content/copilot/how-tos/copilot-sdk/getting-started.md b/content/copilot/how-tos/copilot-sdk/getting-started.md index 1dd730d0233c..666c71ee5114 100644 --- a/content/copilot/how-tos/copilot-sdk/getting-started.md +++ b/content/copilot/how-tos/copilot-sdk/getting-started.md @@ -32,7 +32,7 @@ Copilot: In Tokyo it's 75°F and sunny. Great day to be outside! Before you begin, make sure you have: -* **GitHub Copilot CLI** installed and authenticated (the Node.js, Python, and .NET SDKs bundle the CLI automatically—see [AUTOTITLE](/copilot/how-tos/copilot-sdk/setup/bundled-cli). Required for Go, Java, and Rust unless using their application-level CLI bundling features.) +* **GitHub Copilot CLI** installed and authenticated (the Node.js, Python, and .NET SDKs provide the CLI automatically—see [AUTOTITLE](/copilot/how-tos/copilot-sdk/setup/bundled-cli). Required for Go, Java, and Rust unless using their application-level CLI bundling features.) * Your preferred language runtime: * **Node.js** 20+ or **Python** 3.11+ or **Go** 1.24+ or **Rust** 1.94+ or **Java** 17+ or **.NET** 8.0+ @@ -408,7 +408,7 @@ import asyncio import sys from copilot import CopilotClient from copilot.session import PermissionHandler -from copilot.generated.session_events import SessionEventType +from copilot.session_events import SessionEventType async def main(): client = CopilotClient() @@ -652,7 +652,7 @@ unsubscribeIdle(); ```python from copilot import CopilotClient, PermissionDecisionApproveOnce -from copilot.generated.session_events import SessionEvent, SessionEventType +from copilot.session_events import SessionEvent, SessionEventType client = CopilotClient() @@ -920,7 +920,7 @@ import sys from copilot import CopilotClient from copilot.session import PermissionHandler from copilot.tools import define_tool -from copilot.generated.session_events import SessionEventType +from copilot.session_events import SessionEventType from pydantic import BaseModel, Field # Define the parameters for the tool using Pydantic @@ -1336,7 +1336,7 @@ import sys from copilot import CopilotClient from copilot.session import PermissionHandler from copilot.tools import define_tool -from copilot.generated.session_events import SessionEventType +from copilot.session_events import SessionEventType from pydantic import BaseModel, Field class GetWeatherParams(BaseModel): @@ -1870,11 +1870,13 @@ const session = await client.createSession({ }); ``` -Available section IDs: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `runtime_instructions`, `last_instructions`. +Available section IDs: `preamble`, `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `runtime_instructions`, `last_instructions`. -Each override supports four actions: `replace`, `remove`, `append`, and `prepend`. Unknown section IDs are handled gracefully—content is appended to additional instructions and a warning is emitted; `remove` on unknown sections is silently ignored. +`identity` and `tool_instructions` are section *groups*: they target a collection of related sub-sections as a unit. Use `preamble` to target just the identity preamble without affecting its sibling sub-sections. -See the language-specific SDK READMEs for examples in [TypeScript](https://github.com/github/copilot-sdk/tree/main/nodejs/README.md?utm_source=docs-copilot-sdk-typescript-readme&utm_medium=docs&utm_campaign=msbuild-2026), [Python](https://github.com/github/copilot-sdk/tree/main/python/README.md?utm_source=docs-copilot-sdk-python-readme&utm_medium=docs&utm_campaign=msbuild-2026), [Go](https://github.com/github/copilot-sdk/tree/main/go/README.md?utm_source=docs-copilot-sdk-go-readme&utm_medium=docs&utm_campaign=msbuild-2026), [Rust](https://github.com/github/copilot-sdk/tree/main/rust/README.md?utm_source=docs-copilot-sdk-rust-readme&utm_medium=docs&utm_campaign=msbuild-2026), [Java](https://github.com/github/copilot-sdk/tree/main/java/README.md?utm_source=docs-copilot-sdk-java-readme&utm_medium=docs&utm_campaign=msbuild-2026), and [C#](https://github.com/github/copilot-sdk/tree/main/dotnet/README.md?utm_source=docs-copilot-sdk-csharp-readme&utm_medium=docs&utm_campaign=msbuild-2026). +Each override supports five actions: `replace`, `remove`, `append`, `prepend`, and `preserve`. The `preserve` action is a no-op that opts an individually-addressable section out of a group-level `remove` (for example, keep `tone` when removing the `identity` group). Unknown section IDs are handled gracefully: content from `replace`/`append`/`prepend` overrides is appended to additional instructions, and `remove` overrides are silently ignored. + +See the language-specific SDK READMEs for examples in [TypeScript](https://github.com/github/copilot-sdk/tree/main/nodejs/README.md), [Python](https://github.com/github/copilot-sdk/tree/main/python/README.md), [Go](https://github.com/github/copilot-sdk/tree/main/go/README.md), [Rust](https://github.com/github/copilot-sdk/tree/main/rust/README.md), [Java](https://github.com/github/copilot-sdk/tree/main/java/README.md), and [C#](https://github.com/github/copilot-sdk/tree/main/dotnet/README.md). ## Connecting to an external CLI server @@ -2172,11 +2174,14 @@ Dependency: `io.opentelemetry:opentelemetry-api` | Option | Node.js | Python | Go | Rust | Java | .NET | Description | |---|---|---|---|---|---|---|---| | OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `otlp_endpoint` | `otlpEndpoint` | `OtlpEndpoint` | OTLP HTTP endpoint URL | +| OTLP protocol | `otlpProtocol` | `otlp_protocol` | `OTLPProtocol` | `otlp_protocol` | `otlpProtocol` | `OtlpProtocol` | OTLP HTTP protocol for all signals: `"http/json"` or `"http/protobuf"` | | File path | `filePath` | `file_path` | `FilePath` | `file_path` | `filePath` | `FilePath` | File path for JSON-lines trace output | | Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `exporter_type` | `exporterType` | `ExporterType` | `"otlp-http"` or `"file"` | | Source name | `sourceName` | `source_name` | `SourceName` | `source_name` | `sourceName` | `SourceName` | Instrumentation scope name | | Capture content | `captureContent` | `capture_content` | `CaptureContent` | `capture_content` | `captureContent` | `CaptureContent` | Whether to capture message content | +The OTLP protocol field configures the CLI's `"otlp-http"` exporter for all signals. Leave it unset to use the CLI default, or set it to `"http/protobuf"` to export protobuf over HTTP. + ### File export To write traces to a local file instead of an OTLP endpoint: @@ -2205,12 +2210,12 @@ Trace context is propagated automatically—no manual instrumentation is needed: * [AUTOTITLE](/copilot/how-tos/copilot-sdk/auth/authenticate) - GitHub OAuth, environment variables, and BYOK * [AUTOTITLE](/copilot/how-tos/copilot-sdk/auth/byok) - Use your own API keys from Azure AI Foundry, OpenAI, etc. -* [Node.js SDK Reference](https://github.com/github/copilot-sdk/tree/main/nodejs/README.md?utm_source=docs-copilot-sdk-nodejs-reference&utm_medium=docs&utm_campaign=msbuild-2026) -* [Python SDK Reference](https://github.com/github/copilot-sdk/tree/main/python/README.md?utm_source=docs-copilot-sdk-python-reference&utm_medium=docs&utm_campaign=msbuild-2026) -* [Go SDK Reference](https://github.com/github/copilot-sdk/tree/main/go/README.md?utm_source=docs-copilot-sdk-go-reference&utm_medium=docs&utm_campaign=msbuild-2026) -* [Rust SDK Reference](https://github.com/github/copilot-sdk/tree/main/rust/README.md?utm_source=docs-copilot-sdk-rust-reference&utm_medium=docs&utm_campaign=msbuild-2026) -* [.NET SDK Reference](https://github.com/github/copilot-sdk/tree/main/dotnet/README.md?utm_source=docs-copilot-sdk-dotnet-reference&utm_medium=docs&utm_campaign=msbuild-2026) -* [Java SDK Reference](https://github.com/github/copilot-sdk/tree/main/java/README.md?utm_source=docs-copilot-sdk-java-reference&utm_medium=docs&utm_campaign=msbuild-2026) +* [Node.js SDK Reference](https://github.com/github/copilot-sdk/tree/main/nodejs/README.md) +* [Python SDK Reference](https://github.com/github/copilot-sdk/tree/main/python/README.md) +* [Go SDK Reference](https://github.com/github/copilot-sdk/tree/main/go/README.md) +* [Rust SDK Reference](https://github.com/github/copilot-sdk/tree/main/rust/README.md) +* [.NET SDK Reference](https://github.com/github/copilot-sdk/tree/main/dotnet/README.md) +* [Java SDK Reference](https://github.com/github/copilot-sdk/tree/main/java/README.md) * [AUTOTITLE](/copilot/how-tos/copilot-sdk/features/mcp) - Integrate external tools via Model Context Protocol * [GitHub MCP Server Documentation](https://github.com/github/github-mcp-server) * [MCP Servers Directory](https://github.com/modelcontextprotocol/servers) - Explore more MCP servers diff --git a/content/copilot/how-tos/copilot-sdk/observability/opentelemetry.md b/content/copilot/how-tos/copilot-sdk/observability/opentelemetry.md index cd017a2892da..39d471e5c8f6 100644 --- a/content/copilot/how-tos/copilot-sdk/observability/opentelemetry.md +++ b/content/copilot/how-tos/copilot-sdk/observability/opentelemetry.md @@ -112,11 +112,14 @@ let client = Client::start(ClientOptions::new() | Option | Node.js | Python | Go | .NET | Java | Rust | Description | |---|---|---|---|---|---|---|---| | OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `OtlpEndpoint` | `otlpEndpoint` | `otlp_endpoint` | OTLP HTTP endpoint URL | +| OTLP protocol | `otlpProtocol` | `otlp_protocol` | `OTLPProtocol` | `OtlpProtocol` | `otlpProtocol` | `otlp_protocol` | OTLP HTTP protocol for all signals: `"http/json"` or `"http/protobuf"` | | File path | `filePath` | `file_path` | `FilePath` | `FilePath` | `filePath` | `file_path` | File path for JSON-lines trace output | | Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `ExporterType` | `exporterType` | `exporter_type` | `"otlp-http"` or `"file"` | | Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | `sourceName` | `source_name` | Instrumentation scope name | | Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | `captureContent` | `capture_content` | Whether to capture message content | +The OTLP protocol field configures the CLI's `"otlp-http"` exporter for all signals. Leave it unset to use the CLI default, or set it to `"http/protobuf"` to export protobuf over HTTP. + ### Trace context propagation > **Most users don't need this.** The `TelemetryConfig` above is all you need to collect traces from the CLI. The trace context propagation described in this section is an **advanced feature** for applications that create their own OpenTelemetry spans and want them to appear in the **same distributed trace** as the CLI's spans. diff --git a/content/copilot/how-tos/copilot-sdk/setup/azure-managed-identity.md b/content/copilot/how-tos/copilot-sdk/setup/azure-managed-identity.md index 6e898e07262c..7f228f5edcf9 100644 --- a/content/copilot/how-tos/copilot-sdk/setup/azure-managed-identity.md +++ b/content/copilot/how-tos/copilot-sdk/setup/azure-managed-identity.md @@ -3,8 +3,8 @@ title: Azure managed identity with BYOK shortTitle: Azure Managed Identity intro: >- The Copilot SDK's [AUTOTITLE](/copilot/how-tos/copilot-sdk/auth/byok) accepts static API keys, but - Azure deployments often use **Managed Identity** (Entra ID) instead of - long-lived keys. Since the SDK doesn't natively support Entra ID + Azure deployments often use **Managed Identity** (Microsoft Entra ID) instead + of long-lived keys. Since the SDK doesn't natively support Microsoft Entra authentication, you can use a short-lived bearer token via the `bearer_token` provider config field. versions: @@ -18,28 +18,99 @@ contentType: how-tos -This guide shows how to use `DefaultAzureCredential` from the [Azure Identity](https://learn.microsoft.com/python/api/azure-identity/azure.identity.defaultazurecredential) library to authenticate with Azure AI Foundry models through the Copilot SDK. +This guide shows how to use the Azure Identity SDK's `DefaultAzureCredential` API to authenticate with Microsoft Foundry models through the Copilot SDK. ## How it works -Azure AI Foundry's OpenAI-compatible endpoint accepts bearer tokens from Entra ID in place of static API keys. The pattern is: +Microsoft Foundry's OpenAI-compatible endpoint accepts bearer tokens from Microsoft Entra ID in place of static API keys. The pattern is: -1. Use `DefaultAzureCredential` to obtain a token for the `https://cognitiveservices.azure.com/.default` scope +1. Use `DefaultAzureCredential` to obtain a token for the `https://ai.azure.com/.default` scope 1. Pass the token as the `bearer_token` in the BYOK provider config 1. Refresh the token before it expires (tokens are typically valid for ~1 hour) ![Diagram: Sequence diagram showing the described process.](/assets/images/help/copilot/copilot-sdk/setup-azure-managed-identity-diagram-0.png) -## Python example +## Code samples ### Prerequisites +Install the Azure Identity and Copilot SDK packages for your language: + +{% codetabs %} +{% codetab dotnet %} + + + +```bash +dotnet add package GitHub.Copilot.SDK +dotnet add package Azure.Core +``` + +{% endcodetab %} +{% codetab python %} + + + ```bash pip install github-copilot-sdk azure-identity ``` +{% endcodetab %} +{% codetab typescript %} + + + +```bash +npm install @github/copilot-sdk @azure/identity +``` + +{% endcodetab %} +{% endcodetabs %} + ### Basic usage +Get a token using `DefaultAzureCredential` and pass it as the bearer token in your provider configuration: + +{% codetabs %} +{% codetab dotnet %} + + + +```csharp +using Azure.Core; +using Azure.Identity; +using GitHub.Copilot; + +DefaultAzureCredential credential = new( + DefaultAzureCredential.DefaultEnvironmentVariableName); +AccessToken token = await credential.GetTokenAsync( + new TokenRequestContext(new[] { "https://ai.azure.com/.default" })); + +await using CopilotClient client = new(); +string? foundryUrl = Environment.GetEnvironmentVariable("FOUNDRY_RESOURCE_URL"); + +await using CopilotSession session = await client.CreateSessionAsync(new SessionConfig +{ + Model = "gpt-5.5", + Provider = new ProviderConfig + { + Type = "openai", + BaseUrl = $"{foundryUrl!.TrimEnd('/')}/openai/v1/", + BearerToken = token.Token, + WireApi = "responses", + }, +}); + +AssistantMessageEvent? response = await session.SendAndWaitAsync( + new MessageOptions { Prompt = "Hello from Managed Identity!" }); +Console.WriteLine(response?.Data.Content); +``` + +{% endcodetab %} +{% codetab python %} + + + ```python import asyncio import os @@ -48,22 +119,22 @@ from azure.identity import DefaultAzureCredential from copilot import CopilotClient from copilot.session import PermissionHandler, ProviderConfig -COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default" +SCOPE = "https://ai.azure.com/.default" async def main(): # Get a token using Managed Identity, Azure CLI, or other credential chain - credential = DefaultAzureCredential() - token = credential.get_token(COGNITIVE_SERVICES_SCOPE).token + credential = DefaultAzureCredential(require_envvar=True) + token = credential.get_token(SCOPE).token - foundry_url = os.environ["AZURE_AI_FOUNDRY_RESOURCE_URL"] + foundry_url = os.environ["FOUNDRY_RESOURCE_URL"] client = CopilotClient() await client.start() session = await client.create_session( on_permission_request=PermissionHandler.approve_all, - model="gpt-4.1", + model="gpt-5.5", provider=ProviderConfig( type="openai", base_url=f"{foundry_url.rstrip('/')}/openai/v1/", @@ -81,30 +152,69 @@ async def main(): asyncio.run(main()) ``` +{% endcodetab %} +{% codetab typescript %} + + + +```typescript +import { DefaultAzureCredential } from "@azure/identity"; +import { CopilotClient } from "@github/copilot-sdk"; + +const credential = new DefaultAzureCredential({ + requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"], +}); +const tokenResponse = await credential.getToken( + "https://ai.azure.com/.default" +); + +const client = new CopilotClient(); + +const session = await client.createSession({ + model: "gpt-5.5", + provider: { + type: "openai", + baseUrl: `${process.env.FOUNDRY_RESOURCE_URL}/openai/v1/`, + bearerToken: tokenResponse.token, + wireApi: "responses", + }, +}); + +const response = await session.sendAndWait({ prompt: "Hello!" }); +console.log(response?.data.content); + +await client.stop(); +``` + +{% endcodetab %} +{% endcodetabs %} + ### Token refresh for long-running applications -Bearer tokens expire (typically after ~1 hour). For servers or long-running agents, refresh the token before creating each session: +Bearer tokens expire (typically after ~1 hour). For servers or long-running agents, refresh the token before creating each session. The following Python example demonstrates this pattern: + + ```python from azure.identity import DefaultAzureCredential from copilot import CopilotClient from copilot.session import PermissionHandler, ProviderConfig -COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default" +SCOPE = "https://ai.azure.com/.default" class ManagedIdentityCopilotAgent: - """Copilot agent that refreshes Entra ID tokens for Azure AI Foundry.""" + """Copilot agent that refreshes Microsoft Entra tokens for Microsoft Foundry.""" - def __init__(self, foundry_url: str, model: str = "gpt-4.1"): + def __init__(self, foundry_url: str, model: str = "gpt-5.5"): self.foundry_url = foundry_url.rstrip("/") self.model = model - self.credential = DefaultAzureCredential() + self.credential = DefaultAzureCredential(require_envvar=True) self.client = CopilotClient() def _get_provider_config(self) -> ProviderConfig: """Build a ProviderConfig with a fresh bearer token.""" - token = self.credential.get_token(COGNITIVE_SERVICES_SCOPE).token + token = self.credential.get_token(SCOPE).token return ProviderConfig( type="openai", base_url=f"{self.foundry_url}/openai/v1/", @@ -127,75 +237,12 @@ class ManagedIdentityCopilotAgent: return response.data.content if response else "" ``` -## Node.js / TypeScript example - - - -```typescript -import { DefaultAzureCredential } from "@azure/identity"; -import { CopilotClient } from "@github/copilot-sdk"; - -const credential = new DefaultAzureCredential(); -const tokenResponse = await credential.getToken( - "https://cognitiveservices.azure.com/.default" -); - -const client = new CopilotClient(); - -const session = await client.createSession({ - model: "gpt-4.1", - provider: { - type: "openai", - baseUrl: `${process.env.AZURE_AI_FOUNDRY_RESOURCE_URL}/openai/v1/`, - bearerToken: tokenResponse.token, - wireApi: "responses", - }, -}); - -const response = await session.sendAndWait({ prompt: "Hello!" }); -console.log(response?.data.content); - -await client.stop(); -``` - -## .NET example - - - -```csharp -using Azure.Identity; -using GitHub.Copilot; - -var credential = new DefaultAzureCredential(); -var token = await credential.GetTokenAsync( - new Azure.Core.TokenRequestContext( - new[] { "https://cognitiveservices.azure.com/.default" })); - -await using var client = new CopilotClient(); -var foundryUrl = Environment.GetEnvironmentVariable("AZURE_AI_FOUNDRY_RESOURCE_URL"); - -await using var session = await client.CreateSessionAsync(new SessionConfig -{ - Model = "gpt-4.1", - Provider = new ProviderConfig - { - Type = "openai", - BaseUrl = $"{foundryUrl!.TrimEnd('/')}/openai/v1/", - BearerToken = token.Token, - WireApi = "responses", - }, -}); - -var response = await session.SendAndWaitAsync( - new MessageOptions { Prompt = "Hello from Managed Identity!" }); -Console.WriteLine(response?.Data.Content); -``` - ## Environment configuration | Variable | Description | Example | |----------|-------------|---------| -| `AZURE_AI_FOUNDRY_RESOURCE_URL` | Your Azure AI Foundry resource URL | `https://myresource.openai.azure.com` | +| `AZURE_TOKEN_CREDENTIALS` | When running in **Azure**, set it to `ManagedIdentityCredential`. When running **locally**, set it to either `dev` or a developer tool credential name, such as `AzureCliCredential`. | `ManagedIdentityCredential` | +| `FOUNDRY_RESOURCE_URL` | Your Microsoft Foundry resource URL | `https://.openai.azure.com` | No API key environment variable is needed—authentication is handled by `DefaultAzureCredential`, which automatically supports: @@ -204,14 +251,18 @@ No API key environment variable is needed—authentication is handled by `Defaul * **Environment variables** (`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_CLIENT_SECRET`): for service principals * **Workload Identity**: for Kubernetes -See the [DefaultAzureCredential documentation](https://learn.microsoft.com/python/api/azure-identity/azure.identity.defaultazurecredential) for the full credential chain. +See the `DefaultAzureCredential` documentation for the full credential chain: + +* [.NET](https://aka.ms/azsdk/net/identity/credential-chains#defaultazurecredential-overview) +* [Python](https://aka.ms/azsdk/python/identity/credential-chains#defaultazurecredential-overview) +* [TypeScript](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview) ## When to use this pattern | Scenario | Recommendation | |----------|----------------| | Azure-hosted app with Managed Identity | ✅ Use this pattern | -| App with existing Azure AD service principal | ✅ Use this pattern | +| App with existing Microsoft Entra service principal | ✅ Use this pattern | | Local development with `az login` | ✅ Use this pattern | | Non-Azure environment with static API key | Use [AUTOTITLE](/copilot/how-tos/copilot-sdk/auth/byok) | | GitHub Copilot subscription available | Use [AUTOTITLE](/copilot/how-tos/copilot-sdk/setup/github-oauth) | diff --git a/content/copilot/how-tos/copilot-sdk/setup/bundled-cli.md b/content/copilot/how-tos/copilot-sdk/setup/bundled-cli.md index 059cbd25ee8a..4c9b04c41185 100644 --- a/content/copilot/how-tos/copilot-sdk/setup/bundled-cli.md +++ b/content/copilot/how-tos/copilot-sdk/setup/bundled-cli.md @@ -2,9 +2,9 @@ title: Default setup (bundled CLI) shortTitle: Bundled CLI intro: >- - The Node.js, Python, and .NET SDKs include the Copilot CLI as a - dependency—your app ships with everything it needs, with no extra installation - or configuration required. + The Node.js and .NET SDKs include the Copilot CLI as a dependency—your app + ships with everything it needs, with no extra installation or configuration + required. versions: fpt: '*' ghec: '*' @@ -16,11 +16,19 @@ contentType: how-tos +The Python SDK recommends a one-time download step after installation: + +```bash +python -m copilot download-runtime +``` + +This downloads the matching runtime and caches it locally. If you skip this step, the SDK will attempt to download it automatically on first use as a fallback. + **Best for:** Most applications—desktop apps, standalone tools, CLI utilities, prototypes, and more. ## How it works -When you install the SDK, the Copilot CLI binary is included automatically. The SDK starts it as a child process and communicates over stdio. There's nothing extra to configure. +When you install the SDK, the Copilot runtime is included automatically (Node.js, .NET) or downloaded via `python -m copilot download-runtime` (Python). The SDK starts it as a child process and communicates over stdio. There's nothing extra to configure. ![Diagram: Flowchart showing the described process.](/assets/images/help/copilot/copilot-sdk/setup-bundled-cli-diagram-0.png) diff --git a/content/copilot/how-tos/copilot-sdk/setup/local-cli.md b/content/copilot/how-tos/copilot-sdk/setup/local-cli.md index 9586703faa53..81adbda1a09e 100644 --- a/content/copilot/how-tos/copilot-sdk/setup/local-cli.md +++ b/content/copilot/how-tos/copilot-sdk/setup/local-cli.md @@ -2,9 +2,9 @@ title: Local CLI setup shortTitle: Local CLI intro: >- - Use a specific CLI binary instead of the SDK's bundled CLI. This is an - advanced option—you supply the CLI path explicitly, and you are responsible - for ensuring version compatibility with the SDK. + Use a specific CLI binary instead of the SDK's automatic CLI management. This + is an advanced option—you supply the CLI path explicitly, and you are + responsible for ensuring version compatibility with the SDK. versions: fpt: '*' ghec: '*' @@ -56,7 +56,7 @@ await client.stop(); ```python from copilot import CopilotClient -from copilot.generated.session_events import AssistantMessageData +from copilot.session_events import AssistantMessageData from copilot.session import PermissionHandler client = CopilotClient({ diff --git a/content/copilot/how-tos/copilot-sdk/setup/multi-tenancy.md b/content/copilot/how-tos/copilot-sdk/setup/multi-tenancy.md index 3d6e4aedccc0..9fbe6d3870c3 100644 --- a/content/copilot/how-tos/copilot-sdk/setup/multi-tenancy.md +++ b/content/copilot/how-tos/copilot-sdk/setup/multi-tenancy.md @@ -2,8 +2,12 @@ title: Multi-tenancy and server deployments shortTitle: Multi Tenancy intro: >- - Run the Copilot SDK in multi-user server deployments with per-session - isolation for state, authentication, and tools. + Multi-user server mode means running the Copilot SDK from backend code that + serves more than one human, tenant, workspace, or integration account. In this + setup, the application owns request routing and authorization, while the SDK + and runtime provide per-session state, per-session authentication, and + explicit tool registration so one user's session does not inherit another + user's tools or identity. versions: fpt: '*' ghec: '*' @@ -112,7 +116,7 @@ func main() { runtimeInstanceID := "instance-1" runtimeURL := "http://127.0.0.1:8080" requestID := "req-1" - user := appUser{ID: "alice", GitHubToken: "YOUR_GITHUB_TOKEN"} + user := appUser{ID: "alice", GitHubToken: "gho_xxx"} client := copilot.NewClient(&copilot.ClientOptions{ Mode: copilot.ModeEmpty, @@ -157,7 +161,7 @@ using GitHub.Copilot; var runtimeInstanceId = "instance-1"; var runtimeUrl = "http://127.0.0.1:8080"; var requestId = "req-1"; -var user = new { Id = "alice", GitHubToken = "YOUR_GITHUB_TOKEN" }; +var user = new { Id = "alice", GitHubToken = "gho_xxx" }; var client = new CopilotClient(new CopilotClientOptions { diff --git a/content/copilot/how-tos/copilot-sdk/troubleshooting/compatibility.md b/content/copilot/how-tos/copilot-sdk/troubleshooting/compatibility.md index 5eed74af1409..60cd2712584f 100644 --- a/content/copilot/how-tos/copilot-sdk/troubleshooting/compatibility.md +++ b/content/copilot/how-tos/copilot-sdk/troubleshooting/compatibility.md @@ -167,7 +167,9 @@ The Copilot SDK communicates with the CLI via JSON-RPC protocol. Features must b | **Development** | | | | Toggle experimental | `/experimental`, `--experimental` | Runtime flag | | Custom instructions control | `--no-custom-instructions` | CLI flag | +| Diagnose session | `/diagnose` | TUI command | | View/manage instructions | `/instructions` | TUI command | +| Collect debug logs | `/collect-debug-logs` | Diagnostic tool | | Reindex workspace | `/reindex` | TUI command | | IDE integration | `/ide` | IDE-specific workflow | | **Non-interactive Mode** | | | diff --git a/content/copilot/reference/ai-models/model-hosting.md b/content/copilot/reference/ai-models/model-hosting.md index 8b537ba1b772..c6a859e065e3 100644 --- a/content/copilot/reference/ai-models/model-hosting.md +++ b/content/copilot/reference/ai-models/model-hosting.md @@ -50,6 +50,7 @@ Used for: * {% data variables.copilot.copilot_claude_haiku_45 %} * {% data variables.copilot.copilot_claude_sonnet_45 %} * {% data variables.copilot.copilot_claude_sonnet_46 %} +* {% data variables.copilot.copilot_claude_sonnet_5 %} * {% data variables.copilot.copilot_claude_opus_45 %} * {% data variables.copilot.copilot_claude_opus_46 %} * {% data variables.copilot.copilot_claude_opus_47 %} diff --git a/content/copilot/reference/ai-models/supported-models.md b/content/copilot/reference/ai-models/supported-models.md index 470ee888960b..2672b81cbd49 100644 --- a/content/copilot/reference/ai-models/supported-models.md +++ b/content/copilot/reference/ai-models/supported-models.md @@ -83,6 +83,7 @@ Choosing a larger context window or higher reasoning will impact {% data variabl | {% data variables.copilot.copilot_claude_opus_46 %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_claude_opus_47 %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_claude_opus_48 %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | +| {% data variables.copilot.copilot_claude_sonnet_5 %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_claude_opus_48_fast %} | {% octicon "x" aria-label="Not supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_claude_fable_5 %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_gpt_53_codex %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | @@ -141,8 +142,9 @@ Some {% data variables.product.prodname_copilot_short %} models require minimum | {% data variables.copilot.copilot_gpt_54_mini %} | `v1.104.1` and later | `17.14.19` and later | `1.5.66` and later | `0.47.0` and later | `0.15.0` and later | | {% data variables.copilot.copilot_gpt_55 %} | `v1.117` and later | `17.14.19` and later | `1.5.66` and later | `0.47.0` and later | `0.15.0` and later | | {% data variables.copilot.copilot_claude_opus_48 %} | `v1.118` and later | `17.14.6` and later | TBD | TBD | TBD | +| {% data variables.copilot.copilot_claude_sonnet_5 %} | `v1.124` and later | `17.14.6` and later | TBD | TBD | TBD | | {% data variables.copilot.copilot_claude_fable_5 %} | `v1.124` and later | `17.14.6` and later | TBD | TBD | TBD | -| {% data variables.copilot.copilot_mai_code_1_flash %} | `v1.121` and later | Not available | Not available | Not available | Not available | +| {% data variables.copilot.copilot_mai_code_1_flash %} | `v1.121` and later | TBD | TBD | TBD | TBD | {% endrowheaders %} diff --git a/content/copilot/reference/copilot-billing/license-changes.md b/content/copilot/reference/copilot-billing/license-changes.md index 310aea2fde05..9996b11550ea 100644 --- a/content/copilot/reference/copilot-billing/license-changes.md +++ b/content/copilot/reference/copilot-billing/license-changes.md @@ -30,6 +30,14 @@ What you need to know about the following actions: * **Upgrading:** If you upgrade your plan (for example, from {% data variables.copilot.copilot_pro_short %} to {% data variables.copilot.copilot_pro_plus_short %}), the change is **immediate**. You are charged a prorated amount for the new plan. * **Downgrading/canceling:** Access remains until the end of the current billing cycle. **No refund for unused time**. +### Included monthly allowance reset + +Paying for, renewing, upgrading, downgrading, converting from a trial, or resuming a plan after a lapse does not grant a fresh {% data variables.product.prodname_ai_credits_short %} allowance immediately. Your included monthly allowance resets at 00:00:00 UTC on the first day of each calendar month, regardless of your subscription billing date. + +For example, if you exhaust your {% data variables.product.prodname_ai_credits_short %} on May 28 and renew or upgrade your plan on May 30, your allowance does not reset until June 1. + +Any additional usage beyond the included allowance is charged separately and is unaffected by this monthly reset. See [AUTOTITLE](/copilot/concepts/billing/usage-based-billing-for-individuals) and [AUTOTITLE](/billing/how-tos/set-up-budgets#managing-budgets-for-your-personal-account). + ## Organizations What you need to know about the following actions: diff --git a/content/copilot/reference/copilot-billing/models-and-pricing.md b/content/copilot/reference/copilot-billing/models-and-pricing.md index 87b5c0f23e7b..63b94d004f25 100644 --- a/content/copilot/reference/copilot-billing/models-and-pricing.md +++ b/content/copilot/reference/copilot-billing/models-and-pricing.md @@ -97,3 +97,5 @@ You can view your current {% data variables.product.prodname_actions %} usage fo ## Model multipliers for annual {% data variables.copilot.copilot_pro_short %} and {% data variables.copilot.copilot_pro_plus_short %} subscribers {% data variables.copilot.copilot_pro_short %} and {% data variables.copilot.copilot_pro_plus_short %} subscribers on **existing annual billing plans** using the **request-based billing** model have different model multipliers. See [AUTOTITLE](/copilot/reference/copilot-billing/model-multipliers-for-annual-plans). + +[^sonnet-5-promo]: {% data variables.copilot.copilot_claude_sonnet_5 %} is available at the promotional pricing of $2.00 per 1M input tokens, $0.20 per 1M cached input tokens, $2.50 per 1M cache write tokens, and $10.00 per 1M output tokens through August 31, 2026. diff --git a/content/copilot/reference/copilot-cli-reference/cli-command-reference.md b/content/copilot/reference/copilot-cli-reference/cli-command-reference.md index 35c4b1785c1e..efbafcfe7c66 100644 --- a/content/copilot/reference/copilot-cli-reference/cli-command-reference.md +++ b/content/copilot/reference/copilot-cli-reference/cli-command-reference.md @@ -26,6 +26,7 @@ docsTeamMetrics: | `copilot login` [OPTION] | Authenticate with {% data variables.product.prodname_copilot_short %} via the OAuth device flow. See [`copilot login` options](#copilot-login-options). | | `copilot mcp` | Manage MCP server configurations from the command line. | | `copilot plugin` | Manage plugins and plugin marketplaces. | +| `copilot skill` | Manage agent skills from the command line (list, add, and remove skills). See [AUTOTITLE](/copilot/how-tos/copilot-cli/customize-copilot/add-skills). | | `copilot update` | Download and install the latest version. | | `copilot version` | Display version information and check for updates. | diff --git a/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md b/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md index e8358e457d31..a8f8bae09aa2 100644 --- a/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md +++ b/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md @@ -67,7 +67,7 @@ These fields appear in the exported NDJSON reports and in the {% data variables. Reports come in different shapes depending on their scope and granularity, so the fields available in a record depend on which report it comes from: -* **Per-user reports** (`*-users-1-day` and `*-users-28-day`) contain one record per user, including `user_id`, `user_login`, the `used_*` indicators, and `ai_adoption_phase`. They do not contain active-user counts, `pull_requests`, or `totals_by_ai_adoption_phase`. +* **Per-user reports** (`*-users-1-day` and `*-users-28-day`) contain one record per user, including `user_id`, `user_login`, `ai_credits_used`, the `used_*` indicators, and `ai_adoption_phase`. They do not contain active-user counts, `pull_requests`, or `totals_by_ai_adoption_phase`. * **Aggregated reports** (`enterprise-1-day` and `org-1-day`) contain one aggregated record per enterprise or organization, including active-user counts, `pull_requests`, and `totals_by_ai_adoption_phase`. They do not contain `user_id`, `user_login`, or the `used_*` indicators. * **28-day reports** (`enterprise-28-day` and `org-28-day`) wrap an array of daily aggregated records in a `day_totals` field, with the reporting window at the top level. * **User-teams reports** (`*-user-teams-1-day`) map users to the teams they belong to, so you can construct team-level metrics. @@ -96,6 +96,7 @@ Per-user reports contain one record per user for the reporting period. The 28-da |:--|:--|:--|:--| | `user_id` | `integer` | No | Unique identifier for the user. | | `user_login` | `string` | No | {% data variables.product.github %} username for the user. | +| `ai_credits_used` | `number` | No | Total AI credits consumed by the user in the reporting period. This field is included in per-user reports only and is not broken down by feature, model, or surface. This metric is for consumption analysis, not invoicing totals. | | `user_initiated_interaction_count` | `integer` | No | Number of explicit prompts sent to {% data variables.product.prodname_copilot_short %}.

Only counts messages or prompts actively sent to the model. Does **not** include opening the chat panel, switching modes (for example, ask, edit, plan, or agent), using keyboard shortcuts to open the inline UI, or making configuration changes. | | `code_generation_activity_count` | `integer` | No | Number of distinct {% data variables.product.prodname_copilot_short %} output events generated.

**Includes:** All generated content, including comments and docstrings.
**Multiple blocks:** Each distinct code block from a single user prompt counts as a separate generation.
**Note:** This metric is not directly comparable to `user_initiated_interaction_count`, since one prompt can produce multiple generations. | | `code_acceptance_activity_count` | `integer` | No | Number of suggestions or code blocks accepted by users.

**Counts:** All built-in accept actions, such as “apply to file,” “insert at cursor,” “insert into terminal,” and use of the **Copy** button.
**Does not count:** Manual OS clipboard actions (for example, Ctrl+C).
**Granularity:** Each acceptance action increments the count once, regardless of how many code blocks were generated by the initial prompt. | diff --git a/content/copilot/reference/copilot-usage-metrics/example-schema.md b/content/copilot/reference/copilot-usage-metrics/example-schema.md index 2e7db8049773..f4050a182336 100644 --- a/content/copilot/reference/copilot-usage-metrics/example-schema.md +++ b/content/copilot/reference/copilot-usage-metrics/example-schema.md @@ -19,6 +19,7 @@ The following are example schemas for the user-level and enterprise-level data r ```json copy [{ + "ai_credits_used": 12.5, "code_acceptance_activity_count": 1, "code_generation_activity_count": 1, "day": "2025-10-01", diff --git a/content/migrations/elm/about-live-migrations.md b/content/migrations/elm/about-live-migrations.md index 4c149e55dbbf..906316c44faa 100644 --- a/content/migrations/elm/about-live-migrations.md +++ b/content/migrations/elm/about-live-migrations.md @@ -7,7 +7,6 @@ versions: ghes: '*' ghec: '*' contentType: concepts -product: '{% data reusables.elm.ghes-version-requirement %}' --- {% data reusables.elm.preview-note %} @@ -43,7 +42,7 @@ The high-level phases of a migration are: 1. **Creation**: The site admin runs CLI commands to create and start the migration, specifying the source repository and destination. 1. **Preflight checks**: The migration service verifies parameters, tokens, network connectivity, and repository configuration. 1. **Backfill**: The {% data variables.product.prodname_elm_short %} tool does an initial crawl to capture all repository data and sends it to the migration service on the destination platform. During the backfill phase, webhooks check for live updates to the repository as the migration continues. -1. **Cutover**: The source repository is locked and any final live updates are sent to {% data variables.product.prodname_elm_short %}. This is the downtime period for developers. +1. **Cutover**: The source repository is archived (made read-only) and any final live updates are sent to {% data variables.product.prodname_elm_short %}. This is the downtime period for developers. 1. **Completion**: The migration is finished. The site admin can check the data was migrated successfully. 1. **Follow-up**: An organization owner performs follow-up tasks on the destination enterprise, such as reconfiguring organization settings and reattributing activity to users. diff --git a/content/migrations/elm/elm-cli-reference.md b/content/migrations/elm/elm-cli-reference.md index b74b873f85b6..fa2ab60bc75f 100644 --- a/content/migrations/elm/elm-cli-reference.md +++ b/content/migrations/elm/elm-cli-reference.md @@ -20,7 +20,7 @@ contentType: reference | `elm migration status --migration-id MIGRATION-ID` | Shows the status, progress, cutover readiness, and timing of a migration | | `elm migration list` | Lists all migrations and their statuses | | `elm migration cancel --migration-id MIGRATION-ID` | Cancels a migration in progress | -| `elm migration cutover-to-destination --migration-id MIGRATION-ID` | Initiates the final cutover, locking the source repository and completing the migration | +| `elm migration cutover-to-destination --migration-id MIGRATION-ID` | Initiates the final cutover, archiving the source repository and completing the migration | Some of these commands can take additional options. See the later sections in this article. diff --git a/content/migrations/elm/migrate-your-repository.md b/content/migrations/elm/migrate-your-repository.md index a9441a56bbe8..10ba3bf63e90 100644 --- a/content/migrations/elm/migrate-your-repository.md +++ b/content/migrations/elm/migrate-your-repository.md @@ -7,7 +7,6 @@ versions: ghes: '*' ghec: '*' contentType: how-tos -product: '{% data reusables.elm.ghes-version-requirement %}' permissions: 'Site administrators on {% data variables.product.prodname_ghe_server %} who are also enterprise owners on {% data variables.enterprise.data_residency_site %}.' --- @@ -60,18 +59,7 @@ You must set some configuration on the {% data variables.product.prodname_ghe_se | `secrets.elm-exporter.migration-target-token` | The access token you created for {% data variables.enterprise.data_residency_site %}. | | `secrets.elm-exporter.source-token` | The access token you created for {% data variables.product.prodname_ghe_server %}. | | `secrets.elm-exporter.source-user` | The username associated with the {% data variables.product.prodname_ghe_server %} token (for example: `ghe-admin`). | - -1. If you **don't** already have migrations enabled and blob storage configured on the instance, you can configure them now. You can check your existing settings in in "Migrations" section of the Management Console (`HOSTNAME/setup/settings`). - - You can use the following default values, which will not introduce any unexpected functionality. - - ```shell copy - ghe-config app.migrations.enabled true - ``` - - ```shell copy - ghe-config secrets.migrations.blob-storage-type local-storage - ``` + | `app.migrations.enabled` | If you don't already have migrations enabled on the instance, you must set this to `true`. | 1. Apply the configuration. @@ -194,7 +182,7 @@ Tips: ## 7. Complete the migration -When a migration is ready for cutover, you can complete the migration. The cutover process will lock the source repository, making it **permanently unavailable** for developers unless an administrator unlocks it. +When a migration is ready for cutover, you can complete the migration. The cutover process will archive the source repository, making it **permanently read-only** unless a repository administrator unarchives it. ``` shell copy elm migration cutover-to-destination --migration-id $MIGRATION_ID diff --git a/content/migrations/elm/prepare-for-your-migration.md b/content/migrations/elm/prepare-for-your-migration.md index 86d4eb38e42b..afafef08806d 100644 --- a/content/migrations/elm/prepare-for-your-migration.md +++ b/content/migrations/elm/prepare-for-your-migration.md @@ -13,18 +13,22 @@ contentType: concepts ## Is our {% data variables.product.prodname_ghe_server %} instance ready? -{% data variables.product.prodname_elm_short %} has been backported to supported releases. To use it, you must upgrade to one of the following minor versions or later: +{% data variables.product.prodname_elm_short %} is available in the latest patch releases for {% data variables.product.prodname_ghe_server %} 3.17 and later. This documentation assumes you are using the following patch version or later. The instructions may not work on earlier versions. -* `3.21.0` -* `3.20.2` -* `3.19.6` -* `3.18.9` -* `3.17.15` + + +* `3.21.2` +* `3.20.4` +* `3.19.8` +* `3.18.11` +* `3.17.17` Your {% data variables.product.prodname_ghe_server %} instance must also: * Use an **HTTPS** URL. HTTP URLs are not supported. -* Have migrations enabled and blob storage configured. You can check these settings in the "Migrations" section of the Management Console. If you don't already have these settings configured, we will explain how to set them to default values in [AUTOTITLE](/migrations/elm/migrate-your-repository). +* Allow outbound traffic to the destination of the migration. +* Have migrations enabled in the "Migrations" section of the Management Console. +* Be prepared for some additional load during the migration: repository archiving causes all issues and pull requests in the repository to be pulled from MySQL and reindexed in Elasticsearch. ## What will our destination organization look like? @@ -65,7 +69,7 @@ After the migration, someone will need to perform some follow-up tasks on {% dat Before you start, communicate with developers that: -* The repository is moving to a new location. Users can continue to use the source repository during the migration until the operator begins the final cutover to the new location. +* The repository is moving to a new location. Users can continue to use the source repository during the migration until the operator begins the final cutover to the new location. After cutover, the source repository will be archived, so it will be read-only unless it is unarchived by a repository administrator. * While the migration is in progress, developers should avoid force pushes to the repository, because these will disrupt the Git history in a way that {% data variables.product.prodname_elm_short %} cannot resolve. * Certain actions that developers perform during the migration process may not be reflected in the migrated repository. For details, see the unsupported actions in [AUTOTITLE](/migrations/elm/migrated-data-reference#events-included-in-live-updates). diff --git a/content/migrations/elm/troubleshooting.md b/content/migrations/elm/troubleshooting.md index 6448dd0cfadd..36d1afba4fad 100644 --- a/content/migrations/elm/troubleshooting.md +++ b/content/migrations/elm/troubleshooting.md @@ -22,7 +22,7 @@ If your migration encounters a problem, check the migration status with `elm mig | **Exporting** | Data is being exported from the source | Monitor with `elm migration status` | | **Processing** | Exported data is being imported to the destination | Monitor with `elm migration status` | | **Ready for cutover** | The initial migration is complete and the migration is ready for cutover | When ready, run `elm migration cutover-to-destination` | -| **Cutting over** | The source repository is locked and remaining changes are being applied to the destination | Monitor; the status will transition to **Completed** | +| **Cutting over** | The source repository is archived and remaining changes are being applied to the destination | Monitor; the status will transition to **Completed** | | **Completed** | The migration has finished successfully | Verify the destination repository and reclaim mannequins | | **Failed** | The migration encountered an unrecoverable failure | Investigate the error (see below) | | **Paused** | The migration is paused | Check the pause reason and resolve (see below) | @@ -95,7 +95,7 @@ Failed resources are only shown after all automatic retries have been exhausted, If the number and types of failed resources are acceptable, you can proceed with cutover. If not, abort the migration, resolve the underlying issue, then start a new migration. -## Cutover failed and the source repository is locked +## Cutover failed and the source repository is unavailable {% data reusables.elm.locked-repo %} diff --git a/content/migrations/overview/about-locked-repositories.md b/content/migrations/overview/about-locked-repositories.md index b964b610d8dc..00e84121c0e1 100644 --- a/content/migrations/overview/about-locked-repositories.md +++ b/content/migrations/overview/about-locked-repositories.md @@ -35,7 +35,9 @@ While a migration is in progress, access to the destination repository is locked For information about how to unlock repositories that were locked by {% data variables.product.prodname_importer_proper_name %}, see [AUTOTITLE](/migrations/using-github-enterprise-importer/completing-your-migration-with-github-enterprise-importer/troubleshooting-your-migration-with-github-enterprise-importer#locked-repositories). -## Repositories locked by {% data variables.product.prodname_elm %} +## Repositories archived by {% data variables.product.prodname_elm %} + +In the latest {% data variables.product.prodname_ghe_server %} releases, {% data variables.product.prodname_elm %} archives, rather than locks, the source repository. This keeps the repository available for read operations. {% data reusables.elm.locked-repo %} diff --git a/data/release-notes/enterprise-server/3-17/17.yml b/data/release-notes/enterprise-server/3-17/17.yml new file mode 100644 index 000000000000..2d928414e322 --- /dev/null +++ b/data/release-notes/enterprise-server/3-17/17.yml @@ -0,0 +1,90 @@ +date: '2026-06-30' +sections: + security_fixes: + - | + **HIGH**: Current configurations of the GitHub API access controls could allow an attacker to create issues in any public repository via a u2s token without requiring the underlying installation to have issues write permission. This therefore allows an attacker to impersonate the victim in public repositories by creating issues and commit comments. + - | + **MEDIUM**: An attacker with site administrator privileges could extract arbitrary data from the instance's database, including user password hashes, by exploiting a blind SQL injection vulnerability in the `dependenciesPrefers` argument of the `dependencyGraphManifests` GraphQL field. This vulnerability affected instances with the dependency graph enabled and was reported via the GitHub Bug Bounty program. + - | + **MEDIUM**: An attacker could gain unintended access to an organization's runner management by directing a user to authorize an OAuth app whose requested manage_runners:org scope was not displayed on the authorization consent screen. GitHub has requested CVE ID [CVE-2026-9106](https://www.cve.org/cverecord?id=CVE-2026-9106) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + **MEDIUM**: An authenticated GHES user could read source code from private repositories they did not have access to by supplying a cross-repository comparison range to the Copilot pull request description diff summary endpoint, which did not verify the user's permission to view the target repository. GitHub has requested CVE ID [CVE-2026-9132](https://www.cve.org/cverecord?id=CVE-2026-9132) for this vulnerability, which was reported via the [GitHub Bug Bounty program](https://bounty.github.com/). + - | + **MEDIUM**: An attacker could execute arbitrary JavaScript in a victim's browser on a GitHub Enterprise Server instance by creating a discussion in the Q\&A category with a crafted title that breaks out of the JSON-LD structured-data script block when a comment is marked as the answer. To mitigate this issue, GitHub has updated the rendering of JSON-LD structured data in discussions to properly escape user-controlled input. GitHub has requested CVE ID [CVE-2026-10585](https://www.cve.org/cverecord?id=CVE-2026-10585) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + GitHub has updated `dnsmasq` to fix the following vulnerabilities: CVE-2026-4891, CVE-2026-4890, CVE-2026-4892, CVE-2026-4893, CVE-2026-5172, CVE-2026-2291. + - | + Packages have been updated to the latest security versions. + bugs: + - | + After administrators updated a GitHub Enterprise Server instance's TLS certificate, GitHub Pages deployments failed because the necessary services did not restart when `ghe-config-apply` was run. + - | + Administrators could not generate support bundles on stateless high availability nodes because the `ghe-support-bundle` command failed when attempting to query Elasticsearch on nodes without the `elasticsearch-server` role. + - | + On an instance with Enterprise Live Migrations enabled, running `/usr/local/bin/elm` without arguments dropped into a degraded container shell where standard administrative commands were unavailable. + - | + The scheduled job that repairs search indexes could run long enough that its next execution interrupted the in-progress repair, causing the process to restart before completing. The job used a locking mechanism to prevent overlapping runs and was scheduled to run once per month, on the first Saturday, instead of weekly. + - | + On instances with multiple data disks configured, administrators who ran `ghe-restore` encountered an error message: `Runtime error (func=(main), adr=10): Divide by zero`. + - | + For administrators using the Backup Service to back up a high availability (HA) appliance from the replica with GitHub Actions enabled, MSSQL backups would fail with the error `This command can only be run on the primary mssql node.` + - | + When running `ghe-backup` on an instance configured with the Backup Service, the `data` directory inside the backups mountpoint (usually `/data/backup/data`) failed to be automatically created due to missing permissions. + - | + Users who created custom patterns for secret scanning could bypass the restriction on unbounded wildcards by wrapping them in capture groups, which could cause performance degradation during scans. + changes: + - | + To reduce response times for repositories with a large number of code scanning alerts, GitHub Enterprise Server uses an optimized query when counting alerts. + - | + Site administrators can include Enterprise Live Migrations (ELM) Exporter appliance data in scheduled backups using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + - | + Site administrators can restore Enterprise Live Migrations (ELM) Exporter appliance data using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + known_issues: + - | + During an upgrade of GitHub Enterprise Server, custom firewall rules are removed. If you use custom firewall rules, you must reapply them after upgrading. + - | + During the validation phase of a configuration run, a `No such object` error may occur for the Notebook and Viewscreen services. This error can be ignored as the services should still correctly start. + - | + If the root site administrator is locked out of the Management Console after failed login attempts, the account does not unlock automatically after the defined lockout time. Someone with administrative SSH access to the instance must unlock the account using the administrative shell. For more information, see [Troubleshooting access to the Management Console](/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/troubleshooting-access-to-the-management-console#unlocking-the-root-site-administrator-account). + - | + On an instance with the HTTP `X-Forwarded-For` header configured for use behind a load balancer, all client IP addresses in the instance's audit log erroneously appear as 127.0.0.1. + - | + {% data reusables.release-notes.large-adoc-files-issue %} + - | + Admin stats REST API endpoints may time out on appliances with many users or repositories. Retrying the request until data is returned is advised. + - | + When following the steps for [Replacing the primary MySQL node](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-the-primary-mysql-node), step 14 (running `ghe-cluster-config-apply`) might fail with errors. If this occurs, re-running `ghe-cluster-config-apply` is expected to succeed. + - | + Running a config apply as part of the steps for [Replacing a node in an emergency](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-a-node-in-an-emergency) may fail with errors if the node being replaced is still reachable. If this occurs, shutdown the node and repeat the steps. + - | + {% data reusables.release-notes.2024-06-possible-frontend-5-minute-outage-during-hotpatch-upgrade %} + - | + When restoring data originally backed up from a 3.13 or later appliance version, the Elasticsearch indices need to be reindexed before some of the data will show up. This happens via a nightly scheduled job. It can also be forced by running `/usr/local/share/enterprise/ghe-es-search-repair`. + - | + An organization-level code scanning configuration page is displayed on instances that do not use GitHub Advanced Security or code scanning. + - | + When enabling automatic update checks for the first time in the Management Console, the status is not dynamically reflected until the "Updates" page is reloaded. + - | + When restoring from a backup snapshot, a large number of `mapper_parsing_exception` errors may be displayed. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + In a cluster, the host running restore requires access to the storage nodes via their private IPs. + - | + On an instance hosted on Azure, commenting on an issue via email meant the comment was not added to the issue. + - | + After a restore, existing outside collaborators cannot be added to repositories in a new organization. This issue can be resolved by running `/usr/local/share/enterprise/ghe-es-search-repair` on the appliance. + - | + After a geo-replica is promoted to be a primary by running `ghe-repl-promote`, the GitHub Actions workflow of a repository does not have any suggested workflows. + - | + Unexpected elements may appear in the UI on the repository overview page for locked repositories. + - | + When publishing npm packages in a workflow after restoring from a backup to GitHub Enterprise Server 3.13.5.gm4 or 3.14.2.gm3, you may encounter a `401 Unauthorized` error from the GitHub Packages service. This can happen if the restore is from an N-1 or N-2 version and the workflow targets the npm endpoint on the backup instance. To avoid this issue, ensure the access token is valid and includes the correct scopes for publishing to GitHub Packages. + - | + When applying an enterprise security configuration to all repositories (for example, enabling Secret Scanning or Code Scanning across all repositories), the system immediately enqueues enablement jobs for every organization in the enterprise simultaneously. For enterprises with a large number of repositories, this can result in significant system load and potential performance degradation. If you manage a large enterprise with many organizations and repositories, we recommend applying security configurations at the organization level rather than at the enterprise level in the UI. This allows you to enable security features incrementally and monitor system performance as you roll out changes. + - | + Git versions are mismatched between containers on the instance. + - | + Administrators upgrading to certain patch releases encountered a `Failed to generate an OIDC token` error during the `Update Servicing Resources` step when GitHub Actions was configured with Google Cloud Storage (GCS) or AWS S3 using OpenID Connect (OIDC) authentication. The upgrade was blocked and could not complete. To work around this issue, administrators could apply a manual patch by running `sudo sed -i.bak 's|ghe-actions-console -s -c Update-Service|ghe-actions-console -s --no-blob-creds -c Update-Service|g' /usr/local/bin/ghe-actions-update` followed by `ghe-config-apply`. diff --git a/data/release-notes/enterprise-server/3-18/11.yml b/data/release-notes/enterprise-server/3-18/11.yml new file mode 100644 index 000000000000..2e3325559cf8 --- /dev/null +++ b/data/release-notes/enterprise-server/3-18/11.yml @@ -0,0 +1,94 @@ +date: '2026-06-30' +sections: + security_fixes: + - | + **HIGH**: Current configurations of the GitHub API access controls could allow an attacker to create issues in any public repository via a u2s token without requiring the underlying installation to have issues write permission. This therefore allows an attacker to impersonate the victim in public repositories by creating issues and commit comments. + - | + **MEDIUM**: An attacker with site administrator privileges could extract arbitrary data from the instance's database, including user password hashes, by exploiting a blind SQL injection vulnerability in the `dependenciesPrefers` argument of the `dependencyGraphManifests` GraphQL field. This vulnerability affected instances with the dependency graph enabled and was reported via the GitHub Bug Bounty program. + - | + **MEDIUM**: An attacker could gain unintended access to an organization's runner management by directing a user to authorize an OAuth app whose requested manage_runners:org scope was not displayed on the authorization consent screen. GitHub has requested CVE ID [CVE-2026-9106](https://www.cve.org/cverecord?id=CVE-2026-9106) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + **MEDIUM**: An authenticated GHES user could read source code from private repositories they did not have access to by supplying a cross-repository comparison range to the Copilot pull request description diff summary endpoint, which did not verify the user's permission to view the target repository. GitHub has requested CVE ID [CVE-2026-9132](https://www.cve.org/cverecord?id=CVE-2026-9132) for this vulnerability, which was reported via the [GitHub Bug Bounty program](https://bounty.github.com/). + - | + **MEDIUM**: An attacker could execute arbitrary JavaScript in a victim's browser on a GitHub Enterprise Server instance by creating a discussion in the Q\&A category with a crafted title that breaks out of the JSON-LD structured-data script block when a comment is marked as the answer. To mitigate this issue, GitHub has updated the rendering of JSON-LD structured data in discussions to properly escape user-controlled input. GitHub has requested CVE ID [CVE-2026-10585](https://www.cve.org/cverecord?id=CVE-2026-10585) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + GitHub has updated `dnsmasq` to fix the following vulnerabilities: CVE-2026-4891, CVE-2026-4890, CVE-2026-4892, CVE-2026-4893, CVE-2026-5172, CVE-2026-2291. + - | + Packages have been updated to the latest security versions. + bugs: + - | + Administrators experienced "Permission denied" errors when the `ghes-manage-agent` attempted to write logs under `/var/log/license-upgrade` during license upgrade restart tasks. + - | + After administrators updated a GitHub Enterprise Server instance's TLS certificate, GitHub Pages deployments failed because the necessary services did not restart when `ghe-config-apply` was run. + - | + On an instance with Enterprise Live Migrations enabled, running `/usr/local/bin/elm` without arguments dropped into a degraded container shell where standard administrative commands were unavailable. + - | + The scheduled job that repairs search indexes could run long enough that its next execution interrupted the in-progress repair, causing the process to restart before completing. The job used a locking mechanism to prevent overlapping runs and was scheduled to run once per month, on the first Saturday, instead of weekly. + - | + When a site administrator ran `ghe-remove-node` to evacuate and remove a node, orphaned configuration entries remained in node subsections such as `hostname.app.github`. + - | + On instances with multiple data disks configured, administrators who ran `ghe-restore` encountered an error message: `Runtime error (func=(main), adr=10): Divide by zero`. + - | + For administrators using the Backup Service to back up a high availability (HA) appliance from the replica with GitHub Actions enabled, MSSQL backups would fail with the error `This command can only be run on the primary mssql node.` + - | + When running `ghe-backup` on an instance configured with the Backup Service, the `data` directory inside the backups mountpoint (usually `/data/backup/data`) failed to be automatically created due to missing permissions. + - | + On instances processing webhooks, notifications, or other background events, the `github-stream-processors` Nomad job consumed increasing memory and processed events progressively more slowly the longer it ran, requiring site administrators to restart the job to restore baseline throughput. + - | + Administrators experienced gradual memory growth in long-running GitHub Enterprise Server background event processor services. Upgrading resets service-mapping context between messages, and administrators do not need to take any action after upgrading. + changes: + - | + To reduce response times for repositories with a large number of code scanning alerts, GitHub Enterprise Server uses an optimized query when counting alerts. + - | + Site administrators can include Enterprise Live Migrations (ELM) Exporter appliance data in scheduled backups using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + - | + Site administrators can restore Enterprise Live Migrations (ELM) Exporter appliance data using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + known_issues: + - | + During an upgrade of GitHub Enterprise Server, custom firewall rules are removed. If you use custom firewall rules, you must reapply them after upgrading. + - | + During the validation phase of a configuration run, a `No such object` error may occur for the Notebook and Viewscreen services. This error can be ignored as the services should still correctly start. + - | + If the root site administrator is locked out of the Management Console after failed login attempts, the account does not unlock automatically after the defined lockout time. Someone with administrative SSH access to the instance must unlock the account using the administrative shell. For more information, see [Troubleshooting access to the Management Console](/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/troubleshooting-access-to-the-management-console#unlocking-the-root-site-administrator-account). + - | + On an instance with the HTTP `X-Forwarded-For` header configured for use behind a load balancer, all client IP addresses in the instance's audit log erroneously appear as 127.0.0.1. + - | + {% data reusables.release-notes.large-adoc-files-issue %} + - | + Admin stats REST API endpoints may time out on appliances with many users or repositories. Retrying the request until data is returned is advised. + - | + When following the steps for [Replacing the primary MySQL node](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-the-primary-mysql-node), step 14 (running `ghe-cluster-config-apply`) might fail with errors. If this occurs, re-running `ghe-cluster-config-apply` is expected to succeed. + - | + Running a config apply as part of the steps for [Replacing a node in an emergency](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-a-node-in-an-emergency) may fail with errors if the node being replaced is still reachable. If this occurs, shutdown the node and repeat the steps. + - | + {% data reusables.release-notes.2024-06-possible-frontend-5-minute-outage-during-hotpatch-upgrade %} + - | + When restoring data originally backed up from a 3.13 or later appliance version, the Elasticsearch indices need to be reindexed before some of the data will show up. This happens via a nightly scheduled job. It can also be forced by running `/usr/local/share/enterprise/ghe-es-search-repair`. + - | + An organization-level code scanning configuration page is displayed on instances that do not use GitHub Advanced Security or code scanning. + - | + When enabling automatic update checks for the first time in the Management Console, the status is not dynamically reflected until the "Updates" page is reloaded. + - | + When restoring from a backup snapshot, a large number of `mapper_parsing_exception` errors may be displayed. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + In a cluster, the host running restore requires access the storage nodes via their private IPs. + - | + On an instance hosted on Azure, commenting on an issue via email meant the comment was not added to the issue. + - | + After a restore, existing outside collaborators cannot be added to repositories in a new organization. This issue can be resolved by running `/usr/local/share/enterprise/ghe-es-search-repair` on the appliance. + - | + After a geo-replica is promoted to be a primary by running `ghe-repl-promote`, the GitHub Actions workflow of a repository does not have any suggested workflows. + - | + Unexpected elements may appear in the UI on the repository overview page for locked repositories. + - | + When publishing npm packages in a workflow after restoring from a backup to GitHub Enterprise Server 3.13.5.gm4 or 3.14.2.gm3, you may encounter a `401 Unauthorized` error from the GitHub Packages service. This can happen if the restore is from an N-1 or N-2 version and the workflow targets the npm endpoint on the backup instance. To avoid this issue, ensure the access token is valid and includes the correct scopes for publishing to GitHub Packages. + - | + The setting to define private registries at the organization level for code scanning is only available if Dependabot is also enabled for the instance. + - | + Custom NTP settings are removed during the upgrade process. + - | + When applying an enterprise security configuration to all repositories (for example, enabling Secret Scanning or Code Scanning across all repositories), the system immediately enqueues enablement jobs for every organization in the enterprise simultaneously. For enterprises with a large number of repositories, this can result in significant system load and potential performance degradation. If you manage a large enterprise with many organizations and repositories, we recommend applying security configurations at the organization level rather than at the enterprise level in the UI. This allows you to enable security features incrementally and monitor system performance as you roll out changes. + - | + Administrators upgrading to certain patch releases encountered a "Failed to generate an OIDC token" error during the `Update Servicing Resources` step when GitHub Actions was configured with Google Cloud Storage (GCS) or AWS S3 using OpenID Connect (OIDC) authentication. The upgrade was blocked and could not complete. To work around this issue, administrators could apply a manual patch by running `sudo sed -i.bak 's|ghe-actions-console -s -c Update-Service|ghe-actions-console -s --no-blob-creds -c Update-Service|g' /usr/local/bin/ghe-actions-update` followed by `ghe-config-apply`. diff --git a/data/release-notes/enterprise-server/3-19/8.yml b/data/release-notes/enterprise-server/3-19/8.yml new file mode 100644 index 000000000000..dd6bae2b2ba5 --- /dev/null +++ b/data/release-notes/enterprise-server/3-19/8.yml @@ -0,0 +1,98 @@ +date: '2026-06-30' +sections: + security_fixes: + - | + **HIGH**: Current configurations of the GitHub API access controls could allow an attacker to create issues in any public repository via a u2s token without requiring the underlying installation to have issues write permission. This therefore allows an attacker to impersonate the victim in public repositories by creating issues and commit comments. + - | + **MEDIUM**: An attacker with site administrator privileges could extract arbitrary data from the instance's database, including user password hashes, by exploiting a blind SQL injection vulnerability in the `dependenciesPrefers` argument of the `dependencyGraphManifests` GraphQL field. This vulnerability affected instances with the dependency graph enabled and was reported via the GitHub Bug Bounty program. + - | + **MEDIUM**: An attacker could gain unintended access to an organization's runner management by directing a user to authorize an OAuth app whose requested manage_runners:org scope was not displayed on the authorization consent screen. GitHub has requested CVE ID [CVE-2026-9106](https://www.cve.org/cverecord?id=CVE-2026-9106) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + **MEDIUM**: An authenticated GHES user could read source code from private repositories they did not have access to by supplying a cross-repository comparison range to the Copilot pull request description diff summary endpoint, which did not verify the user's permission to view the target repository. GitHub has requested CVE ID [CVE-2026-9132](https://www.cve.org/cverecord?id=CVE-2026-9132) for this vulnerability, which was reported via the [GitHub Bug Bounty program](https://bounty.github.com/). + - | + **MEDIUM**: An attacker could execute arbitrary JavaScript in a victim's browser on a GitHub Enterprise Server instance by creating a discussion in the Q\&A category with a crafted title that breaks out of the JSON-LD structured-data script block when a comment is marked as the answer. To mitigate this issue, GitHub has updated the rendering of JSON-LD structured data in discussions to properly escape user-controlled input. GitHub has requested CVE ID [CVE-2026-10585](https://www.cve.org/cverecord?id=CVE-2026-10585) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + GitHub has updated `dnsmasq` to fix the following vulnerabilities: CVE-2026-4891, CVE-2026-4890, CVE-2026-4892, CVE-2026-4893, CVE-2026-5172, CVE-2026-2291. + - | + Packages have been updated to the latest security versions. + bugs: + - | + Administrators experienced "Permission denied" errors when the `ghes-manage-agent` attempted to write logs under `/var/log/license-upgrade` during license upgrade restart tasks. + - | + After administrators updated a GitHub Enterprise Server instance's TLS certificate, GitHub Pages deployments failed because the necessary services did not restart when `ghe-config-apply` was run. + - | + When uploading an invalid or expired license in the Management Console, the page would not correctly indicate the failure and restart the page without any additional information. + - | + On an instance with Enterprise Live Migrations enabled, running `/usr/local/bin/elm` without arguments dropped into a degraded container shell where standard administrative commands were unavailable. + - | + The scheduled job that repairs search indexes could run long enough that its next execution interrupted the in-progress repair, causing the process to restart before completing. The job used a locking mechanism to prevent overlapping runs and was scheduled to run once per month, on the first Saturday, instead of weekly. + - | + When a site administrator ran `ghe-remove-node` to evacuate and remove a node, orphaned configuration entries remained in node subsections such as `hostname.app.github`. + - | + On instances with multiple data disks configured, administrators who ran `ghe-restore` encountered an error message: `Runtime error (func=(main), adr=10): Divide by zero`. + - | + For administrators using the Backup Service to back up a high availability (HA) appliance from the replica with GitHub Actions enabled, MSSQL backups would fail with the error `This command can only be run on the primary mssql node.` + - | + When running `ghe-backup` on an instance configured with the Backup Service, the `data` directory inside the backups mountpoint (usually `/data/backup/data`) failed to be automatically created due to missing permissions. + - | + On instances processing webhooks, notifications, or other background events, the `github-stream-processors` Nomad job consumed increasing memory and processed events progressively more slowly the longer it ran, requiring site administrators to restart the job to restore baseline throughput. + - | + Administrators experienced gradual memory growth in long-running GitHub Enterprise Server background event processor services. Upgrading resets service-mapping context between messages, and administrators do not need to take any action after upgrading. + - | + On an instance with dependency graph enabled, dependency snapshot uploads via the dependency submission API occasionally failed with internal server errors. + - | + On instances without a GitHub Advanced Security license, the organization Dependabot dashboard in Security Overview returned a 404 error, even though Dependabot is available on those instances. + - | + On an instance with GitHub Code Security enabled, users could bypass code scanning merge protection when the scan had passed on an earlier commit but had not yet run on the latest commit of a pull request. + changes: + - | + To reduce response times for repositories with a large number of code scanning alerts, GitHub Enterprise Server uses an optimized query when counting alerts. + - | + Site administrators can include Enterprise Live Migrations (ELM) Exporter appliance data in scheduled backups using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + - | + Site administrators can restore Enterprise Live Migrations (ELM) Exporter appliance data using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + known_issues: + - | + During an upgrade of GitHub Enterprise Server, custom firewall rules are removed. If you use custom firewall rules, you must reapply them after upgrading. + - | + During the validation phase of a configuration run, a `No such object` error may occur for the Notebook and Viewscreen services. This error can be ignored as the services should still correctly start. + - | + If the root site administrator is locked out of the Management Console after failed login attempts, the account does not unlock automatically after the defined lockout time. Someone with administrative SSH access to the instance must unlock the account using the administrative shell. For more information, see [Troubleshooting access to the Management Console](/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/troubleshooting-access-to-the-management-console#unlocking-the-root-site-administrator-account). + - | + {% data reusables.release-notes.large-adoc-files-issue %} + - | + Admin stats REST API endpoints may timeout on appliances with many users or repositories. Retrying the request until data is returned is advised. + - | + When following the steps for [Replacing the primary MySQL node](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-the-primary-mysql-node), step 14 (running `ghe-cluster-config-apply`) might fail with errors. If this occurs, re-running `ghe-cluster-config-apply` is expected to succeed. + - | + Running a config apply as part of the steps for [Replacing a node in an emergency](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-a-node-in-an-emergency) may fail with errors if the node being replaced is still reachable. If this occurs, shutdown the node and repeat the steps. + - | + {% data reusables.release-notes.2024-06-possible-frontend-5-minute-outage-during-hotpatch-upgrade %} + - | + When restoring data originally backed up from a 3.13 or greater appliance version, the Elasticsearch indices need to be reindexed before some of the data will show up. This happens via a nightly scheduled job. It can also be forced by running `/usr/local/share/enterprise/ghe-es-search-repair`. + - | + When enabling automatic update checks for the first time in the Management Console, the status is not dynamically reflected until the "Updates" page is reloaded. + - | + When restoring from a backup snapshot, a large number of `mapper_parsing_exception` errors may be displayed. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + In a cluster, the host running restore requires access the storage nodes via their private IPs. + - | + On an instance hosted on Azure, commenting on an issue via email means the comment is not added to the issue. + - | + After a restore, existing outside collaborators cannot be added to repositories in a new organization. This issue can be resolved by running `/usr/local/share/enterprise/ghe-es-search-repair` on the appliance. + - | + After a geo-replica is promoted to be a primary by running `ghe-repl-promote`, the GitHub Actions workflow of a repository does not have any suggested workflows. + - | + When publishing npm packages in a workflow after restoring from a backup to GitHub Enterprise Server 3.13.5.gm4 or 3.14.2.gm3, you may encounter a `401 Unauthorized` error from the GitHub Packages service. This can happen if the restore is from an N-1 or N-2 version and the workflow targets the npm endpoint on the backup instance. To avoid this issue, ensure the access token is valid and includes the correct scopes for publishing to GitHub Packages. + - | + The setting to define private registries at the organization level for code scanning is only available if Dependabot is also enabled for the instance. + - | + Upgrading or hotpatching to 3.19.1 may fail on nodes that have been continuously upgraded from versions older than 2021 (i.e. 2.17). If this issue occurs, you will see log entries prefixed with `invalid secret` in ghe-config.log. If you are running nodes from these older versions, it is recommended not to upgrade to 3.19.1. + - | + An issue in the Management Console means the Backups (Preview) and Updates tabs may fail to open and instead return an Internal Server Error. We recommend using the command line interface (CLI) for backups and updates. + - | + When applying an enterprise security configuration to all repositories (for example, enabling Secret Scanning or Code Scanning across all repositories), the system immediately enqueues enablement jobs for every organization in the enterprise simultaneously. For enterprises with a large number of repositories, this can result in significant system load and potential performance degradation. If you manage a large enterprise with many organizations and repositories, we recommend applying security configurations at the organization level rather than at the enterprise level in the UI. This allows you to enable security features incrementally and monitor system performance as you roll out changes. + - | + Administrators upgrading to certain patch releases encountered a "Failed to generate an OIDC token" error during the `Update Servicing Resources` step when GitHub Actions was configured with Google Cloud Storage (GCS) or AWS S3 using OpenID Connect (OIDC) authentication. The upgrade was blocked and could not complete. To work around this issue, administrators could apply a manual patch by running `sudo sed -i.bak 's|ghe-actions-console -s -c Update-Service|ghe-actions-console -s --no-blob-creds -c Update-Service|g' /usr/local/bin/ghe-actions-update` followed by `ghe-config-apply`. diff --git a/data/release-notes/enterprise-server/3-20/4.yml b/data/release-notes/enterprise-server/3-20/4.yml new file mode 100644 index 000000000000..7b28892c117d --- /dev/null +++ b/data/release-notes/enterprise-server/3-20/4.yml @@ -0,0 +1,90 @@ +date: '2026-06-30' +sections: + security_fixes: + - | + **HIGH**: Current configurations of the GitHub API access controls could allow an attacker to create issues in any public repository via a u2s token without requiring the underlying installation to have issues write permission. This therefore allows an attacker to impersonate the victim in public repositories by creating issues and commit comments. + - | + **MEDIUM**: An attacker with site administrator privileges could extract arbitrary data from the instance's database, including user password hashes, by exploiting a blind SQL injection vulnerability in the `dependenciesPrefers` argument of the `dependencyGraphManifests` GraphQL field. This vulnerability affected instances with the dependency graph enabled and was reported via the GitHub Bug Bounty program. + - | + **MEDIUM**: An attacker could gain unintended access to an organization's runner management by directing a user to authorize an OAuth app whose requested manage_runners:org scope was not displayed on the authorization consent screen. GitHub has requested CVE ID [CVE-2026-9106](https://www.cve.org/cverecord?id=CVE-2026-9106) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + **MEDIUM**: An authenticated GHES user could read source code from private repositories they did not have access to by supplying a cross-repository comparison range to the Copilot pull request description diff summary endpoint, which did not verify the user's permission to view the target repository. GitHub has requested CVE ID [CVE-2026-9132](https://www.cve.org/cverecord?id=CVE-2026-9132) for this vulnerability, which was reported via the [GitHub Bug Bounty program](https://bounty.github.com/). + - | + **MEDIUM**: An attacker could execute arbitrary JavaScript in a victim's browser on a GitHub Enterprise Server instance by creating a discussion in the Q\&A category with a crafted title that breaks out of the JSON-LD structured-data script block when a comment is marked as the answer. To mitigate this issue, GitHub has updated the rendering of JSON-LD structured data in discussions to properly escape user-controlled input. GitHub has requested CVE ID [CVE-2026-10585](https://www.cve.org/cverecord?id=CVE-2026-10585) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + GitHub has updated `dnsmasq` to fix the following vulnerabilities: CVE-2026-4891, CVE-2026-4890, CVE-2026-4892, CVE-2026-4893, CVE-2026-5172, CVE-2026-2291. + - | + Packages have been updated to the latest security versions. + - | + Upgraded the Notebooks container base image from Ubuntu Focal (20.04) to Noble (24.04) for continued security support. + bugs: + - | + Administrators experienced "Permission denied" errors when the `ghes-manage-agent` attempted to write logs under `/var/log/license-upgrade` during license upgrade restart tasks. + - | + When uploading an invalid or expired license in the Management Console, the page would not correctly indicate the failure and restart the page without any additional information. + - | + After administrators updated a GitHub Enterprise Server instance's TLS certificate, GitHub Pages deployments failed because the necessary services did not restart when `ghe-config-apply` was run. + - | + On an instance with Enterprise Live Migrations enabled, running `/usr/local/bin/elm` without arguments dropped into a degraded container shell where standard administrative commands were unavailable. + - | + The scheduled job that repairs search indexes could run long enough that its next execution interrupted the in-progress repair, causing the process to restart before completing. The job used a locking mechanism to prevent overlapping runs and was scheduled to run once per month, on the first Saturday, instead of weekly. + - | + When a site administrator ran `ghe-remove-node` to evacuate and remove a node, orphaned configuration entries remained in node subsections such as `hostname.app.github`. + - | + Administrators who had upgraded to GHES 3.20 or later saw validation errors when running a `config-apply`. This is because the required backup service configuration was not populated in `github.conf` during the upgrade. + - | + On instances with multiple data disks configured, administrators who ran `ghe-restore` encountered an error message: `Runtime error (func=(main), adr=10): Divide by zero`. + - | + For administrators using the Backup Service to back up a high availability (HA) appliance from the replica with GitHub Actions enabled, MSSQL backups would fail with the error `This command can only be run on the primary mssql node.` + - | + When running `ghe-backup` on an instance configured with the Backup Service, the `data` directory inside the backups mountpoint (usually `/data/backup/data`) failed to be automatically created due to missing permissions. + - | + Administrators experienced gradual memory growth in long-running GitHub Enterprise Server background event processor services. Upgrading resets service-mapping context between messages, and administrators do not need to take any action after upgrading. + - | + Submitting a dependency snapshot via the REST API could return a 500 internal server error instead of a successful response. + - | + On instances without a GitHub Advanced Security license, the organization Dependabot dashboard in Security Overview returned a 404 error, even though Dependabot is available on those instances. + - | + On an instance with GitHub Code Security enabled, users could bypass code scanning merge protection when the scan had passed on an earlier commit but had not yet run on the latest commit of a pull request. + changes: + - | + To reduce response times for repositories with a large number of code scanning alerts, GitHub Enterprise Server uses an optimized query when counting alerts. + - | + Site administrators can include Enterprise Live Migrations (ELM) Exporter appliance data in scheduled backups using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + - | + Site administrators can restore Enterprise Live Migrations (ELM) Exporter appliance data using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + known_issues: + - | + During an upgrade of GitHub Enterprise Server, custom firewall rules are removed. If you use custom firewall rules, you must reapply them after upgrading. + - | + During the validation phase of a configuration run, a `No such object` error may occur for the Notebook and Viewscreen services. This error can be ignored as the services should still correctly start. + - | + If the root site administrator is locked out of the Management Console after failed login attempts, the account does not unlock automatically after the defined lockout time. Someone with administrative SSH access to the instance must unlock the account using the administrative shell. For more information, see [Troubleshooting access to the Management Console](/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/troubleshooting-access-to-the-management-console#unlocking-the-root-site-administrator-account). + - | + {% data reusables.release-notes.large-adoc-files-issue %} + - | + Admin stats REST API endpoints may time out on appliances with many users or repositories. Retrying the request until data is returned is advised. + - | + When following the steps for [Replacing the primary MySQL node](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-the-primary-mysql-node), step 14 (running `ghe-cluster-config-apply`) might fail with errors. If this occurs, re-running `ghe-cluster-config-apply` is expected to succeed. + - | + Running a config apply as part of the steps for [Replacing a node in an emergency](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-a-node-in-an-emergency) may fail with errors if the node being replaced is still reachable. If this occurs, shutdown the node and repeat the steps. + - | + When restoring data originally backed up from a 3.13 or later appliance version, the Elasticsearch indices need to be reindexed before some of the data will show up. This happens via a nightly scheduled job. It can also be forced by running `/usr/local/share/enterprise/ghe-es-search-repair`. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + In a cluster, the host running restore requires access the storage nodes via their private IPs. + - | + On an instance hosted on Azure, commenting on an issue via email means the comment is not added to the issue. + - | + After a restore, existing outside collaborators cannot be added to repositories in a new organization. This issue can be resolved by running `/usr/local/share/enterprise/ghe-es-search-repair` on the appliance. + - | + After a geo-replica is promoted to be a primary by running `ghe-repl-promote`, the GitHub Actions workflow of a repository does not have any suggested workflows. + - | + When publishing npm packages in a workflow after restoring from a backup to GitHub Enterprise Server 3.13.5.gm4 or 3.14.2.gm3, you may encounter a `401 Unauthorized` error from the GitHub Packages service. This can happen if the restore is from an N-1 or N-2 version and the workflow targets the npm endpoint on the backup instance. To avoid this issue, ensure the access token is valid and includes the correct scopes for publishing to GitHub Packages. + - | + When applying an enterprise security configuration to all repositories (for example, enabling Secret Scanning or Code Scanning across all repositories), the system immediately enqueues enablement jobs for every organization in the enterprise simultaneously. For enterprises with a large number of repositories, this can result in significant system load and potential performance degradation. If you manage a large enterprise with many organizations and repositories, we recommend applying security configurations at the organization level rather than at the enterprise level in the UI. This allows you to enable security features incrementally and monitor system performance as you roll out changes. + - | + On instances with multiple Git storage nodes in a voting configuration, including cluster and geo-replication high availability topologies, upgrading may fail to correctly install Actions that ship with the new version. In some cases, previous versions of these Actions remain on the instance. To resolve this issue, run the following commands on the primary node: `ghe-config --unset 'app.actions.actions-repos-sha1sum'`, `ghe-config-apply`, and `/usr/local/share/enterprise/ghe-run-init-actions-graph`. + - | + Administrators upgrading to certain patch releases encountered a "Failed to generate an OIDC token" error during the `Update Servicing Resources` step when GitHub Actions was configured with Google Cloud Storage (GCS) or AWS S3 using OpenID Connect (OIDC) authentication. The upgrade was blocked and could not complete. To work around this issue, administrators could apply a manual patch by running `sudo sed -i.bak 's|ghe-actions-console -s -c Update-Service|ghe-actions-console -s --no-blob-creds -c Update-Service|g' /usr/local/bin/ghe-actions-update` followed by `ghe-config-apply`. diff --git a/data/release-notes/enterprise-server/3-21/2.yml b/data/release-notes/enterprise-server/3-21/2.yml new file mode 100644 index 000000000000..bf0e3af4d0a1 --- /dev/null +++ b/data/release-notes/enterprise-server/3-21/2.yml @@ -0,0 +1,94 @@ +date: '2026-06-30' +sections: + features: + - | + You can now run the pre-upgrade stage of an upgrade outside the maintenance window using `ghe-upgrade --phase pre-upgrade -y UPGRADE-PACKAGE-FILENAME`. Running the pre-upgrade stage in advance can reduce in-maintenance upgrade time by up to 20 minutes. For more information, see [AUTOTITLE](/admin/administering-your-instance/administering-your-instance-from-the-command-line/command-line-utilities#ghe-upgrade). Additional functionality and documentation will be available when you upgrade to 3.22 and later versions. + security_fixes: + - | + **HIGH**: Current configurations of the GitHub API access controls could allow an attacker to create issues in any public repository via a u2s token without requiring the underlying installation to have issues write permission. This therefore allows an attacker to impersonate the victim in public repositories by creating issues and commit comments. + - | + **MEDIUM**: An attacker with site administrator privileges could extract arbitrary data from the instance's database, including user password hashes, by exploiting a blind SQL injection vulnerability in the `dependenciesPrefers` argument of the `dependencyGraphManifests` GraphQL field. This vulnerability affected instances with the dependency graph enabled and was reported via the GitHub Bug Bounty program. + - | + **MEDIUM**: An attacker could gain unintended access to an organization's runner management by directing a user to authorize an OAuth app whose requested manage_runners:org scope was not displayed on the authorization consent screen. GitHub has requested CVE ID [CVE-2026-9106](https://www.cve.org/cverecord?id=CVE-2026-9106) for this vulnerability, which was reported via the [GitHub Bug Bounty](https://bounty.github.com/) program. + - | + GitHub has updated `dnsmasq` to fix the following vulnerabilities: CVE-2026-4891, CVE-2026-4890, CVE-2026-4892, CVE-2026-4893, CVE-2026-5172, CVE-2026-2291. + - | + Packages have been updated to the latest security versions. + bugs: + - | + After administrators updated a GitHub Enterprise Server instances TLS certificate, GitHub Pages deployments failed because the necessary services did not restart when `ghe-config-apply` was run. + - | + When uploading an invalid or expired license in the Management Console, the page would not correctly indicate the failure and restart the page without any additional information. + - | + On an instance with Enterprise Live Migrations enabled, running `/usr/local/bin/elm` without arguments dropped into a degraded container shell where standard administrative commands were unavailable. + - | + On instances with multiple data disks configured, administrators who ran `ghe-restore` encountered an error message: `Runtime error (func=(main), adr=10): Divide by zero`. + - | + The scheduled job that repairs search indexes could run long enough that its next execution interrupted the in-progress repair, causing the process to restart before completing. The job now uses a locking mechanism to prevent overlapping runs and is scheduled to run once per month, on the first Saturday, instead of weekly. + - | + When a site administrator ran `ghe-remove-node` to evacuate and remove a node, orphaned configuration entries remained in node subsections such as `hostname.app.github`. + - | + Administrators who had upgraded to GHES 3.20 or later saw validation errors when running a `config-apply`. This is because the required backup service configuration was not populated in `github.conf` during the upgrade. + - | + For administrators using the Backup Service to back up a high availability (HA) appliance from the replica with GitHub Actions enabled, MSSQL backups would fail with the error `This command can only be run on the primary mssql node.` + - | + When running `ghe-backup` on an instance configured with the Backup Service, the `data` directory inside the backups mountpoint (usually `/data/backup/data`) failed to be automatically created due to missing permissions. + - | + Administrators experienced gradual memory growth in long-running GitHub Enterprise Server background event processor services. Upgrading resets service-mapping context between messages, and administrators do not need to take any action after upgrading. + - | + On instances without a GitHub Advanced Security license, the organization Dependabot dashboard in Security Overview returned a 404 error, even though Dependabot is available on those instances. + - | + On an instance with GitHub Code Security enabled, users could bypass code scanning merge protection when the scan had passed on an earlier commit but had not yet run on the latest commit of a pull request. + - | + When a user viewed an issue or pull request containing image attachments, the images could appear broken after the page had been open or idle for several minutes, and reloading the page was required to display them again. + changes: + - | + The default `maxconn` (maximum connections) value for HAProxy has increased from 1,024 to 8,192 across all proxies. Previously, large customers reported surpassing the limit on high-traffic services. + - | + Administrators who forward GitHub Enterprise Server logs to external syslog systems can now configure syslog forwarding to use RFC 5424 formatting with microsecond-precision timestamps. This improves event ordering and correlation in SIEM and monitoring systems. To enable this format, run `ghe-config syslog.format RFC5424` and `ghe-config-apply`. + - | + To reduce response times for repositories with a large number of code scanning alerts, GitHub Enterprise Server uses an optimized query when counting alerts. + - | + Site administrators can include Enterprise Live Migrations (ELM) Exporter appliance data in scheduled backups using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + - | + Site administrators can restore Enterprise Live Migrations (ELM) Exporter appliance data using GitHub Enterprise Server Backup Service. For more information, see [AUTOTITLE](/admin/backing-up-and-restoring-your-instance). + known_issues: + - | + During an upgrade of GitHub Enterprise Server, custom firewall rules are removed. If you use custom firewall rules, you must reapply them after upgrading. + - | + During the validation phase of a configuration run, a `No such object` error may occur for the Notebook and Viewscreen services. This error can be ignored as the services should still correctly start. + - | + If the root site administrator is locked out of the Management Console after failed login attempts, the account does not unlock automatically after the defined lockout time. Someone with administrative SSH access to the instance must unlock the account using the administrative shell. For more information, see [Troubleshooting access to the Management Console](/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/troubleshooting-access-to-the-management-console#unlocking-the-root-site-administrator-account). + - | + {% data reusables.release-notes.large-adoc-files-issue %} + - | + Admin stats REST API endpoints may timeout on appliances with many users or repositories. Retrying the request until data is returned is advised. + - | + When following the steps for [Replacing the primary MySQL node](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-the-primary-mysql-node), step 14 (running `ghe-cluster-config-apply`) might fail with errors. If this occurs, re-running `ghe-cluster-config-apply` is expected to succeed. + - | + Running a config apply as part of the steps for [Replacing a node in an emergency](/admin/monitoring-managing-and-updating-your-instance/configuring-clustering/replacing-a-cluster-node#replacing-a-node-in-an-emergency) may fail with errors if the node being replaced is still reachable. If this occurs, shutdown the node and repeat the steps. + - | + When restoring data originally backed up from a 3.13 or greater appliance version, the Elasticsearch indices need to be reindexed before some of the data will show up. This happens via a nightly scheduled job. It can also be forced by running `/usr/local/share/enterprise/ghe-es-search-repair`. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + When initializing a new GHES cluster, nodes with the `consul-server` role should be added to the cluster before adding additional nodes. Adding all nodes simultaneously creates a race condition between nomad server registration and nomad client registration. + - | + In a cluster, the host running restore requires access the storage nodes via their private IPs. + - | + On an instance hosted on Azure, commenting on an issue via email meant the comment was not added to the issue. + - | + After a restore, existing outside collaborators cannot be added to repositories in a new organization. This issue can be resolved by running `/usr/local/share/enterprise/ghe-es-search-repair` on the appliance. + - | + After a geo-replica is promoted to be a primary by running `ghe-repl-promote`, the actions workflow of a repository does not have any suggested workflows. + - | + When publishing npm packages in a workflow after restoring from a backup to GitHub Enterprise Server 3.13.5.gm4 or 3.14.2.gm3, you may encounter a `401 Unauthorized` error from the GitHub Packages service. This can happen if the restore is from an N-1 or N-2 version and the workflow targets the npm endpoint on the backup instance. To avoid this issue, ensure the access token is valid and includes the correct scopes for publishing to GitHub Packages. + - | + When applying an enterprise security configuration to all repositories (for example, enabling Secret Scanning or Code Scanning across all repositories), the system immediately enqueues enablement jobs for every organization in the enterprise simultaneously. For enterprises with a large number of repositories, this can result in significant system load and potential performance degradation. If you manage a large enterprise with many organizations and repositories, we recommend applying security configurations at the organization level rather than at the enterprise level in the UI. This allows you to enable security features incrementally and monitor system performance as you roll out changes. + - | + On instances with multiple Git storage nodes in a voting configuration, including cluster and geo-replication high availability topologies, upgrading may fail to correctly install Actions that ship with the new version. In some cases, previous versions of these Actions remain on the instance. To resolve this issue, run the following commands on the primary node: `ghe-config --unset 'app.actions.actions-repos-sha1sum'`, `ghe-config-apply`, and `/usr/local/share/enterprise/ghe-run-init-actions-graph`. + - | + Users attempting to clone repositories via HTTPS receive an "Internal Server Error" message, and the clone operation fails with a 500 error. This issue affects all deployment topologies including cluster, standalone, high availability, and geo-replication configurations. + errata: + - | + A note about running the pre-upgrade stage outside the maintenance window has been added to the release notes. [Updated: 2026-06-30] diff --git a/data/reusables/elm/locked-repo.md b/data/reusables/elm/locked-repo.md index 7cd9ef640042..4377959ca7f7 100644 --- a/data/reusables/elm/locked-repo.md +++ b/data/reusables/elm/locked-repo.md @@ -1,5 +1,5 @@ -If a cutover fails partway through, the source repository may remain locked or archived. This prevents developers from pushing to the source while the destination may still be incomplete. +If a cutover fails after the source repository has been archived, the {% data variables.product.prodname_elm_short %} service will attempt to unarchive the repository. If this fails, a repository administrator can unarchive the repository. See [AUTOTITLE](/repositories/archiving-a-github-repository/archiving-repositories#unarchiving-a-repository). -To unlock the source repository, a site administrator must unlock it from the {% data variables.product.prodname_ghe_server %} {% data variables.enterprise.management_console %}. +Be aware that unarchiving a repository will cause additional load on the instance, as all issues and pull requests in the repository will be reindexed in Elasticsearch. -After the source is unlocked, you can either retry cutover using `elm migration cutover-to-destination --migration-id MIGRATION-ID`, or abort the migration with `elm migration cancel --migration-id MIGRATION-ID` and start a new migration when you're ready. +After the source repository is unarchived, you can either retry cutover using `elm migration cutover-to-destination --migration-id MIGRATION-ID`, or abort the migration with `elm migration cancel --migration-id MIGRATION-ID` and start a new migration when you're ready. diff --git a/data/reusables/organizations/types-of-team-visibility.md b/data/reusables/organizations/types-of-team-visibility.md index 36b0228741c1..0a73d2f6446f 100644 --- a/data/reusables/organizations/types-of-team-visibility.md +++ b/data/reusables/organizations/types-of-team-visibility.md @@ -1,6 +1,6 @@ Teams can be visible or secret: * Visible teams can be [viewed and @mentioned](/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#mentioning-people-and-teams) by every organization member. -* Secret teams are only visible to the people on the team and people with owner permissions. They're great for hiding teams with sensitive names or members, such as those used for working with external partners or clients. Secret teams cannot be nested under parent teams or have child teams. +* Secret teams are only visible to the people on the team and organization owners. They're great for hiding the members of teams that work with external partners or clients. However, if a team member or organization owner mentions a secret team, the team name is visible in the mention text. Secret teams cannot be nested under parent teams or have child teams. People who are not members of the organization cannot view any teams. diff --git a/data/tables/copilot/model-comparison.yml b/data/tables/copilot/model-comparison.yml index 0ab19e0b16db..109577762406 100644 --- a/data/tables/copilot/model-comparison.yml +++ b/data/tables/copilot/model-comparison.yml @@ -68,6 +68,11 @@ excels_at: Complex problem-solving challenges, sophisticated reasoning further_reading: '[Claude Sonnet 4.6 model card](https://www-cdn.anthropic.com/78073f739564e986ff3e28522761a7a0b4484f84.pdf)' +- name: Claude Sonnet 5 + task_area: General-purpose coding and agent tasks + excels_at: Complex problem-solving challenges, sophisticated reasoning + further_reading: 'Not available' + # Google - name: Gemini 2.5 Pro task_area: Deep reasoning and debugging diff --git a/data/tables/copilot/model-release-status.yml b/data/tables/copilot/model-release-status.yml index b291035bf752..9e05c227c2f7 100644 --- a/data/tables/copilot/model-release-status.yml +++ b/data/tables/copilot/model-release-status.yml @@ -40,6 +40,11 @@ release_status: 'GA' # Anthropic models + +- name: 'Claude Fable 5' + provider: 'Anthropic' + release_status: 'GA' + - name: 'Claude Haiku 4.5' provider: 'Anthropic' release_status: 'GA' @@ -64,15 +69,15 @@ provider: 'Anthropic' release_status: 'GA' -- name: 'Claude Fable 5' +- name: 'Claude Sonnet 4.5' provider: 'Anthropic' release_status: 'GA' -- name: 'Claude Sonnet 4.5' +- name: 'Claude Sonnet 4.6' provider: 'Anthropic' release_status: 'GA' -- name: 'Claude Sonnet 4.6' +- name: 'Claude Sonnet 5' provider: 'Anthropic' release_status: 'GA' diff --git a/data/tables/copilot/model-supported-clients.yml b/data/tables/copilot/model-supported-clients.yml index f5f9fbe6c10b..0a45d99d394c 100644 --- a/data/tables/copilot/model-supported-clients.yml +++ b/data/tables/copilot/model-supported-clients.yml @@ -95,6 +95,15 @@ xcode: false jetbrains: false +- name: Claude Sonnet 5 + dotcom: true + cli: true + vscode: true + vs: true + eclipse: false + xcode: false + jetbrains: false + - name: Gemini 2.5 Pro dotcom: false cli: false diff --git a/data/tables/copilot/model-supported-plans.yml b/data/tables/copilot/model-supported-plans.yml index f3d3e95e7310..dd0c20882c86 100644 --- a/data/tables/copilot/model-supported-plans.yml +++ b/data/tables/copilot/model-supported-plans.yml @@ -75,6 +75,13 @@ business: true enterprise: true +- name: Claude Sonnet 5 + pro: true + pro_plus: true + max: true + business: true + enterprise: true + - name: Gemini 2.5 Pro pro: true pro_plus: true diff --git a/data/tables/copilot/models-and-pricing.yml b/data/tables/copilot/models-and-pricing.yml index dd6592b523ea..81a37cde4281 100644 --- a/data/tables/copilot/models-and-pricing.yml +++ b/data/tables/copilot/models-and-pricing.yml @@ -171,6 +171,15 @@ output: $25.00 cache_write: $6.25 +- model: Claude Sonnet 5[^sonnet-5-promo] + provider: anthropic + release_status: GA + category: Versatile + input: $2.00 + cached_input: $0.20 + output: $10.00 + cache_write: $2.50 + - model: Claude Opus 4.8 (fast mode) (preview) provider: anthropic release_status: GA diff --git a/data/ui.yml b/data/ui.yml index 4eba450206e8..3c0042112d20 100644 --- a/data/ui.yml +++ b/data/ui.yml @@ -54,7 +54,7 @@ search: search_docs_with_query: Search docs for "{{query}}" privacy_disclaimer: For product and service improvement purposes, the GitHub Docs team will retain questions and answers generated in the Docs search function. Please see the GitHub Privacy Statement to review how GitHub collects and uses your data. ai: - disclaimer: Copilot uses AI. Check for mistakes. + disclaimer: Copilot uses AI. Check for mistakes. references: Copilot Sources loading_status_message: Loading Copilot response... done_loading_status_message: Done loading Copilot response diff --git a/data/variables/copilot.yml b/data/variables/copilot.yml index 2e05c6c4ead3..ad3c0c7fbfff 100644 --- a/data/variables/copilot.yml +++ b/data/variables/copilot.yml @@ -202,6 +202,7 @@ copilot_claude_sonnet_37: 'Claude Sonnet 3.7' copilot_claude_sonnet_40: 'Claude Sonnet 4' copilot_claude_sonnet_45: 'Claude Sonnet 4.5' copilot_claude_sonnet_46: 'Claude Sonnet 4.6' +copilot_claude_sonnet_5: 'Claude Sonnet 5' # Gemini: copilot_gemini: 'Gemini' copilot_gemini_flash: 'Gemini 2.0 Flash' diff --git a/eslint.config.ts b/eslint.config.ts index 0be658ea7314..4b004441f956 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -103,6 +103,10 @@ export default [ // Custom rules 'custom-rules/use-custom-logger': 'error', + // Disallow dangerouslySetInnerHTML; render trusted HTML via RenderedHTML / + // renderHTMLString or a hast tree instead (github/docs-engineering#6619). + 'custom-rules/no-dangerously-set-inner-html': 'error', + // Prevent direct res.redirect() usage — use res.safeRedirect() instead // to avoid open redirect vulnerabilities via protocol-relative URLs. 'no-restricted-syntax': [ @@ -232,9 +236,10 @@ export default [ }, // Allow role="list" on list-style:none {item.fields && ( <> - + )} diff --git a/src/graphql/components/Mutation.tsx b/src/graphql/components/Mutation.tsx index 7827e6804cfa..28576c70e262 100644 --- a/src/graphql/components/Mutation.tsx +++ b/src/graphql/components/Mutation.tsx @@ -4,6 +4,7 @@ import { Notice } from './Notice' import { useTranslation } from '@/languages/components/useTranslation' import { Table } from './Table' import type { MutationT } from './types' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' import React from 'react' type Props = { @@ -35,7 +36,7 @@ export function Mutation({ item, headingLevel = 2 }: Props) { {input.preview && } {input.isDeprecated && } - +
))} diff --git a/src/graphql/components/Notice.tsx b/src/graphql/components/Notice.tsx index 154447a5a7af..48a69fbed1b6 100644 --- a/src/graphql/components/Notice.tsx +++ b/src/graphql/components/Notice.tsx @@ -2,6 +2,7 @@ import { Link } from '@/frame/components/Link' import { Alert } from '@/frame/components/ui/Alert' import { useTranslation } from '@/languages/components/useTranslation' import type { GraphqlT } from './types' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { item: GraphqlT @@ -25,11 +26,7 @@ export function Notice({ item, variant = 'preview' }: Props) {

{item.name} is deprecated.

-
+
) : null} diff --git a/src/graphql/components/Object.tsx b/src/graphql/components/Object.tsx index 4c1108ba1589..76f62de9a56b 100644 --- a/src/graphql/components/Object.tsx +++ b/src/graphql/components/Object.tsx @@ -3,6 +3,7 @@ import { GraphqlItem, headingTag } from './GraphqlItem' import { Table } from './Table' import { useTranslation } from '@/languages/components/useTranslation' import type { ObjectT, ImplementsT } from './types' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { item: ObjectT @@ -19,7 +20,7 @@ export function Object({ item, headingLevel = 2 }: Props) { {item.implements && ( <> - +
    {item.implements.map((implement: ImplementsT) => (
  • @@ -36,7 +37,7 @@ export function Object({ item, headingLevel = 2 }: Props) { {item.fields && ( <> - +
)} diff --git a/src/graphql/components/Query.tsx b/src/graphql/components/Query.tsx index ed59b5665404..7aa29ec020fc 100644 --- a/src/graphql/components/Query.tsx +++ b/src/graphql/components/Query.tsx @@ -3,6 +3,7 @@ import { GraphqlItem, headingTag } from './GraphqlItem' import { Table } from './Table' import { useTranslation } from '@/languages/components/useTranslation' import type { QueryT } from './types' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { item: QueryT @@ -24,10 +25,9 @@ export function Query({ item, headingLevel = 2 }: Props) { {item.args.length > 0 && ( <> -
diff --git a/src/graphql/components/Table.tsx b/src/graphql/components/Table.tsx index 3610795c5239..3377cce2b091 100644 --- a/src/graphql/components/Table.tsx +++ b/src/graphql/components/Table.tsx @@ -2,6 +2,7 @@ import { Link } from '@/frame/components/Link' import { Notice } from './Notice' import { useTranslation } from '@/languages/components/useTranslation' import { FieldT } from './types' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { fields: FieldT[] @@ -39,15 +40,7 @@ export function Table({ fields }: Props) {

- {field.description ? ( - - ) : ( - 'N/A' - )} + {field.description ? : 'N/A'} {field.defaultValue !== undefined && (

The default value is {field.defaultValue.toString()}. @@ -58,14 +51,10 @@ export function Table({ fields }: Props) { {field.arguments && (

-

{field.arguments.map((argument, index) => (

    )

    - { - - } + {argument.defaultValue !== undefined && (

    The default value is {argument.defaultValue.toString()}. diff --git a/src/journeys/components/JourneyTrackCard.tsx b/src/journeys/components/JourneyTrackCard.tsx index 01183b2e3934..fd8f42c96369 100644 --- a/src/journeys/components/JourneyTrackCard.tsx +++ b/src/journeys/components/JourneyTrackCard.tsx @@ -4,6 +4,7 @@ import { Link } from '@/frame/components/Link' import type { JourneyContext } from '@/journeys/lib/journey-path-resolver' import { useTranslation } from '@/languages/components/useTranslation' import { useVersion } from '@/versions/components/useVersion' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { journey: JourneyContext @@ -48,10 +49,7 @@ export function JourneyTrackCard({ journey }: Props) { )} {journey.alternativeNextStep && ( -

    + )}
diff --git a/src/landings/components/LandingSection.tsx b/src/landings/components/LandingSection.tsx index 35902d4bda7b..9a8917afe19f 100644 --- a/src/landings/components/LandingSection.tsx +++ b/src/landings/components/LandingSection.tsx @@ -1,6 +1,7 @@ import React from 'react' import cx from 'classnames' import { HeadingLink } from '@/frame/components/article/HeadingLink' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { title?: string @@ -18,9 +19,7 @@ export const LandingSection = ({ title, children, className, sectionLink, descri {title} )} - {description && ( -
- )} + {description && }
{children} diff --git a/src/landings/components/ProductSelectionCard.tsx b/src/landings/components/ProductSelectionCard.tsx index ab8653da45eb..0173d6ae7ad4 100644 --- a/src/landings/components/ProductSelectionCard.tsx +++ b/src/landings/components/ProductSelectionCard.tsx @@ -80,7 +80,7 @@ export const ProductSelectionCard = ({ group }: ProductSelectionCardProps) => {
    {group.children.map((product) => { return ( -
  • +
  • {product.name} {product.external && ( diff --git a/src/landings/components/TableOfContents.tsx b/src/landings/components/TableOfContents.tsx index 2ecb62556359..ba8d5a909c3b 100644 --- a/src/landings/components/TableOfContents.tsx +++ b/src/landings/components/TableOfContents.tsx @@ -2,6 +2,7 @@ import React from 'react' import { Link } from '@/frame/components/Link' import type { TocItem } from '@/landings/types' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type Props = { items: Array @@ -27,9 +28,7 @@ export const TableOfContents = (props: Props) => { {title} - {intro && ( -
    - )} + {intro && }
    ) })} @@ -40,26 +39,22 @@ export const TableOfContents = (props: Props) => { const { fullPath, title, childTocItems } = item const filteredChildren = (childTocItems || []).filter(Boolean) return ( -
  • +
  • {title} + + , {index + 1} of {items.length} + {filteredChildren.length > 0 && (
      {filteredChildren.map((childItem, childIndex) => ( -
    • +
    • {childItem.title} + + , {childIndex + 1} of {filteredChildren.length} +
    • ))} diff --git a/src/landings/components/TocLanding.tsx b/src/landings/components/TocLanding.tsx index 67306e8b1a11..f1812f3cde87 100644 --- a/src/landings/components/TocLanding.tsx +++ b/src/landings/components/TocLanding.tsx @@ -26,6 +26,7 @@ export const TocLanding = () => { variant, featuredLinks, renderedPage, + renderedPageHast, permissions, } = useTocLandingContext() const { t } = useTranslation('toc') @@ -69,9 +70,11 @@ export const TocLanding = () => { )} - {renderedPage && ( + {(renderedPage || renderedPageHast) && (
      - {renderedPage} + + {renderedPage} +
      )} diff --git a/src/landings/components/shared/LandingCarousel.tsx b/src/landings/components/shared/LandingCarousel.tsx index b549b3e560eb..62419e76d265 100644 --- a/src/landings/components/shared/LandingCarousel.tsx +++ b/src/landings/components/shared/LandingCarousel.tsx @@ -6,6 +6,7 @@ import type { ResolvedArticle } from '@/types' import { useTranslation } from '@/languages/components/useTranslation' import { useVersion } from '@/versions/components/useVersion' import styles from './LandingCarousel.module.scss' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type LandingCarouselProps = { heading?: string @@ -177,12 +178,7 @@ export const LandingCarousel = ({

      {article.title}

      -
      + ))}
      diff --git a/src/landings/components/shared/LandingHero.tsx b/src/landings/components/shared/LandingHero.tsx index 25f45650a51c..148e2a2d4468 100644 --- a/src/landings/components/shared/LandingHero.tsx +++ b/src/landings/components/shared/LandingHero.tsx @@ -1,6 +1,7 @@ import { LinkExternalIcon } from '@primer/octicons-react' import styles from './LandingHero.module.scss' import { useTranslation } from '@/languages/components/useTranslation' +import { RenderedHTML } from '@/frame/components/ui/RenderedHTML/RenderedHTML' type LandingHeroProps = { title: string @@ -33,7 +34,7 @@ export const LandingHero = ({ title, intro, heroImage, introLinks }: LandingHero

      {title}

      {intro && (
      -
      +
      )} {(primaryAction || secondaryAction) && ( diff --git a/src/links/lib/link-report.ts b/src/links/lib/link-report.ts index 8204a67669b5..ec60910225bc 100644 --- a/src/links/lib/link-report.ts +++ b/src/links/lib/link-report.ts @@ -123,7 +123,7 @@ ${rows}` prComment: (errors: GroupedBrokenLinks[], warnings: GroupedBrokenLinks[], actionUrl?: string) => { const errorSection = errors.length > 0 - ? `### ❌ ${errors.length} Broken Link${errors.length === 1 ? '' : 's'} + ? `### ⚠️ ${errors.length} Broken Link${errors.length === 1 ? '' : 's'} ${errors .map((group) => { diff --git a/src/links/scripts/check-links-pr.ts b/src/links/scripts/check-links-pr.ts index d6257457b10f..cb216a0b0665 100644 --- a/src/links/scripts/check-links-pr.ts +++ b/src/links/scripts/check-links-pr.ts @@ -177,21 +177,35 @@ async function commentOnPR(brokenLinks: BrokenLink[], actionUrl?: string) { const octokit = github() const comment = generatePRComment(brokenLinks, { actionUrl }) - if (!comment) { - console.log('No broken links to report') - return - } - - // Find existing comment + // Find any existing comment we previously posted (identified by the hidden marker) + const marker = '' const { data: comments } = await octokit.rest.issues.listComments({ owner, repo, issue_number: pullNumber, }) - - const marker = '' const existingComment = comments.find((c) => c.body?.includes(marker)) + if (!comment) { + console.log('No broken links to report') + // Links are now clean: remove any stale comment from an earlier commit. + // Best-effort: a concurrent run may have already deleted it (404), and + // cleanup should never turn an otherwise-passing run into a failure. + if (existingComment) { + try { + await octokit.rest.issues.deleteComment({ + owner, + repo, + comment_id: existingComment.id, + }) + console.log(`Deleted stale PR comment: ${existingComment.id}`) + } catch (err) { + console.warn(`Could not delete stale PR comment ${existingComment.id}:`, err) + } + } + return + } + if (existingComment) { await octokit.rest.issues.updateComment({ owner, @@ -287,6 +301,14 @@ async function main() { if (allBrokenLinks.length === 0 && allRedirectLinks.length === 0) { console.log(chalk.green('✅ All links valid!')) + // Remove any stale comment posted on an earlier commit, now that links are clean + if (process.env.SHOULD_COMMENT === 'true') { + try { + await commentOnPR([], process.env.ACTION_RUN_URL) + } catch (err) { + console.warn('Could not clean up stale PR comment:', err) + } + } process.exit(0) } diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index b1fbb30b3088..311fc39c040b 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -17,6 +17,10 @@ export default class MyDocument extends Document { data-dark-theme={defaultCSSTheme.darkTheme} > + {/* Inline color-mode script must run before paint to avoid a flash; it + injects executable JS (not content HTML), so RenderedHTML/hast do + not apply here. */} + {/* eslint-disable-next-line custom-rules/no-dangerously-set-inner-html */}