Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,66 @@ When `target-branch` is defined:
* All pull requests for version updates are opened targeting the specified branch.
* Options defined for this `package-ecosystem` no longer apply to security updates because security updates always use the default branch for the repository.

## `exclude-paths` {% octicon "versions" aria-label="Version updates only" height="24" %}

Use to specify paths of directories and files that {% data variables.product.prodname_dependabot %} should ignore when scanning for manifests and dependencies. This option is useful when you want to prevent updates for dependencies in certain locations, such as test assets, vendored code, or specific files.

{% data variables.product.prodname_dependabot %} default behavior:

* All directories and files in the specified `directory` are included in the update scan unless excluded by this option.

When `exclude-paths` is defined:

* All files and directories matching the specified paths are ignored during update scans for the given `package-ecosystem` entry.

| Parameter | Purpose |
|-----------|---------|
| `exclude-paths` | A list of glob patterns for files or directories to ignore. |

Glob patterns are supported, such as `**` for recursive matching and `*` for single-segment wildcards. Patterns are relative to the `directory` specified for the update configuration. Each ecosystem can have its own `exclude-paths` settings.

## Example

```yaml copy
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
exclude-paths:
- "src/test/assets"
- "vendor/**"
- "src/*.js"
- "src/test/helper.js"

# Sample patterns that can be used-

# Pattern: docs/*.json
# Matches: docs/foo.json, docs/bar.json

# Pattern: *.lock
# Matches: Gemfile.lock, package.lock, foo.lock (in any directory)

# Pattern: test/**
# Matches: test/foo.rb, test/bar/baz.rb, test/any/depth/file.txt

# Pattern: config/settings.yml
# Matches: config/settings.yml

# Pattern: **/*.md
# Matches: README.md, docs/guide.md, any/depth/file.md

# Pattern: src/*
# Matches: src/main.rb, src/app.js
# Does NOT match: src/utils/helper.rb

# Pattern: hidden/.*
# Matches: hidden/.env, hidden/.secret
```

In this example, {% data variables.product.prodname_dependabot %} will ignore the `src/test/assets` directory, all files under `vendor/`, all JavaScript files directly under `src/`, and the specific file `src/test/helper.js` when scanning for updates.

## `vendor` {% octicon "versions" aria-label="Version updates" height="24" %} {% octicon "shield-check" aria-label="Security updates" height="24" %}

Supported by: `bundler` and `gomod` only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,21 @@ In addition to these generic non-provider patterns, {% data variables.product.pr
> [!NOTE]
> Validity checks are only available to users with {% data variables.product.prodname_team %} or {% data variables.product.prodname_enterprise %} who enable the feature as part of {% data variables.product.prodname_GH_secret_protection %}.

| Provider | Token | Partner | User | Push protection | Validity check |
|----|:----|:----:|:----:|:----:|:----:|
| Provider | Token | Partner | User | Push protection | Validity check | Base 64 |
|----|:----|:----:|:----:|:----:|:----:|:----:|
{%- for entry in secretScanningData %}
| {{ entry.provider }} | {{ entry.secretType }} | {% if entry.isPublic %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.isPrivateWithGhas %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasPushProtection %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasValidityCheck %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} |
| {{ entry.provider }} | {{ entry.secretType }} | {% if entry.isPublic %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.isPrivateWithGhas %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasPushProtection %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasValidityCheck %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.base64Supported %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} |
{%- endfor %}

{% endif %}

<!-- GHES 3.9+ table -->
{% ifversion ghes %}

| Provider | Token | {% data variables.product.prodname_secret_scanning_caps %} alert | Push protection | Validity check |
|----|:----|:----:|:----:|:----:|
| Provider | Token | {% data variables.product.prodname_secret_scanning_caps %} alert | Push protection | Validity check | Base64 |
|----|:----|:----:|:----:|:----:|:----:|
{%- for entry in secretScanningData %}
| {{ entry.provider }} | {{ entry.secretType }} | {% if entry.isPrivateWithGhas %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasPushProtection %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasValidityCheck %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} |
| {{ entry.provider }} | {{ entry.secretType }} | {% if entry.isPrivateWithGhas %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasPushProtection %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.hasValidityCheck %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} | {% if entry.base64Supported %}<span role="img" class="octicon-bg-check" aria-label="Supported">✓</span>{% else %}<span role="img" class="octicon-bg-x" aria-label="Unsupported">✗</span>{% endif %} |
{%- endfor %}

{% endif %}
Expand Down
6 changes: 6 additions & 0 deletions data/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,9 @@ cookbook_landing:
search_articles: Search articles
category: Category
complexity: Complexity

not_found:
title: Ooops!
message: It looks like this page doesn't exist.
contact: We track these errors automatically, but if the problem persists please feel free to contact us.
contact_cta: Contact support
99 changes: 7 additions & 92 deletions src/app/404/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { getAppRouterContext } from '@/app/lib/app-router-context'
import { AppRouterMainContextProvider } from '@/app/components/AppRouterMainContext'
import { translate } from '@/languages/lib/translation-utils'
import { CommentDiscussionIcon, MarkGithubIcon } from '@primer/octicons-react'
import { Client404Wrapper } from '@/app/components/Client404Wrapper'
import { createServerAppRouterContext } from '@/app/lib/server-context-utils'
import { headers } from 'next/headers'
import type { Metadata } from 'next'

export const dynamic = 'force-dynamic'
Expand All @@ -12,94 +11,10 @@ export const metadata: Metadata = {
}

export default async function Page404() {
// Get context with UI data
const appContext = await getAppRouterContext()
const headersList = await headers()
const pathname = headersList.get('x-pathname') || '/404'

const siteTitle = translate(appContext.site.data.ui, 'header.github_docs', 'GitHub Docs')
const oopsTitle = translate(appContext.site.data.ui, 'meta.oops', 'Ooops!')
const appContext = createServerAppRouterContext(pathname)

return (
<AppRouterMainContextProvider context={appContext}>
<div className="min-h-screen d-flex flex-column">
{/* Simple Header */}
<div className="border-bottom color-border-muted no-print">
<header className="container-xl p-responsive py-3 position-relative d-flex width-full">
<div className="d-flex flex-1 flex-items-center">
<a
href={`/${appContext.currentLanguage}`}
className="color-fg-default no-underline d-flex flex-items-center"
>
<MarkGithubIcon size={32} className="mr-2" />
<span className="f4 text-bold">{siteTitle}</span>
</a>
</div>
</header>
</div>

{/* Main Content */}
<div className="container-xl p-responsive py-6 width-full flex-1">
<article className="col-md-10 col-lg-7 mx-auto">
<h1>{oopsTitle}</h1>
<div className="f2 color-fg-muted mb-3" data-container="lead">
It looks like this page doesn't exist.
</div>
<p className="f3">
We track these errors automatically, but if the problem persists please feel free to
contact us.
</p>
<a id="support" href="https://support.github.com" className="btn btn-outline mt-2">
<CommentDiscussionIcon size="small" className="octicon mr-1" />
Contact support
</a>
</article>
</div>

<footer className="py-6">
<div className="container-xl px-3 px-md-6">
<ul className="d-flex flex-wrap list-style-none">
<li className="d-flex mr-xl-3 color-fg-muted">
<span>© 2025 GitHub, Inc.</span>
</li>
<li className="ml-3">
<a
className="text-underline"
href="/site-policy/github-terms/github-terms-of-service"
>
Terms
</a>
</li>
<li className="ml-3">
<a
className="text-underline"
href="/site-policy/privacy-policies/github-privacy-statement"
>
Privacy
</a>
</li>
<li className="ml-3">
<a className="text-underline" href="https://www.githubstatus.com/">
Status
</a>
</li>
<li className="ml-3">
<a className="text-underline" href="https://github.com/pricing">
Pricing
</a>
</li>
<li className="ml-3">
<a className="text-underline" href="https://services.github.com/">
Expert services
</a>
</li>
<li className="ml-3">
<a className="text-underline" href="https://github.blog/">
Blog
</a>
</li>
</ul>
</div>
</footer>
</div>
</AppRouterMainContextProvider>
)
return <Client404Wrapper appContext={appContext} />
}
83 changes: 83 additions & 0 deletions src/app/components/AppRouterFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
'use client'

import { useAppRouterMainContext } from '@/app/components/AppRouterMainContext'
import { createTranslationFunctions } from '@/languages/lib/translation-utils'
import { LinkExternalIcon } from '@primer/octicons-react'

export function AppRouterFooter() {
const context = useAppRouterMainContext()

const { t } = createTranslationFunctions(context.site.data.ui, 'footer')

return (
<section className="container-xl px-3 mt-6 pb-8 px-md-6 color-fg-muted">
{context.currentLanguage !== 'en' && <h2 className="f4 mb-2 col-12">{t('legal_heading')}</h2>}

{/* Machine translation notice for non-English languages */}
{context.currentLanguage !== 'en' && <p>{t('machine')}</p>}

<ul className="d-flex flex-wrap list-style-none">
<li className="mr-3">&copy; {new Date().getFullYear()} GitHub, Inc.</li>

{/* German-specific Impressum link (legally required) */}
{context.currentLanguage === 'de' && (
<li className="mr-3">
<a
className="text-underline"
href="https://aka.ms/impressum_de"
target="_blank"
rel="noopener"
>
{t('imprint')}
</a>
<LinkExternalIcon aria-label="(external site)" size={12} />
</li>
)}

<li className="mr-3">
<a
className="text-underline"
href={`/${context.currentLanguage}/site-policy/github-terms/github-terms-of-service`}
>
{t('terms')}
</a>
</li>

<li className="mr-3">
<a
className={`text-underline ${
context.currentLanguage === 'ko' ? 'color-fg-attention text-bold' : ''
}`}
href={`/${context.currentLanguage}/site-policy/privacy-policies/github-privacy-statement`}
>
{t('privacy')}
</a>
</li>

<li className="mr-3">
<a className="text-underline" href="https://www.githubstatus.com/">
{t('status')}
</a>
</li>

<li className="mr-3">
<a className="text-underline" href="https://github.com/pricing">
{t('pricing')}
</a>
</li>

<li className="mr-3">
<a className="text-underline" href="https://services.github.com">
{t('expert_services')}
</a>
</li>

<li className="mr-3">
<a className="text-underline" href="https://github.blog">
{t('blog')}
</a>
</li>
</ul>
</section>
)
}
29 changes: 29 additions & 0 deletions src/app/components/AppRouterHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client'

import { MarkGithubIcon } from '@primer/octicons-react'
import { useAppRouterMainContext } from '@/app/components/AppRouterMainContext'
import { createTranslationFunctions } from '@/languages/lib/translation-utils'

export function AppRouterHeader() {
const context = useAppRouterMainContext()

const { t } = createTranslationFunctions(context.site.data.ui, 'header')

const siteTitle = t('github_docs')

return (
<div className="border-bottom color-border-muted no-print">
<header className="container-xl p-responsive py-3 position-relative d-flex width-full">
<div className="d-flex flex-1 flex-items-center">
<a
href={`/${context.currentLanguage}`}
className="color-fg-default no-underline d-flex flex-items-center"
>
<MarkGithubIcon size={32} className="mr-2" />
<span className="f4 text-bold">{siteTitle}</span>
</a>
</div>
</header>
</div>
)
}
54 changes: 54 additions & 0 deletions src/app/components/AppRouterLanguagesContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use client'

import { createContext, useContext } from 'react'
import { clientLanguages, type ClientLanguageCode } from '@/languages/lib/client-languages'

export type AppRouterLanguageItem = {
name: string
nativeName?: string
code: string
hreflang?: string
}

export type AppRouterLanguagesContextT = {
languages: Record<string, AppRouterLanguageItem>
currentLanguage?: ClientLanguageCode
}

export const AppRouterLanguagesContext = createContext<AppRouterLanguagesContextT | null>(null)

export const useAppRouterLanguages = (): AppRouterLanguagesContextT => {
const context = useContext(AppRouterLanguagesContext)

if (!context) {
throw new Error(
'"useAppRouterLanguages" may only be used inside "AppRouterLanguagesContext.Provider"',
)
}

return context
}

/**
* Provider component for App Router language context
*/
interface AppRouterLanguagesProviderProps {
children: React.ReactNode
currentLanguage?: ClientLanguageCode
}

export function AppRouterLanguagesProvider({
children,
currentLanguage,
}: AppRouterLanguagesProviderProps) {
const value: AppRouterLanguagesContextT = {
languages: clientLanguages,
currentLanguage,
}

return (
<AppRouterLanguagesContext.Provider value={value}>
{children}
</AppRouterLanguagesContext.Provider>
)
}
Loading
Loading