diff --git a/Dockerfile b/Dockerfile index bee215efbe9b..2573d0924ce9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,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:20251114-221740-gd084d271e AS base +FROM ghcr.io/github/gh-base-image/gh-base-noble:20251119-090131-gb27dc275c 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/content/admin/enforcing-policies/enforcing-policy-with-pre-receive-hooks/about-pre-receive-hooks.md b/content/admin/enforcing-policies/enforcing-policy-with-pre-receive-hooks/about-pre-receive-hooks.md index 505f2dc300aa..98ccf11b8b1a 100644 --- a/content/admin/enforcing-policies/enforcing-policy-with-pre-receive-hooks/about-pre-receive-hooks.md +++ b/content/admin/enforcing-policies/enforcing-policy-with-pre-receive-hooks/about-pre-receive-hooks.md @@ -44,6 +44,26 @@ Due to risk of failure and performance impact for all users of your instance, we > [!NOTE] > To avoid rejection of a push due to a timeout, all combined pre-receive hooks should run in under five seconds. +## Pre-receive hook timeouts + +Pre-receive hooks in {% data variables.product.prodname_ghe_server %} have a fixed timeout budget of 5 seconds (shared across all hooks). This is intentional design to prevent resource exhaustion from long-running hooks and to prevent runaway scripts from blocking repository operations indefinitely. + +All pre-receive hooks for a repository share a **cumulative timeout budget**: +- If hook A takes 3 seconds, hook B gets 2 seconds remaining (from 5 second default) +- If hook A times out at 5 seconds, hook B never executes + +> [!IMPORTANT] +> Pre-receive hook timeouts are handled differently from exit codes: +> - **Exit codes**: Enforcement configuration is honored (non-enforced hooks don't block pushes) +> - **Timeouts**: Push may fail regardless of enforcement configuration + +### Timeout behavior + +Scenario | Enforcement = Enabled | Enforcement = Disabled/Testing +----------|----------------------|-------------------------------- +Exit code ≠ 0 | Push rejected | Push continues (warning only) +Timeout exceeded | Push rejected | Warning + push may still fail + {% ifversion ghes > 3.16 %} {% data reusables.repositories.push-rule-and-prereceive-hooks %} diff --git a/content/billing/concepts/cost-centers.md b/content/billing/concepts/cost-centers.md index 034ce454799b..894eac856c2e 100644 --- a/content/billing/concepts/cost-centers.md +++ b/content/billing/concepts/cost-centers.md @@ -35,3 +35,4 @@ For more details, see [AUTOTITLE](/billing/reference/cost-center-allocation). * The maximum number of resources per cost center is 10,000. * A maximum of 50 resources can be added to or removed from a cost center at a time. * Azure subscriptions can only be added to or removed from cost centers through the UI. +* Outside collaborators can only be added to cost centers via the cost center API. For more information, see [AUTOTITLE](/billing/tutorials/control-costs-at-scale#add-resources-to-the-cost-center). diff --git a/content/copilot/reference/ai-models/model-hosting.md b/content/copilot/reference/ai-models/model-hosting.md index 2aa0dfbc9845..498e0558fa97 100644 --- a/content/copilot/reference/ai-models/model-hosting.md +++ b/content/copilot/reference/ai-models/model-hosting.md @@ -46,11 +46,20 @@ Used for: ## Anthropic models + + + + +{% data reusables.copilot.claude-promo-period %} See [Model multipliers](/copilot/reference/ai-models/supported-models#model-multipliers). + + + Used for: * {% data variables.copilot.copilot_claude_haiku_45 %} * {% data variables.copilot.copilot_claude_sonnet_45 %} * {% data variables.copilot.copilot_claude_opus_41 %} +* {% data variables.copilot.copilot_claude_opus_45 %} * {% data variables.copilot.copilot_claude_sonnet_40 %} These models are hosted by Amazon Web Services, Anthropic PBC, and Google Cloud Platform. {% data variables.product.github %} has provider agreements in place to ensure data is not used for training. Additional details for each provider are included below: @@ -80,8 +89,6 @@ When using {% data variables.copilot.copilot_gemini %} models, input prompts and {% data reusables.copilot.grok-promo-period %} -Complimentary access to Grok Code Fast 1 is continuing past the previously announced end time. A new end date has not been set. We may update or conclude this promotion at any time. Regular pricing applies after the extension ends. See [AUTOTITLE](/copilot/reference/ai-models/supported-models#model-multipliers). - These models are hosted on xAI. xAI operates {% data variables.copilot.copilot_grok_code %} in {% data variables.product.prodname_copilot %} under a zero data retention API policy. This means xAI commits that user content (both inputs sent to the model and outputs generated by the model): Will **not** be: diff --git a/content/copilot/reference/ai-models/supported-models.md b/content/copilot/reference/ai-models/supported-models.md index bb200cd4e228..e45b20d77846 100644 --- a/content/copilot/reference/ai-models/supported-models.md +++ b/content/copilot/reference/ai-models/supported-models.md @@ -98,6 +98,14 @@ Each model has a premium request multiplier, based on its complexity and resourc For more information about premium requests, see [AUTOTITLE](/copilot/managing-copilot/monitoring-usage-and-entitlements/about-premium-requests). + + + + +{% data reusables.copilot.claude-promo-period %} + + + {% data reusables.copilot.model-multipliers %} ## Next steps diff --git a/content/sponsors/receiving-sponsorships-through-github-sponsors/using-a-fiscal-host-to-receive-github-sponsors-payouts.md b/content/sponsors/receiving-sponsorships-through-github-sponsors/using-a-fiscal-host-to-receive-github-sponsors-payouts.md index 1e347cec56b9..b429cf3a4eb0 100644 --- a/content/sponsors/receiving-sponsorships-through-github-sponsors/using-a-fiscal-host-to-receive-github-sponsors-payouts.md +++ b/content/sponsors/receiving-sponsorships-through-github-sponsors/using-a-fiscal-host-to-receive-github-sponsors-payouts.md @@ -24,6 +24,7 @@ When you sign up for a {% data variables.product.prodname_sponsors %} profile so * [Open Collective Europe](https://opencollective.com/europe) * [Open Source Collective](https://opencollective.com/opensource) * [Python Software Foundation](https://www.python.org/psf-landing/) +* [Radiant Earth](https://radiant.earth/) * [Software in the Public Interest](https://www.spi-inc.org/) * [Software Underground](https://softwareunderground.org/) diff --git a/data/reusables/copilot/claude-promo-period.md b/data/reusables/copilot/claude-promo-period.md new file mode 100644 index 000000000000..ea437677b145 --- /dev/null +++ b/data/reusables/copilot/claude-promo-period.md @@ -0,0 +1 @@ +> [!Important] {% data variables.copilot.copilot_claude_opus_45 %} has a promotional multiplier of **1** through Friday, December 5, 2025. After that date, the multiplier will change to **3**. diff --git a/data/tables/copilot/model-multipliers.yml b/data/tables/copilot/model-multipliers.yml index 10ce00d0ad46..e84196b9e475 100644 --- a/data/tables/copilot/model-multipliers.yml +++ b/data/tables/copilot/model-multipliers.yml @@ -17,6 +17,10 @@ multiplier_paid: 10 multiplier_free: Not applicable +- name: Claude Opus 4.5 + multiplier_paid: 1 (**3** after Dec 5, 2025) + multiplier_free: Not applicable + - name: Claude Sonnet 4 multiplier_paid: 1 multiplier_free: Not applicable diff --git a/data/tables/copilot/model-release-status.yml b/data/tables/copilot/model-release-status.yml index 78ef028992e9..d20ba3f0bacc 100644 --- a/data/tables/copilot/model-release-status.yml +++ b/data/tables/copilot/model-release-status.yml @@ -82,6 +82,13 @@ ask_mode: true edit_mode: true +- name: 'Claude Opus 4.5' + provider: 'Anthropic' + release_status: 'Public preview' + agent_mode: true + ask_mode: true + edit_mode: true + - name: 'Claude Sonnet 4' provider: 'Anthropic' release_status: 'GA' diff --git a/data/tables/copilot/model-supported-clients.yml b/data/tables/copilot/model-supported-clients.yml index 151dc7bcc116..bb94dddca429 100644 --- a/data/tables/copilot/model-supported-clients.yml +++ b/data/tables/copilot/model-supported-clients.yml @@ -29,6 +29,14 @@ xcode: true jetbrains: true +- name: Claude Opus 4.5 + dotcom: true + vscode: true + vs: false + eclipse: false + xcode: false + jetbrains: false + - name: Claude Sonnet 4 dotcom: true vscode: true diff --git a/data/tables/copilot/model-supported-plans.yml b/data/tables/copilot/model-supported-plans.yml index 63d94d9f89dd..c0db26603d48 100644 --- a/data/tables/copilot/model-supported-plans.yml +++ b/data/tables/copilot/model-supported-plans.yml @@ -26,6 +26,13 @@ business: false enterprise: true +- name: Claude Opus 4.5 + free: false + pro: true + pro_plus: true + business: true + enterprise: true + - name: Claude Sonnet 4 free: false pro: true diff --git a/data/variables/copilot.yml b/data/variables/copilot.yml index 07fd47e4c8f5..ca733c518085 100644 --- a/data/variables/copilot.yml +++ b/data/variables/copilot.yml @@ -138,6 +138,7 @@ copilot_claude: 'Claude' copilot_claude_haiku_45: 'Claude Haiku 4.5' copilot_claude_opus: 'Claude Opus 4' copilot_claude_opus_41: 'Claude Opus 4.1' +copilot_claude_opus_45: 'Claude Opus 4.5' copilot_claude_sonnet: 'Claude Sonnet' copilot_claude_sonnet_35: 'Claude Sonnet 3.5' copilot_claude_sonnet_37: 'Claude Sonnet 3.7' diff --git a/src/landings/components/journey/JourneyLearningTracks.module.scss b/src/landings/components/journey/JourneyLearningTracks.module.scss index 58e3fff5fda1..44b7dcf89f29 100644 --- a/src/landings/components/journey/JourneyLearningTracks.module.scss +++ b/src/landings/components/journey/JourneyLearningTracks.module.scss @@ -1,11 +1,12 @@ -.learningTracks { +.journeyTracks { + margin-bottom: 1rem; + margin-left: 1rem; +} + +.trackCard { border: 1px solid var(--borderColor-default, var(--color-border-default, #d1d9e0)); border-radius: 12px; - padding: 1.5rem; - padding-bottom: 0.75rem; - margin-bottom: 1rem; - margin-left: 1rem; box-shadow: 0px 1px 3px 0px rgba(31, 35, 40, 0.08), 0px 1px 0px 0px rgba(31, 35, 40, 0.06); @@ -15,6 +16,24 @@ --bgColor-default, var(--color-canvas-default, #ffffff) ); + transition: all 0.2s ease-in-out; + + // journey card hover effect only when the card is not expanded + &:not([open]):hover { + box-shadow: + 0 0.25rem 0.5rem 0 rgba(31, 35, 40, 0.12), + 0 0.125rem 0.25rem 0 rgba(31, 35, 40, 0.08); + transform: translateY(-2px); + background-color: var(--bgColor-muted, var(--color-canvas-subtle)); + } +} + +.trackSummary { + list-style: none; + cursor: pointer; + display: block; + position: relative; + padding: 1.5rem 1.5rem 1.75rem 1.5rem; } .trackHeader { @@ -26,25 +45,25 @@ gap: 0.5rem; } -.anchorLink { - color: var(--fgColor-default, var(--color-fg-default, #1f2328)); - text-decoration: none; -} - .trackDescription { - margin: 0 0 1rem 0; - color: var(--fgColor-muted, var(--color-fg-muted, #656d76)); + margin: 0; + padding-right: 2rem; + + p { + margin: 0; + color: var(--fgColor-muted, var(--color-fg-muted, #656d76)); + } } .expandButton { - top: 0; - right: 0; + top: 1.5rem; + right: 1.5rem; } .trackGuides { - margin-top: 1rem; - margin-bottom: 1rem; - padding-left: 0; + margin-top: 0; + margin-bottom: 0; + padding: 0 1.5rem 0.75rem 1.5rem; list-style: none; counter-reset: guide-counter; } @@ -76,11 +95,6 @@ line-height: 1; } -.guideLink { - color: var(--fgColor-accent, var(--color-accent-fg, #0969da)); - text-decoration: none; -} - /* Hide only the timeline line that extends below the last badge, preserve everything else */ .timelineContainer :global(.Timeline-Item:last-child::before) { background: linear-gradient( @@ -189,21 +203,20 @@ } .mobileItem .mobileTile { - border: 1px solid - var(--borderColor-default, var(--color-border-default, #d1d9e0)); - border-radius: 12px; - padding: 1rem; margin-top: 0.5rem; text-align: left; - box-shadow: - 0px 1px 3px 0px rgba(31, 35, 40, 0.08), - 0px 1px 0px 0px rgba(31, 35, 40, 0.06); - position: relative; - z-index: 3; - background-color: var( - --bgColor-default, - var(--color-canvas-default, #ffffff) - ); + + .trackCard { + z-index: 3; + } + + .trackSummary { + padding: 1rem 1rem 1.75rem 1rem; + } + + .trackGuides { + padding: 0 1rem 0.75rem 1rem; + } } /* Desktop: show Timeline component */ diff --git a/src/landings/components/journey/JourneyLearningTracks.tsx b/src/landings/components/journey/JourneyLearningTracks.tsx index 03997a07873c..20cbcc355b34 100644 --- a/src/landings/components/journey/JourneyLearningTracks.tsx +++ b/src/landings/components/journey/JourneyLearningTracks.tsx @@ -1,6 +1,6 @@ /* filepath: /workspaces/docs-internal/src/landings/components/journey/JourneyLearningTracks.tsx */ import { ChevronDownIcon, ChevronUpIcon } from '@primer/octicons-react' -import { Button, Details, Timeline, Token, useDetails } from '@primer/react' +import { Details, Timeline, Token, useDetails } from '@primer/react' import { Link } from '@/frame/components/Link' import { JourneyTrack } from '@/journeys/lib/journey-path-resolver' import styles from './JourneyLearningTracks.module.scss' @@ -14,40 +14,38 @@ export const JourneyLearningTracks = ({ tracks }: JourneyLearningTracksProps) => return null } - const renderTrackContent = (track: JourneyTrack, trackIndex: number) => { + const renderTrackContent = (track: JourneyTrack) => { const { getDetailsProps, open } = useDetails({}) return ( - <> -
-

{track.title}

- -
-

{track.description}

-
- -
    - {(track.guides || []).map((article: { href: string; title: string }) => ( -
  1. - - {article.title} - -
  2. - ))} -
-
- + + +
    + {(track.guides || []).map((article: { href: string; title: string }) => ( +
  1. + + {article.title} + +
  2. + ))} +
+ ) } @@ -60,10 +58,8 @@ export const JourneyLearningTracks = ({ tracks }: JourneyLearningTracksProps) => return ( {trackIndex + 1} - -
- {renderTrackContent(track, trackIndex)} -
+ + {renderTrackContent(track)}
) @@ -76,11 +72,7 @@ export const JourneyLearningTracks = ({ tracks }: JourneyLearningTracksProps) => {tracks.map((track, trackIndex) => (
{trackIndex + 1}
-
-
- {renderTrackContent(track, trackIndex)} -
-
+
{renderTrackContent(track)}
{trackIndex < tracks.length - 1 &&
}
))}