Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 101 KiB |
@@ -39,6 +39,8 @@ When you remove a custom pattern, {% data variables.product.github %} gives you
|
|||||||
1. Review the confirmation, and select a method for dealing with any open alerts relating to the custom pattern.
|
1. Review the confirmation, and select a method for dealing with any open alerts relating to the custom pattern.
|
||||||
1. Click **Yes, delete this pattern**.
|
1. Click **Yes, delete this pattern**.
|
||||||
|
|
||||||
|
If you choose to close the alerts when removing a custom pattern, you need to be aware that the deletion process happens asynchronously in the background. For custom patterns that have generated a high volume of alerts (thousands or more), the deletion process may take several minutes to hours to complete. You can continue working while the process completes.
|
||||||
|
|
||||||
## Enabling push protection for a custom pattern
|
## Enabling push protection for a custom pattern
|
||||||
|
|
||||||
You can enable {% data variables.product.prodname_secret_scanning %} as a push protection for custom patterns stored at the enterprise, organization, or repository level.
|
You can enable {% data variables.product.prodname_secret_scanning %} as a push protection for custom patterns stored at the enterprise, organization, or repository level.
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ You can assign an issue to {% data variables.product.prodname_copilot_short %}:
|
|||||||
|
|
||||||
### Assigning an issue to {% data variables.product.prodname_copilot_short %} on {% data variables.product.prodname_dotcom_the_website %}
|
### Assigning an issue to {% data variables.product.prodname_copilot_short %} on {% data variables.product.prodname_dotcom_the_website %}
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This feature is in {% data variables.release-phases.public_preview %} and subject to change.
|
||||||
|
|
||||||
{% data reusables.repositories.navigate-to-repo %}
|
{% data reusables.repositories.navigate-to-repo %}
|
||||||
{% data reusables.repositories.sidebar-issues %}
|
{% data reusables.repositories.sidebar-issues %}
|
||||||
|
|
||||||
@@ -113,9 +116,32 @@ You can also assign issues to {% data variables.product.prodname_copilot_short %
|
|||||||
|
|
||||||
### Assigning an issue to {% data variables.product.prodname_copilot_short %} via the {% data variables.product.github %} API
|
### Assigning an issue to {% data variables.product.prodname_copilot_short %} via the {% data variables.product.github %} API
|
||||||
|
|
||||||
You can assign issues to {% data variables.product.prodname_copilot_short %} using the GraphQL API.
|
> [!NOTE]
|
||||||
|
> This feature is in {% data variables.release-phases.public_preview %} and subject to change.
|
||||||
|
|
||||||
#### Creating and assigning a new issue
|
You can assign issues to {% data variables.product.prodname_copilot_short %} using either the GraphQL API or the REST API. Both APIs support an optional Agent Assignment input to customize the task:
|
||||||
|
|
||||||
|
| GraphQL parameter | REST parameter | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `targetRepositoryId` | `target_repo` | The repository where {% data variables.product.prodname_copilot_short %} will work |
|
||||||
|
| `baseRef` | `base_branch` | The branch that {% data variables.product.prodname_copilot_short %} will branch from |
|
||||||
|
| `customInstructions` | `custom_instructions` | Additional instructions for {% data variables.product.prodname_copilot_short %} |
|
||||||
|
| `customAgent` | `custom_agent` | A custom agent to use for the task |
|
||||||
|
| `model` | `model` | The model for {% data variables.product.prodname_copilot_short %} to use |
|
||||||
|
|
||||||
|
#### Using the GraphQL API
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> You must include the `GraphQL-Features` header with the values `issues_copilot_assignment_api_support` and `coding_agent_model_selection`.
|
||||||
|
|
||||||
|
You can use the following GraphQL mutations to assign issues to {% data variables.product.prodname_copilot_short %}:
|
||||||
|
|
||||||
|
* [`updateIssue`](/graphql/reference/mutations#updateissue)
|
||||||
|
* [`createIssue`](/graphql/reference/mutations#createissue)
|
||||||
|
* [`addAssigneesToAssignable`](/graphql/reference/mutations#addassigneestoassignable)
|
||||||
|
* [`replaceActorsForAssignable`](/graphql/reference/mutations#replaceactorsforassignable)
|
||||||
|
|
||||||
|
##### Creating and assigning a new issue
|
||||||
|
|
||||||
1. Make sure you're authenticating with the API using a user token, for example a {% data variables.product.pat_generic %} or a {% data variables.product.prodname_github_app %} user-to-server token.
|
1. Make sure you're authenticating with the API using a user token, for example a {% data variables.product.pat_generic %} or a {% data variables.product.prodname_github_app %} user-to-server token.
|
||||||
|
|
||||||
@@ -163,11 +189,23 @@ You can assign issues to {% data variables.product.prodname_copilot_short %} usi
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Create the issue with the `createIssue` mutation. Replace `REPOSITORY_ID` with the ID returned from the previous step, and `BOT_ID` with the ID returned from the step before that.
|
1. Create the issue with the `createIssue` mutation. Replace `REPOSITORY_ID` with the ID returned from the previous step, and `BOT_ID` with the ID returned from the step before that. You can optionally include the `agentAssignment` input to customize the task.
|
||||||
|
|
||||||
```graphql copy
|
```shell copy
|
||||||
mutation {
|
gh api graphql -f query='mutation {
|
||||||
createIssue(input: {repositoryId: "REPOSITORY_ID", title: "Implement comprehensive unit tests", body: "DETAILS", assigneeIds: ["BOT_ID"]}) {
|
createIssue(input: {
|
||||||
|
repositoryId: "REPOSITORY_ID",
|
||||||
|
title: "Implement comprehensive unit tests",
|
||||||
|
body: "DETAILS",
|
||||||
|
assigneeIds: ["BOT_ID"],
|
||||||
|
agentAssignment: {
|
||||||
|
targetRepositoryId: "REPOSITORY_ID",
|
||||||
|
baseRef: "main",
|
||||||
|
customInstructions: "Add comprehensive test coverage",
|
||||||
|
customAgent: "",
|
||||||
|
model: ""
|
||||||
|
}
|
||||||
|
}) {
|
||||||
issue {
|
issue {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
@@ -178,10 +216,10 @@ You can assign issues to {% data variables.product.prodname_copilot_short %} usi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}' -H 'GraphQL-Features: issues_copilot_assignment_api_support,coding_agent_model_selection'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Assigning an existing issue
|
##### Assigning an existing issue
|
||||||
|
|
||||||
1. Make sure you're authenticating with the API using a user token, for example a {% data variables.product.pat_generic %} or a {% data variables.product.prodname_github_app %} user-to-server token.
|
1. Make sure you're authenticating with the API using a user token, for example a {% data variables.product.pat_generic %} or a {% data variables.product.prodname_github_app %} user-to-server token.
|
||||||
1. Verify that {% data variables.copilot.copilot_coding_agent %} is enabled in the repository by checking if the repository's `suggestedActors` in the GraphQL API includes {% data variables.product.prodname_copilot_short %}. Replace `octo-org` with the repository owner, and `octo-repo` with the repository name.
|
1. Verify that {% data variables.copilot.copilot_coding_agent %} is enabled in the repository by checking if the repository's `suggestedActors` in the GraphQL API includes {% data variables.product.prodname_copilot_short %}. Replace `octo-org` with the repository owner, and `octo-repo` with the repository name.
|
||||||
@@ -222,11 +260,21 @@ You can assign issues to {% data variables.product.prodname_copilot_short %} usi
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Assign the existing issue to {% data variables.product.prodname_copilot_short %} using the `replaceActorsForAssignable` mutation. Replace `ISSUE_ID` with the ID returned from the previous step, and `BOT_ID` with the ID returned from the step before that.
|
1. Assign the existing issue to {% data variables.product.prodname_copilot_short %} using the `replaceActorsForAssignable` mutation. Replace `ISSUE_ID` with the ID returned from the previous step, `BOT_ID` with the ID returned from the step before that, and `REPOSITORY_ID` with the repository ID. You can optionally include the `agentAssignment` input to customize the task.
|
||||||
|
|
||||||
```graphql copy
|
```shell copy
|
||||||
mutation {
|
gh api graphql -f query='mutation {
|
||||||
replaceActorsForAssignable(input: {assignableId: "ISSUE_ID", actorIds: ["BOT_ID"]}) {
|
replaceActorsForAssignable(input: {
|
||||||
|
assignableId: "ISSUE_ID",
|
||||||
|
actorIds: ["BOT_ID"],
|
||||||
|
agentAssignment: {
|
||||||
|
targetRepositoryId: "REPOSITORY_ID",
|
||||||
|
baseRef: "main",
|
||||||
|
customInstructions: "Fix the reported bug",
|
||||||
|
customAgent: "",
|
||||||
|
model: ""
|
||||||
|
}
|
||||||
|
}) {
|
||||||
assignable {
|
assignable {
|
||||||
... on Issue {
|
... on Issue {
|
||||||
id
|
id
|
||||||
@@ -239,9 +287,137 @@ You can assign issues to {% data variables.product.prodname_copilot_short %} usi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}' -H 'GraphQL-Features: issues_copilot_assignment_api_support,coding_agent_model_selection'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. Alternatively, you can use the `updateIssue` mutation to update an existing issue and assign it to {% data variables.product.prodname_copilot_short %}. Replace `ISSUE_ID` with the issue ID and `BOT_ID` with the bot ID.
|
||||||
|
|
||||||
|
```shell copy
|
||||||
|
gh api graphql -f query='mutation {
|
||||||
|
updateIssue(input: {
|
||||||
|
id: "ISSUE_ID",
|
||||||
|
assigneeIds: ["BOT_ID"],
|
||||||
|
agentAssignment: {
|
||||||
|
targetRepositoryId: "REPOSITORY_ID",
|
||||||
|
baseRef: "main",
|
||||||
|
customInstructions: "Update feature implementation",
|
||||||
|
customAgent: "",
|
||||||
|
model: ""
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
issue {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
assignees(first: 10) {
|
||||||
|
nodes {
|
||||||
|
login
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}' -H 'GraphQL-Features: issues_copilot_assignment_api_support,coding_agent_model_selection'
|
||||||
|
```
|
||||||
|
|
||||||
|
1. You can also use the `addAssigneesToAssignable` mutation to add {% data variables.product.prodname_copilot_short %} to an existing issue while keeping other assignees. Replace `ISSUE_ID` with the issue ID and `BOT_ID` with the bot ID.
|
||||||
|
|
||||||
|
```shell copy
|
||||||
|
gh api graphql -f query='mutation {
|
||||||
|
addAssigneesToAssignable(input: {
|
||||||
|
assignableId: "ISSUE_ID",
|
||||||
|
assigneeIds: ["BOT_ID"],
|
||||||
|
agentAssignment: {
|
||||||
|
targetRepositoryId: "REPOSITORY_ID",
|
||||||
|
baseRef: "main",
|
||||||
|
customInstructions: "Collaborate on this task",
|
||||||
|
customAgent: "",
|
||||||
|
model: ""
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
assignable {
|
||||||
|
... on Issue {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
assignees(first: 10) {
|
||||||
|
nodes {
|
||||||
|
login
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}' -H 'GraphQL-Features: issues_copilot_assignment_api_support,coding_agent_model_selection'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using the REST API
|
||||||
|
|
||||||
|
You can use the following REST API endpoints to assign issues to {% data variables.product.prodname_copilot_short %}:
|
||||||
|
|
||||||
|
* [Add assignees to an issue](/rest/issues/assignees#add-assignees-to-an-issue)
|
||||||
|
* [Create an issue](/rest/issues/issues#create-an-issue)
|
||||||
|
* [Update an issue](/rest/issues/issues#update-an-issue)
|
||||||
|
|
||||||
|
##### Adding assignees to an existing issue
|
||||||
|
|
||||||
|
```shell copy
|
||||||
|
gh api \
|
||||||
|
--method POST \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
|
/repos/OWNER/REPO/issues/ISSUE_NUMBER/assignees \
|
||||||
|
--input - <<< '{
|
||||||
|
"assignees": ["copilot-swe-agent[bot]"],
|
||||||
|
"agent_assignment": {
|
||||||
|
"target_repo": "OWNER/REPO",
|
||||||
|
"base_branch": "main",
|
||||||
|
"custom_instructions": "",
|
||||||
|
"custom_agent": "",
|
||||||
|
"model": ""
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Creating a new issue
|
||||||
|
|
||||||
|
```shell copy
|
||||||
|
gh api \
|
||||||
|
--method POST \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
|
/repos/OWNER/REPO/issues \
|
||||||
|
--input - <<< '{
|
||||||
|
"title": "Issue title",
|
||||||
|
"body": "Issue description.",
|
||||||
|
"assignees": ["copilot-swe-agent[bot]"],
|
||||||
|
"agent_assignment": {
|
||||||
|
"target_repo": "OWNER/REPO",
|
||||||
|
"base_branch": "main",
|
||||||
|
"custom_instructions": "",
|
||||||
|
"custom_agent": "",
|
||||||
|
"model": ""
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Updating an existing issue
|
||||||
|
|
||||||
|
```shell copy
|
||||||
|
gh api \
|
||||||
|
--method PATCH \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
|
/repos/OWNER/REPO/issues/ISSUE_NUMBER \
|
||||||
|
--input - <<< '{
|
||||||
|
"assignees": ["copilot-swe-agent[bot]"],
|
||||||
|
"agent_assignment": {
|
||||||
|
"target_repo": "OWNER/REPO",
|
||||||
|
"base_branch": "main",
|
||||||
|
"custom_instructions": "",
|
||||||
|
"custom_agent": "",
|
||||||
|
"model": ""
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
## Asking {% data variables.product.prodname_copilot_short %} to create a pull request from the agents tab or panel
|
## Asking {% data variables.product.prodname_copilot_short %} to create a pull request from the agents tab or panel
|
||||||
|
|
||||||
You can ask {% data variables.product.prodname_copilot_short %} to open a pull request from either the agents tab or the agents panel. The only difference is the entry point - once you see the "New agent task" form, the steps are the same.
|
You can ask {% data variables.product.prodname_copilot_short %} to open a pull request from either the agents tab or the agents panel. The only difference is the entry point - once you see the "New agent task" form, the steps are the same.
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{%- ifversion ghec %}
|
{%- ifversion ghec %}
|
||||||
* SOC 1, Type 2
|
* SOC 1, Type 2
|
||||||
* SOC 2, Type 1 ({% data variables.copilot.copilot_for_business %} only)
|
|
||||||
* SOC 2, Type 2
|
* SOC 2, Type 2
|
||||||
{%- elsif fpt %}
|
{%- elsif fpt %}
|
||||||
* SOC 3
|
* SOC 3
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
* Cloud Security Alliance CAIQ self-assessment (CSA CAIQ - Level 1)
|
* Cloud Security Alliance CAIQ self-assessment (CSA CAIQ - Level 1)
|
||||||
* ISO/IEC 27001:2013 certification
|
* ISO/IEC 27001:2022 certification
|
||||||
{%- ifversion ghec %}
|
{%- ifversion ghec %}
|
||||||
* Cloud Security Alliance STAR certification (CSA STAR - Level 2)
|
* Cloud Security Alliance STAR certification (CSA STAR - Level 2)
|
||||||
* {% data variables.product.github %} Bug Bounty Quarterly reports
|
* {% data variables.product.github %} Bug Bounty Quarterly reports
|
||||||
* {% data variables.product.prodname_dotcom_the_website %} Services Continuity and Incident Management Plan
|
* {% data variables.product.prodname_dotcom_the_website %} Services Continuity and Incident Management Plan
|
||||||
|
* {% data variables.product.github %} PCI DSS Attestation of Compliance
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|||||||
@@ -1,3 +1,79 @@
|
|||||||
# Early access
|
# Early Access
|
||||||
|
|
||||||
Early access allows the Docs team to publish docs to docs.github.com without putting the content files in github/docs or github/docs-internal. This allows the Docs team to publish articles about limited access features.
|
The Early Access module enables the GitHub Docs team to publish documentation for features that are in limited access (beta, technical preview, etc.) without exposing the content in the public `github/docs` repository.
|
||||||
|
|
||||||
|
## Purpose & Scope
|
||||||
|
|
||||||
|
This system allows for:
|
||||||
|
- **Private Content Hosting**: Storing sensitive or unreleased documentation in a separate, private repository (`github/docs-early-access`).
|
||||||
|
- **Seamless Integration**: Merging this private content into the main site build so it appears native to the user (e.g., under `/en/early-access`).
|
||||||
|
- **Access Control**: Hiding these pages from public navigation and search engines, making them accessible only via direct links or specific "Early Access" index pages.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Content Storage
|
||||||
|
|
||||||
|
Early access content lives in a separate private repository: `github/docs-early-access`.
|
||||||
|
- **Structure**: It mirrors the main repo's structure (`content/`, `data/`, `assets/`).
|
||||||
|
- **Integration**: During the build process (or local development), files from the private repo are copied or symlinked into the main `docs-internal` directory.
|
||||||
|
|
||||||
|
### Middleware
|
||||||
|
|
||||||
|
The logic for serving and listing these pages is handled in `src/early-access/middleware/early-access-links.ts`.
|
||||||
|
- **`earlyAccessContext`**: This middleware runs on requests to `/early-access`. It:
|
||||||
|
- Checks if the user is on an early access path.
|
||||||
|
- Retrieves a list of hidden pages whose path starts with `early-access`.
|
||||||
|
- Injects these links into the rendering context (`req.context.earlyAccessPageLinks`), allowing index pages to dynamically list available early access content.
|
||||||
|
|
||||||
|
### Scripts
|
||||||
|
|
||||||
|
A suite of scripts in `src/early-access/scripts` manages the workflow:
|
||||||
|
- **`clone-locally`**: Clones the private `docs-early-access` repo for local development.
|
||||||
|
- **`symlink-from-local-repo.ts`**: Symlinks the cloned content into the main `content/` and `assets/` directories so the Next.js server can see them.
|
||||||
|
- **`merge-early-access.sh`**: Used in CI/CD to physically move files from the checked-out private repo into the build directory.
|
||||||
|
- **`update-data-and-image-paths.ts`**: A utility to fix up paths when moving content between the main repo and early access.
|
||||||
|
|
||||||
|
## Setup & Usage
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
To work on Early Access content locally:
|
||||||
|
|
||||||
|
1. **Clone the Repo**:
|
||||||
|
```bash
|
||||||
|
npm run clone-early-access
|
||||||
|
```
|
||||||
|
This clones `github/docs-early-access` into a sibling directory.
|
||||||
|
|
||||||
|
2. **Symlink Content**:
|
||||||
|
```bash
|
||||||
|
npm run symlink-from-local-repo
|
||||||
|
```
|
||||||
|
This links the content into `docs-internal`.
|
||||||
|
|
||||||
|
3. **Run the Server**:
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
You can now access pages at `http://localhost:4000/en/early-access`.
|
||||||
|
|
||||||
|
### Adding New Content
|
||||||
|
|
||||||
|
1. Create markdown files in the `docs-early-access` repo.
|
||||||
|
2. Ensure the frontmatter includes `hidden: true` to prevent it from appearing in the main sidebar navigation (unless specifically desired).
|
||||||
|
3. Use the `early-access` directory prefix.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- **`github/docs-early-access`**: The private repository containing the actual content.
|
||||||
|
- **CI/CD Workflows**: The deployment process must have access to the private repo to merge the content before building.
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
- **Team**: `@github/docs-engineering`
|
||||||
|
- **Content Owners**: The Writers and Product Managers responsible for the specific early access features.
|
||||||
|
|
||||||
|
## Current State & Known Issues
|
||||||
|
|
||||||
|
- **"Hidden" but Public**: While the source is private, once deployed to `docs.github.com`, the pages are technically public if you know the URL. They are "security through obscurity" (hidden from nav/search), not authenticated.
|
||||||
|
- **Build Complexity**: The merging process adds complexity to the build pipeline and can sometimes cause confusion with path resolution or asset loading if files are moved incorrectly.
|
||||||
@@ -1,3 +1,82 @@
|
|||||||
# Learning track
|
# Learning Tracks
|
||||||
|
|
||||||
Learning tracks display on guides pages. Learning tracks are a list of related articles that learners can go through sequentially.
|
This module manages "Learning Tracks"—curated, ordered lists of articles that guide a user through a specific topic or goal. When a user enters a learning track, they see a persistent banner or navigation element that helps them move sequentially through the guides.
|
||||||
|
|
||||||
|
## Purpose & Scope
|
||||||
|
|
||||||
|
The goal of this feature is to:
|
||||||
|
- **Group Content**: Logically group related articles into a sequence.
|
||||||
|
- **Guide Users**: Provide "Next" and "Previous" navigation context to keep users on the path.
|
||||||
|
- **Track Progress**: Visually indicate where the user is within the sequence (e.g., "Step 2 of 5").
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Data Source
|
||||||
|
|
||||||
|
Learning tracks are defined in YAML files located in `data/learning-tracks`.
|
||||||
|
- **Structure**: `data/learning-tracks/<product>.yml`
|
||||||
|
- **Schema**: Each file contains multiple tracks, where each track is defined as a top-level key with properties like:
|
||||||
|
- `title`: Display title of the track.
|
||||||
|
- `description`: Short summary.
|
||||||
|
- `guides`: An ordered list of relative paths to the articles.
|
||||||
|
- `versions`: (Optional) Which versions this track applies to.
|
||||||
|
|
||||||
|
### Middleware
|
||||||
|
|
||||||
|
The core logic for *active* tracking happens in `src/learning-track/middleware/learning-track.ts`.
|
||||||
|
- **Trigger**: It looks for the `?learn=<track_name>` query parameter in the URL.
|
||||||
|
- **Context Injection**: If a valid track is found:
|
||||||
|
- It calculates the current position (index) based on the current page path.
|
||||||
|
- It resolves the `prevGuide` and `nextGuide` links.
|
||||||
|
- It injects a `currentLearningTrack` object into `req.context`, which the UI components use to render the progress banner.
|
||||||
|
|
||||||
|
### Library
|
||||||
|
|
||||||
|
`src/learning-track/lib/process-learning-tracks.ts` is used (often by landing pages) to list available tracks.
|
||||||
|
- **Rendering**: It handles Liquid rendering for titles and descriptions.
|
||||||
|
- **Versioning**: It filters out tracks or specific guides that don't exist in the current documentation version.
|
||||||
|
- **Translation Fallback**: It ensures that if a translated track has broken data, it falls back to the English structure (guides list) while keeping translated titles if possible.
|
||||||
|
|
||||||
|
## Setup & Usage
|
||||||
|
|
||||||
|
### Defining a Track
|
||||||
|
|
||||||
|
Add a track to `data/learning-tracks/YOUR_PRODUCT.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
getting_started:
|
||||||
|
title: "Getting Started with GitHub"
|
||||||
|
description: "Learn the basics of repositories and commits."
|
||||||
|
versions:
|
||||||
|
fpt: '*'
|
||||||
|
ghec: '*'
|
||||||
|
guides:
|
||||||
|
- /get-started/signing-up-for-github/signing-up-for-a-new-github-account
|
||||||
|
- /get-started/first-steps-with-git/set-up-git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linking to a Track
|
||||||
|
|
||||||
|
To start a user on a track, link to the first guide with the `learn` parameter (matching the track key defined in the YAML):
|
||||||
|
`/en/get-started/signing-up-for-github/signing-up-for-a-new-github-account?learn=getting_started`
|
||||||
|
|
||||||
|
### URL Structure
|
||||||
|
|
||||||
|
- **`learn=<track_name>`**: Identifies the active track.
|
||||||
|
- **`learnProduct=<product_name>`**: (Optional) Used when the track belongs to a different product than the current page context.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- **`data/learning-tracks`**: The source of truth for track definitions.
|
||||||
|
- **`src/content-render`**: Used to render Liquid within track titles and descriptions.
|
||||||
|
- **`src/versions`**: Used to filter tracks based on the current page version.
|
||||||
|
|
||||||
|
## Ownership
|
||||||
|
|
||||||
|
- **Team**: `@github/docs-engineering`
|
||||||
|
- **Content Owners**: The Writers and Content Strategists who define the tracks in the `data` directory.
|
||||||
|
|
||||||
|
## Current State & Known Issues
|
||||||
|
|
||||||
|
- **Query Param Persistence**: The feature relies on the `?learn=` parameter persisting as the user clicks links. If a user navigates away via a link that doesn't preserve query params (e.g., a standard markdown link outside the track navigation), they "fall off" the track.
|
||||||
|
- **Translation Sync**: Translators sometimes translate the `guides` list paths or break the YAML structure. The code has specific logic to force-use English guide lists to prevent 404s in translated versions.
|
||||||
Reference in New Issue
Block a user