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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/node-npm-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ runs:
key: ${{ runner.os }}-node_modules-${{ hashFiles('package*.json') }}-${{ hashFiles('.github/actions/node-npm-setup/action.yml') }}

- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version-file: 'package.json'
cache: npm
Expand Down
18 changes: 9 additions & 9 deletions content/copilot/concepts/prompting/response-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ category:

There are three main types of custom instructions that you can use to customize {% data variables.product.prodname_copilot_short %} responses on the {% data variables.product.github %} website:

* **[Personal custom instructions](#about-personal-custom-instructions)** apply to all conversations you have with {% data variables.copilot.copilot_chat_short %} across the {% data variables.product.github %} website. They allow you to specify your individual preferences, such as preferred language or response style, ensuring that the responses are tailored to your personal needs.
* **[Personal instructions](#about-personal-instructions)** apply to all conversations you have with {% data variables.copilot.copilot_chat_short %} across the {% data variables.product.github %} website. They allow you to specify your individual preferences, such as preferred language or response style, ensuring that the responses are tailored to your personal needs.
* **[Repository custom instructions](#about-repository-custom-instructions)** apply to conversations within the context of a specific repository. They are useful for defining project-specific coding standards, frameworks, or tools. For example, you can specify that a repository uses TypeScript and a particular library, ensuring consistent responses for all contributors.
* **[Organization custom instructions](#about-organization-custom-instructions)** (public preview) apply to conversations within the context of an organization on the {% data variables.product.github %} website. They are ideal for enforcing organization-wide preferences, such as a common language or security guidelines. Organization custom instructions can only be set by organization owners for organizations with a {% data variables.copilot.copilot_enterprise_short %} subscription.

## About personal custom instructions
## About personal instructions

{% data reusables.copilot.personal-instructions-note %}

Expand Down Expand Up @@ -67,12 +67,12 @@ Some examples of instructions you could add are:

The following list shows the complete order of precedence, with instructions higher in this list taking precedence over those lower in the list:

* Personal custom instructions
* Repository custom instructions:
* Path-specific instructions in any applicable `.github/instructions/**/NAME.instructions.md` file
* Repository-wide instructions in the `.github/copilot-instructions.md` file
* Agent instructions (for example, in an `AGENTS.md` file)
* Organization custom instructions
* **Personal** instructions
* **Repository** custom instructions:
* **Path-specific** instructions in any applicable `.github/instructions/**/NAME.instructions.md` file
* **Repository-wide** instructions in the `.github/copilot-instructions.md` file
* **Agent** instructions (for example, in an `AGENTS.md` file)
* **Organization** custom instructions

{% data reusables.copilot.custom-instructions-conflict %}

Expand All @@ -81,7 +81,7 @@ The following list shows the complete order of precedence, with instructions hig
Custom instructions consist of natural language instructions and are most effective when they are short, self-contained statements. Consider the scope over which you want the instruction to apply when choosing whether to add an instruction on the personal, repository, or organization level.

Here are some common use cases and examples for each type of custom instructions:
* **Personal custom instructions:**
* **Personal instructions:**
* Preferred individual language: `Always respond in Portuguese.`
* Individual response preferences: `Explain a single concept per line. Be clear and concise.`
* **Repository custom instructions:**
Expand Down
1 change: 0 additions & 1 deletion data/reusables/contributing/content-linter-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
| GHD041 | third-party-action-pinning | Code examples that use third-party actions must always pin to a full length commit SHA | error | feature, actions |
| GHD042 | liquid-tag-whitespace | Liquid tags should start and end with one whitespace. Liquid tag arguments should be separated by only one whitespace. | error | liquid, format |
| GHD043 | link-quotation | Internal link titles must not be surrounded by quotations | error | links, url |
| GHD044 | octicon-aria-labels | Octicons should always have an aria-label attribute even if aria-hidden. | warning | accessibility, octicons |
| GHD045 | code-annotation-comment-spacing | Code comments in annotation blocks must have exactly one space after the comment character(s) | warning | code, comments, annotate, spacing |
| GHD046 | outdated-release-phase-terminology | Outdated release phase terminology should be replaced with current GitHub terminology | warning | terminology, consistency, release-phases |
| GHD047 | table-column-integrity | Tables must have consistent column counts across all rows | warning | tables, accessibility, formatting |
Expand Down
2 changes: 1 addition & 1 deletion data/reusables/copilot/custom-instructions-org-support.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
> [!NOTE]
> This feature is currently in {% data variables.release-phases.public_preview %} and is subject to change.
>
> **Support:** Organization custom instructions are currently only supported for {% data variables.copilot.copilot_chat_short %} on {% data variables.product.prodname_dotcom_the_website %} and {% data variables.copilot.copilot_code-review_short %} on {% data variables.product.prodname_dotcom_the_website %}.
> **Support:** Organization custom instructions are currently only supported for {% data variables.copilot.copilot_chat_short %} on {% data variables.product.prodname_dotcom_the_website %}, {% data variables.copilot.copilot_code-review_short %} on {% data variables.product.prodname_dotcom_the_website %} and {% data variables.copilot.copilot_coding_agent %} on {% data variables.product.prodname_dotcom_the_website %}.
69 changes: 69 additions & 0 deletions src/article-api/tests/article-body.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { beforeAll, describe, expect, test } from 'vitest'

import { get } from '@/tests/helpers/e2etest'

const makeURL = (pathname: string): string =>
`/api/article/body?${new URLSearchParams({ pathname })}`

describe('article body api', () => {
beforeAll(() => {
// If you didn't set the `ROOT` variable, the tests will fail rather
// cryptically. So as a warning for engineers running these tests,
// alert in case it was accidentally forgotten.
if (!process.env.ROOT) {
console.warn(
'WARNING: The article body tests require the ROOT environment variable to be set to the fixture root',
)
}
})

test('happy path', async () => {
const res = await get(makeURL('/en/get-started/start-your-journey/hello-world'))
expect(res.statusCode).toBe(200)
expect(res.body).toContain('## Introduction')
expect(res.body).toContain('This is just a test.')
expect(res.headers['content-type']).toContain('text/markdown')
})

test('octicons auto-generate aria-labels', async () => {
const res = await get(makeURL('/en/get-started/start-your-journey/hello-world'))
expect(res.statusCode).toBe(200)

// Check that octicons without aria-label get auto-generated ones
expect(res.body).toContain('aria-label="check icon"')
expect(res.body).toContain('aria-label="git branch icon"')
})

test('octicons with custom aria-labels use the custom value', async () => {
const res = await get(makeURL('/en/get-started/start-your-journey/hello-world'))
expect(res.statusCode).toBe(200)

// Check that custom aria-labels are preserved
expect(res.body).toContain('aria-label="Supported"')
expect(res.body).toContain('aria-label="Not supported"')
})

test('octicons with other attributes still get auto-generated aria-labels', async () => {
const res = await get(makeURL('/en/get-started/start-your-journey/hello-world'))
expect(res.statusCode).toBe(200)

// Check that octicons with width attribute still get aria-labels
expect(res.body).toContain('aria-label="rocket icon"')
expect(res.body).toContain('width="32"')
})

test('a pathname that does not exist', async () => {
const res = await get(makeURL('/en/never/heard/of'))
expect(res.statusCode).toBe(404)
const { error } = JSON.parse(res.body)
expect(error).toBe("No page found for '/en/never/heard/of'")
})

test('non-article pages return error', async () => {
// Index pages are not articles and should not be renderable
const res = await get(makeURL('/en/get-started'))
expect(res.statusCode).toBe(403)
const { error } = JSON.parse(res.body)
expect(error).toContain("isn't yet available in markdown")
})
})
3 changes: 1 addition & 2 deletions src/content-linter/lib/linting-rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import { tableColumnIntegrity } from '@/content-linter/lib/linting-rules/table-c
import { thirdPartyActionPinning } from '@/content-linter/lib/linting-rules/third-party-action-pinning'
import { liquidTagWhitespace } from '@/content-linter/lib/linting-rules/liquid-tag-whitespace'
import { linkQuotation } from '@/content-linter/lib/linting-rules/link-quotation'
import { octiconAriaLabels } from '@/content-linter/lib/linting-rules/octicon-aria-labels'
import { liquidIfversionVersions } from '@/content-linter/lib/linting-rules/liquid-ifversion-versions'
import { outdatedReleasePhaseTerminology } from '@/content-linter/lib/linting-rules/outdated-release-phase-terminology'
import { frontmatterVersionsWhitespace } from '@/content-linter/lib/linting-rules/frontmatter-versions-whitespace'
Expand Down Expand Up @@ -105,7 +104,7 @@ export const gitHubDocsMarkdownlint = {
thirdPartyActionPinning, // GHD041
liquidTagWhitespace, // GHD042
linkQuotation, // GHD043
octiconAriaLabels, // GHD044
// GHD044 removed - octicon aria-labels are now auto-generated
codeAnnotationCommentSpacing, // GHD045
outdatedReleasePhaseTerminology, // GHD046
tableColumnIntegrity, // GHD047
Expand Down
58 changes: 0 additions & 58 deletions src/content-linter/lib/linting-rules/octicon-aria-labels.ts

This file was deleted.

7 changes: 1 addition & 6 deletions src/content-linter/style/github-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,7 @@ const githubDocsConfig = {
'partial-markdown-files': true,
'yml-files': true,
},
'octicon-aria-labels': {
// GHD044
severity: 'warning',
'partial-markdown-files': true,
'yml-files': true,
},
// GHD044 removed - octicon aria-labels are now auto-generated
'code-annotation-comment-spacing': {
// GHD045
severity: 'warning',
Expand Down
155 changes: 0 additions & 155 deletions src/content-linter/tests/unit/octicon-aria-labels.ts

This file was deleted.

10 changes: 10 additions & 0 deletions src/content-render/lib/prompt-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import murmur from 'imurmurhash'

/**
* Generate a deterministic ID for a prompt based on its content.
* Uses MurmurHash to create a unique ID that remains consistent across renders,
* avoiding hydration mismatches in the client.
*/
export function generatePromptId(promptContent: string): string {
return murmur('prompt').hash(promptContent).result().toString()
}
Loading