1
0
mirror of synced 2025-12-30 03:01:36 -05:00

Merge pull request #34131 from github/repo-sync

Repo sync
This commit is contained in:
docs-bot
2024-07-29 14:30:39 -07:00
committed by GitHub
29 changed files with 446 additions and 480 deletions

View File

@@ -95,7 +95,7 @@ jobs:
changes=$(git diff --name-only | wc -l)
untracked=$(git status --untracked-files --short | wc -l)
if [[ $changes -eq 0 ]] && [[ $untracked -eq 0 ]]; then
echo "There are no changes to commit after running src/rest/scripts/update-files.js. Exiting..."
echo "There are no changes to commit or untracked files. Exiting."
exit 0
fi

View File

@@ -55,7 +55,7 @@ jobs:
changes=$(git diff --name-only | wc -l)
untracked=$(git status --untracked-files --short | wc -l)
if [[ $changes -eq 0 ]] && [[ $untracked -eq 0 ]]; then
echo "There are no changes to commit after running src/rest/scripts/update-files.js. Exiting..."
echo "There are no changes to commit or untracked files. Exiting..."
exit 0
fi

View File

@@ -49,7 +49,7 @@ jobs:
# Needed for gh
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_WRITEORG_PROJECT }}
run: |
src/rest/scripts/update-files.js --source-repo rest-api-description --output rest github-apps webhooks rest-redirects
npm run sync-rest -- --source-repo rest-api-description --output rest github-apps webhooks rest-redirects
git status
echo "Deleting the cloned github/rest-api-description repo..."
rm -rf rest-api-description
@@ -73,7 +73,7 @@ jobs:
# If nothing to commit, exit now. It's fine. No orphans.
changes=$(git diff --name-only | wc -l)
if [[ $changes -eq 0 ]]; then
echo "There are no changes to commit after running src/rest/scripts/update-files.js. Exiting..."
echo "There are no changes to commit after running `npm run sync-rest` Exiting..."
exit 0
fi

View File

@@ -11,6 +11,7 @@ children:
- /managing-requests-for-copilot-business-in-your-organization
- /revoking-access-to-copilot-for-members-of-your-organization
- /reviewing-usage-data-for-github-copilot-in-your-organization
- /reviewing-changes-to-content-exclusions-for-github-copilot
- /reviewing-audit-logs-for-copilot-business
redirect_from:
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/reviewing-github-copilot-activity-in-your-organization

View File

@@ -1,15 +1,16 @@
---
title: Reviewing changes to content exclusions for GitHub Copilot
intro: 'You can monitor changes to content exclusions in your repositories and organizations.'
shortTitle: Content exclusion changes
intro: You can monitor changes to content exclusions in your repositories and organizations.
permissions: Organization owners
product: '{% data reusables.gated-features.copilot-business-and-enterprise %}'
versions:
feature: copilot
topics:
- Copilot
shortTitle: Review content exclusion changes
redirect_from:
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/reviewing-changes-to-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/setting-policies-for-copilot-in-your-organization/reviewing-changes-to-content-exclusions-for-github-copilot
---
{% data reusables.copilot.content-exclusions-availability-and-beta-note %}

View File

@@ -1,81 +0,0 @@
---
title: About content exclusions for GitHub Copilot
intro: 'Learn how content exclusions for {% data variables.product.prodname_copilot %} work.'
permissions: '{% data reusables.copilot.content-exclusion-permissions %}'
product: '{% data reusables.gated-features.copilot-business-and-enterprise %}'
versions:
feature: copilot
redirect_from:
- /copilot/managing-copilot-business/configuring-content-exclusions-for-github-copilot
- /copilot/managing-github-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/about-content-exclusions-for-github-copilot
topics:
- Copilot
shortTitle: About content exclusions
---
{% data reusables.copilot.content-exclusion-note %}
You can configure {% data variables.product.prodname_copilot %} to **ignore certain files by excluding specific paths to content** in the settings for your repository or organization.
When you specify content exclusions, there are up to three effects depending on the level of support for your IDE:
* Code completion will not be available in the affected files.
* The content in affected files will not inform code completion suggestions in other files.
* The content in affected files will not inform {% data variables.product.prodname_copilot_chat %}'s responses.
{% data reusables.copilot.content-exclusions-delay %} See "[AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/testing-changes-to-content-exclusions-in-your-ide)."
## Availability of content exclusions
| Tool | Code completion support | {% data variables.product.prodname_copilot_chat_short %} support |
|--------|:--------:|:--------:|
| {% data variables.product.prodname_vs %} | {% octicon "check" aria-label="Supported" %} | {% octicon "x" aria-label="Not supported" %} |
| {% data variables.product.prodname_vscode %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} |
| JetBrains IDEs | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} |
| Vim/Neovim | {% octicon "check" aria-label="Supported" %} | Not applicable |
| Azure Data Studio | {% octicon "x" aria-label="Not supported" %} | Not applicable |
| {% data variables.product.prodname_dotcom_the_website %} | Not applicable | {% octicon "x" aria-label="Not supported" %} |
## Limitations of content exclusions
{% data reusables.copilot.content-exclusion-limitations %}
## What can you exclude?
When you specify content exclusion in the settings for a repository, you can only exclude files in that repository.
When you specify content exclusion in the settings for an organization, you can exclude files in any Git-based repository hosted on {% data variables.product.prodname_dotcom_the_website %}, or anywhere that can be accessed using any of the following syntaxes:
```text
http[s]://host.xz[:port]/path/to/repo.git/
git://host.xz[:port]/path/to/repo.git/
[user@]host.xz:path/to/repo.git/
ssh://[user@]host.xz[:port]/path/to/repo.git/
```
## Who is affected by a content exclusion setting?
{% data reusables.copilot.content-exclusions-scope %}
{% ifversion fpt %}All exclusions, whether they are defined in repository settings or in organization settings, apply to all members of the organization who have been granted a {% data variables.product.prodname_copilot_short %} seat as part of a {% data variables.product.prodname_copilot_business_short %} subscription.{% endif %}
{% ifversion ghec %}
You can't specify content exclusions in the settings for an enterprise. However, all content exclusions defined in organization or repository settings apply to all members of the enterprise who have been granted a {% data variables.product.prodname_copilot_short %} seat as part of a {% data variables.product.prodname_copilot_business_short %} or {% data variables.product.prodname_copilot_enterprise_short %} subscription.
This means, for example, that if you are an admin of an organization that belongs to Enterprise X, you can set up an exclusion for files in any Git-based repositories, hosted on {% data variables.product.prodname_dotcom %} or elsewhere, and the exclusion will apply to anyone who gets their {% data variables.product.prodname_copilot_business_short %} or {% data variables.product.prodname_copilot_enterprise_short %} license from any organization in Enterprise X.
> [!TIP] To more easily track content exclusions, create exclusions in the settings of the repository containing the affected files, or in the settings of the organization that owns the repository.
{% endif %}
## Data sent to {% data variables.product.prodname_dotcom %}
After you configure content exclusion, the client (for example, the {% data variables.product.prodname_copilot_short %} extension for {% data variables.product.prodname_vscode_shortname %}) sends the current repository URL to the {% data variables.product.prodname_dotcom %} server so that the server can return the correct policy to the client. These URLs are not logged anywhere.
## Next steps
To set up content exclusions in your repository or organization, see "[AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/configuring-content-exclusions-for-github-copilot)."

View File

@@ -1,138 +0,0 @@
---
title: Configuring content exclusions for GitHub Copilot
intro: 'You can prevent {% data variables.product.prodname_copilot %} from accessing certain content.'
permissions: '{% data reusables.copilot.content-exclusion-permissions %}'
product: '{% data reusables.gated-features.copilot-business-and-enterprise %}'
layout: inline
versions:
feature: copilot
topics:
- Copilot
shortTitle: Configure content exclusions
redirect_from:
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/configuring-content-exclusions-for-github-copilot
---
{% data reusables.copilot.content-exclusions-availability-and-beta-note %}
## Configuring content exclusions for your repository
You can use your repository settings to specify content in your repository that {% data variables.product.prodname_copilot %} should ignore.
{% data reusables.repositories.navigate-to-repo %}
{% data reusables.repositories.sidebar-settings %}
1. In the "Code & automation" section of the side bar, click **{% octicon "copilot" aria-hidden="true" %} {% data variables.product.prodname_copilot_short %}**.
If your repository inherits any exclusions from {%ifversion fpt %}its parent organization{% else %} organizations in the same enterprise{% endif %}, you'll see {%ifversion ghec %}one or more{% else %} a{% endif %} gray box{%ifversion ghec %}es{% endif %} at the top of the page containing details of these exclusions. You cannot edit these settings.
1. In the box following "Paths to exclude in this repository," enter the paths to files from which {% data variables.product.prodname_copilot_short %} should be excluded.
Use the format: `- "/PATH/TO/DIRECTORY/OR/FILE"`, with each path on a separate line. You can add comments by starting a line with `#`.
> [!TIP] {% data reusables.copilot.content-exclusion-fnmatch-tip %}
### Example of paths specified in the repository settings
```yaml annotate
# Ignore the `/src/some-dir/kernel.rs` file in this repository.
- "/src/some-dir/kernel.rs"
# Ignore files called `secrets.json` anywhere in this repository.
- "secrets.json"
# Ignore all files whose names begin with `secret` anywhere in this repository.
- "secret*"
# Ignore files whose names end with `.cfg` anywhere in this repository.
- "*.cfg"
# Ignore all files in or below the `/scripts` directory of this repository.
- "/scripts/**"
```
## Configuring content exclusions for your organization
You can use your organization settings to specify content in any Git repository that {% data variables.product.prodname_copilot %} should ignore.
{% data reusables.profile.access_org %}
{% data reusables.profile.org_settings %}
1. In the left sidebar, click **{% octicon "copilot" aria-hidden="true" %} {% data variables.product.prodname_copilot_short %}** then click **Content exclusion**.
1. In the box following "Repositories and paths to exclude," enter details of where {% data variables.product.prodname_copilot_short %} should be excluded.
For each repository in which you want files to be excluded from {% data variables.product.prodname_copilot_short %}, enter a reference to the repository on one line, followed by paths to locations within the repository, with each path on a separate line. Use the following format:
```yaml
REPOSITORY-REFERENCE:
- "/PATH/TO/DIRECTORY/OR/FILE"
- "/PATH/TO/DIRECTORY/OR/FILE"
- ...
```
Repositories can be referenced using various protocols. You can use any of the following syntaxes for `REPOSITORY-REFERENCE` and {% data variables.product.prodname_copilot_short %} will match them regardless of how the repository was cloned locally:
```text
http[s]://host.xz[:port]/path/to/repo.git/
git://host.xz[:port]/path/to/repo.git/
[user@]host.xz:path/to/repo.git/
ssh://[user@]host.xz[:port]/path/to/repo.git/
```
### Formatting tips for `REPOSITORY-REFERENCE`
* {% data reusables.copilot.content-exclusion-fnmatch-tip %}
* The `user@` and `:port` parts of the `REPOSITORY-REFERENCE` are ignored in the calculation of which paths to ignore for a repository.
* Each repository reference can contain a single `*` wildcard. For example, `https://github.com/octo-org/*` matches all repositories in the `octo-org` organization.
* For Azure DevOps, you can use the new (dev.azure.com) or old (visualstudio.com) host format when specifying `REPOSITORY-REFERENCE`, and {% data variables.product.prodname_copilot_short %} will match them regardless of which host was used to clone the repository locally.
### Example of repositories and paths in organization settings
```yaml annotate
# Ignore all `.env` files at any path, in any repository.
# This setting applies to all repositories, not just to those on GitHub.com.
# This could also have been written on a single line as:
#
# "*": ["**/.env"]
"*":
- "**/.env"
# In the `octo-repo` repository in this organization:
octo-repo:
# Ignore the `/src/some-dir/kernel.rs` file.
- "/src/some-dir/kernel.rs"
# In the `primer/react` repository on {% data variables.product.prodname_dotcom %}:
https://github.com/primer/react.git:
# Ignore files called `secrets.json` anywhere in this repository.
- "secrets.json"
# Ignore files called `temp.rb` in or below the `/src` directory.
- "/src/**/temp.rb"
# In the `copilot` repository of any {% data variables.product.prodname_dotcom %} organization:
git@github.com:*/copilot:
# Ignore any files in or below the `/__tests__` directory.
- "/__tests__/**"
# Ignore any files in the `/scripts` directory.
- "/scripts/*"
# In the `gitlab-org/gitlab-runner` repository on GitLab:
git@gitlab.com:gitlab-org/gitlab-runner.git:
# Ignore the `/main_test.go` file.
- "/main_test.go"
# Ignore any files with names beginning with `server` or `session` anywhere in this repository.
- "{server,session}*"
# Ignore any files with names ending with `.md` or `.mk` anywhere in this repository.
- "*.m[dk]"
# Ignore files directly within directories such as `packages` or `packaged` anywhere in this repository.
- "**/package?/*"
# Ignore files in or below any `security` directories, anywhere in this repository.
- "**/security/**"
```
## Next steps
To test your changes, see "[AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/testing-changes-to-content-exclusions-in-your-ide)."

View File

@@ -0,0 +1,190 @@
---
title: Excluding content from GitHub Copilot
shortTitle: Exclude content from Copilot
intro: 'You can prevent {% data variables.product.prodname_copilot_short %} from accessing certain content.'
permissions: '{% data reusables.copilot.content-exclusion-permissions %}'
product: '{% data reusables.gated-features.copilot-business-and-enterprise %}'
layout: inline
versions:
feature: copilot
redirect_from:
- /copilot/managing-copilot-business/configuring-content-exclusions-for-github-copilot
- /copilot/managing-github-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/about-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/setting-policies-for-copilot-in-your-organization/about-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/setting-policies-for-copilot-in-your-organization/configuring-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/setting-policies-for-copilot-in-your-organization/testing-changes-to-content-exclusions-in-your-ide
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/configuring-content-exclusions-for-github-copilot
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/testing-changes-to-content-exclusions-in-your-ide
topics:
- Copilot
---
## About content exclusions for {% data variables.product.prodname_copilot_short %}
{% data reusables.copilot.content-exclusion-note %}
You can use content exclusions to configure {% data variables.product.prodname_copilot_short %} to ignore certain files in a repository or organization. When you exclude content from {% data variables.product.prodname_copilot_short %}:
* Code completion will not be available in the affected files.
* The content in affected files will not inform code completion suggestions in other files.
* The content in affected files will not inform {% data variables.product.prodname_copilot_chat %}'s responses.
{% data reusables.copilot.content-exclusions-scope %}
### Limitations of content exclusions
Content exclusions are not currently available for Copilot Chat in Visual Studio, Copilot Chat in GitHub.com, or code completion in Azure Data Studio. Additionally:
{% data reusables.copilot.content-exclusion-limitations %}
### Data sent to {% data variables.product.prodname_dotcom %}
After you configure content exclusion, the client (for example, the {% data variables.product.prodname_copilot_short %} extension for {% data variables.product.prodname_vscode_shortname %}) sends the current repository URL to the {% data variables.product.prodname_dotcom %} server so that the server can return the correct policy to the client. These URLs are not logged anywhere.
## Configuring content exclusions for your repository
You can use your repository settings to specify content in your repository that {% data variables.product.prodname_copilot %} should ignore.
{% data reusables.repositories.navigate-to-repo %}
{% data reusables.repositories.sidebar-settings %}
1. In the "Code & automation" section of the side bar, click **{% octicon "copilot" aria-hidden="true" %} {% data variables.product.prodname_copilot_short %}**.
If your repository inherits any exclusions from {%ifversion fpt %}its parent organization{% else %} organizations in the same enterprise{% endif %}, you'll see {%ifversion ghec %}one or more{% else %} a{% endif %} gray box{%ifversion ghec %}es{% endif %} at the top of the page containing details of these exclusions. You cannot edit these settings.
1. In the box following "Paths to exclude in this repository," enter the paths to files from which {% data variables.product.prodname_copilot_short %} should be excluded.
Use the format: `- "/PATH/TO/DIRECTORY/OR/FILE"`, with each path on a separate line. You can add comments by starting a line with `#`.
> [!TIP] {% data reusables.copilot.content-exclusion-fnmatch-tip %}
### Example of paths specified in the repository settings
```yaml annotate
# Ignore the `/src/some-dir/kernel.rs` file in this repository.
- "/src/some-dir/kernel.rs"
# Ignore files called `secrets.json` anywhere in this repository.
- "secrets.json"
# Ignore all files whose names begin with `secret` anywhere in this repository.
- "secret*"
# Ignore files whose names end with `.cfg` anywhere in this repository.
- "*.cfg"
# Ignore all files in or below the `/scripts` directory of this repository.
- "/scripts/**"
```
## Configuring content exclusions for your organization
You can use your organization settings to specify content in any Git repository that {% data variables.product.prodname_copilot %} should ignore.
{% data reusables.profile.access_org %}
{% data reusables.profile.org_settings %}
1. In the left sidebar, click **{% octicon "copilot" aria-hidden="true" %} {% data variables.product.prodname_copilot_short %}** then click **Content exclusion**.
1. In the box following "Repositories and paths to exclude," enter details of where {% data variables.product.prodname_copilot_short %} should be excluded.
For each repository in which you want files to be excluded from {% data variables.product.prodname_copilot_short %}, enter a reference to the repository on one line, followed by paths to locations within the repository, with each path on a separate line. Use the following format, replacing `REPOSITORY-REFERENCE` with a reference to the repository that contains the files you'd like to exclude:
```yaml
REPOSITORY-REFERENCE:
- "/PATH/TO/DIRECTORY/OR/FILE"
- "/PATH/TO/DIRECTORY/OR/FILE"
- ...
```
Repositories can be referenced using various protocols. You can use any of the following syntaxes for `REPOSITORY-REFERENCE` and {% data variables.product.prodname_copilot_short %} will match them regardless of how the repository was cloned locally:
```text
http[s]://host.xz[:port]/path/to/repo.git/
git://host.xz[:port]/path/to/repo.git/
[user@]host.xz:path/to/repo.git/
ssh://[user@]host.xz[:port]/path/to/repo.git/
```
The `user@` and `:port` parts of the `REPOSITORY-REFERENCE` are ignored in the calculation of which paths to ignore for a repository.
For Azure DevOps, you can use the new (dev.azure.com) or old (visualstudio.com) host format when specifying `REPOSITORY-REFERENCE`, and {% data variables.product.prodname_copilot_short %} will match them regardless of which host was used to clone the repository locally.
> [!TIP] {% data reusables.copilot.content-exclusion-fnmatch-tip %}
### Example of repositories and paths in organization settings
```yaml annotate
# Ignore all `.env` files at any path, in any repository.
# This setting applies to all repositories, not just to those on GitHub.com.
# This could also have been written on a single line as:
#
# "*": ["**/.env"]
"*":
- "**/.env"
# In the `octo-repo` repository in this organization:
octo-repo:
# Ignore the `/src/some-dir/kernel.rs` file.
- "/src/some-dir/kernel.rs"
# In the `primer/react` repository on {% data variables.product.prodname_dotcom %}:
https://github.com/primer/react.git:
# Ignore files called `secrets.json` anywhere in this repository.
- "secrets.json"
# Ignore files called `temp.rb` in or below the `/src` directory.
- "/src/**/temp.rb"
# In the `copilot` repository of any {% data variables.product.prodname_dotcom %} organization:
git@github.com:*/copilot:
# Ignore any files in or below the `/__tests__` directory.
- "/__tests__/**"
# Ignore any files in the `/scripts` directory.
- "/scripts/*"
# In the `gitlab-org/gitlab-runner` repository on GitLab:
git@gitlab.com:gitlab-org/gitlab-runner.git:
# Ignore the `/main_test.go` file.
- "/main_test.go"
# Ignore any files with names beginning with `server` or `session` anywhere in this repository.
- "{server,session}*"
# Ignore any files with names ending with `.md` or `.mk` anywhere in this repository.
- "*.m[dk]"
# Ignore files directly within directories such as `packages` or `packaged` anywhere in this repository.
- "**/package?/*"
# Ignore files in or below any `security` directories, anywhere in this repository.
- "**/security/**"
```
## Testing changes to content exclusions
You can use your IDE to confirm that your changes to content exclusions are working as expected.
### Propagate content exclusion changes to your IDE
After you add or change content exclusions, it can take up to 30 minutes to take effect in IDEs where the settings are already loaded. If you don't want to wait, you can manually reload the content exclusion settings using the following instructions.
* **For JetBrains IDEs and {% data variables.product.prodname_vs %}**, reload the content exclusion settings by closing and reopening the application.
* **For {% data variables.product.prodname_vscode %}**, use the following steps to reload the content exclusion settings:
1. Access the Command Palette. For example, by pressing <kbd>Shift</kbd>+<kbd>Command</kbd>+<kbd>P</kbd> (Mac) / <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> (Windows/Linux).
1. Type: `reload`.
1. Select **Developer: Reload Window**.
* **For Vim/Neovim**, content exclusions are automatically fetched from {% data variables.product.prodname_dotcom %} each time you open a file.
### Test your content exclusions
There are a few different ways to test your content exclusions, depending on which IDE you're using.
1. Open a file that you expect to be affected by your content exclusions.
1. Use one or more of the following techniques to test if content is being excluded:
* **In JetBrains IDEs, {% data variables.product.prodname_vs %}, and {% data variables.product.prodname_vscode %}**, check the {% data variables.product.prodname_copilot_short %} icon in the status bar. If a {% data variables.product.prodname_copilot_short %} content exclusion applies to the file, the {% data variables.product.prodname_copilot_short %} icon will have a diagonal line through it. Hover over the icon to see whether an organization or the parent repository disabled {% data variables.product.prodname_copilot_short %} for the file.
* **In JetBrains IDEs and {% data variables.product.prodname_vscode %}**, you can also test content exclusions in {% data variables.product.prodname_copilot_chat_short %}. Open the {% data variables.product.prodname_copilot_chat_short %} window, and ask {% data variables.product.prodname_copilot_chat_short %} a question about the excluded file. If your content is excluded successfully, {% data variables.product.prodname_copilot_short %} will be unable to answer your question, and will explain that some files were excluded from the conversation due to content exclusion rules.
* **In Vim/Neovim**, begin typing in the file. If {% data variables.product.prodname_copilot %} no longer provides inline suggestions as you type, the file is excluded.
## Further reading
* "[AUTOTITLE](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-access-to-github-copilot-in-your-organization/reviewing-changes-to-content-exclusions-for-github-copilot)"

View File

@@ -8,10 +8,8 @@ topics:
- Copilot
children:
- /managing-policies-for-copilot-in-your-organization
- /about-content-exclusions-for-github-copilot
- /configuring-content-exclusions-for-github-copilot
- /testing-changes-to-content-exclusions-in-your-ide
- /reviewing-changes-to-content-exclusions-for-github-copilot
- /excluding-content-from-github-copilot
redirect_from:
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization
---

View File

@@ -1,104 +0,0 @@
---
title: Testing changes to content exclusions in your IDE
intro: 'You can confirm your changes to content exclusions work as expected using your IDE.'
permissions: '{% data reusables.copilot.content-exclusion-permissions %}'
product: '{% data reusables.gated-features.copilot-business-and-enterprise %}'
versions:
feature: copilot
topics:
- Copilot
shortTitle: Test content exclusions
redirect_from:
- /copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-github-copilot-features-in-your-organization/testing-changes-to-content-exclusions-in-your-ide
---
{% data reusables.copilot.content-exclusions-availability-and-beta-note %}
{% vscode %}
## Propagating content exclusion changes to {% data variables.product.prodname_vscode %}
In {% data variables.product.prodname_vscode_shortname %}, you can wait up to 30 minutes to see the effect of a settings change, or you can manually reload content exclusion settings as follows:
1. Access the Command Palette. For example, by pressing <kbd>Shift</kbd>+<kbd>Command</kbd>+<kbd>P</kbd> (Mac) / <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> (Windows/Linux).
1. Type: `reload`.
1. Select **Developer: Reload Window**.
## Testing changes to content exclusions in {% data variables.product.prodname_vscode %}
After content exclusion changes propagate to {% data variables.product.prodname_vscode_shortname %}, the {% data variables.product.prodname_copilot_short %} icon indicates when {% data variables.product.prodname_copilot_short %} has been disabled by a content exclusion.
1. Open a file that you expect to be affected by your content exclusions.
If a {% data variables.product.prodname_copilot_short %} content exclusion applies to this file, the {% data variables.product.prodname_copilot_short %} icon in the status bar has a diagonal line through it.
1. Hover over the {% data variables.product.prodname_copilot_short %} icon. A popup message tells you whether an organization or the parent repository disabled {% data variables.product.prodname_copilot_short %} for this file.
![Screenshot of the {% data variables.product.prodname_copilot_short %} disabled popup in the {% data variables.product.prodname_vscode_shortname %} toolbar.](/assets/images/help/copilot/copilot-disabled-for-repo.png)
1. Optionally, you can also test content exclusions in {% data variables.product.prodname_copilot_chat_short %}. Open the {% data variables.product.prodname_copilot_chat_short %} window by clicking the {% data variables.product.prodname_copilot_chat_short %} icon in the activity bar.
![Screenshot of the {% data variables.product.prodname_copilot_chat_short %} icon in the Activity Bar.](/assets/images/help/copilot/vsc-copilot-chat-icon.png)
{% data reusables.copilot.test-content-exclusions-chat %}
{% endvscode %}
{% visualstudio %}
## Propagating content exclusion changes to {% data variables.product.prodname_vs %}
In {% data variables.product.prodname_vs %}, you can wait up to 30 minutes to see the effect of a settings change, or you can manually reload the content exclusion settings by closing and reopening the application.
## Testing changes to content exclusions in {% data variables.product.prodname_vs %}
In {% data variables.product.prodname_vs %}, the {% data variables.product.prodname_copilot_short %} icon indicates when {% data variables.product.prodname_copilot_short %} has been disabled by a content exclusion.
1. Open a file that you expect to be affected by your content exclusions.
If a {% data variables.product.prodname_copilot_short %} content exclusion applies to this file, the {% data variables.product.prodname_copilot_short %} icon in the status bar has a diagonal line through it.
1. Hover over the {% data variables.product.prodname_copilot_short %} icon. A popup message tells you whether an organization or the parent repository disabled {% data variables.product.prodname_copilot_short %} for this file.
![Screenshot of the {% data variables.product.prodname_copilot_short %} disabled popup in the {% data variables.product.prodname_vscode_shortname %} toolbar.](/assets/images/help/copilot/copilot-disabled-for-repo.png)
{% endvisualstudio %}
{% jetbrains %}
## Propagating content exclusion changes to JetBrains IDEs
In supported JetBrains IDEs, you can wait up to 30 minutes to see the effect of a settings change, or you can manually reload the content exclusion settings by closing and reopening the application.
## Testing changes to content exclusions in JetBrains IDEs
In supported JetBrains IDEs, the {% data variables.product.prodname_copilot_short %} icon indicates when {% data variables.product.prodname_copilot_short %} has been disabled by a content exclusion.
1. Open a file that you expect to be affected by your content exclusions.
If a {% data variables.product.prodname_copilot_short %} content exclusion applies to this file, the {% data variables.product.prodname_copilot_short %} icon in the status bar has a diagonal line through it.
1. Hover over the {% data variables.product.prodname_copilot_short %} icon. A popup message tells you whether an organization or the parent repository disabled {% data variables.product.prodname_copilot_short %} for this file.
![Screenshot of the {% data variables.product.prodname_copilot_short %} disabled popup in the {% data variables.product.prodname_vscode_shortname %} toolbar.](/assets/images/help/copilot/copilot-disabled-for-repo.png)
1. Optionally, you can also test content exclusions in {% data variables.product.prodname_copilot_chat_short %}. Open the {% data variables.product.prodname_copilot_chat_short %} window by clicking the **{% data variables.product.prodname_copilot_chat_short %}** icon at the right side of the JetBrains IDE window.
![Screenshot of the {% data variables.product.prodname_copilot_chat_short %} icon in the Activity Bar.](/assets/images/help/copilot/jetbrains-copilot-chat-icon.png)
{% data reusables.copilot.test-content-exclusions-chat %}
{% endjetbrains %}
{% vimneovim %}
## Propagating content exclusion changes to Vim/Neovim
If you are working in Vim/Neovim, content exclusions are automatically fetched from {% data variables.product.prodname_dotcom %} each time you open a file.
## Testing changes to content exclusions in Vim/Neovim
1. Open a file that you expect to be affected by your content exclusions.
1. Begin typing. If {% data variables.product.prodname_copilot %} no longer provides inline suggestions as you type, the file is excluded.
{% endvimneovim %}

View File

@@ -32,9 +32,9 @@ Repository admins can add any topics they'd like to a repository. Helpful topics
You can search for repositories that are associated with a particular topic. For more information, see "[AUTOTITLE](/search-github/searching-on-github/searching-for-repositories#search-by-topic)." You can also search for a list of topics on {% data variables.product.product_name %}. For more information, see "[AUTOTITLE](/search-github/searching-on-github/searching-topics)."
When creating a topic:
* use lowercase letters, numbers, and hyphens.
* use 50 characters or less.
* add no more than 20 topics.
* Use lowercase letters, numbers, and hyphens.
* Use 50 characters or less.
* Add no more than 20 topics.
## Adding topics to your repository

View File

@@ -1,5 +1,11 @@
A content exclusion setting **only applies to people who meet each of the following criteria**:
* They have been granted a seat as part of a {% data variables.product.prodname_copilot_for_business %} or {% data variables.product.prodname_copilot_enterprise %} subscription
* They are members of the same {% ifversion fpt %}organization{% else %}enterprise{% endif %} in which the content exclusion is configured
{% ifversion fpt %}
Content exclusion settings only apply to members of the organization in which the content exclusion is configured, who have been granted a seat as part of a {% data variables.product.prodname_copilot_for_business %} or {% data variables.product.prodname_copilot_enterprise %} subscription.
{% else %}
You can only specify content exclusions in the settings for an organization or repository, not in the settings for an enterprise. Content exclusion settings defined in an organization or repository within an enterprise will apply to all members of the enterprise who have been granted a seat as part of a {% data variables.product.prodname_copilot_for_business %} or {% data variables.product.prodname_copilot_enterprise %} subscription.
{% endif %}
Anyone else who can access the specified files will still see code completion suggestions and {% data variables.product.prodname_copilot_chat %} responses referencing the specified files.

View File

@@ -67,7 +67,7 @@
"start-all-languages": "cross-env NODE_ENV=development tsx src/frame/server.ts",
"start-for-playwright": "cross-env ROOT=src/fixtures/fixtures TRANSLATIONS_FIXTURE_ROOT=src/fixtures/fixtures/translations ENABLED_LANGUAGES=en,ja NODE_ENV=test tsx src/frame/server.ts",
"symlink-from-local-repo": "node src/early-access/scripts/symlink-from-local-repo.js",
"sync-rest": "node src/rest/scripts/update-files.js",
"sync-rest": "tsx src/rest/scripts/update-files.ts",
"sync-search": "cross-env NODE_OPTIONS='--max_old_space_size=8192' start-server-and-test sync-search-server 4002 sync-search-indices",
"sync-search-ghes-release": "cross-env GHES_RELEASE=1 start-server-and-test sync-search-server 4002 sync-search-indices",
"sync-search-indices": "node src/search/scripts/sync-search-indices.js",

View File

@@ -310,6 +310,10 @@ async function getIndexFileVersions(directory, files) {
`File ${filepath} does not exist while assembling directory index.md files to create parent version.`,
)
}
// If not a markdown(x) file, skip it
if (!file.endsWith('.md') && !file.endsWith('.mdx')) {
return
}
const { data } = matter(await readFile(filepath, 'utf-8'))
if (!data || !data.versions) {
throw new Error(`Frontmatter in ${filepath} does not contain versions.`)

View File

@@ -24,9 +24,9 @@ To run the CodeQL CLI pipeline locally:
## About this directory
- `src/rest/lib/config.json` - A configuration file used to specify metadata about the REST pipeline.
- `src/rest/scripts` - The scripts and source code used run the CodeQL CLI pipeline.
- `src/rest/scripts/sync.js` - The entrypoint script that runs the CodeQL CLI pipeline.
- `src/codeql-cli/lib/config.json` - A configuration file used to specify metadata about the CodeQL CLI pipeline.
- `src/codeql-cli/scripts` - The scripts and source code used run the CodeQL CLI pipeline.
- `src/codeql-cli/scripts/sync.js` - The entrypoint script that runs the CodeQL CLI pipeline.
## Content team

View File

@@ -133,7 +133,7 @@ The benefit of the first method is that you don't need to deal with merging two
- [ ] To update the OpenAPI data, run the following command.
```shell
src/rest/scripts/update-files.js --source-repo rest-api-description --output rest github-apps webhooks rest-redirects
npm run sync-rest -- --source-repo rest-api-description --output rest github-apps webhooks rest-redirects
```
You may see an error that indicates that "...you must have the GITHUB_TOKEN environment variable set to access the programmatic access and resource files via the GitHub REST API." You can ignore this error.

View File

@@ -34,7 +34,8 @@ If the OpenAPI has changed, you will need to first wait for the OpenAPI to be me
To run the GitHub Apps pipeline locally:
1. Clone the [`github/rest-api-description`](https://github.com/github/rest-api-description) repository inside your local `docs-internal` repository.
1. Run `src/rest/scripts/update-files.js -s rest-api-description -o github-apps`.
1. Set a `GITHUB_TOKEN` in your `.env` with (classic) `repo` scopes & enable SSO for the github org.
1. Run `npm run sync-rest -- -s rest-api-description -o github-apps`.
## About this directory

View File

@@ -14,7 +14,7 @@ A [workflow](.github/workflows/sync-openapi.yml) is used to trigger the automati
- REST
- Webhooks
The workflow automatically creates a pull request with the changes (for all three pipelines) and the label `github-openapi-bot`. The workflow runs the `src/rest/scripts/update-files.js` script, which creates, deletes, or updates Markdown files in the `content/rest` directory.
The workflow automatically creates a pull request with the changes (for all three pipelines) and the label `github-openapi-bot`. The workflow runs the `npm run sync-rest` script, which creates, deletes, or updates Markdown files in the `content/rest` directory.
### Triggering the workflow sooner than the scheduled time
@@ -35,7 +35,8 @@ Then, you can manually sync the data used by the REST, Webhooks, and GitHub App
To run the REST pipeline locally:
1. Clone the [`github/rest-api-description`](https://github.com/github/rest-api-description) repository inside your local `docs-internal` repository.
1. Run `src/rest/scripts/update-files.js -s rest-api-description -o rest`. Note, by default `-o rest` is specified, so you can omit it.
1. Set a `GITHUB_TOKEN` in your `.env` with (classic) `repo` scopes & enable SSO for the github org.
1. Run `npm run sync-rest -- -s rest-api-description -o rest`. Note, by default `-o rest` is specified, so you can omit it.
## About this directory
@@ -45,7 +46,7 @@ To run the REST pipeline locally:
- `src/rest/lib` - The source code used in production for the automated documentation generated by the REST pipeline and configuration files edited by content and engineering team members.
- `src/rest/lib/config.json` - A configuration file used to specify metadata about the REST pipeline.
- `src/rest/scripts` - The scripts and source code used run the REST pipeline, which updates the `src/rest/data` directory.
- `src/rest/scripts/update-files.js` - The entrypoint script that runs the REST pipeline.
- `src/rest/scripts/update-files.ts` - The entrypoint script that runs the REST pipeline.
- `src/rest/tests` - The tests used to verify the REST pipeline.
## Configuring the pipeline

View File

@@ -1,8 +1,8 @@
# REST scripts
Writers run the [update-files.js](./update-files.js) script to get the latest dereferenced OpenAPI schema files.
Writers run the [update-files.ts](./update-files.ts) script to get the latest dereferenced OpenAPI schema files.
```
src/rest/scripts/update-files.js
npm run sync-rest
```
These scripts update the dereferenced OpenAPI files to create [the decorated files](../../src/rest/data) used to
render REST docs. See the [`src/rest/README`](../../src/rest/README.md)
@@ -20,7 +20,7 @@ Writers and developers depend on this script to preview OpenAPI changes in the d
## Production `--decorate-only` option
When changes to the OpenAPI are merged to the default branch of the `github/github` repository, a pull request is automatically opened with the updated dereferenced OpenAPI files. When pull requests are authored by `github-openapi-bot`, a CI test runs the `src/rest/scripts/update-files.js` script with the `--decorate-only` option. The `--decorate-only` option only decorates the dereferenced OpenAPI files, using the existing dereferenced OpenAPI schema files, and checks those changes in to the existing branch. The `--decorate-only` option is only used by a 🤖 and is only used on production dereferenced OpenAPI schema files.
When changes to the OpenAPI are merged to the default branch of the `github/github` repository, a pull request is automatically opened with the updated dereferenced OpenAPI files. When pull requests are authored by `github-openapi-bot`, a CI test runs the `npm run sync-rest` script with the `--decorate-only` option. The `--decorate-only` option only decorates the dereferenced OpenAPI files, using the existing dereferenced OpenAPI schema files, and checks those changes in to the existing branch. The `--decorate-only` option is only used by a 🤖 and is only used on production dereferenced OpenAPI schema files.
The `.github/workflows/openapi-schema-check.yml` CI test checks that the dereferenced and decorated schema files match. If the files don't match, potential causes could be:
- something went wrong when the schema changes (created by `github-openapi-bot`) were merged into another branch
@@ -28,4 +28,4 @@ The `.github/workflows/openapi-schema-check.yml` CI test checks that the derefer
⚠️ Only do this if you know exactly what the `--decorate-only` option does. ⚠️
If you know that the dereferenced schema files are correct, you can run the `src/rest/scripts/update-files.js --decorate-only` command on the branch locally to update the decorated files in your branch.
If you know that the dereferenced schema files are correct, you can run the `npm run sync-rest -- --decorate-only` command on the branch locally to update the decorated files in your branch.

View File

@@ -17,12 +17,12 @@ import { fileURLToPath } from 'url'
import walk from 'walk-sync'
import { existsSync } from 'fs'
import { syncRestData, getOpenApiSchemaFiles } from './utils/sync.js'
import { validateVersionsOptions } from './utils/get-openapi-schemas.js'
import { allVersions } from '#src/versions/lib/all-versions.js'
import { syncWebhookData } from '../../webhooks/scripts/sync.js'
import { syncGitHubAppsData } from '../../github-apps/scripts/sync.js'
import { syncRestRedirects } from './utils/get-redirects.js'
import { syncRestData, getOpenApiSchemaFiles } from './utils/sync'
import { validateVersionsOptions } from './utils/get-openapi-schemas'
import { allVersions } from '@/versions/lib/all-versions'
import { syncWebhookData } from '../../webhooks/scripts/sync'
import { syncGitHubAppsData } from '../../github-apps/scripts/sync'
import { syncRestRedirects } from './utils/get-redirects'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const TEMP_OPENAPI_DIR = path.join(__dirname, '../../../rest-api-description/openApiTemp')
@@ -30,7 +30,9 @@ const TEMP_BUNDLED_OPENAPI_DIR = path.join(TEMP_OPENAPI_DIR, 'bundled')
const GITHUB_REP_DIR = '../github'
const REST_API_DESCRIPTION_ROOT = 'rest-api-description'
const REST_DESCRIPTION_DIR = path.join(REST_API_DESCRIPTION_ROOT, 'descriptions-next')
const VERSION_NAMES = JSON.parse(await readFile('src/rest/lib/config.json', 'utf8')).versionMapping
const VERSION_NAMES: Record<string, string> = JSON.parse(
await readFile('src/rest/lib/config.json', 'utf8'),
).versionMapping
const noConfig = ['rest-redirects']
program
@@ -105,7 +107,10 @@ async function main() {
// so that we don't spend time generating data files for them.
if (sourceRepo === REST_API_DESCRIPTION_ROOT) {
const derefDir = await readdir(TEMP_OPENAPI_DIR)
const currentOpenApiVersions = Object.values(allVersions).map((elem) => elem.openApiVersionName)
// TODO: After migrating all-version.js to TypeScript, we can remove the type assertion
const currentOpenApiVersions = Object.values(allVersions).map(
(elem) => (elem as any).openApiVersionName,
)
for (const schema of derefDir) {
// if the schema does not start with a current version name, delete it
@@ -162,7 +167,7 @@ async function main() {
)
}
async function getBundledFiles() {
async function getBundledFiles(): Promise<void> {
// Get the github/github repo branch name and pull latest
const githubBranch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: GITHUB_REP_DIR })
.toString()
@@ -197,7 +202,7 @@ async function getBundledFiles() {
}
}
async function getBundlerOptions() {
async function getBundlerOptions(): Promise<string> {
let includeParams = ['--generate_dref_json_only']
if (versions) {
@@ -213,7 +218,7 @@ async function getBundlerOptions() {
return includeParams.join(' ')
}
async function validateInputParameters() {
async function validateInputParameters(): Promise<void> {
// The `--versions` option cannot be used
// with the `--include-deprecated` option
if (includeDeprecated && versions) {
@@ -248,7 +253,7 @@ async function validateInputParameters() {
// the short name of the version defined in lib/allVersions.js.
// This function also translates calendar-date format from .2022-11-28 to
// -2022-11-28
export async function normalizeDataVersionNames(sourceDirectory) {
export async function normalizeDataVersionNames(sourceDirectory: string): Promise<void> {
const schemas = await readdir(sourceDirectory)
for (const schema of schemas) {
@@ -259,8 +264,8 @@ export async function normalizeDataVersionNames(sourceDirectory) {
// Update the version name to use docs convention, e.g.,
// api.github.com.2022-11-28 -> fpt.2022-11-28
const docsBaseName = baseName.replace(
matchingSourceVersion,
VERSION_NAMES[matchingSourceVersion],
matchingSourceVersion!,
VERSION_NAMES[matchingSourceVersion!],
)
// Match a calendar version if it exists, e.g., .2022-11-28
const regex = /.\d{4}-\d{2}-\d{2}/

View File

@@ -1,5 +1,39 @@
#!/usr/bin/env node
import { renderContent } from '#src/content-render/index.js'
import { renderContent } from '@/content-render/index'
interface Schema {
oneOf?: any[]
type?: string
items?: any
properties?: Record<string, any>
required?: string[]
additionalProperties?: any
description?: string
enum?: string[]
nullable?: boolean
allOf?: any[]
anyOf?: any[]
[key: string]: any
}
export interface TransformedParam {
type: string
name: string
description: string
isRequired?: boolean
in?: string
childParamsGroups?: TransformedParam[]
enum?: string[]
oneOfObject?: boolean
default?: any
}
interface BodyParamProps {
paramKey?: string
required?: string[]
childParamsGroups?: TransformedParam[]
topLevel?: boolean
}
// If there is a oneOf at the top level, then we have to present just one
// in the docs. We don't currently have a convention for showing more than one
@@ -8,14 +42,16 @@ import { renderContent } from '#src/content-render/index.js'
// Currently there aren't very many operations that require this treatment.
// As an example, the 'Add status check contexts' and 'Set status check contexts'
// operations have a top-level oneOf.
async function getTopLevelOneOfProperty(schema) {
async function getTopLevelOneOfProperty(
schema: Schema,
): Promise<{ properties: Record<string, any>; required: string[] }> {
if (!schema.oneOf) {
throw new Error('Schema does not have a requestBody oneOf property defined')
}
if (!(Array.isArray(schema.oneOf) && schema.oneOf.length > 0)) {
throw new Error('Schema requestBody oneOf property is not an array')
}
// When a oneOf exists but the `type` differs, the case has historically
// been that the alternate option is an array, where the first option
// is the array as a property of the object. We need to ensure that the
@@ -39,8 +75,8 @@ async function getTopLevelOneOfProperty(schema) {
}
// Gets the body parameters for a given schema recursively.
export async function getBodyParams(schema, topLevel = false) {
const bodyParametersParsed = []
export async function getBodyParams(schema: Schema, topLevel = false): Promise<TransformedParam[]> {
const bodyParametersParsed: TransformedParam[] = []
const schemaObject = schema.oneOf && topLevel ? await getTopLevelOneOfProperty(schema) : schema
const properties = schemaObject.properties || {}
const required = schemaObject.required || []
@@ -48,7 +84,7 @@ export async function getBodyParams(schema, topLevel = false) {
// Most operation requestBody schemas are objects. When the type is an array,
// there will not be properties on the `schema` object.
if (topLevel && schema.type === 'array') {
const childParamsGroups = []
const childParamsGroups: TransformedParam[] = []
const arrayType = schema.items.type
const paramType = [schema.type]
if (arrayType === 'object') {
@@ -76,7 +112,7 @@ export async function getBodyParams(schema, topLevel = false) {
? param.additionalProperties.type
: [param.additionalProperties.type]
: []
const childParamsGroups = []
const childParamsGroups: TransformedParam[] = []
// If the parameter is an array or object there may be child params
// If the parameter has oneOf or additionalProperties, they need to be
@@ -88,7 +124,7 @@ export async function getBodyParams(schema, topLevel = false) {
// Create a snapshot of dependencies for a repository
// Update a gist
if (param.additionalProperties && additionalPropertiesType.includes('object')) {
const keyParam = {
const keyParam: TransformedParam = {
type: 'object',
name: 'key',
description: await renderContent(
@@ -99,11 +135,13 @@ export async function getBodyParams(schema, topLevel = false) {
default: param.default,
childParamsGroups: [],
}
keyParam.childParamsGroups.push(...(await getBodyParams(param.additionalProperties, false)))
if (keyParam.childParamsGroups) {
keyParam.childParamsGroups.push(...(await getBodyParams(param.additionalProperties, false)))
}
childParamsGroups.push(keyParam)
} else if (paramType && paramType.includes('array') && param.items) {
if (param.items && param.items.oneOf) {
if (param.items.oneOf.every((object) => object.type === 'object')) {
} else if (paramType.includes('array') && param.items) {
if (param.items.oneOf) {
if (param.items.oneOf.every((object: TransformedParam) => object.type === 'object')) {
paramType.splice(paramType.indexOf('array'), 1, `array of objects`)
param.oneOfObject = true
childParamsGroups.push(...(await getOneOfChildParams(param.items)))
@@ -116,31 +154,25 @@ export async function getBodyParams(schema, topLevel = false) {
if (arrayType === 'object') {
childParamsGroups.push(...(await getBodyParams(param.items, false)))
}
// If the type is an enumerated list of strings
if (arrayType === 'string' && param.items.enum) {
param.description += `${
param.description ? '\n' : ''
}Supported values are: ${param.items.enum
.map((lang) => `<code>${lang}</code>`)
.join(', ')}`
}Supported values are: ${param.items.enum.map((lang: string) => `<code>${lang}</code>`).join(', ')}`
}
}
} else if (paramType && paramType.includes('object')) {
if (param && param.oneOf) {
if (param.oneOf.every((object) => object.type === 'object')) {
} else if (paramType.includes('object')) {
if (param.oneOf) {
if (param.oneOf.every((object: TransformedParam) => object.type === 'object')) {
param.oneOfObject = true
childParamsGroups.push(...(await getOneOfChildParams(param)))
}
} else {
childParamsGroups.push(...(await getBodyParams(param, false)))
}
} else if (param && param.oneOf) {
// get concatenated description and type
const descriptions = []
} else if (param.oneOf) {
const descriptions: { type: string; description: string }[] = []
for (const childParam of param.oneOf) {
paramType.push(childParam.type)
// If there is no parent description, create a description from
// each type
if (!param.description) {
if (childParam.type === 'array') {
if (childParam.items.description) {
@@ -164,13 +196,14 @@ export async function getBodyParams(schema, topLevel = false) {
if (!param.description) param.description = oneOfDescriptions
// This is a workaround for an operation that incorrectly defines anyOf
// for a body parameter. As a workaround, we will use the first object
// in the list of the anyOf array. Otherwise, fallback to the first item
// in the array. There is currently only one occurrence for the operation
// id repos/update-information-about-pages-site. See Ecosystem API issue
// for a body parameter. We use the first object in the list of the anyOf array.
// There is currently only one occurrence for the operation id
// repos/update-information-about-pages-site. See Ecosystem API issue
// number #3332 for future plans to fix this in the OpenAPI
} else if (param && param.anyOf && Object.keys(param).length === 1) {
const firstObject = Object.values(param.anyOf).find((item) => item.type === 'object')
} else if (param.anyOf && Object.keys(param).length === 1) {
const firstObject = Object.values(param.anyOf).find(
(item) => (item as Schema).type === 'object',
) as Schema
if (firstObject) {
paramType.push('object')
param.description = firstObject.description
@@ -181,8 +214,8 @@ export async function getBodyParams(schema, topLevel = false) {
param.description = param.anyOf[0].description
param.isRequired = param.anyOf[0].required
}
} else if (param && param.allOf) {
// this else is only used for webhooks handling of allOf
// Used only for webhooks handling allOf
} else if (param.allOf) {
for (const prop of param.allOf) {
paramType.push('object')
childParamsGroups.push(...(await getBodyParams(prop, false)))
@@ -200,20 +233,24 @@ export async function getBodyParams(schema, topLevel = false) {
return bodyParametersParsed
}
async function getTransformedParam(param, paramType, props) {
async function getTransformedParam(
param: Schema,
paramType: string[],
props: BodyParamProps,
): Promise<TransformedParam> {
const { paramKey, required, childParamsGroups, topLevel } = props
const paramDecorated = {}
const paramDecorated: TransformedParam = {} as TransformedParam
// Supports backwards compatibility for OpenAPI 3.0
// In 3.1 a nullable type is part of the param.type array and
// the property param.nullable does not exist.
if (param.nullable) paramType.push('null')
paramDecorated.type = Array.from(new Set(paramType.filter(Boolean))).join(' or ')
paramDecorated.name = paramKey
paramDecorated.name = paramKey || ''
if (topLevel) {
paramDecorated.in = 'body'
}
paramDecorated.description = await renderContent(param.description)
if (required && required.includes(paramKey)) {
paramDecorated.description = await renderContent(param.description || '')
if (required && required.includes(paramKey || '')) {
paramDecorated.isRequired = true
}
if (childParamsGroups && childParamsGroups.length > 0 && !param.oneOfObject) {
@@ -227,12 +264,12 @@ async function getTransformedParam(param, paramType, props) {
obj.name,
curr ? (!Object.hasOwn(curr, 'isRequired') ? obj : curr) : obj,
)
}, new Map())
}, new Map<string, TransformedParam>())
.values(),
)
paramDecorated.childParamsGroups = mergedChildParamsGroups
} else if (childParamsGroups.length > 0) {
} else if (childParamsGroups && childParamsGroups.length > 0) {
paramDecorated.childParamsGroups = childParamsGroups
}
if (param.enum) {
@@ -243,24 +280,28 @@ async function getTransformedParam(param, paramType, props) {
paramDecorated.oneOfObject = true
}
// we also want to catch default values of `false` for booleans
if (param.default !== undefined) {
paramDecorated.default = param.default
}
return paramDecorated
}
async function getOneOfChildParams(param) {
const childParamsGroups = []
async function getOneOfChildParams(param: Schema): Promise<TransformedParam[]> {
const childParamsGroups: TransformedParam[] = []
if (!param.oneOf) {
return childParamsGroups
}
for (const oneOfParam of param.oneOf) {
const objParam = {
const objParam: TransformedParam = {
type: 'object',
name: oneOfParam.title,
description: await renderContent(oneOfParam.description),
isRequired: oneOfParam.required,
childParamsGroups: [],
}
objParam.childParamsGroups.push(...(await getBodyParams(oneOfParam, false)))
if (objParam.childParamsGroups) {
objParam.childParamsGroups.push(...(await getBodyParams(oneOfParam, false)))
}
childParamsGroups.push(objParam)
}
return childParamsGroups

View File

@@ -8,7 +8,7 @@ import { renderContent } from '#src/content-render/index.js'
import getCodeSamples from './create-rest-examples.js'
import operationSchema from './operation-schema.js'
import { validateJson } from '#src/tests/lib/validate-json-schema.js'
import { getBodyParams } from './get-body-params.js'
import { getBodyParams } from './get-body-params'
export default class Operation {
#operation

View File

@@ -3,11 +3,15 @@ import { existsSync } from 'fs'
import path from 'path'
import { mkdirp } from 'mkdirp'
import { updateRestFiles } from './update-markdown.js'
import { allVersions } from '#src/versions/lib/all-versions.js'
import { createOperations, processOperations } from './get-operations.js'
import { getProgAccessData } from '#src/github-apps/scripts/sync.js'
import { REST_DATA_DIR, REST_SCHEMA_FILENAME } from '../../lib/index.js'
import { updateRestFiles } from './update-markdown'
import { allVersions } from '@/versions/lib/all-versions'
import { createOperations, processOperations } from './get-operations'
import { getProgAccessData } from '@/github-apps/scripts/sync'
import { REST_DATA_DIR, REST_SCHEMA_FILENAME } from '../../lib/index'
type Schema = Record<string, any>
type Operation = { category: string; subcategory: string; [key: string]: any }
type OperationsByCategory = Record<string, Record<string, Operation[]>>
// All of the schema releases that we store in allVersions
// Ex: 'api.github.com', 'ghec', 'ghes-3.6', 'ghes-3.5',
@@ -16,13 +20,17 @@ const OPENAPI_VERSION_NAMES = Object.keys(allVersions).map(
(elem) => allVersions[elem].openApiVersionName,
)
export async function syncRestData(sourceDirectory, restSchemas, progAccessSource) {
export async function syncRestData(
sourceDirectory: string,
restSchemas: string[],
progAccessSource: string,
): Promise<void> {
await Promise.all(
restSchemas.map(async (schemaName) => {
const file = path.join(sourceDirectory, schemaName)
const schema = JSON.parse(await readFile(file, 'utf-8'))
const schema = JSON.parse(await readFile(file, 'utf-8')) as Schema
const operations = []
const operations: Operation[] = []
console.log('Instantiating operation instances from schema ', schemaName)
try {
const newOperations = await createOperations(schema)
@@ -62,30 +70,10 @@ export async function syncRestData(sourceDirectory, restSchemas, progAccessSourc
await updateRestConfigData(restSchemas)
}
/*
Orders the operations by their category and subcategories.
All operations must have a category, but operations don't need
a subcategory. When no subcategory is present, the subcategory
property is an empty string ('').
Example:
{
[category]: {
'': {
"description": "",
"operations": []
},
[subcategory sorted alphabetically]: {
"description": "",
"operations": []
}
}
}
*/
async function formatRestData(operations) {
async function formatRestData(operations: Operation[]): Promise<OperationsByCategory> {
const categories = [...new Set(operations.map((operation) => operation.category))].sort()
const operationsByCategory = {}
const operationsByCategory: OperationsByCategory = {}
categories.forEach((category) => {
operationsByCategory[category] = {}
const categoryOperations = operations.filter((operation) => operation.category === category)
@@ -102,7 +90,7 @@ async function formatRestData(operations) {
}
subcategories.forEach((subcategory) => {
operationsByCategory[category][subcategory] = {}
operationsByCategory[category][subcategory] = []
const subcategoryOperations = categoryOperations.filter(
(operation) => operation.subcategory === subcategory,
@@ -116,9 +104,12 @@ async function formatRestData(operations) {
// Every time we update the REST data files, we'll want to make sure the
// config.json file is updated with the latest api versions.
async function updateRestConfigData(schemas) {
async function updateRestConfigData(schemas: string[]): Promise<void> {
const restConfigFilename = 'src/rest/lib/config.json'
const restConfigData = JSON.parse(await readFile(restConfigFilename, 'utf8'))
const restConfigData = JSON.parse(await readFile(restConfigFilename, 'utf8')) as Record<
string,
any
>
const restApiVersionData = restConfigData['api-versions'] || {}
// If the version isn't one of the OpenAPI version,
// then it's an api-versioned schema
@@ -126,6 +117,9 @@ async function updateRestConfigData(schemas) {
const schemaBaseName = path.basename(schema, '.json')
if (!OPENAPI_VERSION_NAMES.includes(schemaBaseName)) {
const openApiVer = OPENAPI_VERSION_NAMES.find((ver) => schemaBaseName.startsWith(ver))
if (!openApiVer) {
throw new Error(`Could not find the OpenAPI version for schema ${schemaBaseName}`)
}
const date = schemaBaseName.split(`${openApiVer}-`)[1]
if (!restApiVersionData[openApiVer]) {
@@ -142,9 +136,11 @@ async function updateRestConfigData(schemas) {
await writeFile(restConfigFilename, JSON.stringify(restConfigData, null, 2))
}
export async function getOpenApiSchemaFiles(schemas) {
const restSchemas = []
const webhookSchemas = []
export async function getOpenApiSchemaFiles(
schemas: string[],
): Promise<{ restSchemas: string[]; webhookSchemas: string[] }> {
const restSchemas: string[] = []
const webhookSchemas: string[] = []
// The full list of dereferened OpenAPI schemas received from
// bundling the OpenAPI in github/github
const schemaNames = schemas.map((schema) => path.basename(schema, '.json'))

View File

@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { getOpenApiSchemaFiles } from '../scripts/utils/sync.js'
import { getOpenApiSchemaFiles } from '../scripts/utils/sync'
import { allVersions } from '#src/versions/lib/all-versions.js'
const supportedReleases = Object.keys(allVersions).map(

View File

@@ -16,7 +16,7 @@ A [workflow](.github/workflows/sync-openapi.yml) is used to trigger the automati
The workflow automatically creates a pull request with the changes (for all three pipelines) and the label `github-openapi-bot`.
The workflow runs the `src/rest/scripts/update-files.js` script, which then calls the `src/webhooks/scripts/sync.js` script.
The workflow runs the `npm run sync-rest` script, which then calls the `src/webhooks/scripts/sync.ts` script.
## Manually running the pipeline
@@ -29,7 +29,8 @@ Then, you can manually sync the data used by the REST, Webhooks, and GitHub App
To run the webhooks pipeline locally:
1. Clone the [`github/rest-api-description`](https://github.com/github/rest-api-description) repository inside your local `docs-internal` repository.
1. Run `src/rest/scripts/update-files.js -s rest-api-description -o webhooks`.
1. Set a `GITHUB_TOKEN` in your `.env` with (classic) `repo` scopes & enable SSO for the github org.
1. Run `npm run sync-rest -- -s rest-api-description -o webhooks`.
## About this directory
@@ -37,7 +38,7 @@ To run the webhooks pipeline locally:
- `src/webhooks/lib` - The source code used in production to display the webhook docs and configuration files edited by content and engineering team members.
- `src/webhooks/lib/config.json` - A configuration file used to specify metadata about the webhooks pipeline.
- `src/webhooks/scripts` - The scripts and source code used run the webhooks pipeline, which updates the `src/webhooks/data` directory.
- `src/webhooks/scripts/sync.js` - The entrypoint script that runs the webhooks pipeline.
- `src/webhooks/scripts/sync.ts` - The entrypoint script that runs the webhooks pipeline.
- `src/webhooks/tests` - The tests used to verify the webhooks pipeline.
## Configuring the pipeline

View File

@@ -3,14 +3,26 @@ import { existsSync } from 'fs'
import path from 'path'
import { mkdirp } from 'mkdirp'
import { WEBHOOK_DATA_DIR, WEBHOOK_SCHEMA_FILENAME } from '../lib/index.js'
import Webhook from './webhook.js'
import { WEBHOOK_DATA_DIR, WEBHOOK_SCHEMA_FILENAME } from '../lib/index'
import Webhook, { WebhookSchema } from '@/webhooks/scripts/webhook'
export async function syncWebhookData(sourceDirectory, webhookSchemas) {
interface WebhookFile {
webhooks?: {
post: WebhookSchema
}[]
'x-webhooks'?: {
post: WebhookSchema
}[]
}
export async function syncWebhookData(
sourceDirectory: string,
webhookSchemas: string[],
): Promise<void> {
await Promise.all(
webhookSchemas.map(async (schemaName) => {
const file = path.join(sourceDirectory, schemaName)
const schema = JSON.parse(await readFile(file, 'utf-8'))
const schema: WebhookFile = JSON.parse(await readFile(file, 'utf-8'))
// In OpenAPI version 3.1, the schema data is under the `webhooks`
// key, but in 3.0 the schema data was in `x-webhooks`.
// We just fallback to `x-webhooks` for now since there's
@@ -47,7 +59,7 @@ export async function syncWebhookData(sourceDirectory, webhookSchemas) {
)
}
async function processWebhookSchema(webhooks) {
async function processWebhookSchema(webhooks: Webhook[]): Promise<void> {
try {
if (webhooks.length) {
await Promise.all(webhooks.map((webhook) => webhook.process()))
@@ -62,9 +74,11 @@ async function processWebhookSchema(webhooks) {
// Create an object with all webhooks where the key is the webhook name.
// Webhooks typically have a property called `action` that describes the
// events that trigger the webhook. Some webhooks (like `ping`) don't have
// action types -- in that case we set a the value of action to 'default'.
async function formatWebhookData(webhooks) {
const categorizedWebhooks = {}
// action types -- in that case we set the value of action to 'default'.
async function formatWebhookData(
webhooks: Webhook[],
): Promise<Record<string, Record<string, Webhook>>> {
const categorizedWebhooks: Record<string, Record<string, Webhook>> = {}
for (const webhook of Object.values(webhooks)) {
if (!webhook.action) webhook.action = 'default'

View File

@@ -1,10 +1,9 @@
#!/usr/bin/env node
import { get, isPlainObject } from 'lodash-es'
import { getJsonValidator } from '#src/tests/lib/validate-json-schema.js'
import { renderContent } from '#src/content-render/index.js'
import webhookSchema from './webhook-schema.js'
import { getBodyParams } from '../../rest/scripts/utils/get-body-params.js'
import { getJsonValidator } from '@/tests/lib/validate-json-schema'
import { renderContent } from '@/content-render/index'
import webhookSchema from './webhook-schema'
import { getBodyParams, TransformedParam } from '../../rest/scripts/utils/get-body-params'
const NO_CHILD_PROPERTIES = [
'action',
@@ -17,13 +16,45 @@ const NO_CHILD_PROPERTIES = [
const validate = getJsonValidator(webhookSchema)
export default class Webhook {
#webhook
constructor(webhook) {
export interface WebhookSchema {
description: string
summary: string
requestBody?: {
content: {
'application/json': {
schema: Record<string, any>
}
}
}
'x-github': {
'supported-webhook-types': string[]
subcategory: string
}
}
interface WebhookInterface {
descriptionHtml: string
summaryHtml: string
bodyParameters: TransformedParam[]
availability: string[]
action: string | null
category: string
process(): Promise<void>
renderDescription(): Promise<this>
renderBodyParameterDescriptions(): Promise<void>
}
export default class Webhook implements WebhookInterface {
#webhook: WebhookSchema
descriptionHtml: string = ''
summaryHtml: string = ''
bodyParameters: TransformedParam[] = []
availability: string[]
action: string | null
category: string
constructor(webhook: WebhookSchema) {
this.#webhook = webhook
this.descriptionHtml = ''
this.summaryHtml = ''
this.bodyParameters = []
this.availability = webhook['x-github']['supported-webhook-types']
this.action = get(
webhook,
@@ -45,30 +76,29 @@ export default class Webhook {
// The OpenAPI uses hyphens for the webhook names, but the webhooks
// are sent using underscores (e.g. `branch_protection_rule` instead
// of `branch-protection-rule`)
this.category = webhook['x-github'].subcategory.replaceAll('-', '_')
return this
this.category = webhook['x-github'].subcategory.replace(/-/g, '_')
}
async process() {
async process(): Promise<void> {
await Promise.all([this.renderDescription(), this.renderBodyParameterDescriptions()])
const isValid = validate(this)
const isValid = validate(this as WebhookInterface) // Add type assertion here
if (!isValid) {
console.error(JSON.stringify(validate.errors, null, 2))
throw new Error(`Invalid OpenAPI webhook found: ${this.category}`)
}
}
async renderDescription() {
async renderDescription(): Promise<this> {
this.descriptionHtml = await renderContent(this.#webhook.description)
this.summaryHtml = await renderContent(this.#webhook.summary)
return this
}
async renderBodyParameterDescriptions() {
if (!this.#webhook.requestBody) return []
const schema = get(this.#webhook, `requestBody.content.['application/json'].schema`, {})
this.bodyParameters = isPlainObject(schema) ? await getBodyParams(schema, true, this.title) : []
async renderBodyParameterDescriptions(): Promise<void> {
if (!this.#webhook.requestBody) return
const schema = get(this.#webhook, `requestBody.content['application/json'].schema`, {})
this.bodyParameters = isPlainObject(schema) ? await getBodyParams(schema, true) : []
// Removes the children of the common properties
this.bodyParameters.forEach((param) => {

View File

@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { getOpenApiSchemaFiles } from '../../rest/scripts/utils/sync.js'
import { getOpenApiSchemaFiles } from '../../rest/scripts/utils/sync'
import { allVersions } from '#src/versions/lib/all-versions.js'
describe('webhook data files are generated correctly from dereferenced openapi files', () => {