1
0
mirror of synced 2026-01-01 00:04:41 -05:00

Merge branch 'main' into remove-3.4-markup-new

This commit is contained in:
Rachael Sewell
2023-06-28 09:13:06 -07:00
committed by GitHub
35 changed files with 168 additions and 175 deletions

View File

@@ -43,11 +43,13 @@ jobs:
{ name: 'automated-pipelines', path: 'src/automated-pipelines/tests', },
{ name: 'content', path: 'tests/content', },
// { name: 'content-linter', path: 'src/content-linter/tests', },
{ name: 'content-render', path: 'src/content-render/tests', },
{ name: 'events', path: 'src/events/tests', },
{ name: 'ghes-releases', path: 'src/ghes-releases/tests', },
{ name: 'github-apps', path: 'src/github-apps/tests', },
{ name: 'graphql', path: 'src/graphql/tests', },
{ name: 'landings', path: 'src/landings/tests', },
// { name: 'learning-track', path: 'src/learning-track/tests', },
{ name: 'linting', path: 'src/content-linter/tests', },
{ name: 'observability', path: 'src/observability/tests' },
{ name: 'pageinfo', path: 'src/pageinfo/tests', },

View File

@@ -1,9 +0,0 @@
export default function localization() {
const linkToEnglish = document.querySelector('#to-english-doc') as HTMLAnchorElement
if (linkToEnglish) {
const pathname = window.location.pathname.split('/')
pathname[1] = 'en'
linkToEnglish.href = pathname.join('/')
}
}

View File

@@ -46,11 +46,6 @@ export const HeaderNotifications = () => {
type: NotificationType.TRANSLATION,
content: data.reusables.policies.translation,
})
} else if (router.locale) {
translationNotices.push({
type: NotificationType.TRANSLATION,
content: t('notices.localization_complete'),
})
}
}
const releaseNotices: Array<Notif> = []

View File

@@ -15,7 +15,9 @@ redirect_from:
## Configuring a workflow to run manually
To run a workflow manually, the workflow must be configured to run on the `workflow_dispatch` event. To trigger the `workflow_dispatch` event, your workflow must be in the default branch. For more information about configuring the `workflow_dispatch` event, see "[AUTOTITLE](/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)".
To run a workflow manually, the workflow must be configured to run on the `workflow_dispatch` event.
To trigger the `workflow_dispatch` event, your workflow must be in the default branch. For more information about configuring the `workflow_dispatch` event, see "[AUTOTITLE](/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)."
{% data reusables.repositories.permissions-statement-write %}
@@ -32,7 +34,12 @@ To run a workflow manually, the workflow must be configured to run on the `workf
{%- else -%}
![Screenshot of the "Actions" page. Features apart from one workflow in the left sidebar are grayed out.](/assets/images/help/repository/actions-select-workflow.png)
{%- endif %}
1. Above the list of workflow runs, select **Run workflow**.
1. Above the list of workflow runs, click the **Run workflow** button.
{% note %}
**Note:** To see the **Run workflow** button, your workflow file must use the `workflow_dispatch` event trigger. Only workflow files that use the `workflow_dispatch` event trigger will have the option to run the workflow manually using the **Run workflow** button. For more information about configuring the `workflow_dispatch` event, see "[AUTOTITLE](/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)."
{% endnote %}
![Screenshot of a workflow page. Above the list of workflow runs, a button, labeled "Run workflow", is outlined in dark orange.](/assets/images/help/actions/actions-workflow-dispatch.png)
1. Select the **Branch** dropdown menu and click a branch to run the workflow on.

View File

@@ -18,6 +18,12 @@ topics:
While using {% data variables.product.prodname_emus %}, you may need to migrate your enterprise to a new IdP or Azure AD tenant. For example, you might be ready to migrate from a test environment to your production environment.
{% warning %}
**Warning**: Migrating to a new identity provider or tenant can cause disruption to integrations and automated flows in your enterprise. When your current SAML identity provider is disabled, {% data variables.product.pat_generic_plural %} and SSH keys associated with {% data variables.enterprise.prodname_managed_users %} will be deleted. You should plan for a migration window after configuring your new identity provider, during which you can create and deploy new keys to your integrations where necessary.
{% endwarning %}
Before you migrate your {% data variables.enterprise.prodname_emu_enterprise %} to a new IdP or tenant, determine whether the values of the normalized SCIM `userName` attribute will remain the same for your {% data variables.enterprise.prodname_managed_users %} in the new environment. For more information about username normalization, see "[AUTOTITLE](/admin/identity-and-access-management/managing-iam-for-your-enterprise/username-considerations-for-external-authentication)."
If the normalized SCIM `userName` values will remain the same after the migration, you can complete the migration by yourself. For instructions, see "[Migrating when the normalized SCIM `userName` values will remain the same](#migrating-when-the-normalized-scim-username-values-will-remain-the-same)."

View File

@@ -90,7 +90,7 @@ If you're setting up your AMI for the first time, you will need to create a secu
1. Take note of the security group ID (`sg-xxxxxxxx`) of your newly created security group.
1. Create a security group rule for each of the ports in the table below. For more information, see "[authorize-security-group-ingress](https://docs.aws.amazon.com/cli/latest/reference/ec2/authorize-security-group-ingress.html)" in the AWS documentation.
1. Create a security group rule for each of the ports in the table below. We recommend opening network ports selectively based on the network services you need to expose for administrative and user purposes. For more information, see "[AUTOTITLE](/admin/configuration/configuring-network-settings/network-ports#administrative-ports)," and [`authorize-security-group-ingress`](https://docs.aws.amazon.com/cli/latest/reference/ec2/authorize-security-group-ingress.html) in the AWS documentation.
```shell
aws ec2 authorize-security-group-ingress --group-id SECURITY_GROUP_ID --protocol PROTOCOL --port PORT_NUMBER --cidr SOURCE IP RANGE

View File

@@ -53,7 +53,7 @@ Before launching {% data variables.location.product_location %} on Azure, you'll
az vm create -n VM_NAME -g RESOURCE_GROUP --size VM_SIZE -l REGION --image APPLIANCE_IMAGE_NAME --storage-sku Premium_LRS
```
1. Configure the security settings on your VM to open up required ports. For more information, see "[`az vm open-port`](https://docs.microsoft.com/cli/azure/vm?view=azure-cli-latest#az_vm_open_port)" in the Microsoft documentation. See the table below for a description of each port to determine what ports you need to open.
1. Configure the security settings on your VM to open up required ports. We recommend opening network ports selectively based on the network services you need to expose for administrative and user purposes. For more information, see "[AUTOTITLE](/admin/configuration/configuring-network-settings/network-ports#administrative-ports)," and [`az vm open-port`](https://docs.microsoft.com/cli/azure/vm?view=azure-cli-latest#az_vm_open_port) in the Microsoft documentation. See the table below for a description of each port to determine what ports you need to open.
```shell
az vm open-port -n VM_NAME -g RESOURCE_GROUP --port PORT_NUMBER
@@ -90,21 +90,21 @@ To configure the instance, you must confirm the instance's status, upload a lice
> Name ResourceGroup PowerState PublicIps Fqdns Location Zones
> ------ --------------- ------------ ------------ ------- ---------- -------
> VM_NAME RESOURCE_GROUP VM running 40.76.79.202 eastus
```
{% note %}
**Note:** Azure does not automatically create a FQDNS entry for the VM. For more information, see Azure's guide on how to "[Create a fully qualified domain name in the Azure portal for a Linux VM](https://docs.microsoft.com/azure/virtual-machines/linux/portal-create-fqdn)."
{% endnote %}
{% data reusables.enterprise_installation.copy-the-vm-public-dns-name %}
{% data reusables.enterprise_installation.upload-a-license-file %}
{% data reusables.enterprise_installation.save-settings-in-web-based-mgmt-console %} For more information, see "[AUTOTITLE](/admin/configuration/configuring-your-enterprise)."
{% data reusables.enterprise_installation.instance-will-restart-automatically %}
{% data reusables.enterprise_installation.visit-your-instance %}
## Azure extension features
{% data variables.product.product_name %} does not support the installation of Azure extension features. The {% data variables.product.prodname_ghe_server %} image is shipped with a customized `waagent` package which only supports basic VM management functions and blocks advanced VM management functions.

View File

@@ -45,7 +45,7 @@ Before launching {% data variables.location.product_location %} on Google Cloud
## Configuring the firewall
GCE virtual machines are created as a member of a network, which has a firewall. For the network associated with the {% data variables.product.prodname_ghe_server %} VM, you'll need to configure the firewall to allow the required ports listed in the table below. For more information about firewall rules on Google Cloud Platform, see the Google guide "[Firewall Rules Overview](https://cloud.google.com/vpc/docs/firewalls)."
GCE virtual machines are created as a member of a network, which has a firewall. For the network associated with the {% data variables.product.prodname_ghe_server %} VM, you'll need to configure the firewall to allow the required ports listed in the table below. We recommend opening network ports selectively based on the network services you need to expose for administrative and user purposes. For more information, see "[AUTOTITLE](/admin/configuration/configuring-network-settings/network-ports#administrative-ports)," and [Firewall Rules Overview](https://cloud.google.com/vpc/docs/firewalls) in the Google Cloud Platform documentation.
1. Using the gcloud compute command-line tool, create the network. For more information, see "[gcloud compute networks create](https://cloud.google.com/sdk/gcloud/reference/compute/networks/create)" in the Google documentation.

View File

@@ -37,7 +37,7 @@ The benefits of streaming audit data include:
- **Data continuity**. You can pause the stream for up to seven days without losing any audit data.{% endif %}
- **Data retention**. You can keep your exported audit logs and Git events data as long as you need to.
Enterprise owners can set up{% ifversion pause-audit-log-stream %}, pause,{% endif %} or delete a stream at any time. The stream exports the audit and Git events data for all of the organizations in your enterprise.
Enterprise owners can set up{% ifversion pause-audit-log-stream %}, pause,{% endif %} or delete a stream at any time. The stream exports audit and Git events data for all of the organizations in your enterprise, for activity from the time the stream is enabled onwards.
All streamed audit logs are sent as compressed JSON files. The filename format is in`YYYY/MM/HH/MM/<uuid>.json.gz`.

View File

@@ -3,7 +3,7 @@ title: Configuring GitHub Copilot in your environment
shortTitle: In your environment
intro: 'You can enable, configure, or disable {% data variables.product.prodname_copilot %} in a supported IDE.'
product: '{% data reusables.gated-features.copilot %}'
redirect_from:
redirect_from:
- /copilot/configuring-github-copilot/configuring-github-copilot-in-visual-studio
- /copilot/configuring-github-copilot/configuring-github-copilot-in-visual-studio-code
- /copilot/configuring-github-copilot/configuring-github-copilot-in-a-jetbrains-ide
@@ -20,13 +20,11 @@ versions:
If you use a JetBrains IDE, {% data variables.product.prodname_copilot %} can autocomplete code as you type. After installation, you can enable or disable {% data variables.product.prodname_copilot %}, and you can configure advanced settings within your IDE or on {% data variables.product.prodname_dotcom_the_website %}. This article describes how to configure {% data variables.product.prodname_copilot %} in the IntelliJ IDE, but the user interfaces of other JetBrains IDEs may differ.
{% data reusables.copilot.dotcom-settings %}
## Prerequisites
To configure {% data variables.product.prodname_copilot %} in a JetBrains IDE, you must install the {% data variables.product.prodname_copilot %} plugin. For more information, see "[AUTOTITLE](/copilot/getting-started-with-github-copilot?tool=jetbrains)."
## Keyboard shortcuts for {% data variables.product.prodname_copilot %}
## Using or rebinding keyboard shortcuts for {% data variables.product.prodname_copilot %}
You can use the default keyboard shortcuts for inline suggestions in your JetBrains IDE when using {% data variables.product.prodname_copilot %}. Alternatively, you can rebind the shortcuts to your preferred keyboard shortcuts for each specific command. For more information on rebinding keyboard shortcuts in your JetBrains IDE, see the JetBrains documentation. For example, you can view the [IntelliJ IDEA](https://www.jetbrains.com/help/idea/mastering-keyboard-shortcuts.html#choose-keymap) documentation.
@@ -110,17 +108,19 @@ If you use {% data variables.product.prodname_vs %}, {% data variables.product.p
To configure {% data variables.product.prodname_copilot %} in {% data variables.product.prodname_vs %}, you must install the {% data variables.product.prodname_copilot %} plugin. For more information, see "[AUTOTITLE](/copilot/getting-started-with-github-copilot?tool=visualstudio)."
## Keyboard shortcuts for {% data variables.product.prodname_copilot %}
## Using or rebinding keyboard shortcuts for {% data variables.product.prodname_copilot %}
You can use the default keyboard shortcuts in {% data variables.product.prodname_vs %} when using {% data variables.product.prodname_copilot %}. Alternatively, you can rebind the shortcuts in the Tools settings for {% data variables.product.prodname_vs %} using your preferred keyboard shortcuts for each specific command. You can search for each keyboard shortcut by its command name in the Keyboard Shortcuts editor.
### Using default keyboard shortcuts
| Action | Shortcut | Command name |
|:---|:---|:---|
|Show next inline suggestion|<kbd>Alt</kbd>+<kbd>.</kbd>|Tools.Nextsuggestion|
|Show previous inline suggestion|<kbd>Alt</kbd>+<kbd>,</kbd>|Tools.Previoussuggestion|
|Trigger inline suggestion|<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>\</kbd>|Edit.Copilot.TriggerInlineSuggestion|
## Rebinding keyboard shortcuts
### Rebinding keyboard shortcuts
If you don't want to use the default keyboard shortcuts in {% data variables.product.prodname_vs %} when using {% data variables.product.prodname_copilot %}, you can rebind the shortcuts in the Keyboard editor using your preferred keyboard shortcuts for each specific command.
@@ -164,7 +164,9 @@ To configure {% data variables.product.prodname_copilot %} in {% data variables.
## Keyboard shortcuts for {% data variables.product.prodname_copilot %}
You can use the default keyboard shortcuts in {% data variables.product.prodname_vscode %} when using {% data variables.product.prodname_copilot %}. Alternatively, you can rebind the shortcuts in the Keyboard Shortcuts editor using your preferred keyboard shortcuts for each specific command. You can search for each keyboard shortcut by command name in the Keyboard Shortcuts editor.
You can use the default keyboard shortcuts in {% data variables.product.prodname_vscode %} when using {% data variables.product.prodname_copilot %}. Alternatively, you can rebind the shortcuts in the Keyboard Shortcuts editor using your preferred keyboard shortcuts for each specific command. For more information, see "[Rebinding keyboard shortcuts](/copilot/configuring-github-copilot/configuring-github-copilot-in-your-environment?tool=vscode#rebinding-keyboard-shortcuts-1)."
You can search for each keyboard shortcut by command name in the Keyboard Shortcuts editor.
### Keyboard shortcuts for macOS
@@ -329,6 +331,10 @@ For guidance on configuring {% data variables.product.prodname_copilot %} in Vim
:help copilot
## Rebinding keyboard shortcuts
You can rebind the keyboard shortcuts in Vim/Neovim when using {% data variables.product.prodname_copilot %} to use your preferred keyboard shortcuts for each specific command. For more information, see the [Map](https://neovim.io/doc/user/map.html) article in the Neovim documentation.
{% data reusables.copilot.dotcom-settings %}
{% endvimneovim %}

View File

@@ -1,5 +1,5 @@
---
title: Amending a commit in Github Desktop
title: Amending a commit in GitHub Desktop
shortTitle: Amending commits
intro: 'You can use {% data variables.product.prodname_desktop %} to amend your last commit.'
versions:

View File

@@ -35,7 +35,7 @@ The `upload-pages-artifact` actions enables you to package and upload artifacts.
To use the action in your current workflow place this snippet under `jobs`.
```yaml
- name: Upload Github Pages artifact
- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v1
```

View File

@@ -177,12 +177,8 @@ Customer is responsible for managing access to its Private Repositories, includi
GitHub considers Customer Content in Customers Private Repositories to be Customers Confidential Information. GitHub will protect and keep strictly confidential the Customer Content of Private Repositories in accordance with Section P.
### 3. Access
<<<<<<< HEAD
GitHub personnel may only access Customer's Private Repositories in the situations described in our [Privacy Statement](/site-policy/privacy-policies/github-privacy-statement#repository-contents).
=======
GitHub personnel may only access Customer's Private Repositories in the situations described in our [Privacy Statement](/site-policy/privacy-policies/github-privacy-statement#repository-contents).
>>>>>>> main
Customer may choose to enable additional access to its Private Repositories. For example, Customer may enable various GitHub services or features that require additional rights to Customer Content in Private Repositories. These rights may vary depending on the service or feature, but GitHub will continue to treat Customer Content in Customers Private Repositories as Customers Confidential Information. If those services or features require rights in addition to those it needs to provide the Service, GitHub will provide an explanation of those rights.

View File

@@ -25,12 +25,8 @@ The Program is offered to verified students on GitHub Global Campus in countries
You hereby grant the Octernships Partners a non-exclusive, irrevocable, perpetual, royalty-free, worldwide license to make, have made, use, offer to sell, sell, import, copy, modify, create derivative works based upon, distribute, sublicense, display, perform and transmit any work product you create in connection with the Program or during your internship, including, without limitation, concepts, works, inventions, information, drawings, designs, programs, or software.
### 2.2 Likeness
<<<<<<< HEAD
GitHub and Octernships Partners reserve all rights, including the right to edit, publish, use, adapt, modify or dispose of any work product/description, likenesses, and photographs for advertising and promotional purposes in all media (including, but not limited to, the internet) without additional compensation, except where prohibited by law.
=======
GitHub and Octernships Partners reserve all rights, including the right to edit, publish, use, adapt, modify or dispose of any work product/description, likenesses, and photographs for advertising and promotional purposes in all media (including, but not limited to, the internet) without additional compensation, except where prohibited by law.
>>>>>>> main
## 3. Confidentiality and non-disclosure

View File

@@ -39,7 +39,13 @@ Warnings and danger notices are rendered in red `{% warning %}` tags.
For more information on formatting callouts, see “Callouts” in the [markup reference guide](content-markup-reference.md).
## Call to action (CTA) buttons
## Buttons
Landing pages and some articles have buttons that take people to relevant content in other articles or on other GitHub webpages. Buttons should be used when someone needs to navigate to another page to complete the task being described. For example, "[Setting up a trial of GitHub Enterprise Cloud](https://docs.github.com/en/enterprise-cloud@latest/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud)" has a button that takes people to the Enterprise trial sign up page since that is the next step in the process of setting up a trial. The "[Migrations](https://docs.github.com/en/migrations)" landing page uses a button to direct people to the article that most people will need to read to start a migration.
If a button encourages people to navigate away from the GitHub Docs site, follow the call to action (CTA) button guidelines. If you want to include another type of button on a landing page or article, open an issue in `docs-strategy` to share your use case for approval by Content Strategy.
### Call to action (CTA) buttons
CTA buttons emphasize a link that we expect or encourage readers to navigate to after reading an article or as part of completing the task that an article describes. CTAs should only take people to GitHub-owned domains. For example, the CTA in "[Getting started with GitHub Copilot in Visual Studio Code](https://docs.github.com/en/copilot/getting-started-with-github-copilot/getting-started-with-github-copilot-in-visual-studio-code)" links to the [GitHub Copilot settings menu](https://github.com/settings/copilot) on github.com.

View File

@@ -1,8 +1,6 @@
date: '2023-05-09'
sections:
security_fixes:
- |
**HIGH:** Updated Git to include fixes from 2.39.2, which address [CVE-2023-22490](https://github.com/git/git/security/advisories/GHSA-gw92-x3fm-3g3q) and [CVE-2023-23946](https://github.com/git/git/security/advisories/GHSA-r87m-v37r-cwfh).
- |
**MEDIUM**: Updated Git to include fixes from 2.40.1. For more information, see [Git security vulnerabilities announced](https://github.blog/2023-04-25-git-security-vulnerabilities-announced-4/) on the GitHub Blog.
bugs:

View File

@@ -1,8 +1,6 @@
date: '2023-06-20'
sections:
security_fixes:
- |
**HIGH:** Updated Git to include fixes from 2.39.2, which address [CVE-2023-22490](https://github.com/git/git/security/advisories/GHSA-gw92-x3fm-3g3q) and [CVE-2023-23946](https://github.com/git/git/security/advisories/GHSA-r87m-v37r-cwfh).
- |
**MEDIUM**: Scoped installation tokens for a GitHub App kept approved permissions after the permissions on the integration installation were downgraded or removed. GitHub has requested CVE ID [CVE-2023-23765](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23765) for this vulnerability, which was reported via the [GitHub Bug Bounty program](https://bounty.github.com).
- |

View File

@@ -1,8 +1,6 @@
date: '2023-05-09'
sections:
security_fixes:
- |
**HIGH:** Updated Git to include fixes from 2.39.2, which address [CVE-2023-22490](https://github.com/git/git/security/advisories/GHSA-gw92-x3fm-3g3q) and [CVE-2023-23946](https://github.com/git/git/security/advisories/GHSA-r87m-v37r-cwfh).
- |
**MEDIUM**: Updated Git to include fixes from 2.40.1. For more information, see [Git security vulnerabilities announced](https://github.blog/2023-04-25-git-security-vulnerabilities-announced-4/) on the GitHub Blog.
bugs:

View File

@@ -1,8 +1,6 @@
date: '2023-06-20'
sections:
security_fixes:
- |
**HIGH:** Updated Git to include fixes from 2.39.2, which address [CVE-2023-22490](https://github.com/git/git/security/advisories/GHSA-gw92-x3fm-3g3q) and [CVE-2023-23946](https://github.com/git/git/security/advisories/GHSA-r87m-v37r-cwfh).
- |
If a user's request to the instance's API included authentication credentials within a URL parameter, administrators could see the credentials in JSON within the instance's audit log.
- Packages have been updated to the latest security versions.

View File

@@ -1,8 +1,6 @@
date: '2023-05-09'
sections:
security_fixes:
- |
**HIGH:** Updated Git to include fixes from 2.39.2, which address [CVE-2023-22490](https://github.com/git/git/security/advisories/GHSA-gw92-x3fm-3g3q) and [CVE-2023-23946](https://github.com/git/git/security/advisories/GHSA-r87m-v37r-cwfh).
- |
**MEDIUM**: Updated Git to include fixes from 2.40.1. For more information, see [Git security vulnerabilities announced](https://github.blog/2023-04-25-git-security-vulnerabilities-announced-4/) on the GitHub Blog.
bugs:

View File

@@ -1,8 +1,6 @@
date: '2023-06-20'
sections:
security_fixes:
- |
**HIGH:** Updated Git to include fixes from 2.39.2, which address [CVE-2023-22490](https://github.com/git/git/security/advisories/GHSA-gw92-x3fm-3g3q) and [CVE-2023-23946](https://github.com/git/git/security/advisories/GHSA-r87m-v37r-cwfh).
- |
**MEDIUM**: Updated Git to include fixes from [2.40.1](https://github.blog/2023-04-25-git-security-vulnerabilities-announced-4/).
- |

View File

@@ -1,3 +1,6 @@
1. In the upper-right corner of any page on {% data variables.product.prodname_dotcom %}, click your profile photo.
1. Navigate to your account settings.
- For a {% data variables.product.prodname_github_app %} owned by a personal account, in the upper-right corner of any page, click your profile photo, then click **Settings**.
- For a {% data variables.product.prodname_github_app %} owned by an organization, in the upper-right corner of any page, click your profile photo, then click **Your organizations**. Then, to the right of the organization, click **Settings**.
- For a {% data variables.product.prodname_github_app %} owned by a personal account, click **Settings**.
- For a {% data variables.product.prodname_github_app %} owned by an organization:
1. Click **Your organizations**.
1. To the right of the organization, click **Settings**.

View File

@@ -8,10 +8,6 @@ header:
release_candidate:
# The version name is rendered before the below text via includes/header-notification.html
' is currently available as a release candidate. For more information, see "<a href="/admin/overview/about-upgrades-to-new-releases">About upgrades to new releases</a>."'
localization_complete:
We publish frequent updates to our documentation, and translation of this page may still be in progress.
For the most current information, please visit the
<a id="to-english-doc" href="/en">English documentation</a>.
early_access: 📣 Please <b>do not share</b> this URL publicly. This page contains content about an early access feature.
release_notes_use_latest: Please use the latest release for the latest security, performance, and bug fixes.
# GHES release notes

6
package-lock.json generated
View File

@@ -169,8 +169,7 @@
"node": "^16 || ^18"
},
"optionalDependencies": {
"esm": "^3.2.25",
"website-scraper": "^5.3.1"
"esm": "^3.2.25"
}
},
"node_modules/@actions/core": {
@@ -18472,8 +18471,9 @@
},
"node_modules/website-scraper": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/website-scraper/-/website-scraper-5.3.1.tgz",
"integrity": "sha512-gogqPXD2gVsxoyd2yRiympw3rA5GuEpD1CaDEJ/J8zzanx7hkbTtneoO1SGs436PpLbWVcUge+6APGLhzsuZPA==",
"dev": true,
"license": "MIT",
"dependencies": {
"cheerio": "1.0.0-rc.12",
"css-url-parser": "^1.0.0",

View File

@@ -213,8 +213,7 @@
"website-scraper": "^5.3.1"
},
"optionalDependencies": {
"esm": "^3.2.25",
"website-scraper": "^5.3.1"
"esm": "^3.2.25"
},
"engines": {
"node": "^16 || ^18"

View File

@@ -1,6 +1,3 @@
import { fileURLToPath } from 'url'
import path from 'path'
import { afterAll, beforeAll, expect, describe, it } from '@jest/globals'
import Page from '../../../lib/page.js'
@@ -8,8 +5,6 @@ import languages from '../../../lib/languages.js'
import nonEnterpriseDefaultVersion from '../../../lib/non-enterprise-default-version.js'
import { DataDirectory } from '../../../tests/helpers/data-directory.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
describe('data tag', () => {
let dd
const enDirBefore = languages.en.dir
@@ -35,7 +30,7 @@ describe('data tag', () => {
it('should render fine if data is found', async () => {
const page = await Page.init({
relativePath: 'liquid-tags/good-data-variable.md',
basePath: path.join(__dirname, '../../fixtures'),
basePath: './tests/fixtures',
languageCode: 'en',
})
const context = {
@@ -52,7 +47,7 @@ describe('data tag', () => {
it('should throw if the data tag is used with something unrecognized', async () => {
const page = await Page.init({
relativePath: 'liquid-tags/bad-data-variable.md',
basePath: path.join(__dirname, '../../fixtures'),
basePath: './tests/fixtures',
languageCode: 'en',
})
const context = {

View File

@@ -10,7 +10,6 @@
import path from 'path'
import fs from 'fs'
import { execSync } from 'child_process'
import scrape from 'website-scraper'
import { program } from 'commander'
import { rimraf } from 'rimraf'
@@ -35,6 +34,7 @@ program
'-o, --output <PATH>',
`output directory to place scraped HTML files and redirects. By default, this temp directory is named 'tmpArchivalDir_<VERSION_TO_DEPRECATE>'`
)
.option('-l, --local-dev', 'Do not rewrite asset paths to enable testing scraped content locally')
.option('-d, --dry-run', 'only scrape the first 10 pages for testing purposes')
.option(
'-p, --page <PATH>',
@@ -45,6 +45,7 @@ program
const output = program.opts().output
const dryRun = program.opts().dryRun
const singlePage = program.opts().page
const localDev = program.opts().localDev
const tmpArchivalDirectory = output
? path.join(process.cwd(), output)
: path.join(process.cwd(), `tmpArchivalDir_${version}`)
@@ -67,19 +68,30 @@ class RewriteAssetPathsPlugin {
// Get the text contents of the resource
const text = resource.getText()
let newBody = ''
let newBody = text
// Rewrite HTML asset paths. Example:
// ../assets/images/foo/bar.png ->
// https://githubdocs.azureedge.net/github-images/enterprise/2.17/assets/images/foo/bar.png
if (resource.isHtml()) {
newBody = text.replace(
/(?<attribute>src|href)="(?:\.\.\/|\/)*(?<basepath>_next\/static|javascripts|stylesheets|assets\/fonts|assets\/cb-\d+\/images|node_modules)/g,
(match, attribute, basepath) => {
const replaced = `${REMOTE_ENTERPRISE_STORAGE_URL}/${this.version}/${basepath}`
return `${attribute}="${replaced}`
}
// Remove nextjs scripts and manifest.json link
newBody = newBody.replace(
/<script\ssrc="(\.\.\/)*_next\/static\/[\w]+\/(_buildManifest|_ssgManifest).js?".*?><\/script>/g,
''
)
newBody = newBody.replace(/<link href=".*manifest.json".*?>/g, '')
if (!localDev) {
// Rewrite asset paths
newBody = newBody.replace(
/(?<attribute>src|href)="(?:\.\.\/|\/)*(?<basepath>_next\/static|javascripts|stylesheets|assets\/fonts|assets\/cb-\d+\/images|node_modules)/g,
(match, attribute, basepath) => {
const replaced = `${REMOTE_ENTERPRISE_STORAGE_URL}/${this.version}/${basepath}`
return `${attribute}="${replaced}`
}
)
}
}
// Rewrite CSS asset paths. Example
@@ -88,25 +100,25 @@ class RewriteAssetPathsPlugin {
// url(../../../assets/cb-303/images/octicons/search-24.svg) ->
// url(https://githubdocs.azureedge.net/github-images/enterprise/2.20/assets/cb-303/images/octicons/search-24.svg)
if (resource.isCss()) {
newBody = text.replace(
/(?<attribute>url)(?<paren>\("|\()(?:\.\.\/)*(?<basepath>_next\/static|assets\/fonts|assets\/images|assets\/cb-\d+\/images)/g,
(match, attribute, paren, basepath) => {
const replaced = `${REMOTE_ENTERPRISE_STORAGE_URL}/${this.version}/${basepath}`
return `${attribute}${paren}${replaced}`
}
)
if (!localDev) {
newBody = newBody.replace(
/(?<attribute>url)(?<paren>\("|\()(?:\.\.\/)*(?<basepath>_next\/static|assets\/fonts|assets\/images|assets\/cb-\d+\/images)/g,
(match, attribute, paren, basepath) => {
const replaced = `${REMOTE_ENTERPRISE_STORAGE_URL}/${this.version}/${basepath}`
return `${attribute}${paren}${replaced}`
}
)
}
}
const filePath = path.join(this.tempDirectory, resource.getFilename())
await fs.promises.writeFile(filePath, newBody, 'binary')
await fs.promises.writeFile(filePath, newBody, resource.encoding)
})
}
}
async function main() {
// Build the production assets, to simulate a production deployment
console.log('Running `npm run build` for production assets')
execSync('npm run build', { stdio: 'inherit' })
console.log('Finish building production assets')
if (dryRun) {
console.log(

View File

@@ -1,3 +1,5 @@
// Returns false when no changes were made to the frontmatter,
// true when changes were made.
export default function removeDeprecatedFrontmatter(
file,
frontmatterVersions,
@@ -5,13 +7,13 @@ export default function removeDeprecatedFrontmatter(
nextOldestRelease
) {
// skip files with no Enterprise Server versions frontmatter
if (!frontmatterVersions) return
if (!frontmatterVersions.ghes) return
if (!frontmatterVersions) return false
if (!frontmatterVersions.ghes) return false
const ghesRange = frontmatterVersions.ghes
// skip files with versions frontmatter that already applies to all enterprise-server releases
if (ghesRange === '*') return
if (ghesRange === '*') return false
// if the release to deprecate is 2.13, and the FM is either '>=2.13', '>2.13', or '>=2.14',
// we can safely change the FM to ghes: '*'
@@ -22,7 +24,7 @@ export default function removeDeprecatedFrontmatter(
if (appliesToAllSupportedGhesReleases) {
frontmatterVersions.ghes = '*'
return
return true
}
// if the release to deprecate is 2.13, and the FM is either '=2.13', '<2.13', '<=2.13', or '<2.14',
@@ -39,9 +41,10 @@ export default function removeDeprecatedFrontmatter(
console.log(
`Warning! ${file} has frontmatter versioning that will make it never appear when ${releaseToDeprecate} is deprecated. The article should probably be removed.`
)
return
return false
}
delete frontmatterVersions.ghes
return true
}
}

View File

@@ -22,10 +22,11 @@ const tokenize = (str) => {
// src/ghes-releases/tests/remove-liquid-statements.js.
export default function removeLiquidStatements(content, release, nextOldestRelease, file) {
let newContent = content
let contentChanged = false
// Get an array of ifversion blocks with their content included.
const blocks = getLiquidConditionalsWithContent(newContent, 'ifversion')
if (!blocks.length) return newContent
if (!blocks.length) return { newContent, contentChanged }
// Decorate those blocks with more GHES versioning information.
const versionBlocks = getVersionBlocks(blocks)
@@ -233,6 +234,7 @@ export default function removeLiquidStatements(content, release, nextOldestRelea
// in the general content and return the updated general content.
versionBlocks.forEach((versionBlock) => {
if (versionBlock.action !== 'none') {
contentChanged = true
const newBlockContent = versionBlock.newContent.replaceAll(/\n\n\n+?/g, '\n\n')
newContent = newContent
@@ -246,7 +248,7 @@ export default function removeLiquidStatements(content, release, nextOldestRelea
}
})
return newContent
return { newContent, contentChanged }
}
// Hack to use a regex with lastIndexOf.

View File

@@ -60,37 +60,55 @@ async function main() {
for (const file of allFiles) {
const oldContents = fs.readFileSync(file, 'utf8')
const { content, data } = frontmatter(oldContents)
let fileChanged = false
// update frontmatter versions prop
removeDeprecatedFrontmatter(file, data.versions, release, nextOldestRelease)
fileChanged ||= removeDeprecatedFrontmatter(file, data.versions, release, nextOldestRelease)
// update liquid statements in content and data
const newContent = removeLiquidStatements(content, release, nextOldestRelease, file)
const { newContent, contentChanged } = removeLiquidStatements(
content,
release,
nextOldestRelease,
file
)
fileChanged ||= contentChanged
// update liquid statements in content frontmatter (like intro and title)
for (const key in data) {
const value = data[key]
if (typeof value === 'string' && value.includes('{% ifversion')) {
const newValue = removeLiquidStatements(value, release, nextOldestRelease, file)
data[key] = newValue
const { newContent, contentChanged } = removeLiquidStatements(
value,
release,
nextOldestRelease,
file
)
fileChanged ||= contentChanged
data[key] = newContent
}
}
// make sure any intro fields that exist and are empty return an empty string, not null
if (typeof data.intro !== 'undefined' && !data.intro) {
data.intro = ''
// When stringifying frontmatter, the frontmatter is also formatted.
// This means that even if there were no Liquid versioning changes,
// the frontmatter may still be modified to modify line breaks or quotes.
// This an already difficult PR noisier to review. This prevents writing
// the file unless there are versioning changes made.
if (fileChanged) {
// make sure any intro fields that exist and are empty return an empty string, not null
if (typeof data.intro !== 'undefined' && !data.intro) {
data.intro = ''
}
// put it all back together
const newContents = frontmatter.stringify(newContent, data, { lineWidth: 10000 })
// if the content file is now empty, remove it
if (newContents.replace(/\s/g, '').length === 0) {
fs.unlinkSync(file)
continue
}
fs.writeFileSync(file, newContents)
}
// put it all back together
const newContents = frontmatter.stringify(newContent, data, { lineWidth: 10000 })
// if the content file is now empty, remove it
if (newContents.replace(/\s/g, '').length === 0) {
fs.unlinkSync(file)
continue
}
fs.writeFileSync(file, newContents)
}
console.log(`Removed GHES ${release} markup from content and data files! Review and run tests.`)

View File

@@ -39,9 +39,9 @@ function processFrontmatter(contents, file) {
describe('removing liquid statements only', () => {
test('removes liquid statements that specify "greater than version to deprecate"', async () => {
let contents = await fs.readFile(greaterThan, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(greaterThan, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe(`{% ifversion ghes %}\n
Alpha\n\n{% endif %}`)
expect($('.example2').text().trim()).toBe(`{% ifversion fpt or ghes %}\n
@@ -65,9 +65,9 @@ Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion ghes > 2.16 %}\n\nCharlie\n
{% else %}\n\nBravo\n\n{% endif %}`)
})
test('removes liquid statements that specify all known versions, including some nested conditionals"', async () => {
let contents = await fs.readFile(unnecessary, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(unnecessary, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe(`Alpha`)
expect($('.example2').text().trim()).toBe(
`Alpha\n {% ifversion fpt or ghec %}\n Bravo\n {% endif %}`
@@ -84,9 +84,9 @@ Alpha\n\n{% else %}\n\nBravo\n\n{% ifversion ghes > 2.16 %}\n\nCharlie\n
})
test('removes liquid statements that specify "and greater than version to deprecate"', async () => {
let contents = await fs.readFile(andGreaterThan1, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(andGreaterThan1, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe(
'{% ifversion not fpt and ghes %}\n\nAlpha\n\n{% endif %}'
)
@@ -102,9 +102,9 @@ Alpha\n\n{% ifversion ghes > 2.16 %}\n\nBravo\n\n{% endif %}\n\n{% else %}\n\nCh
})
test('removes liquid statements that specify "and greater than version to deprecate" (alternate format)', async () => {
let contents = await fs.readFile(andGreaterThan2, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(andGreaterThan2, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('{% ifversion ghes < 2.16 %}\n\nAlpha\n\n{% endif %}')
expect($('.example2').text().trim()).toBe(`{% ifversion ghes < 2.16 %}\n\nAlpha\n\n{% else %}\n
Bravo\n\n{% endif %}`)
@@ -117,9 +117,9 @@ Alpha\n\n{% ifversion not fpt %}\n\nBravo\n\n{% endif %}\n\n{% else %}\n\nCharli
})
test('removes liquid statements that specify "not equals version to deprecate"', async () => {
let contents = await fs.readFile(notEquals, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(notEquals, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('{% ifversion ghes %}\n\nAlpha\n\n{% endif %}')
expect($('.example2').text().trim()).toBe('{% ifversion fpt or ghes %}\n\nAlpha\n\n{% endif %}')
expect($('.example3').text().trim()).toBe(`{% ifversion fpt %}\n
@@ -136,9 +136,9 @@ Alpha\n\n{% endif %}`)
describe('removing liquid statements and content', () => {
test('removes interior content and liquid statements that specify "equals version to deprecate"', async () => {
let contents = await fs.readFile(equals, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(equals, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('')
expect($('.example2').text().trim()).toBe('{% ifversion not fpt %}\n\nAlpha\n\n{% endif %}')
expect($('.example3').text().trim()).toBe(`{% ifversion fpt %}\n
@@ -152,9 +152,9 @@ Alpha\n\n{% else %}\n\nCharlie\n\n{% endif %}`)
})
test('removes interior content and liquid statements that specify "less than next oldest than version to deprecate"', async () => {
let contents = await fs.readFile(lessThanNextOldest, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(lessThanNextOldest, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text().trim()).toBe('Alpha')
expect($('.example2').text().trim()).toBe(
'Alpha\n\n{% ifversion fpt %}\n\nBravo\n\n{% endif %}'
@@ -193,9 +193,9 @@ describe('updating frontmatter', () => {
describe('whitespace', () => {
test('does not add newlines when whitespace control is used', async () => {
let contents = await fs.readFile(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(whitespace, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example1').text()).toBe('\n{% ifversion ghes %}\n Alpha\n{% endif %}\n')
expect($('.example2').text()).toBe('\n{%- ifversion ghes %}\n Alpha\n{% endif %}\n')
expect($('.example3').text()).toBe('\n{% ifversion fpt or ghes %}\n Alpha\n{%- endif %}\n')
@@ -203,9 +203,9 @@ describe('whitespace', () => {
})
test('does not add newlines when no newlines are present', async () => {
let contents = await fs.readFile(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(whitespace, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example5').text()).toBe('\n{% ifversion ghes %}\n Alpha\n{% endif %}\n')
expect($('.example6').text()).toBe(
'\n Alpha\n{% ifversion fpt or ghes %}\n Bravo\n{% endif %}\n Charlie\n'
@@ -214,9 +214,9 @@ describe('whitespace', () => {
})
test('only remove newlines when tag starts at beginning of line', async () => {
let contents = await fs.readFile(whitespace, 'utf8')
contents = removeLiquidStatements(contents, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(contents)
const content = await fs.readFile(whitespace, 'utf8')
const { newContent } = removeLiquidStatements(content, versionToDeprecate, nextOldestVersion)
const $ = cheerio.load(newContent)
expect($('.example8').text()).toBe('\nAlpha\nBravo\n')
expect($('.example9').text()).toBe('\nAlpha\nBravo\n')
expect($('.example10').text()).toBe('\nPre\nBravo\n')

View File

@@ -5,7 +5,6 @@ import { useRouter } from 'next/router'
// typically operating on elements **within** an article.
import copyCode from 'components/lib/copy-code'
import toggleAnnotation from 'components/lib/toggle-annotations'
import localization from 'components/lib/localization'
import wrapCodeTerms from 'components/lib/wrap-code-terms'
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
@@ -40,7 +39,6 @@ import { useEffect } from 'react'
function initiateArticleScripts() {
copyCode()
localization()
wrapCodeTerms()
toggleAnnotation()
}

View File

@@ -8,10 +8,6 @@ header:
release_candidate:
# The version name is rendered before the below text via includes/header-notification.html
' is currently available as a release candidate. For more information, see "<a href="/admin/overview/about-upgrades-to-new-releases">About upgrades to new releases</a>."'
localization_complete:
We publish frequent updates to our documentation, and translation of this page may still be in progress.
For the most current information, please visit the
<a id="to-english-doc" href="/en">English documentation</a>.
early_access: 📣 Please <b>do not share</b> this URL publicly. This page contains content about an early access feature.
release_notes_use_latest: Please use the latest release for the latest security, performance, and bug fixes.
# GHES release notes

View File

@@ -456,13 +456,6 @@ test.describe('translations', () => {
await expect(page.getByRole('heading', { name: '日本 GitHub Docs' })).toBeVisible()
})
test('switch to English from Japanese using banner on home page', async ({ page }) => {
await page.goto('/ja')
await page.getByRole('link', { name: 'English documentation' }).click()
await expect(page).toHaveURL('/en')
await expect(page.getByRole('heading', { name: 'GitHub Docs' })).toBeVisible()
})
test('switch to Japanese from English using widget on home page', async ({ page }) => {
await page.goto('/en')
await page.getByRole('button', { name: 'Select language: current language is English' }).click()
@@ -475,14 +468,6 @@ test.describe('translations', () => {
await expect(page).toHaveURL('/ja')
})
test('switch to English from Japanese using banner on article', async ({ page }) => {
await page.goto('/ja/get-started/quickstart/hello-world')
await expect(page.getByRole('heading', { name: 'こんにちは World' })).toBeVisible()
await page.getByRole('link', { name: 'English documentation' }).click()
await expect(page).toHaveURL('/en/get-started/quickstart/hello-world')
await expect(page.getByRole('heading', { name: 'Hello World' })).toBeVisible()
})
test('switch to Japanese from English using widget on article', async ({ page }) => {
await page.goto('/get-started/quickstart/hello-world')
await page.getByRole('button', { name: 'Select language: current language is English' }).click()

View File

@@ -16,13 +16,6 @@ describe('translations', () => {
// You gotta know your tests/fixtures/translations/ja-jp/data/ui.yml
expect(h1).toBe('日本 GitHub Docs')
// The header banner mentions something about
// "For the most up-to-date content, see the English version."
const notification = $('[data-testid="header-notification"]')
expect(notification.length).toBe(1)
const toEnglishDoc = notification.find('a#to-english-doc')
expect(toEnglishDoc.text()).toBe('English documentation')
// Sidebar uses the translated shortTitle
const links = $('[data-testid=sidebar] a[href]')
const hrefs = links