diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 02099ff3b840..000000000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,22 +0,0 @@ -# Copilot instructions for docs.github.com - -This repository powers the GitHub Docs site (docs.github.com). It contains both the Next.js application code (TypeScript) and the documentation content (Markdown). - -## Instruction files - -Read the relevant instruction files in `.github/instructions/` before making changes: - -* **`all.instructions.md`** — General project guidelines, PR conventions, and how to access docs.github.com content programmatically. Applies to all files. -* **`code.instructions.md`** — TypeScript/JavaScript coding standards, test commands (per-suite with environment variables), and validation steps. Read this before any code change. -* **`content.instructions.md`** — Markdown content conventions, Liquid variable usage, reusables, and linking with `[AUTOTITLE]`. Read this before any content change. -* **`style-guide-summary.instructions.md`** — Condensed docs style guide covering voice, headers, lists, alerts, and formatting. Read this before any content change. - -## Key rules - -* All new code must be TypeScript (not JavaScript). -* Use `@/` absolute imports (e.g., `import getRedirect from '@/redirects/lib/get-redirect'`). -* Do not run `npm test` without a path argument — always target a specific suite. -* Run `npm run build` before running tests. -* Do not commit to `main`. Create a branch and open a draft PR. -* Use Liquid variables for product names — never hardcode them. Check `data/variables/`. -* Use `[AUTOTITLE](/path/to/article)` for internal links — never hardcode article titles. diff --git a/.github/instructions/all.instructions.md b/.github/instructions/all.instructions.md index 373e3d77ad1b..9651217e785f 100644 --- a/.github/instructions/all.instructions.md +++ b/.github/instructions/all.instructions.md @@ -4,7 +4,7 @@ applyTo: "**" # Copilot instructions for docs.github.com -This repository contains code to run the GitHub Docs site on docs.github.com, as well as the content that the site displays. We write the code in JavaScript and TypeScript, and we write the content primarily in Markdown. +This repository powers the GitHub Docs site (docs.github.com). It contains both the Next.js application code (TypeScript) and the documentation content (Markdown). ## Creating a pull request @@ -29,6 +29,8 @@ When you create a pull request: 3. Label with "llm-generated". 4. If an issue exists, include "fixes owner/repo#issue" or "towards owner/repo#issue" as appropriate. 5. Always create PRs in **draft mode** using `--draft` flag. +6. Do not commit directly to `main`. +7. Whenever you create or comment on an issue or pull request, indicate you are GitHub Copilot. ## Accessing docs.github.com content programmatically diff --git a/.github/instructions/code.instructions.md b/.github/instructions/code.instructions.md index b8b1f9875055..faddea52665a 100644 --- a/.github/instructions/code.instructions.md +++ b/.github/instructions/code.instructions.md @@ -11,13 +11,11 @@ For code reviews, follow guidelines, tests, and validate instructions. For creat - If available, use ripgrep (`rg`) instead of `grep`. - When using gh cli in double-quoted strings, escape backticks to prevent bash command substitution. In single-quoted strings, backticks do not need escaping. - All scripts should be listed in `package.json` and use `tsx`. -- Whenever you create or comment on an issue or pull request, indicate you are GitHub Copilot. - Be careful fetching full HTML pages off the internet. Prefer to use MCP or gh cli whenever possible for github.com. Limit the number of tokens when grabbing HTML. - Avoid pull requests with over 300 lines of code changed. When significantly larger, offer to split up into smaller pull requests if possible. - All new code should be written in TypeScript and not JavaScript. - We use absolute imports, relative to the `src` directory, using the `@` symbol. For example, `getRedirect` which lives in `src/redirects/lib/get-redirect.ts` can be imported with `import getRedirect from '@/redirects/lib/get-redirect'`. The same rule applies for TypeScript (`.ts`) imports, e.g. `import type { GeneralSearchHit } from '@/search/types'` - For updates to the content linter, read important information in `src/content-linter/README.md`. -- Do not commit to `main` branch. - Do not use git force push, and avoid git rebase. ## Tests diff --git a/.github/instructions/style-guide-summary.instructions.md b/.github/instructions/style-guide-summary.instructions.md index 3280cf435c36..c3ff2b213a15 100644 --- a/.github/instructions/style-guide-summary.instructions.md +++ b/.github/instructions/style-guide-summary.instructions.md @@ -6,7 +6,7 @@ applyTo: "content/**,data/**,**/*.md" **When to use**: Any content editing, documentation writing, or Markdown file changes. This is a condensed version of the full style guide at `/content/contributing/style-guide-and-content-model/style-guide.md`. Use these rules for routine work. Only consult the full style guide if you encounter a style question not covered here. -For Liquid variable usage, reusables, linking conventions, bullet-list formatting, and parenthetical dashes, see `content.instructions.md` (loaded automatically alongside this file). +For Liquid variable usage, reusables, linking conventions, bullet-list markers, and parenthetical dashes, see `content.instructions.md` (loaded automatically alongside this file). ## Core principles @@ -52,7 +52,6 @@ For Liquid variable usage, reusables, linking conventions, bullet-list formattin ## Links -* Use `[AUTOTITLE](/path/to/article)` for all internal links. Never hardcode article titles in link text. * Introduce links with "For more information, see" or "See" when context is clear. * Do not use inline links where words within a sentence are hyperlinked without additional context. * Do not include punctuation inside a hyperlink. @@ -60,7 +59,6 @@ For Liquid variable usage, reusables, linking conventions, bullet-list formattin ## Lists -* Use `*` (asterisks) for unordered lists, never `-` (hyphens). * Capitalize the first letter of each list item. * Use periods only if the item is a complete sentence. * Introduce lists with a descriptive sentence, not vague phrases like "the following" in isolation. @@ -83,9 +81,8 @@ For Liquid variable usage, reusables, linking conventions, bullet-list formattin * Use full words for Apple modifier keys (`Command`, `Option`, `Control`), not symbols. * Capitalize letter keys. -## Product names and variables +## Product names -* Always use Liquid variables for product names—never hardcode them. Check `data/variables/product.yml` and `data/variables/copilot.yml`. * Product names are always singular (for example, "GitHub Actions helps" not "help"). ## Word choice diff --git a/content/admin/managing-accounts-and-repositories/managing-repositories-in-your-enterprise/restoring-a-deleted-repository.md b/content/admin/managing-accounts-and-repositories/managing-repositories-in-your-enterprise/restoring-a-deleted-repository.md index b3e7eb17e276..c48c18f4fab7 100644 --- a/content/admin/managing-accounts-and-repositories/managing-repositories-in-your-enterprise/restoring-a-deleted-repository.md +++ b/content/admin/managing-accounts-and-repositories/managing-repositories-in-your-enterprise/restoring-a-deleted-repository.md @@ -21,7 +21,7 @@ If a repository was part of a fork network when it was deleted, the restored rep It can take up to an hour after a repository is deleted before that repository is available for restoration. -Restoring a repository will not restore release attachments or team permissions. Issues that are restored will not be labeled. +Restoring a repository will not restore release attachments or team permissions. ## Restoring a deleted repository diff --git a/content/copilot/concepts/billing/budgets-for-usage-based-billing.md b/content/copilot/concepts/billing/budgets-for-usage-based-billing.md index 1c504a4bea91..6439cf068cf7 100644 --- a/content/copilot/concepts/billing/budgets-for-usage-based-billing.md +++ b/content/copilot/concepts/billing/budgets-for-usage-based-billing.md @@ -26,6 +26,12 @@ There are two types: * **Universal user-level budget:** A default budget applied to every {% data variables.product.prodname_copilot_short %}-licensed user in your enterprise. This is your primary tool for ensuring fair access to the shared pool. * **Individual user-level budget:** A budget set for a specific user, which overrides the universal default and takes precedence over it entirely. Use this for power users who need higher limits, or to restrict specific users to a lower amount. +#### When users appear in a universal user-level budget + +A universal user-level budget can apply to thousands of licensed users. {% data variables.product.github %} creates each user's budget record the first time they consume {% data variables.product.prodname_ai_credits_short %} after the budget is created, or after the start of a new billing cycle. As a result, users appear in the universal budget list gradually rather than all at once, and a licensed user who does not use {% data variables.product.prodname_copilot_short %} in a given billing cycle will not appear in the list for that billing cycle. + +For a complete view of all licensed users regardless of activity, use the **AI usage** or **Licensing** pages. + ### Cost center budget A cost center budget caps metered charges for a defined group of users or an organization. It does not limit how much a team draws from the pool. It is only active after the shared pool is exhausted. diff --git a/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests.md b/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests.md index a42e8e9881a7..21c975095e10 100644 --- a/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests.md +++ b/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests.md @@ -46,7 +46,7 @@ When you open a pull request, {% data variables.product.github %} creates up to | `refs/pull/PULL_REQUEST_NUMBER/head` | Points to the latest commit on the pull request's head branch. | | `refs/pull/PULL_REQUEST_NUMBER/merge` | A merge branch—a simulated merge commit that represents what the repository would look like if the pull request were merged right now. This ref is only available when the pull request has no merge conflicts. | -The merge branch automatically updates when the head branch or base branch changes. To fetch it locally: +The merge branch automatically updates when the head branch changes. To fetch it locally: ```shell git fetch origin refs/pull/PULL_REQUEST_NUMBER/merge diff --git a/content/repositories/creating-and-managing-repositories/restoring-a-deleted-repository.md b/content/repositories/creating-and-managing-repositories/restoring-a-deleted-repository.md index e16dcb9ddb7b..ad1d910a49a0 100644 --- a/content/repositories/creating-and-managing-repositories/restoring-a-deleted-repository.md +++ b/content/repositories/creating-and-managing-repositories/restoring-a-deleted-repository.md @@ -36,7 +36,7 @@ If you want to restore a repository that was part of a fork network that is not It can take up to an hour after a repository is deleted before that repository is available for restoration. -Restoring a repository will not restore team permissions. Issues that are restored will not be labeled. +Restoring a repository will not restore team permissions. ## Restoring a deleted repository that was owned by a personal account diff --git a/src/automated-pipelines/components/AutomatedPage.tsx b/src/automated-pipelines/components/AutomatedPage.tsx index 9d0b74d8d7ad..a14b1f12fa30 100644 --- a/src/automated-pipelines/components/AutomatedPage.tsx +++ b/src/automated-pipelines/components/AutomatedPage.tsx @@ -10,6 +10,7 @@ import { MiniTocs } from '@/frame/components/ui/MiniTocs' import { useAutomatedPageContext } from '@/automated-pipelines/components/AutomatedPageContext' import { ClientSideHighlight } from '@/frame/components/ClientSideHighlight' import { Breadcrumbs } from '@/frame/components/page-header/Breadcrumbs' +import { JourneyTrackCard, JourneyTrackNav } from '@/journeys/components' type Props = { children?: React.ReactNode @@ -18,8 +19,18 @@ type Props = { } export const AutomatedPage = ({ children, rawChildren, fullWidth }: Props) => { - const { title, intro, renderedPage, miniTocItems, product, permissions, currentLayout } = - useAutomatedPageContext() + const { + title, + intro, + renderedPage, + miniTocItems, + product, + permissions, + currentLayout, + currentJourneyTrack, + } = useAutomatedPageContext() + const isJourneyTrack = !!currentJourneyTrack?.trackId + const hasTocContent = isJourneyTrack || miniTocItems.length > 1 const articleContents = (
@@ -40,21 +51,33 @@ export const AutomatedPage = ({ children, rawChildren, fullWidth }: Props) => { ) - const toc = miniTocItems.length > 1 ? : undefined + const toc = hasTocContent ? ( + <> + {isJourneyTrack && } + {miniTocItems.length > 1 && } + + ) : undefined return ( {currentLayout === 'inline' ? ( - {title}} - intro={introProp} - toc={toc} - breadcrumbs={} - > - {articleContents} - + <> + {title}} + intro={introProp} + toc={toc} + breadcrumbs={} + > + {articleContents} + + {isJourneyTrack ? ( +
+ +
+ ) : null} + ) : (
{ > {articleContents} + + {isJourneyTrack ? ( +
+ +
+ ) : null}
)}
diff --git a/src/automated-pipelines/components/AutomatedPageContext.tsx b/src/automated-pipelines/components/AutomatedPageContext.tsx index 8776a580444a..03fb1d944d91 100644 --- a/src/automated-pipelines/components/AutomatedPageContext.tsx +++ b/src/automated-pipelines/components/AutomatedPageContext.tsx @@ -2,6 +2,7 @@ import { createContext, useContext } from 'react' import type { IncomingMessage } from 'http' import type { JSX } from 'react' import type { MiniTocItem } from '@/frame/components/context/ArticleContext' +import type { JourneyContext } from '@/journeys/lib/journey-path-resolver' import type { Context } from '@/types' export type AutomatedPageContextT = { @@ -12,6 +13,7 @@ export type AutomatedPageContextT = { product?: string permissions?: string currentLayout?: string + currentJourneyTrack?: JourneyContext | null } export const AutomatedPageContext = createContext(null) @@ -59,5 +61,6 @@ export const getAutomatedPageContextFromRequest = ( product: page.product ?? '', permissions: page.permissions ?? page.rawPermissions ?? '', currentLayout: context.currentLayoutName ?? 'default', + currentJourneyTrack: (context.currentJourneyTrack as JourneyContext | null | undefined) ?? null, } } diff --git a/src/frame/components/context/MainContext.tsx b/src/frame/components/context/MainContext.tsx index d48b37267880..2316958598c0 100644 --- a/src/frame/components/context/MainContext.tsx +++ b/src/frame/components/context/MainContext.tsx @@ -183,6 +183,9 @@ export const getMainContext = async (req: any, res: any): Promise const ui: UIStrings = {} addUINamespaces(req, ui, DEFAULT_UI_NAMESPACES) + if (req.context.currentJourneyTrack?.trackId) { + addUINamespaces(req, ui, ['journey_track_nav']) + } // Product index pages (depth-2 index.md, e.g. actions/index.md) need the // full product tree for landing rendering. diff --git a/src/secret-scanning/data/pattern-docs/fpt/public-docs.yml b/src/secret-scanning/data/pattern-docs/fpt/public-docs.yml index bf998e3a68af..6503750acc80 100644 --- a/src/secret-scanning/data/pattern-docs/fpt/public-docs.yml +++ b/src/secret-scanning/data/pattern-docs/fpt/public-docs.yml @@ -105,7 +105,7 @@ isPrivateWithGhas: true hasPushProtection: true hasValidityCheck: false - hasExtendedMetadata: false + hasExtendedMetadata: '{% ifversion ghes %}false{% else %}true{% endif %}' base64Supported: false isduplicate: false - provider: Airtable @@ -115,7 +115,7 @@ isPrivateWithGhas: true hasPushProtection: true hasValidityCheck: true - hasExtendedMetadata: false + hasExtendedMetadata: '{% ifversion ghes %}false{% else %}true{% endif %}' base64Supported: false isduplicate: false - provider: Aiven @@ -144,7 +144,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: true hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -356,7 +356,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -366,7 +366,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -376,7 +376,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -466,7 +466,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -516,7 +516,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -546,7 +546,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -556,7 +556,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -586,7 +586,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -896,7 +896,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -1026,7 +1026,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false diff --git a/src/secret-scanning/data/pattern-docs/ghec/public-docs.yml b/src/secret-scanning/data/pattern-docs/ghec/public-docs.yml index bf998e3a68af..6503750acc80 100644 --- a/src/secret-scanning/data/pattern-docs/ghec/public-docs.yml +++ b/src/secret-scanning/data/pattern-docs/ghec/public-docs.yml @@ -105,7 +105,7 @@ isPrivateWithGhas: true hasPushProtection: true hasValidityCheck: false - hasExtendedMetadata: false + hasExtendedMetadata: '{% ifversion ghes %}false{% else %}true{% endif %}' base64Supported: false isduplicate: false - provider: Airtable @@ -115,7 +115,7 @@ isPrivateWithGhas: true hasPushProtection: true hasValidityCheck: true - hasExtendedMetadata: false + hasExtendedMetadata: '{% ifversion ghes %}false{% else %}true{% endif %}' base64Supported: false isduplicate: false - provider: Aiven @@ -144,7 +144,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: true hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -356,7 +356,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -366,7 +366,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -376,7 +376,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -466,7 +466,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -516,7 +516,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -546,7 +546,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -556,7 +556,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -586,7 +586,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -896,7 +896,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false @@ -1026,7 +1026,7 @@ isPublic: true isPrivateWithGhas: true hasPushProtection: true - hasValidityCheck: false + hasValidityCheck: '{% ifversion ghes %}false{% else %}true{% endif %}' hasExtendedMetadata: false base64Supported: false isduplicate: false