diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b04da84f0758..2de8b05958fb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -15,7 +15,8 @@ "ghcr.io/devcontainers/features/copilot-cli:1": { "version": "prerelease" }, - "ghcr.io/devcontainers/features/github-cli:1": {} + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, "customizations": { diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000000..02099ff3b840 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,22 @@ +# 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/code.instructions.md b/.github/instructions/code.instructions.md index 17d3679bd61d..fcbb06f1a9b1 100644 --- a/.github/instructions/code.instructions.md +++ b/.github/instructions/code.instructions.md @@ -24,13 +24,53 @@ For code reviews, follow guidelines, tests, and validate instructions. For creat We use `vitest` to write unit tests. Tests live in their own files in the `tests` subdirectory of a source (src) directory, e.g. `src/search/tests/api-ai-search.ts`. For integration tests, we can use the mock server in `src/tests/mocks/start-mock-server.ts` to mock external requests. For UI rendering tests, we use `playwright` and write tests in `src/fixtures/tests/playwright-rendering.spec.ts` -- `npm run test`: For all unit tests - - You can pass specific paths, e.g. `npm run test -- src/search/tests/ai-search-proxy` - - You can add `--silent=false` to include `console.log` debugging. -- `npm run build && npm run playwright-test -- playwright-rendering`: You need to build for changes outside of the test to be picked up. We use playwright for all rendering and end-to-end tests +**Important: Do NOT run `npm test` without a path argument.** Tests must be run per-suite because different suites require different environment variables. Running all tests at once will produce many false failures. + +**Important: Run `npm run build` before running tests.** Many test suites depend on Next.js build artifacts. Without a build, tests may fail with `Could not find a production build` or other confusing errors. + +### Running tests by suite + +Always target the specific suite for the code you changed: + +```shell +npm test -- src//tests/ +``` + +For example: `npm test -- src/search/tests/` or `npm test -- src/versions/tests/` + +You can also target a single file: `npm test -- src/search/tests/ai-search-proxy.ts` + +Add `--silent=false` to include `console.log` debugging output. + +### Suites that require environment variables + +Some test suites depend on fixture content or external services. These suites have dedicated npm scripts in `package.json` that set the required environment variables automatically: + +```shell +npm run test:article-api +npm run test:changelogs +npm run test:fixtures +npm run test:landings +npm run test:languages # requires Elasticsearch running +npm run test:search # requires Elasticsearch running +``` + +For the `content-linter` suite, you can optionally scope linting to changed files by setting `DIFF_FILES` (space-separated list) or `DIFF_FILE` (path to a text file containing a space-separated list of changed files). Without these, the linter runs against all content: + +```shell +DIFF_FILES="content/foo.md content/bar.md" npm test -- src/content-linter/tests/ +``` + +All other suites (e.g., `versions`, `redirects`, `rest`, `frame`, `content-render`, `graphql`, etc.) can be run without special environment variables. + +### Playwright (rendering and end-to-end tests) + +- `npm run build && npm run playwright-test -- playwright-rendering`: You need to build for changes outside of the test to be picked up. We use playwright for all rendering and end-to-end tests. - You can add `--ui` to keep open `localhost:4000` which can be viewed in a simple browser for debugging UI state. + +### Development server + - `npm run dev` to start the development server on `localhost:4000`. -- `ROOT=src/fixtures/fixtures TRANSLATIONS_FIXTURE_ROOT=src/fixtures/fixtures/translations vitest src/fixtures/tests` for tests that involve fixtures. ## Validate diff --git a/.github/prompts/code-review.prompt.md b/.github/prompts/code-review.prompt.md new file mode 100644 index 000000000000..2c74a9862345 --- /dev/null +++ b/.github/prompts/code-review.prompt.md @@ -0,0 +1,316 @@ +# Copilot code review prompt + +Review these code changes adversarially. Assume every change is guilty until proven correct. Your job is to find bugs, security holes, performance traps, and subtle logic errors that the author missed. + +DO NOT MODIFY ANY FILES except the review report. Only provide feedback and suggestions. + +## Finding changes to review + +Use git to find the files changed on this branch compared to main: + +```bash +git diff --name-only $(git merge-base main HEAD)...HEAD +``` + +Only review files returned by this command. Do not review files that are not in this list. + +IMPORTANT: Only review committed changes. + +DO NOT review: +- Staged changes (files in the index) +- Unstaged changes (modified files not yet staged) +- Untracked files + +## Coding standards + +**CRITICAL**: Before reviewing any code, use `read_file` to read each of these instruction files in full: + +- .github/instructions/all.instructions.md (general project guidelines) +- .github/instructions/code.instructions.md (for TypeScript/JavaScript and code files) +- .github/instructions/content.instructions.md (for .md content files) +- .github/instructions/style-guide-summary.instructions.md (for documentation style) + +Read all instruction files FULLY without limit/offset parameters. Do NOT skip this step or rely on summaries. Apply the standards from these files when reviewing changed code. + +## Paths to ignore + +IGNORE these paths entirely - do not review or comment on them: + +- node_modules/* +- .next/* +- tmp/* +- tsconfig.tsbuildinfo + +## Focus areas + +- Violations of the project's coding standards (especially: all new code must be TypeScript, use `@/` absolute imports, scripts in `package.json` that execute TypeScript source files must use `tsx`) +- Bugs and logic errors +- Error handling issues +- Security concerns +- Defensive programming: Functions should validate inputs at trust boundaries. Specifically check for: + - `undefined`/`null` access that will throw at runtime (e.g., destructuring a possibly-undefined object, indexing into a possibly-null array) + - Optional chaining (`?.`) used where a hard failure would be more appropriate (silently returning `undefined` instead of surfacing a bug) + - Type assertions (`as`, `!`) that bypass the type system—each one must be justified or flagged +- Configuration consistency: Ports, URLs, or service names hardcoded in `docker-compose.yaml`, `Dockerfile`, or `config/` must match what `package.json` scripts and env vars reference. +- Documentation accuracy: JSDoc comments, README text, test descriptions, and inline comments must match actual behavior + +## TypeScript-specific code quality + +For `.ts` and `.tsx` files, check for: + +- **`any` leaks**: Any use of `any` that could be replaced with a proper type, `unknown`, or a generic. Each `any` is a hole in the type system. `as any` to silence a compiler error is almost always a bug in disguise. +- **Unchecked `as` casts**: Type assertions that narrow without a runtime guard. Example: `const user = data as User` without validating `data` actually matches `User`. Prefer type guards or schema validation (e.g., zod). +- **Promise handling**: Every `async` function call or Promise must be `await`ed, returned, or explicitly voided with `void promise`. Unhandled promises silently swallow errors and are a top source of production mystery failures. +- **Floating promises in Express/Next handlers**: An `async` function passed to `app.get()` or used as a Next.js API route that throws will NOT be caught by Express/Next—it becomes an unhandled rejection. Verify error boundaries exist. +- **`===` vs `==`**: All comparisons must use strict equality. Flag any `==` or `!=` usage. +- **Mutable default parameters**: Function parameters with mutable default values (e.g., `function foo(opts = {})`) can share state across calls if the default is mutated. Ensure defaults are not mutated. +- **Import hygiene**: All imports must use the `@/` absolute path convention per project rules. No relative imports (`../`) reaching outside the current directory's subtree. `import type` must be used for type-only imports. +- **Dead exports**: Exported functions, types, or constants that are not imported anywhere else in the codebase. Run `grep -r` to verify usage. +- **Implicit return types on exported functions**: Exported functions should have explicit return type annotations. Inferred returns leak implementation details and can silently break callers when the implementation changes. + +## Performance and reliability (HOT PATH) + +These are the highest-priority review checks. Every issue found here is 🔴 Critical or 🟠 High by default. + +### Blocking the event loop + +Node.js is single-threaded. Any synchronous work in a request handler, middleware, or server-side Next.js function blocks ALL concurrent requests. Flag any of these on a code path reachable from an HTTP request: + +- **Synchronous file system calls**: `fs.readFileSync`, `fs.writeFileSync`, `fs.existsSync`, `fs.statSync`, `fs.readdirSync`, `fs.accessSync`, or any `*Sync` method from `fs` or `node:fs`. These must use their async counterparts (`fs.promises.*` or callback-based) or be moved to build-time/startup-only code. +- **Synchronous child processes**: `execSync`, `spawnSync`, `execFileSync` in request-handling code. +- **CPU-intensive computation**: `JSON.parse()` on unbounded/user-controlled input, large regex matches, synchronous crypto (`crypto.pbkdf2Sync`, `crypto.scryptSync`, `crypto.randomBytes` without callback), or tight loops iterating over large datasets. These should be streaming, chunked, or offloaded to a worker thread. +- **Synchronous `require()`**: Dynamic `require()` calls at request time (not at module load). `require()` is synchronous and hits the filesystem on first call. +- **Blocking iteration patterns**: `Array.prototype.sort()`, `.filter().map().reduce()` chains on arrays that could be large (e.g., all pages in the docs site). Ask: what is the upper bound of this array's length? + +### File IO on the hot path + +Any file read/write reachable from an HTTP request handler is suspect. Check for: + +- **Unbounded file reads**: `fs.readFile` (async or sync) on files whose size is not bounded. Reading a multi-megabyte file into memory per request is a DoS vector. Prefer streaming with `fs.createReadStream` and pipe to the response. +- **Repeated reads of the same file**: Files read on every request that could be read once at startup and cached. Example: reading a YAML config file, parsing markdown, or loading a JSON data file inside a request handler instead of at module initialization. +- **No error handling on file operations**: `fs.readFile` or `fs.createReadStream` without handling `ENOENT`, `EACCES`, or `EMFILE` (too many open files). Missing error handling on streams is especially dangerous—an uncaught `'error'` event crashes the process. +- **`fs.watch`/`fs.watchFile` in production**: File watchers are appropriate in development but leak file descriptors in production. Verify they are gated behind `NODE_ENV === 'development'` or similar. +- **Temporary file cleanup**: Code that writes temp files (`/tmp`, `os.tmpdir()`) must clean them up in a `finally` block. Missing cleanup under error paths causes disk exhaustion over time. + +### Caching correctness + +In-memory caches are the #1 source of subtle production bugs. For any caching (in-memory `Map`/`Object`, LRU, `node-cache`, module-level variables, Next.js `unstable_cache`, HTTP cache headers), verify: + +- **Unbounded growth**: Any `Map`, `Set`, `Object`, or array used as a cache that grows without eviction. Module-level `const cache = new Map()` that is populated on each unique request key but never pruned will eventually OOM the process. Require an eviction strategy (LRU, TTL, max size) or justify why the keyspace is bounded. +- **Missing cache invalidation**: Cached data derived from mutable sources (database, file system, external API) with no TTL or invalidation mechanism. Ask: when the source data changes, how does the cache learn about it? +- **Cache key collisions**: Cache keys that do not fully encode the request context. Example: caching by `pathname` alone when the response also varies by `version`, `language`, or user role. Two different users hitting the same cache key get each other's data. +- **Caching user-specific data globally**: Any cache that stores per-user or per-session data in a module-level variable. This leaks data between requests/users in the same process. In Next.js, also check for accidentally caching inside a shared server component module. +- **Stale reads after writes**: Code that writes to a data source then immediately reads from a cache that still holds the old value. Verify write-through or cache-bust-on-write semantics. +- **Cache stampede**: When a popular cache entry expires, many concurrent requests may simultaneously compute the same expensive value. Check if there is a lock/dedup mechanism for expensive recomputation. +- **Next.js-specific caching pitfalls**: + - `fetch()` in server components is cached by default. Verify `{ cache: 'no-store' }` or `{ next: { revalidate: N } }` is set appropriately for data that changes. + - `unstable_cache` keys must be unique and include all parameters that affect the result. + - Static generation caching persists across deploys unless `revalidate` is configured. + +### Memory leaks + +A memory leak in a long-running Node.js server is a ticking time bomb. For any new code, check: + +- **Event listener accumulation**: `emitter.on()` or `addEventListener()` called in a request handler or repeated code path without a corresponding `removeListener()` / `removeEventListener()`. Each request adds a listener that is never removed. Node warns at 11 listeners but the damage is done earlier. Also check for `.once()` where `.on()` was intended (and vice versa). +- **Uncleared timers**: `setInterval()` or `setTimeout()` created in request-scoped code without `clearInterval()`/`clearTimeout()` in cleanup/error paths. `setInterval` is especially dangerous—if the handle is lost, the interval runs forever. +- **Closure retention**: Functions or callbacks that close over large objects (request/response bodies, parsed HTML trees, database result sets) and are then stored in a long-lived structure (module-level cache, event emitter, global array). The large object cannot be GC'd as long as the closure is reachable. +- **Stream pipe leaks**: `stream.pipe(dest)` without error handling. If the source errors, the destination is not automatically cleaned up (and vice versa). Use `pipeline()` from `node:stream/promises` which handles cleanup. Also check for readable streams created but never consumed (they buffer in memory). +- **Global/module-level arrays and maps used as queues**: Arrays that `.push()` items but rely on a consumer to `.shift()` them. If the consumer fails or falls behind, the array grows without bound. +- **WeakRef misuse**: `WeakRef` / `FinalizationRegistry` used for correctness (not just optimization). GC timing is non-deterministic—code must not depend on weak references being collected at any particular time. +- **Express `req`/`res` captured in closures that outlive the request**: Middleware that stores `req` or `res` in a module-level structure (for logging, metrics, or tracing) must use weak references or clear the reference when the response finishes (`res.on('finish', ...)`). + +## Security checks (Node/Next.js-specific) + +For API routes, middleware, and server-side code, verify: + +- **Error exposure**: Errors returned to clients should NOT include raw `error.message` or `error.stack` which may leak internal details (file paths, dependency versions, SQL queries). Use generic messages and log the real error server-side. +- **Fail-safe defaults**: Boolean conditions controlling access should fail closed (deny by default), not fail open. Example: `const isDev = env === 'development'` (allowlist) NOT `const isDev = env !== 'production'` (denylist—allows `staging`, `test`, typos, and `undefined`). +- **Input validation**: All user inputs from `req.query`, `req.body`, `req.params`, URL search params, and headers must be validated and typed before use. Never trust that a query param is a string—it could be an array. +- **Prototype pollution**: Object spread (`{ ...userInput }`) or `Object.assign({}, userInput)` on unsanitized user input can inject `__proto__`, `constructor`, or `prototype` keys. Flag any code that merges user-controlled objects into configuration or state. +- **Path traversal**: Any use of user-supplied strings in `fs.readFile`, `path.join`, `path.resolve`, or dynamic `import()` must be validated against traversal (`../`, encoded variants). `path.join` does NOT sanitize—`path.join('/safe', '../../etc/passwd')` resolves outside the root. +- **ReDoS**: Regular expressions applied to user input must not contain catastrophic backtracking patterns (nested quantifiers like `(a+)+`, `(a|a)*`). Flag any regex operating on untrusted strings. +- **SSRF in fetch/axios**: Server-side `fetch()` or `axios` calls using user-supplied URLs or URL components must validate the target is not an internal/private IP range (`127.0.0.1`, `169.254.169.254`, `10.*`, `172.16-31.*`, `192.168.*`, `[::1]`, `localhost`). +- **Environment variable trust**: Code should not branch on `process.env.NODE_ENV` for security decisions. `NODE_ENV` is a build/runtime hint, not a security boundary. + +## Test quality checks + +For test files (`*.test.ts`, `*.spec.ts`, files under `tests/`): + +- **Test isolation**: Tests must not depend on execution order or shared mutable state. Each test should set up and tear down its own state. +- **Assertion quality**: Tests should assert on observable outputs (return values, HTTP status codes, response bodies, DOM state) not implementation details. `expect(spy).toHaveBeenCalled()` without checking *what* it was called with is a weak assertion. +- **Missing negative tests**: For every happy path, ask: where is the test for invalid input, network failure, timeout, or permission denied? +- **Snapshot overuse**: Snapshots that capture large objects or HTML trees are brittle and encourage "update snapshot" without review. Flag new snapshots over 20 lines. +- **Hardcoded ports/URLs in tests**: Tests that hardcode `localhost:4000` or similar will fail in parallel or in CI environments with different port assignments. +- **Async test correctness**: Verify `async` tests actually `await` the operations they are testing. A test that creates a promise but does not await it will always pass (it resolves after the test completes). + +## Test coverage check + +For new code in implementation files: + +1. Identify new exported functions, types, and config fields +2. Check that corresponding test files exist and cover the new code +3. Flag any new config fields (especially `required` ones) that lack test coverage +4. For each modified module with new or changed code, check existing tests cover the new paths. Flag any new exported function with no corresponding test as a critical gap. + +## External call performance + +For any code making outbound HTTP requests (`fetch`, `axios`, `node-fetch`, or any HTTP client): + +- **Missing timeouts**: Every outbound `fetch()` call on a request-handling code path MUST use `fetchWithTimeout` (from `@/frame/lib/fetch-utils`) or provide an `AbortSignal` with a timeout. A `fetch()` without a timeout will hang the request (and the event loop slot) indefinitely if the remote server is slow or unresponsive. Note: `fetchWithTimeout` clears its timer when headers arrive—it does NOT cover slow body streaming. If the response body is large or streamed, additional timeout handling is needed. +- **Missing retries with backoff**: Calls to external services that can transiently fail should use `fetchWithRetry` (from `@/frame/lib/fetch-utils`). Bare `fetch()` with a try/catch that gives up on the first failure will cause unnecessary user-facing errors during brief upstream blips. +- **Unbounded retry loops**: If retries ARE used, verify there is a maximum retry count and that backoff is exponential (not fixed-delay). `fetchWithRetry` already handles this, but custom retry logic might not. +- **N+1 fetch patterns**: Sequential `await fetch()` calls inside a `for`/`for...of`/`.forEach`/`.map` loop. If the iterations are independent, they should be parallelized with `Promise.all()` (with a concurrency limit if the count is unbounded). Example anti-pattern: + ```typescript + // 🔴 BAD: 50 sequential round-trips + for (const id of ids) { + const data = await fetch(`/api/${id}`) + } + // ✅ GOOD: parallel with concurrency limit + await Promise.all(ids.map(id => fetch(`/api/${id}`))) + ``` +- **Missing error classification**: Fetch errors should distinguish between network failures (retry-safe), 4xx client errors (do not retry, likely a bug), and 5xx server errors (retry-safe). Code that retries on 400 or 404 is wasting time and masking bugs. +- **Response body consumption**: Every `fetch()` response body MUST be consumed (`.json()`, `.text()`, `.arrayBuffer()`, or explicitly `.body?.cancel()`). Unconsumed response bodies leak sockets and can exhaust the connection pool. This is especially easy to miss in error paths where the response is discarded. + +## Middleware and Express checks + +For Express middleware and request handlers: + +- **Middleware ordering**: New middleware must be inserted at the correct position in the chain. Auth/security middleware must run before route handlers. Logging middleware should capture both request and response. +- **Missing `next()` calls**: Every middleware must call `next()` or send a response. A middleware that conditionally calls `next()` but has a code path that does neither will hang the request. +- **Response after `res.end()`**: Verify no code path calls `res.json()`, `res.send()`, or `res.redirect()` after the response has already been sent. This causes "headers already sent" errors. +- **Memory leaks in closures**: Middleware closures that capture large objects (request bodies, database connections) and store them in module-level caches or event listeners that are never cleaned up. +- **Streaming response handling**: If using `res.write()` for streaming, verify error handling on the writable stream and that the response is properly ended in all code paths (including errors). + +## Observability and metric hygiene + +This project uses `hot-shots` StatsD (prefix `docs.`, global tag `app:docs`) configured in `src/observability/lib/statsd.ts`, and a structured logger in `src/observability/logger/index.ts`. Every review must enforce these standards: + +### Metric cardinality (🔴 Critical when violated) + +High-cardinality tags are the #1 cause of metric cost explosions and Datadog aggregation failures. For ANY new `statsd.increment()`, `statsd.histogram()`, `statsd.gauge()`, or `statsd.asyncTimer()` call, verify: + +- **No user-controlled values in tags**: Tags like `path:${req.path}`, `url:${req.url}`, `query:${req.query.q}`, or `user:${userId}` create a unique time series per unique value. With thousands of docs pages and infinite query strings, this quickly creates millions of time series. Tags must use bounded, enumerable values (e.g., `product:actions`, `status:200`, `cache:hit`). +- **Audit existing high-cardinality patterns being copied**: The codebase already has some `path:${req.pagePath}` tags (in `abort.ts`, `handle-errors.ts`, `render-page.ts`). New code MUST NOT copy this pattern without justification. If the tag is on a low-volume error/abort path, it may be acceptable. If it is on a hot path (every request), it is not. +- **Tag value normalization**: If a path-like tag is genuinely needed, it must be normalized to a bounded set. Example: use the top-level product category (`actions`, `copilot`, `rest`) not the full URL path. Use route patterns (`/[version]/[product]/[...slug]`) not resolved paths. +- **New metric names**: Every new metric name should follow the existing `docs..` convention (e.g., `docs.middleware.render_page`, `docs.cache.lookup`). Inconsistent naming fragments the metric namespace. +- **Missing metrics on new code paths**: New middleware, new API routes, and new cache layers should emit at minimum: + - A counter for requests/invocations + - A timer/histogram for latency (use `statsd.asyncTimer()` for async functions) + - For caches: hit/miss counter and size gauge (see `src/frame/lib/get-remote-json.ts` for the pattern) +- **Tag consistency**: Tags on related metrics must use the same key names and value sets. Example: if one metric uses `cache:remote_json` and another uses `cache_name:remote_json`, dashboards and alerts will miss the correlation. + +### Structured logging + +- **No `console.log`/`console.warn`/`console.error` in new code**: The project has a structured logger (`import { createLogger } from '@/observability/logger'`). All new logging must use it. `console.*` calls bypass log levels, structured context (request UUID, path, version), and production logfmt formatting. Flag any new `console.*` call in `src/` that is not inside a test file. +- **Logger instantiation**: Each module should create its own logger with `const logger = createLogger(import.meta.url)` so logs include the source file. Flag loggers created without `import.meta.url`. +- **Log level correctness**: `logger.error()` is for unexpected failures that need human attention. `logger.warn()` is for degraded but recoverable situations. `logger.info()` is for significant state changes. `logger.debug()` is for developer troubleshooting. Flag misuse—especially `logger.info()` on every request (that is debug-level noise) or `logger.error()` for expected conditions (e.g., 404s). +- **Sensitive data in logs**: Log messages must not include auth tokens, cookies, full request bodies, or user-identifiable information. Check for `logger.error('Failed', { headers: req.headers })` or similar patterns that dump entire objects. + +## Next.js-specific checks + +For Next.js application code, check for: + +- **Client/server boundary violations**: Code importing server-only modules (e.g., `fs`, `path`, database clients, `process.env` secrets) in files that end up in the client bundle. Verify `'use client'` / `'use server'` directives are correct. +- **Data fetching in wrong context**: `getServerSideProps` or server components doing work that should be client-side (or vice versa). Watch for `useEffect` fetches that duplicate server-side data. +- **Middleware correctness**: Next.js middleware runs on every matched request. Verify `matcher` config is not overly broad. Expensive operations in middleware multiply across every request. +- **Dynamic route parameter injection**: `params` from dynamic routes (`[slug]`, `[...catchAll]`) are user-controlled strings. They must be validated/sanitized before use in database queries, file paths, or rendered HTML. +- **Missing error boundaries**: New pages or complex component trees should have error boundaries. An unhandled throw in a React Server Component crashes the entire page. +- **Accidental client bundle bloat**: Importing large server-side libraries in shared modules that are also imported by client components. Check import chains. +- **`headers()`, `cookies()`, `searchParams` in cached contexts**: These dynamic APIs opt a route out of static generation. Verify the author intended dynamic rendering. + +## Dependency security + +When `package.json` or `package-lock.json` is changed, check for: + +- **New dependencies with known vulnerabilities**: Run `npm audit --json` (or check the npm advisory database) for any newly added package. Flag any dependency introduced with known critical or high severity CVEs. +- **Unnecessary new dependencies**: Before accepting a new `dependencies` entry, ask: does the project already have a library that does this? Adding a package for something achievable with existing deps or a few lines of code increases supply chain risk and bundle size. +- **`dependencies` vs `devDependencies`**: Packages used only in tests, linting, or build tooling must be in `devDependencies`, not `dependencies`. Production `dependencies` are installed in the Docker image and loaded at runtime—every unnecessary entry increases attack surface and image size. +- **Pinning and lockfile hygiene**: New entries should have a semver range consistent with the rest of `package.json` (typically `^`). Verify `package-lock.json` is updated and committed alongside `package.json` changes. A `package.json` change without a corresponding lockfile update is a red flag. +- **Postinstall scripts**: Check if a newly added package has `postinstall`, `preinstall`, or `install` scripts by inspecting its `package.json` in `node_modules/`. These scripts run arbitrary code at install time and are a common supply-chain attack vector. +- **Deprecated packages**: Flag any newly added dependency that npm marks as deprecated. Deprecated packages receive no security updates. + +## Bash script checks + +For shell scripts, check for: + +- Working directory assumptions (e.g., `cat .nvmrc` without resolving script dir first) +- Fragile version parsing (e.g., grepping `package.json` instead of using `node -p "require('./package.json').version"`) +- Hard-coded env var requirements that may not be set in all environments (local, CI, production) +- Sourcing files (`. script/foo` or `source script/foo`) without checking the file exists first +- Suppressing stderr with `2>/dev/null` on commands whose failure matters +- `set -e` gotchas: command substitution inside `echo`, `local`, or `readonly` masks the substitution's exit code + +## Docker/container checks + +For `Dockerfile` and `docker-compose.yaml`: + +- Multi-stage build layers that copy `node_modules` from a builder stage must ensure the builder used the same platform/architecture as the runtime stage +- `COPY package*.json ./` before `npm ci` to preserve layer caching. Copying the entire source tree first invalidates the dependency cache on every code change +- Running as `root` in the final stage without dropping privileges +- Missing `NODE_ENV=production` in the runtime stage (affects dependency installation, Next.js optimizations, and Express behavior) +- Health check endpoints that always return 200 without actually verifying service readiness +- Secrets or tokens passed as `ARG`/`ENV` that persist in image layers + +## Verification requirements + +CRITICAL: Before reporting ANY issue, you MUST verify it exists in the actual file. + +Git diff output can be misleading due to: +- Long lines wrapping in terminal display +- Diff excerpts not showing the complete file +- Display artifacts from terminal width + +For each potential issue identified in a diff: + +1. Use `read_file` or `grep` to verify the issue exists in the actual file +2. Only report issues that are confirmed in the source file +3. If verification shows the issue doesn't exist, discard it silently + +Example verification commands: +```bash +# Verify a pattern exists +rg -n "suspected_issue" path/to/file + +# Verify something is missing at end of file +tail -10 path/to/file + +# Check if a function is exported but never imported +rg -l "import.*functionName" src/ + +# Verify an `any` type exists +rg -n ": any\b" path/to/file + +# Check for unhandled promises +rg -n "(?:^|\s)(?!await\s)(?!return\s)(?!void\s)\w+\(" path/to/file.ts +``` + +Do NOT report issues based solely on how the diff appears in terminal output. + +## Output format + +1. First, write all issues to a markdown file at `tmp/copilot-review-{branch-name}.md` where `{branch-name}` is the current git branch name (replace `/` with `-` in the branch name) + - Example: branch `jmoody/my-feature` → `tmp/copilot-review-jmoody-my-feature.md` +2. The report file should contain: + - A summary section with total issue count by severity (🔴 Critical, 🟠 High, 🟡 Medium, 🔵 Low) + - All issues with file paths and line numbers +3. Then present each issue ONE AT A TIME in the chat, starting with the highest severity +4. For each issue, wait for user feedback before proceeding to the next +5. Format each issue as: + +```markdown +## Issue N: [Brief title] [🔴|🟠|🟡|🔵] + +**File**: path/to/file:line +**Description**: What the issue is +**Impact**: What happens if this is not fixed (be specific—"could crash" is not enough, say *when* and *how*) +**Suggestion**: How to fix it (include a code snippet if the fix is non-obvious) +``` + +After presenting each issue, ask: + +> How would you like to proceed? +> 1. Fix it for me +> 2. I'll fix it differently +> 3. More details please +> 4. Show me other options +> 5. Skip to next issue diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000000..644c8c38c014 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,34 @@ +name: 'Copilot Setup Steps' + +on: + workflow_dispatch: + +jobs: + copilot-setup-steps: + runs-on: ubuntu-latest + if: github.repository == 'github/docs-internal' || github.repository == 'github/docs' + permissions: + contents: read + id-token: write + env: + ELASTICSEARCH_URL: http://localhost:9200/ + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - uses: ./.github/actions/node-npm-setup + + - uses: ./.github/actions/setup-elasticsearch + with: + token: ${{ secrets.DOCS_BOT_PAT_BASE }} + + - uses: ./.github/actions/get-docs-early-access + if: ${{ github.repository == 'github/docs-internal' }} + with: + token: ${{ secrets.DOCS_BOT_PAT_BASE }} + + - name: Build + run: npm run build + + - name: Index fixtures into the local Elasticsearch + run: npm run index-test-fixtures diff --git a/assets/images/help/copilot/vsc-copilot-chat-icon.png b/assets/images/help/copilot/vsc-copilot-chat-icon.png index 1a338b5546c5..929096c293da 100644 Binary files a/assets/images/help/copilot/vsc-copilot-chat-icon.png and b/assets/images/help/copilot/vsc-copilot-chat-icon.png differ diff --git a/content/admin/data-residency/feature-overview-for-github-enterprise-cloud-with-data-residency.md b/content/admin/data-residency/feature-overview-for-github-enterprise-cloud-with-data-residency.md index 6bfe57ddbd69..7819f0f2fa4d 100644 --- a/content/admin/data-residency/feature-overview-for-github-enterprise-cloud-with-data-residency.md +++ b/content/admin/data-residency/feature-overview-for-github-enterprise-cloud-with-data-residency.md @@ -71,6 +71,7 @@ The following examples are not exhaustive. | OIDC trusts for {% data variables.product.prodname_actions %} deployments | The OIDC token is issued from `https://token.actions.githubusercontent.com`. | The OIDC token is issued from `https://token.actions.SUBDOMAIN.ghe.com` | | Raw URLs | `https://raw.githubusercontent.com/` | `https://raw.SUBDOMAIN.ghe.com/` | | Anonymized URLs for images and videos | `https://private-user-images.githubusercontent.com/` | `https://SUBDOMAIN.ghe.com/user-attachments/assets/` | +| Cloning repositories using SSH | `git clone git@github.com:OWNER/REPOSITORY.git` | `git clone SUBDOMAIN@SUBDOMAIN.ghe.com:OWNER/REPOSITORY.git` | {% endrowheaders %} diff --git a/content/admin/data-residency/network-details-for-ghecom.md b/content/admin/data-residency/network-details-for-ghecom.md index 1cb44bd1c603..ddfa94fa0f6c 100644 --- a/content/admin/data-residency/network-details-for-ghecom.md +++ b/content/admin/data-residency/network-details-for-ghecom.md @@ -27,6 +27,14 @@ gh api /meta --hostname octocorp.ghe.com For more information, see [AUTOTITLE](/rest/meta/meta). +## Using SSH with {% data variables.enterprise.data_residency_site %} + +To clone a repository using Git over SSH from `{% data variables.enterprise.data_residency_domain %}`, where SUBDOMAIN is your enterprise's dedicated subdomain on {% data variables.enterprise.data_residency_site %}, use the SUBDOMAIN as the SSH username instead of `git`. + +```shell +git clone SUBDOMAIN@SUBDOMAIN.ghe.com:OWNER/REPO.git +``` + ## {% data variables.product.github %}'s hostnames * `*.{% data variables.enterprise.data_residency_domain %}`, where SUBDOMAIN is your enterprise's dedicated subdomain on {% data variables.enterprise.data_residency_site %} diff --git a/content/authentication/connecting-to-github-with-ssh/managing-deploy-keys.md b/content/authentication/connecting-to-github-with-ssh/managing-deploy-keys.md index a5afd50c0f6e..149983df6748 100644 --- a/content/authentication/connecting-to-github-with-ssh/managing-deploy-keys.md +++ b/content/authentication/connecting-to-github-with-ssh/managing-deploy-keys.md @@ -103,6 +103,22 @@ For enhanced security and fine-grained control over repository access and permis You can also use the REST API to create deploy keys. For more information, see [AUTOTITLE](/rest/deploy-keys/deploy-keys). +You can then interact with the repository using SSH. For example: + +```bash +git clone git@{% ifversion fpt or ghec %}github.com{% else %}my-GHE-hostname.com{% endif %}:OWNER/REPO.git +``` + +{% ifversion ghec %} + +> [!NOTE] {% data reusables.enterprise-data-residency.ssh-user %} +> +> ```bash +> git clone {% data variables.enterprise.data_residency_example_git_ssh %}:OWNER/REPO.git +> ``` + +{% endif %} + ### Using multiple repositories on one server If you use multiple repositories on one server, you will need to generate a dedicated key pair for each one. You can't reuse a deploy key for multiple repositories. diff --git a/content/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection.md b/content/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection.md index 35859bd5ef32..3ed3e9dc536f 100644 --- a/content/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection.md +++ b/content/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection.md @@ -69,3 +69,14 @@ You'll need to authenticate this action using your password, which is the SSH ke > The remote command should exit with code 1. 1. Verify that the resulting message contains your username. If you receive a "permission denied" message, see [AUTOTITLE](/authentication/troubleshooting-ssh/error-permission-denied-publickey). + +{% ifversion ghec or fpt %} + +> [!TIP] {% data reusables.enterprise-data-residency.ssh-user %} +> +> ```shell +> ssh -T {% data variables.enterprise.data_residency_example_git_ssh %} +> # Attempts to ssh to {% data variables.enterprise.data_residency_example_domain %} +> ``` + +{% endif %} diff --git a/content/authentication/troubleshooting-ssh/error-permission-denied-publickey.md b/content/authentication/troubleshooting-ssh/error-permission-denied-publickey.md index 05c2612edac1..fc569e308b03 100644 --- a/content/authentication/troubleshooting-ssh/error-permission-denied-publickey.md +++ b/content/authentication/troubleshooting-ssh/error-permission-denied-publickey.md @@ -68,6 +68,17 @@ You should see this output: > Hi USERNAME! You've successfully authenticated... ``` +{% ifversion ghec %} + +> [!WARNING] +> {% data reusables.enterprise-data-residency.ssh-user %} +> +> ```shell +> ssh -T {% data variables.enterprise.data_residency_example_git_ssh %} +> ``` + +{% endif %} + ## Make sure you have a key that is being used {% mac %} diff --git a/content/copilot/concepts/agents/coding-agent/about-coding-agent.md b/content/copilot/concepts/agents/coding-agent/about-coding-agent.md index 9717159f6e66..f194d1942f25 100644 --- a/content/copilot/concepts/agents/coding-agent/about-coding-agent.md +++ b/content/copilot/concepts/agents/coding-agent/about-coding-agent.md @@ -142,7 +142,9 @@ Security is a fundamental consideration when you enable {% data variables.copilo * {% data variables.copilot.copilot_coding_agent %}'s security validation **does not require** a {% data variables.product.prodname_GHAS_cs_or_sp %} license. * **Subject to existing governance**: Organization settings and enterprise policies control availability. Any security policies and practices set up for the organization also apply to {% data variables.copilot.copilot_coding_agent %}. * **Restricted development environment**: {% data variables.copilot.copilot_coding_agent %} works in a sandbox development environment with internet access controlled by a firewall. It has read-only access to the repository it's assigned to work in. -* **Limited access to branches**: {% data variables.copilot.copilot_coding_agent %} can only create and push to branches beginning with `copilot/`. It is subject to any branch protections and required checks for the working repository. +* **Limited access to branches** + * {% data variables.copilot.copilot_coding_agent %} only has the ability to push to a single branch. When the agent is triggered by mentioning `@copilot` on an existing pull request, {% data variables.product.prodname_copilot_short %} has write access to the pull request's branch. In other cases, a new `copilot/` branch is created for {% data variables.product.prodname_copilot_short %}, and the agent can only push to that branch. + * {% data variables.copilot.copilot_coding_agent %} is subject to any branch protections and required checks for the working repository. * **Responds only to users with write permissions**: {% data variables.copilot.copilot_coding_agent %} will not respond to feedback from users with lower levels of access. * **Treated as an outside collaborator** * Draft pull requests created by {% data variables.copilot.copilot_coding_agent %} must be reviewed and merged by a human. {% data variables.copilot.copilot_coding_agent %} cannot mark its pull requests as "Ready for review" and cannot approve or merge a pull request. @@ -163,7 +165,7 @@ For more information, see: To mitigate this risk, {% data variables.product.github %}: * **Limits who can assign tasks to {% data variables.copilot.copilot_coding_agent %}.** Only users with write access to the repository can trigger {% data variables.copilot.copilot_coding_agent %} to work. Comments from users without write access are never presented to the agent. -* **Limits the permissions in access tokens used by {% data variables.copilot.copilot_coding_agent %}.** Pushes are only allowed to branches beginning with `copilot/`. {% data variables.copilot.copilot_coding_agent %} cannot push to the `main` or `master` branches. +* **Limits the branch that {% data variables.copilot.copilot_coding_agent %} can push to.** The agent only has the ability to push to a single branch. When the agent is triggered by mentioning `@copilot` on an existing pull request, {% data variables.product.prodname_copilot_short %} has write access to the pull request's branch. In other cases, a new `copilot/` branch is created for {% data variables.product.prodname_copilot_short %}, and the agent can only push to that branch. * **Limits {% data variables.copilot.copilot_coding_agent %}'s credentials.** {% data variables.copilot.copilot_coding_agent %} can only perform simple push operations. It cannot directly run `git push` or other Git commands. * **Restricts {% data variables.product.prodname_actions %} workflow runs.** By default, workflows are not triggered until {% data variables.copilot.copilot_coding_agent %}'s code is reviewed and a user with write access to the repository clicks the **Approve and run workflows** button. Optionally, you can configure {% data variables.product.prodname_copilot_short %} to allow workflows to run automatically. See [AUTOTITLE](/copilot/how-tos/use-copilot-agents/coding-agent/review-copilot-prs#managing-github-actions-workflow-runs). * **Prevents the user who asked {% data variables.copilot.copilot_coding_agent %} to create a pull request from approving it.** This maintains the expected controls in the "Required approvals" rule and branch protection. See [AUTOTITLE](/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets). diff --git a/content/copilot/concepts/agents/coding-agent/access-management.md b/content/copilot/concepts/agents/coding-agent/access-management.md index 205578c14d29..5c154f108bb2 100644 --- a/content/copilot/concepts/agents/coding-agent/access-management.md +++ b/content/copilot/concepts/agents/coding-agent/access-management.md @@ -45,11 +45,11 @@ By default, users with {% data variables.copilot.copilot_coding_agent %} enabled Enterprise administrators and organization owners (for organization-owned repositories) and users (for user-owned repositories) can opt out repositories and prevent {% data variables.copilot.copilot_coding_agent %} from being used in those repositories. -For information on disabling {% data variables.copilot.copilot_coding_agent %} in repositories owned by your personal user account, see [AUTOTITLE](/copilot/managing-copilot/managing-copilot-as-an-individual-subscriber/managing-your-copilot-plan/managing-copilot-policies-as-an-individual-subscriber#enabling-or-disabling-copilot-coding-agent). +For information on disabling {% data variables.copilot.copilot_coding_agent %} in some or all repositories owned by an organization, see [AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization). For information on disabling {% data variables.copilot.copilot_coding_agent %} in all repositories owned by an enterprise, see [AUTOTITLE](/enterprise-cloud@latest/copilot/managing-copilot/managing-copilot-for-your-enterprise/managing-copilot-coding-agent-in-your-enterprise). -For information on disabling {% data variables.copilot.copilot_coding_agent %} in some or all repositories owned by an organization, see [AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization). +For information on disabling {% data variables.copilot.copilot_coding_agent %} in repositories owned by your personal user account, see [AUTOTITLE](/copilot/managing-copilot/managing-copilot-as-an-individual-subscriber/managing-your-copilot-plan/managing-copilot-policies-as-an-individual-subscriber#enabling-or-disabling-copilot-coding-agent). ## Further reading diff --git a/content/copilot/concepts/completions/code-suggestions.md b/content/copilot/concepts/completions/code-suggestions.md index fc1f9e4b122d..436b9803df9e 100644 --- a/content/copilot/concepts/completions/code-suggestions.md +++ b/content/copilot/concepts/completions/code-suggestions.md @@ -17,10 +17,13 @@ category: {% data variables.product.prodname_copilot_short %} in {% data variables.product.prodname_vscode %} provides two kinds of code suggestions: +* **{% data variables.copilot.next_edit_suggestions_caps %}** + + Based on the edits you are making, {% data variables.product.prodname_copilot_short %} both predicts the location of the next edit you'll want to make and what that edit should be. To enable {% data variables.copilot.next_edit_suggestions %}, see [AUTOTITLE](/copilot/managing-copilot/configure-personal-settings/configuring-github-copilot-in-your-environment#enabling-next-edit-suggestions). + * **Ghost text suggestions** - * {% data variables.product.prodname_copilot_short %} offers coding suggestions as you type. You can also describe something you want to do using natural language within a comment, and {% data variables.product.prodname_copilot_short %} will suggest the code to accomplish your goal. -* **{% data variables.copilot.next_edit_suggestions_caps %} ({% data variables.release-phases.public_preview %})** - * Based on the edits you are making, {% data variables.product.prodname_copilot_short %} will predict the location of the next edit you are likely to make and suggest a completion for it. Suggestions may span a single symbol, an entire line, or multiple lines, depending on the scope of the potential change. To enable {% data variables.copilot.next_edit_suggestions %}, see [AUTOTITLE](/copilot/managing-copilot/configure-personal-settings/configuring-github-copilot-in-your-environment#enabling-next-edit-suggestions). + + {% data variables.product.prodname_copilot_short %} offers coding suggestions as you type. Start typing in the editor, and Copilot provides dimmed ghost text suggestions at your current cursor location. You can also describe something you want to do using natural language within a comment, and {% data variables.product.prodname_copilot_short %} will suggest the code to accomplish your goal. {% data reusables.copilot.supported-languages %} @@ -43,9 +46,12 @@ category: {% data variables.product.prodname_copilot_short %} in {% data variables.product.prodname_vs %} provides two kinds of code suggestions: * **Ghost text suggestions** - * {% data variables.product.prodname_copilot_short %} offers coding suggestions as you type. + + {% data variables.product.prodname_copilot_short %} offers coding suggestions as you type. + * **{% data variables.copilot.next_edit_suggestions_caps %} ({% data variables.release-phases.public_preview %})** - * Based on the edits you are making, {% data variables.product.prodname_copilot_short %} will predict the location of the next edit you are likely to make and suggest a completion for it. Suggestions may span a single symbol, an entire line, or multiple lines, depending on the scope of the potential change. To enable {% data variables.copilot.next_edit_suggestions %}, see [AUTOTITLE](/copilot/managing-copilot/configure-personal-settings/configuring-github-copilot-in-your-environment#enabling-next-edit-suggestions). + + Based on the edits you are making, {% data variables.product.prodname_copilot_short %} will predict the location of the next edit you are likely to make and suggest a completion for it. Suggestions may span a single symbol, an entire line, or multiple lines, depending on the scope of the potential change. To enable {% data variables.copilot.next_edit_suggestions %}, see [AUTOTITLE](/copilot/managing-copilot/configure-personal-settings/configuring-github-copilot-in-your-environment#enabling-next-edit-suggestions). {% data reusables.copilot.supported-languages %} @@ -99,10 +105,6 @@ category: {% data variables.product.prodname_copilot %} checks each suggestion for matches with publicly available code. Matches may be discarded or suggested with a code reference, based on the setting of the "Suggestions matching public code" policy for your account or organization. See [AUTOTITLE](/copilot/concepts/completions/code-referencing). -## About the AI model used for {% data variables.product.prodname_copilot_short %} inline suggestions - -{% data variables.product.prodname_copilot_short %} inline suggestions use the {% data variables.copilot.copilot_gpt_41 %} {% data variables.product.prodname_copilot_short %} model. The {% data variables.copilot.copilot_gpt_41 %} {% data variables.product.prodname_copilot_short %} model was trained on a wide range of high quality public {% data variables.product.github %} repositories, providing coverage of over 30 programming languages. See [Programming languages included in the default model](#programming-languages-included-in-the-default-model) below. - {% vscode %} ## Changing the model used for inline suggestions diff --git a/content/copilot/get-started/features.md b/content/copilot/get-started/features.md index ac4457cdf75b..a5592d652382 100644 --- a/content/copilot/get-started/features.md +++ b/content/copilot/get-started/features.md @@ -17,12 +17,6 @@ category: ## {% data variables.product.prodname_copilot %} features -### Inline suggestions - -Autocomplete-style suggestions from {% data variables.product.prodname_copilot_short %} in supported IDEs _({% data variables.product.prodname_vscode %}, {% data variables.product.prodname_vs %}, JetBrains IDEs, Azure Data Studio, Xcode, Vim/Neovim, and Eclipse)_. See [AUTOTITLE](/copilot/using-github-copilot/getting-code-suggestions-in-your-ide-with-github-copilot). - -If you use {% data variables.product.prodname_vscode_shortname %}, Xcode, and Eclipse, you can also use {% data variables.copilot.next_edit_suggestions %} ({% data variables.release-phases.public_preview %}), which will predict the location of the next edit you are likely to make and suggest a completion for it. - ### {% data variables.copilot.copilot_chat_short %} A chat interface that lets you ask coding-related questions. {% data variables.copilot.copilot_chat %} is available on the {% data variables.product.github %} website, in {% data variables.product.prodname_mobile %}, in supported IDEs _({% data variables.product.prodname_vscode %}, {% data variables.product.prodname_vs %}, JetBrains IDEs, Eclipse IDE, and Xcode)_, and in {% data variables.product.prodname_windows_terminal %}. Users can also use skills with {% data variables.copilot.copilot_chat_short %}. See [AUTOTITLE](/copilot/using-github-copilot/asking-github-copilot-questions-in-github) and [AUTOTITLE](/copilot/using-github-copilot/asking-github-copilot-questions-in-your-ide). @@ -49,6 +43,12 @@ Several {% data variables.copilot.copilot_code-review-tools_short %} are in {% d AI-generated summaries of the changes that were made in a pull request, which files they impact, and what a reviewer should focus on when they conduct their review. See [AUTOTITLE](/copilot/using-github-copilot/creating-a-pull-request-summary-with-github-copilot). +### Inline suggestions + +Autocomplete-style suggestions from {% data variables.product.prodname_copilot_short %} in supported IDEs ({% data variables.product.prodname_vscode %}, {% data variables.product.prodname_vs %}, JetBrains IDEs, Azure Data Studio, Xcode, Vim/Neovim, and Eclipse). See [AUTOTITLE](/copilot/using-github-copilot/getting-code-suggestions-in-your-ide-with-github-copilot). + +If you use {% data variables.product.prodname_vscode_shortname %}, Xcode, and Eclipse, you can also use {% data variables.copilot.next_edit_suggestions %}, which will predict the location of the next edit you are likely to make and suggest a completion for it. + ### {% data variables.copilot.copilot_edits_short %} {% data variables.copilot.copilot_edits_short %} is available in {% data variables.product.prodname_vscode %}, {% data variables.product.prodname_vs %}, and JetBrains IDEs. {% data reusables.copilot.copilot-edits.about-copilot-edits %} diff --git a/content/copilot/get-started/quickstart.md b/content/copilot/get-started/quickstart.md index 917c2c2032c6..335c546941c3 100644 --- a/content/copilot/get-started/quickstart.md +++ b/content/copilot/get-started/quickstart.md @@ -158,25 +158,15 @@ Instructions for using {% data variables.product.prodname_copilot_short %} diffe ## Chat with {% data variables.product.prodname_copilot %} -After you've installed the {% data variables.product.prodname_copilot %} extension, you can ask {% data variables.product.prodname_copilot_short %} coding-related questions. +After you've installed the {% data variables.product.prodname_copilot %} Chat extension, you can ask {% data variables.product.prodname_copilot_short %} coding-related questions. > [!NOTE] {% data reusables.copilot.chat-access-denied %} -1. Open an existing code file. -1. Open the Chat view from the Activity Bar. - - ![Screenshot of the Chat icon in the {% data variables.product.prodname_vscode_shortname %} Activity Bar.](/assets/images/help/copilot/chat-button-vscode.png) - -1. At the bottom of the chat view, in the chat input field, type: `explain this file`. -1. Press Enter. - - {% data variables.product.prodname_copilot_short %} replies in the chat view. - -1. In the editor, select one or more lines of code that are not commented. -1. In the chat input field, type: `add comments to these lines`. -1. If you like the comments that {% data variables.product.prodname_copilot_short %} suggests, hover over the suggested code in the chat view and click the "Insert at Cursor" icon to replace the selected lines with the suggested code. - - ![Screenshot of the "Insert at Cursor" icon in the chat view.](/assets/images/help/copilot/insert-at-cursor-vscode.png) +1. Create a new folder for your project and open it in VS Code. +1. Open the Chat view by pressing Control+Command+i (Mac) / Ctrl+Alt+i (Windows/Linux) or by selecting the chat icon in the VS Code title bar. +1. At the bottom of the chat view, in the chat input field, type: `Create a complete task manager web application with the ability to add, delete, and mark tasks as completed. Include modern CSS styling and make it responsive. Use semantic HTML and ensure it's accessible. Separate markup, styles, and scripts into their own files.` +1. Press Enter. Watch as the agent generates the necessary files and code to implement your request. You should see it update the `index.html` file, create a `styles.css` file for styling, and a `script.js` file for functionality. +1. Review the generated files and select Keep to accept all the changes. ## Get your first inline suggestion diff --git a/content/copilot/how-tos/administer-copilot/manage-for-organization/add-copilot-coding-agent.md b/content/copilot/how-tos/administer-copilot/manage-for-organization/add-copilot-coding-agent.md index 59ef63d55b6a..5e60d4592fd8 100644 --- a/content/copilot/how-tos/administer-copilot/manage-for-organization/add-copilot-coding-agent.md +++ b/content/copilot/how-tos/administer-copilot/manage-for-organization/add-copilot-coding-agent.md @@ -40,7 +40,7 @@ Organizations with {% data variables.copilot.copilot_enterprise_short %} or {% d ## Disabling or enabling {% data variables.copilot.copilot_coding_agent %} in your repositories -By default, {% data variables.copilot.copilot_coding_agent %} is available in all repositories for users who have access to the agent, but you can block it from being used in some or all repositories owned by your organization. +By default, {% data variables.copilot.copilot_coding_agent %} is available in all repositories for users who have access to the agent, but you can block it from being used in some or all repositories owned by your organization. You can manage repository availability using the following instructions, or programmatically using the [REST API](/rest/copilot/copilot-coding-agent-management). {% data reusables.profile.access_org %} {% data reusables.profile.org_settings %} diff --git a/content/copilot/how-tos/chat-with-copilot/chat-in-ide.md b/content/copilot/how-tos/chat-with-copilot/chat-in-ide.md index a8dcbc5bc260..485fada7259a 100644 --- a/content/copilot/how-tos/chat-with-copilot/chat-in-ide.md +++ b/content/copilot/how-tos/chat-with-copilot/chat-in-ide.md @@ -23,7 +23,7 @@ category: ## Introduction -This guide describes how to use {% data variables.copilot.copilot_chat_short %} to ask questions about software development in your IDE. You can ask general questions about software development, or specific questions about the code in your project. For more information, see [AUTOTITLE](/copilot/concepts/about-github-copilot-chat). +This guide describes how to use {% data variables.copilot.copilot_chat_short %} and agents to automate coding tasks by breaking them into steps, using tools to read files, edit code, and run commands, and self-correcting when something goes wrong. You can also ask general questions about software development, or specific questions about the code in your project. For more information, see [AUTOTITLE](/copilot/concepts/about-github-copilot-chat). @@ -38,172 +38,154 @@ This guide describes how to use {% data variables.copilot.copilot_chat_short %} {% data reusables.copilot.chat-access-denied %} -## Submitting prompts - -You can ask {% data variables.copilot.copilot_chat_short %} to give you code suggestions, explain code, generate unit tests, and suggest code fixes. - -1. To open the chat view, click the **{% octicon "copilot" aria-hidden="true" aria-label="copilot" %}** icon in the title bar of {% data variables.product.prodname_vscode %}. If the **{% octicon "copilot" aria-hidden="true" aria-label="copilot" %}** icon is not displayed, right-click the title bar and make sure that **Command Center** is selected. - - ![Screenshot of the '{% data variables.copilot.copilot_chat_short %}' button, highlighted with a dark orange outline.](/assets/images/help/copilot/vsc-copilot-chat-icon.png) - -1. Enter a prompt in the prompt box, or click one of the suggested prompts. For an introduction to the kinds of prompts you can use, see [AUTOTITLE](/copilot/get-started/getting-started-with-prompts-for-copilot-chat). - -1. Evaluate {% data variables.product.prodname_copilot_short %}'s response, and make a follow-up request if needed. +## {% data variables.copilot.copilot_chat_short %} agents - The response may contain text, code blocks, buttons, images, URIs, and file trees. The response often includes interactive elements. For example, the response may include a menu to insert a code block, or a button to invoke a {% data variables.product.prodname_vscode %} command. - - To see the files that {% data variables.copilot.copilot_chat_short %} used to generate the response, select the **Used _n_ references** dropdown at the top of the response. The references may include a link to a custom instructions file for your repository. This file contains additional information that is automatically added to all of your chat questions to improve the quality of the responses. For more information, see [AUTOTITLE](/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot). +You can use {% data variables.copilot.copilot_chat_short %} in the following modes: -## Using keywords in your prompt +* [Agent mode](#agent-mode): to get {% data variables.product.prodname_copilot_short %} to autonomously accomplish a set task. +* [Plan mode](#plan-mode): to get {% data variables.product.prodname_copilot_short %} to create detailed implementation plans to ensure all requirements are met. +* [Ask mode](#ask-mode): to get answers to coding questions and get {% data variables.product.prodname_copilot_short %} to provide code suggestions. -You can use special keywords to help {% data variables.product.prodname_copilot_short %} understand your prompt. For examples, see [AUTOTITLE](/copilot/get-started/getting-started-with-prompts-for-copilot-chat). +To switch between modes, use the agents dropdown at the bottom of the chat view. -### Chat participants +### Agent mode -Chat participants are like domain experts who have a specialty that they can help you with. +{% data reusables.copilot.copilot-edits.agent-mode-description %} -{% data variables.copilot.copilot_chat_short %} can infer relevant chat participants based on your natural language prompt, improving discovery of advanced capabilities without you having to explicitly specify the participant you want to use in your prompt. +#### Using agents -> [!NOTE] Automatic inference for chat participants is currently in {% data variables.release-phases.public_preview %} and is subject to change. +1. If the chat view is not already displayed, select **Open Chat** from the {% data variables.copilot.copilot_chat_short %} menu. +1. At the bottom of the chat view, ensure **Agent** is selected from the agents dropdown. +1. Submit a prompt. In response to your prompt, {% data variables.product.prodname_copilot_short %} streams the edits in the editor, updates the working set, and if necessary, runs terminal commands, if necessary. +1. Review and iterate on changes or run a code review. -Alternatively, you can manually specify a chat participant to scope your prompt to a specific domain. To do this, type `@` in the chat prompt box, followed by a chat participant name. +You can also [click this link](vscode://GitHub.Copilot-Chat/chat?mode=agent&ref_product=copilot&ref_type=engagement&ref_style=text) to go directly to agent mode in {% data variables.product.prodname_vscode_shortname %}. -For a list of available chat participants, type `@` in the chat prompt box. See also [AUTOTITLE](/copilot/using-github-copilot/github-copilot-chat-cheat-sheet?tool=vscode#chat-participants) or [Chat participants](https://code.visualstudio.com/docs/copilot/copilot-chat#_chat-participants) in the {% data variables.product.prodname_vscode %} documentation. +For more information, see [Chat overview](https://aka.ms/vscode-copilot-agent) in the {% data variables.product.prodname_vscode %} documentation. -### Slash commands +{% data reusables.copilot.copilot-edits.agent-mode-requests %} -Use slash commands to avoid writing complex prompts for common scenarios. To use a slash command, type `/` in the chat prompt box, followed by a command. +#### Using {% data variables.copilot.subagents_short %} -To see all available slash commands, type `/` in the chat prompt box. See also [AUTOTITLE](/copilot/using-github-copilot/github-copilot-chat-cheat-sheet?tool=vscode#slash-commands) or [Slash commands](https://code.visualstudio.com/docs/copilot/copilot-chat#_slash-commands) in the {% data variables.product.prodname_vscode %} documentation. +{% data reusables.copilot.subagent-intro %} -### Chat variables +#### Enabling {% data variables.copilot.subagents_short %} -Use chat variables to include specific context in your prompt. To use a chat variable, type `#` in the chat prompt box, followed by a chat variable. +1. In the {% data variables.copilot.copilot_chat_short %} window, click the tools icon. +1. Enable the `runSubagent` tool. -To see all available chat variables, type `#` in the chat prompt box. See also [AUTOTITLE](/copilot/using-github-copilot/github-copilot-chat-cheat-sheet?tool=vscode#chat-variables) or [Chat variables](https://code.visualstudio.com/docs/copilot/copilot-chat#_chat-variables) in the {% data variables.product.prodname_vscode %} documentation. +If you use custom prompt files or {% data variables.copilot.custom_agents_short %}, ensure you specify the `runSubagent` tool in the `tools` frontmatter property. See [AUTOTITLE](/copilot/how-tos/use-copilot-agents/coding-agent/create-custom-agents#creating-a-custom-agent-profile-in-visual-studio-code), and [Use prompt files in VS Code](https://code.visualstudio.com/docs/copilot/customization/prompt-files) in the {% data variables.product.prodname_vscode %} documentation. -## Using {% data variables.product.prodname_dotcom %} skills for {% data variables.product.prodname_copilot_short %} +#### Invoking {% data variables.copilot.subagents_short %} -{% data reusables.copilot.using-skills %} +{% data reusables.copilot.using-subagents %} +* **Calling the #runSubagent tool.** -## Using Model Context Protocol (MCP) servers + ```text + Evaluate the #file:databaseSchema using #runSubagent and generate an optimized data-migration plan. + ``` -{% data reusables.copilot.mcp.mcp-chat-in-ide %} +When the {% data variables.copilot.subagent_short %} completes its task, its results appear back in the main chat session, ready for follow-up questions or next steps. -## AI models for {% data variables.copilot.copilot_chat_short %} +### Plan mode -{% data reusables.copilot.change-the-ai-model %} +Plan mode helps you to create detailed implementation plans before executing them. This ensures that all requirements are considered and addressed before any code changes are made. The plan agent does not make any code changes until the plan is reviewed and approved by you. Once approved, you can hand off the plan to the default agent or save it for further refinement, review, or team discussions. -## Additional ways to access {% data variables.copilot.copilot_chat_short %} +The plan agent is designed to: -In addition to submitting prompts through the chat view, you can submit prompts in other ways: +* Research the task comprehensively using read-only tools and codebase analysis to identify requirements and constraints. +* Break down the task into manageable, actionable steps and include open questions about ambiguous requirements. +* Present a concise plan draft, based on a standardized plan format, for user review and iteration. -* **Quick chat:** To open the quick chat dropdown, enter +++L (Mac) / Ctrl+Shift+Alt+L (Windows/Linux). -* **Inline:** To start an inline chat directly in the editor or integrated terminal, enter Command+i (Mac) / Ctrl+i (Windows/Linux). -* **Smart actions:** To submit prompts via the context menu, right click in your editor, select **{% data variables.product.prodname_copilot_short %}** in the menu that appears, then select one of the actions. Smart actions can also be accessed via the sparkle icon that sometimes appears when you select a line of code. +#### Using the plan agent -See [inline chat](https://code.visualstudio.com/docs/copilot/copilot-chat#_inline-chat), [quick chat](https://code.visualstudio.com/docs/copilot/copilot-chat#_quick-chat), and [chat smart actions](https://code.visualstudio.com/docs/copilot/copilot-chat#_chat-smart-actions) in the {% data variables.product.prodname_vscode %} documentation for more details. +1. If the chat view is not already displayed, select **Open Chat** from the {% data variables.copilot.copilot_chat_short %} menu. +1. At the bottom of the chat view, select **Plan** from the agents dropdown. +1. Type a prompt that describes a task, such as adding a feature to an existing application, refactoring code, fixing a bug, or creating an initial version of a new application. -## {% data variables.copilot.copilot_chat_short %} chat modes + For example: `Create a simple to-do web app with HTML, CSS, and JS files.` -You can use {% data variables.copilot.copilot_chat_short %} in the following modes: + After a few moments, the plan agent outputs a plan in the chat view. The plan provides a high-level summary and a breakdown of steps, including any open questions for clarification. -* [Ask mode](#ask-mode): to get answers to coding questions and get {% data variables.product.prodname_copilot_short %} to provide code suggestions. -* [Edit mode](#edit-mode): to get {% data variables.product.prodname_copilot_short %} to make controlled edits to multiple files. -* [Agent mode](#agent-mode): to get {% data variables.product.prodname_copilot_short %} to autonomously accomplish a set task. -* [Plan mode](#plan-mode): to get {% data variables.product.prodname_copilot_short %} to create detailed implementation plans to ensure all requirements are met. +{% data reusables.copilot.plan-agent-steps %} -To switch between modes, use the agents dropdown at the bottom of the chat view. +For more information, see [Planning with agents in VS Code](https://code.visualstudio.com/docs/copilot/agents/planning) in the {% data variables.product.prodname_vscode %} documentation. ### Ask mode -Ask mode is optimized for answering questions about your codebase, coding, and general technology concepts. Use ask mode when you want to understand how something works, explore ideas, or get help with coding tasks. For larger changes across multiple files or more complex coding tasks, consider using edit mode or agent mode. +Ask mode is optimized for answering questions about your codebase, coding, and general technology concepts. Use ask mode when you want to understand how something works, explore ideas, or get help with coding tasks. -#### Using ask mode +#### Using the ask agent 1. If the chat view is not already displayed, select **Open Chat** from the {% data variables.copilot.copilot_chat_short %} menu. 1. At the bottom of the chat view, select **Ask** from the agents dropdown. 1. Type a prompt in the prompt box and press Enter. -### Edit mode +## Submitting prompts -{% data reusables.copilot.copilot-edits.edit-mode-description %} +You can give the agent a high-level description of what you want to build and it gets to work. Each task runs inside an agent session, a persistent conversation you can track, pause, resume, or hand off to another agent. -#### Using edit mode +1. To open the chat view, click the chat icon in the title bar of {% data variables.product.prodname_vscode %}. If the chat icon is not displayed, right-click the title bar and make sure that **Command Center** is selected. -1. If the chat view is not already displayed, select **Open Chat** from the {% data variables.copilot.copilot_chat_short %} menu. -1. At the bottom of the chat view, select **Edit** from the agents dropdown. + ![Screenshot of the '{% data variables.copilot.copilot_chat_short %}' button, highlighted with a dark orange outline.](/assets/images/help/copilot/vsc-copilot-chat-icon.png) - ![Screenshot of the {% data variables.copilot.copilot_chat_short %} agents dropdown. The "Edit" option is outlined in dark orange.](/assets/images/help/copilot/chat-mode-vscode.png) +1. Enter a prompt in the prompt box. For an introduction to the kinds of prompts you can use, see [AUTOTITLE](/copilot/get-started/getting-started-with-prompts-for-copilot-chat). -1. Optionally, add relevant files to the _working set_ to indicate to {% data variables.product.prodname_copilot %} which files you want to work on. -1. Submit a prompt. In response to your prompt, {% data variables.copilot.copilot_edits_short %} determines which files in your _working set_ to change and adds a short description of the change. -1. Review the changes and **Apply** or **Discard** the edits for each file. +1. Evaluate {% data variables.product.prodname_copilot_short %}'s response, and make a follow-up request if needed. -For more detailed instructions, see [{% data variables.copilot.copilot_edits_short %}](https://code.visualstudio.com/docs/copilot/copilot-edits) in the {% data variables.product.prodname_vscode %} documentation. + The response may contain text, code blocks, buttons, images, URIs, and file trees. The response often includes interactive elements. For example, the response may include a menu to insert a code block, or a button to invoke a {% data variables.product.prodname_vscode %} command. -### Agent mode + To see the files that {% data variables.copilot.copilot_chat_short %} used to generate the response, select the **Used _n_ references** dropdown at the top of the response. The references may include a link to a custom instructions file for your repository. This file contains additional information that is automatically added to all of your chat questions to improve the quality of the responses. For more information, see [AUTOTITLE](/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot). -{% data reusables.copilot.copilot-edits.agent-mode-description %} +## Using keywords in your prompt -#### Using agent mode +You can use special keywords to help {% data variables.product.prodname_copilot_short %} understand your prompt. For examples, see [AUTOTITLE](/copilot/get-started/getting-started-with-prompts-for-copilot-chat). -1. If the chat view is not already displayed, select **Open Chat** from the {% data variables.copilot.copilot_chat_short %} menu. -1. At the bottom of the chat view, select **Agent** from the agents dropdown. -1. Submit a prompt. In response to your prompt, {% data variables.product.prodname_copilot_short %} streams the edits in the editor, updates the working set, and if necessary, suggests terminal commands to run. -1. Review the changes. If {% data variables.product.prodname_copilot_short %} suggested terminal commands, confirm whether or not {% data variables.product.prodname_copilot_short %} can run them. In response, {% data variables.product.prodname_copilot_short %} iterates and performs additional actions to complete the task in your original prompt. +### Chat participants -You can also directly [open agent mode in {% data variables.product.prodname_vscode_shortname %}](vscode://GitHub.Copilot-Chat/chat?mode=agent&ref_product=copilot&ref_type=engagement&ref_style=text). +Chat participants are like domain experts who have a specialty that they can help you with. -For more information, see [{% data variables.copilot.copilot_edits_short %}](https://aka.ms/vscode-copilot-agent) in the {% data variables.product.prodname_vscode %} documentation. +{% data variables.copilot.copilot_chat_short %} can infer relevant chat participants based on your natural language prompt, improving discovery of advanced capabilities without you having to explicitly specify the participant you want to use in your prompt. -{% data reusables.copilot.copilot-edits.agent-mode-requests %} +> [!NOTE] Automatic inference for chat participants is currently in {% data variables.release-phases.public_preview %} and is subject to change. -### Using {% data variables.copilot.subagents_short %} +Alternatively, you can manually specify a chat participant to scope your prompt to a specific domain. To do this, type `@` in the chat prompt box, followed by a chat participant name. -{% data reusables.copilot.subagent-intro %} +For a list of available chat participants, type `@` in the chat prompt box. See also [AUTOTITLE](/copilot/using-github-copilot/github-copilot-chat-cheat-sheet?tool=vscode#chat-participants) or [Chat participants](https://code.visualstudio.com/docs/copilot/copilot-chat#_chat-participants) in the {% data variables.product.prodname_vscode %} documentation. -#### Enabling {% data variables.copilot.subagents_short %} +### Slash commands -1. In the {% data variables.copilot.copilot_chat_short %} window, click the tools icon. -1. Enable the `runSubagent` tool. +Use slash commands to avoid writing complex prompts for common scenarios. To use a slash command, type `/` in the chat prompt box, followed by a command. -If you use custom prompt files or {% data variables.copilot.custom_agents_short %}, ensure you specify the `runSubagent` tool in the `tools` frontmatter property. +To see all available slash commands, type `/` in the chat prompt box. See also [AUTOTITLE](/copilot/using-github-copilot/github-copilot-chat-cheat-sheet?tool=vscode#slash-commands) or [Slash commands](https://code.visualstudio.com/docs/copilot/reference/copilot-vscode-features#_slash-commands) in the {% data variables.product.prodname_vscode %} documentation. -#### Invoking {% data variables.copilot.subagents_short %} - -{% data reusables.copilot.using-subagents %} -* **Calling the #runSubagent tool.**. +### Chat variables - ```text - Evaluate the #file:databaseSchema using #runSubagent and generate an optimized data-migration plan. - ``` +Use chat variables to include specific context in your prompt. To use a chat variable, type `#` in the chat prompt box, followed by a chat variable. -When the {% data variables.copilot.subagent_short %} completes its task, its results appear back in the main chat session, ready for follow-up questions or next steps. +To see all available chat variables, type `#` in the chat prompt box. See also [AUTOTITLE](/copilot/using-github-copilot/github-copilot-chat-cheat-sheet?tool=vscode#chat-variables). -### Plan mode +## Using {% data variables.product.prodname_dotcom %} skills for {% data variables.product.prodname_copilot_short %} -Plan mode helps you to create detailed implementation plans before executing them. This ensures that all requirements are considered and addressed before any code changes are made. The plan agent does not make any code changes until the plan is reviewed and approved by you. Once approved, you can hand off the plan to the default agent or save it for further refinement, review, or team discussions. +{% data reusables.copilot.using-skills %} -The plan agent is designed to: +## Using Model Context Protocol (MCP) servers -* Research the task comprehensively using read-only tools and codebase analysis to identify requirements and constraints. -* Break down the task into manageable, actionable steps and include open questions about ambiguous requirements. -* Present a concise plan draft, based on a standardized plan format, for user review and iteration. +{% data reusables.copilot.mcp.mcp-chat-in-ide %} -#### Using plan mode +## AI models for {% data variables.copilot.copilot_chat_short %} -1. If the chat view is not already displayed, select **Open Chat** from the {% data variables.copilot.copilot_chat_short %} menu. -1. At the bottom of the chat view, select **Plan** from the agents dropdown. -1. Type a prompt that describes a task, such as adding a feature to an existing application, refactoring code, fixing a bug, or creating an initial version of a new application. +{% data reusables.copilot.change-the-ai-model %} - For example: `Create a simple to-do web app with HTML, CSS, and JS files.` +## Additional ways to access {% data variables.copilot.copilot_chat_short %} - After a few moments, the plan agent outputs a plan in the chat view. The plan provides a high-level summary and a breakdown of steps, including any open questions for clarification. +In addition to submitting prompts through the chat view, you can submit prompts in other ways: -{% data reusables.copilot.plan-agent-steps %} +* **Quick chat:** To open the quick chat dropdown, enter Shift+Optin+Command+L (Mac) / Ctrl+Shift+Alt+L (Windows/Linux). +* **Inline:** To start an inline chat directly in the editor or integrated terminal, enter Command+i (Mac) / Ctrl+i (Windows/Linux). +* **Smart actions:** To submit prompts via the context menu, right click in your editor, select **{% data variables.product.prodname_copilot_short %}** in the menu that appears, then select one of the actions. Smart actions can also be accessed via the sparkle icon that sometimes appears when you select a line of code. -For more information, see [Planning in VS Code chat](https://code.visualstudio.com/docs/copilot/chat/copilot-chat) in the {% data variables.product.prodname_vscode %} documentation. +See [inline chat](https://code.visualstudio.com/docs/copilot/copilot-chat#_inline-chat), [quick chat](https://code.visualstudio.com/docs/copilot/copilot-chat#_quick-chat), and [chat smart actions](https://code.visualstudio.com/docs/copilot/copilot-chat#_chat-smart-actions) in the {% data variables.product.prodname_vscode %} documentation for more details. ## Using images in {% data variables.copilot.copilot_chat_short %} @@ -211,10 +193,6 @@ For more information, see [Planning in VS Code chat](https://code.visualstudio.c ### Attaching images to your chat prompt -1. If you see the AI model picker at the bottom right of the chat view, select one of the models that supports adding images to prompts: - - ![Screenshot of {% data variables.copilot.copilot_chat_short %} with the model picker highlighted with a dark orange outline.](/assets/images/help/copilot/vsc-chat-model-picker.png) - 1. Do one of the following: * Copy an image and paste it into the chat view. diff --git a/content/copilot/how-tos/use-copilot-agents/coding-agent/make-changes-to-an-existing-pr.md b/content/copilot/how-tos/use-copilot-agents/coding-agent/make-changes-to-an-existing-pr.md index 4aa1192ce54f..5b8cb66a7efd 100644 --- a/content/copilot/how-tos/use-copilot-agents/coding-agent/make-changes-to-an-existing-pr.md +++ b/content/copilot/how-tos/use-copilot-agents/coding-agent/make-changes-to-an-existing-pr.md @@ -2,7 +2,7 @@ title: Asking GitHub Copilot to make changes to an existing pull request shortTitle: Update existing PR allowTitleToDifferFromFilename: true -intro: 'You can ask {% data variables.product.prodname_copilot_short %} to make changes to an existing pull request created by a human by mentioning `@copilot`.' +intro: 'You can ask {% data variables.product.prodname_copilot_short %} to make changes to an existing pull request by mentioning `@copilot`.' product: '{% data reusables.gated-features.copilot-coding-agent %}
Sign up for {% data variables.product.prodname_copilot_short %} {% octicon "link-external" height:16 %}' versions: feature: copilot @@ -16,13 +16,11 @@ category: ## Introduction -You can ask {% data variables.product.prodname_copilot_short %} to make changes to an existing pull request created by a human developer by mentioning `@copilot` in a comment. +You can ask {% data variables.product.prodname_copilot_short %} to make changes to an existing pull request by mentioning `@copilot` in a comment. -{% data variables.product.prodname_copilot_short %} will create a child pull request, using the existing pull request's branch as the base branch. Once it has finished work on the changes you requested, it requests your review on the child pull request. +By default, {% data variables.product.prodname_copilot_short %} pushes commits directly to the pull request's branch. Once it has finished work on the changes you requested, it requests your review. -You maintain control of the original pull request: until you accept Copilot's proposed changes by merging its child pull request into your branch, the pull request will remain untouched. - -You can ask {% data variables.product.prodname_copilot_short %} to make changes to its child pull request by leaving a review. See [AUTOTITLE](/copilot/using-github-copilot/coding-agent/reviewing-a-pull-request-created-by-copilot). +If you prefer {% data variables.product.prodname_copilot_short %} to create a separate pull request instead, you can ask for this using natural language in your comment—for example, "open a PR to fix the tests." ## Asking {% data variables.product.prodname_copilot_short %} to make changes @@ -31,9 +29,7 @@ You can ask {% data variables.product.prodname_copilot_short %} to make changes 1. Optionally, when leaving a pull request comment (not a review or review comment) through the {% data variables.product.github %} web interface, select a model using the model picker. 1. Submit your comment or review. -{% data variables.product.prodname_copilot_short %} will open a child pull request, using the existing pull request's branch as the base branch. - -{% data variables.product.prodname_copilot_short %} will leave a comment linking to the new pull request. Once the agent finishes work, it will request a review from you. +If you prefer not to use this default behavior, you can ask {% data variables.product.prodname_copilot_short %} to create a new branch and a new pull request targeting your branch instead. Once the agent finishes work, it will request a review from you. {% data reusables.copilot.coding-agent.monitoring-progress-heading %} diff --git a/content/copilot/how-tos/use-copilot-agents/coding-agent/review-copilot-prs.md b/content/copilot/how-tos/use-copilot-agents/coding-agent/review-copilot-prs.md index fd0910f626ef..d5ae3a779c8d 100644 --- a/content/copilot/how-tos/use-copilot-agents/coding-agent/review-copilot-prs.md +++ b/content/copilot/how-tos/use-copilot-agents/coding-agent/review-copilot-prs.md @@ -26,7 +26,7 @@ After {% data variables.product.prodname_copilot_short %} has finished working o > [!IMPORTANT] > If you have rules or branch protections that require pull request approvals, and you ask {% data variables.product.prodname_copilot_short %} to create a pull request, you can approve the pull request, but **your approval won't count** toward the required number of approvals. Someone else must approve the pull request for it to be merged. -You can ask {% data variables.product.prodname_copilot_short %} to make changes by mentioning `@copilot` in pull request comments, or you can check out {% data variables.product.prodname_copilot_short %}'s branch and make changes yourself. +You can ask {% data variables.product.prodname_copilot_short %} to make changes by mentioning `@copilot` in pull request comments. By default, {% data variables.product.prodname_copilot_short %} pushes commits directly to the pull request's branch. If you prefer, you can ask {% data variables.product.prodname_copilot_short %} to create a separate pull request instead by using natural language in your comment. You can also check out {% data variables.product.prodname_copilot_short %}'s branch and make changes yourself. Optionally, when submitting a pull request comment (not a review or review comment) through the {% data variables.product.github %} web interface, you can select a model using the model picker. By default, {% data variables.product.prodname_copilot_short %} will use the model originally used to create the pull request. diff --git a/content/copilot/responsible-use/copilot-coding-agent.md b/content/copilot/responsible-use/copilot-coding-agent.md index b107e85d58c7..e243807ec0a4 100644 --- a/content/copilot/responsible-use/copilot-coding-agent.md +++ b/content/copilot/responsible-use/copilot-coding-agent.md @@ -117,7 +117,7 @@ The agent filters hidden characters, that are not displayed on {% data variables Copilot only has access to the repository where it is creating a pull request, and cannot access other repositories. -Its permissions are limited, allowing it to push code and read other resources. Built-in protections mean that Copilot can only push to branches with names beginning with `copilot/`. This means that Copilot cannot push to your default branch (for example, `main`). +Its permissions are limited, allowing it to push code and read other resources. Built-in protections mean that Copilot can only push to a single branch: the existing pull request branch when triggered via `@copilot`, or otherwise to a new `copilot/` branch. This means that Copilot cannot push directly to your default branch (for example, `main`). {% data variables.copilot.copilot_coding_agent %} does not have access to Actions organization or repository secrets or variables during runtime. Only secrets and variables specifically added to the `copilot` environment are passed to the agent. diff --git a/content/copilot/tutorials/coding-agent/get-the-best-results.md b/content/copilot/tutorials/coding-agent/get-the-best-results.md index 1b4baabbe188..9ef0380f987b 100644 --- a/content/copilot/tutorials/coding-agent/get-the-best-results.md +++ b/content/copilot/tutorials/coding-agent/get-the-best-results.md @@ -64,7 +64,7 @@ Issues that you may choose to work on yourself, rather than assigning to {% data Working with {% data variables.product.prodname_copilot_short %} on a pull request is just like working with a human developer: it's common for the pull request to need further work before it can be merged. The process for getting the pull request to a mergeable state is exactly the same when the pull request is created by {% data variables.product.prodname_copilot_short %} as when it's created by a human. -You can also mention `@copilot` in comments on the pull request—explaining what you think is incorrect, or could be improved—and leave {% data variables.product.prodname_copilot_short %} to make the required changes. Alternatively, you can work on the feature branch yourself and push changes to the pull request. +You can also mention `@copilot` in comments on the pull request—explaining what you think is incorrect, or could be improved—and {% data variables.product.prodname_copilot_short %} will push commits directly to the pull request's branch. Alternatively, you can work on the feature branch yourself and push changes to the pull request. After a user with write access mentions `@copilot` in a comment, {% data variables.product.prodname_copilot_short %} will start to make any required changes, and will update the pull request when it's done. Because {% data variables.product.prodname_copilot_short %} starts looking at comments as soon as they are submitted, if you are likely to make multiple comments on a pull request it's best to batch them by clicking **Start a review**, rather than clicking **Add single comment**. You can then submit all of your comments at once, triggering {% data variables.product.prodname_copilot_short %} to work on your entire review, rather than working on individual comments separately. diff --git a/data/release-notes/enterprise-server/3-18/6.yml b/data/release-notes/enterprise-server/3-18/6.yml index 2f0453723fd0..cc42d5b1013d 100644 --- a/data/release-notes/enterprise-server/3-18/6.yml +++ b/data/release-notes/enterprise-server/3-18/6.yml @@ -41,8 +41,6 @@ sections: To improve performance on large instances, HAProxy automatically scales its thread count based on available CPUs and uses higher connection limits for high-traffic backend services including GitHub Actions, database connections, job queues, and package registry. Administrators can override the thread count using `ghe-config haproxy-nbthread` if needed. - | API consumers can update issues via the REST API (PATCH) or the GraphQL `updateIssue` mutation using fine-grained permissions for closing and reopening issues, and for setting milestones. - - | - The "In-product messages" notification toggle no longer appears in user notification settings as GitHub Enterprise Server does not use in-product messages. 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. diff --git a/data/release-notes/enterprise-server/3-18/7.yml b/data/release-notes/enterprise-server/3-18/7.yml index 68f94ccd7e30..f1b171046855 100644 --- a/data/release-notes/enterprise-server/3-18/7.yml +++ b/data/release-notes/enterprise-server/3-18/7.yml @@ -35,8 +35,6 @@ sections: To improve performance on large instances, HAProxy automatically scales its thread count based on available CPUs and uses higher connection limits for high-traffic backend services including GitHub Actions, database connections, job queues, and package registry. Administrators can override the thread count using `ghe-config haproxy-nbthread` if needed. - | API consumers can update issues via the REST API (PATCH) or the GraphQL `updateIssue` mutation using fine-grained permissions for closing and reopening issues, and for setting milestones. - - | - The "In-product messages" notification toggle no longer appears in user notification settings as GitHub Enterprise Server does not use in-product messages. 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. diff --git a/data/release-notes/enterprise-server/3-19/3.yml b/data/release-notes/enterprise-server/3-19/3.yml index e7d5458ada4f..8b88f0e037ab 100644 --- a/data/release-notes/enterprise-server/3-19/3.yml +++ b/data/release-notes/enterprise-server/3-19/3.yml @@ -57,8 +57,6 @@ sections: API consumers can update issues via the REST API (PATCH) using fine-grained permissions for closing and reopening issues, and for setting milestones. - | API consumers can update issues via the GraphQL `updateIssue` mutation using fine-grained permissions for closing and reopening issues, and for setting milestones. - - | - The "In-product messages" notification toggle no longer appears in user notification settings as GitHub Enterprise Server does not use in-product messages. 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. diff --git a/data/release-notes/enterprise-server/3-19/4.yml b/data/release-notes/enterprise-server/3-19/4.yml index 8a22d884f2e5..d78f3c32d326 100644 --- a/data/release-notes/enterprise-server/3-19/4.yml +++ b/data/release-notes/enterprise-server/3-19/4.yml @@ -51,8 +51,6 @@ sections: API consumers can update issues via the REST API (PATCH) using fine-grained permissions for closing and reopening issues, and for setting milestones. - | API consumers can update issues via the GraphQL `updateIssue` mutation using fine-grained permissions for closing and reopening issues, and for setting milestones. - - | - The "In-product messages" notification toggle no longer appears in user notification settings as GitHub Enterprise Server does not use in-product messages. 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. diff --git a/data/reusables/enterprise-data-residency/ssh-user.md b/data/reusables/enterprise-data-residency/ssh-user.md new file mode 100644 index 000000000000..15b16fbc0e97 --- /dev/null +++ b/data/reusables/enterprise-data-residency/ssh-user.md @@ -0,0 +1 @@ +If you are accessing {% data variables.product.github %} at a different domain such as `{% data variables.enterprise.data_residency_example_domain %}`, then you need to replace `git@{% data variables.product.product_url %}` with `{% data variables.enterprise.data_residency_example_git_ssh %}`. diff --git a/data/variables/enterprise.yml b/data/variables/enterprise.yml index 1614a1334626..5d2accc0aa98 100644 --- a/data/variables/enterprise.yml +++ b/data/variables/enterprise.yml @@ -16,6 +16,7 @@ data_residency_site: 'GHE.com' data_residency_domain: 'SUBDOMAIN.ghe.com' data_residency_api: 'api.SUBDOMAIN.ghe.com' data_residency_example_domain: 'octocorp.ghe.com' +data_residency_example_git_ssh: 'octocorp@octocorp.ghe.com' # GitHub Connect (enterprise accounts, other unified features) ## Phrase content so that the uncapitalized unified contributions or unified search variables are not used at the start of a sentence. diff --git a/package-lock.json b/package-lock.json index c98ae0e2012c..169412d5638b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -495,6 +495,7 @@ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -535,6 +536,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", + "peer": true, "bin": { "semver": "bin/semver.js" } @@ -571,6 +573,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", @@ -587,6 +590,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "license": "ISC", + "peer": true, "dependencies": { "yallist": "^3.0.2" } @@ -596,6 +600,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", + "peer": true, "bin": { "semver": "bin/semver.js" } @@ -627,6 +632,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", @@ -670,6 +676,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -679,6 +686,7 @@ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" @@ -2335,6 +2343,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -2601,7 +2610,6 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -2902,7 +2910,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -3810,7 +3817,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.1.tgz", "integrity": "sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, @@ -5388,7 +5394,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5428,7 +5433,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5449,7 +5453,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5470,7 +5473,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5491,7 +5493,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5512,7 +5513,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5533,7 +5533,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5554,7 +5553,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5575,7 +5573,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5596,7 +5593,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5617,7 +5613,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5638,7 +5633,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5659,7 +5653,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5680,7 +5673,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5698,7 +5690,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, "license": "Apache-2.0", "optional": true, "bin": { @@ -5727,7 +5718,6 @@ "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "playwright": "1.58.2" }, @@ -6662,7 +6652,6 @@ "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", @@ -6872,7 +6861,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -6884,7 +6872,6 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -7066,7 +7053,6 @@ "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.39.1", "@typescript-eslint/types": "8.39.1", @@ -7739,7 +7725,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -7779,7 +7764,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -8345,7 +8329,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001733", "electron-to-chromium": "^1.5.199", @@ -9171,7 +9154,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/cookie": { "version": "0.7.2", @@ -10044,7 +10028,6 @@ "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -10105,7 +10088,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -10356,7 +10338,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -11489,7 +11470,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -11590,6 +11570,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -11808,7 +11789,6 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", "dev": true, - "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -13180,7 +13160,6 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, - "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -13325,6 +13304,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "license": "MIT", + "peer": true, "bin": { "json5": "lib/cli.js" }, @@ -15496,7 +15476,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, "license": "MIT", "optional": true }, @@ -16292,7 +16271,6 @@ "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "playwright-core": "cli.js" }, @@ -16395,7 +16373,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -16589,7 +16566,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -16610,7 +16586,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -16638,8 +16613,7 @@ "version": "19.2.4", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.4.tgz", "integrity": "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-markdown": { "version": "10.1.0", @@ -17314,7 +17288,6 @@ "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -18217,7 +18190,6 @@ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -18479,7 +18451,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -18812,7 +18783,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -19160,7 +19130,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -19365,7 +19334,6 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -19474,7 +19442,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -20080,7 +20047,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/yaml": { "version": "2.8.2", diff --git a/package.json b/package.json index 51fbb0747bcd..cf2755fb08a2 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,12 @@ "sync-secret-scanning": "tsx src/secret-scanning/scripts/sync.ts", "sync-webhooks": "npx tsx src/rest/scripts/update-files.ts -o webhooks", "test": "vitest", + "test:article-api": "cross-env ROOT=src/fixtures/fixtures TRANSLATIONS_FIXTURE_ROOT=src/fixtures/fixtures/translations npm test -- --no-file-parallelism --maxWorkers=1 src/article-api/tests/", + "test:changelogs": "cross-env CHANGELOG_CACHE_FILE_PATH=src/fixtures/fixtures/changelog-feed.json npm test -- src/changelogs/tests/", + "test:fixtures": "cross-env ROOT=src/fixtures/fixtures TRANSLATIONS_FIXTURE_ROOT=src/fixtures/fixtures/translations npm test -- src/fixtures/tests/", + "test:landings": "cross-env ROOT=src/fixtures/fixtures npm test -- src/landings/tests/", + "test:languages": "cross-env ENABLED_LANGUAGES=all ELASTICSEARCH_URL=http://localhost:9200/ npm test -- src/languages/tests/", + "test:search": "cross-env ELASTICSEARCH_URL=http://localhost:9200/ npm test -- src/search/tests/", "test-moved-content": "tsx src/content-render/scripts/test-moved-content.ts", "tsc": "tsc --noEmit", "unallowed-contributions": "tsx src/workflows/unallowed-contributions.ts", diff --git a/src/tests/README.md b/src/tests/README.md index d5f931d5b48a..f4d6402976ee 100644 --- a/src/tests/README.md +++ b/src/tests/README.md @@ -37,31 +37,72 @@ Test-only dependencies are optional to keep standard installs faster: npm ci --include=optional ``` -### Running all tests +### Running tests by suite + +**Important: Do NOT run `npm test` without a path argument.** Tests must be run per-suite because different suites require different environment variables. Running all tests at once will produce many false failures. + +**Important: Run `npm run build` before running tests.** Many test suites depend on Next.js build artifacts. Without a build, tests may fail with `Could not find a production build` or other confusing errors. + +Always target the specific suite for the code you changed: ```bash -npm test +# By directory (recommended) +npm test -- src/search/tests/ + +# Single test file +npm test -- src/versions/tests/versions.ts ``` -### Running tests in watch mode +Some suites require environment variables or tests will fail with 404s or content mismatches. These suites have dedicated npm scripts that set the required variables automatically: -Continuously re-runs tests on file changes: +```bash +npm run test:article-api +npm run test:changelogs +npm run test:fixtures +npm run test:landings +npm run test:languages # requires Elasticsearch running +npm run test:search # requires Elasticsearch running +``` + +For the `content-linter` suite, you can optionally scope to changed files: ```bash -npm run test-watch +DIFF_FILES="content/foo.md content/bar.md" \ + npm test -- src/content-linter/tests/ ``` -### Running specific tests +All other suites (e.g., `versions`, `redirects`, `rest`, `frame`, `content-render`) can be run without special environment variables. + +### Running Elasticsearch locally + +The `search` and `languages` test suites require Elasticsearch on `localhost:9200`. To start it with Docker: ```bash -# By filename or path -npm test -- +docker run -d \ + -p 127.0.0.1:9200:9200 \ + -e 'discovery.type=single-node' \ + -e 'xpack.security.enabled=false' \ + --name es-local \ + docker.elastic.co/elasticsearch/elasticsearch:8.12.0 +``` -# By directory -vitest src/search/tests +Wait for it to be ready, then index the test fixtures: -# Single test file -vitest src/versions/tests/versions.ts +```bash +curl --silent --fail http://localhost:9200 # verify ES is up +ELASTICSEARCH_URL=http://localhost:9200/ npm run index-test-fixtures +``` + +After that, `npm run test:search` and `npm run test:languages` will work. + +See `.github/workflows/test.yml` for the full CI matrix and per-suite configuration. + +### Running tests in watch mode + +Continuously re-runs tests on file changes: + +```bash +npm test -- --watch ``` ### Viewing console output @@ -77,11 +118,11 @@ npm test -- --silent=false Some tests require a production build: ```bash -npx next build -npm test +npm run build +npm test -- src//tests/ ``` -Error: `Could not find a production build` means you need to run `next build`. +Error: `Could not find a production build` means you need to run `npm run build`. ## Data & External Dependencies @@ -176,7 +217,7 @@ npm run lint ### Known limitations - Optional dependencies must be installed for local testing -- Some tests require production build (`next build`) +- Some tests require production build (`npm run build`) - Server startup/shutdown adds overhead to test runs - Fixtures may lag behind actual content structure @@ -203,17 +244,12 @@ Shared utilities belong in `src/tests/`: ### CI integration -Tests run automatically in GitHub Actions: -- On pull requests -- On pushes to main -- Various test suites in parallel for speed - -See `.github/workflows/` for CI configuration. +Tests run automatically in GitHub Actions on pull requests and merge groups. Each test suite runs as a separate matrix job with its own environment variables—see `.github/workflows/test.yml` for the full configuration. Locally, always target a specific suite rather than running all tests at once. ### Troubleshooting **Tests fail with missing build:** -Run `npx next build` before tests. +Run `npm run build` before tests. **Tests hang or timeout:** Check if server started correctly. Use `DEBUG_MIDDLEWARE_TESTS=true`.