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

Merge branch 'main' into patch-2

This commit is contained in:
Ethan Palm
2022-03-10 11:41:21 -08:00
committed by GitHub
37 changed files with 424 additions and 158 deletions

View File

@@ -165,8 +165,8 @@ jobs:
rsync -rptovR ./user-code/components/./**/*.{ts,tsx} ./components
rsync -rptovR --ignore-missing-args ./user-code/lib/./**/*.{js,ts} ./lib
rsync -rptovR --ignore-missing-args ./user-code/middleware/./**/*.{js,ts} ./middleware
rsync -rptovR ./user-code/pages/./**/*.{tsx} ./pages
rsync -rptovR ./user-code/stylesheets/./**/*.{scss} ./stylesheets
rsync -rptovR ./user-code/pages/./**/*.tsx ./pages
rsync -rptovR ./user-code/stylesheets/./**/*.scss ./stylesheets
# In addition to making the final image smaller, we also save time by not sending unnecessary files to the docker build context
- name: 'Prune for preview env'

View File

@@ -24,7 +24,7 @@ jobs:
- name: move PR
uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
with:
project: Docs team reviews
project: Docs open source board
column: Triage
repo-token: ${{ secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES }}

View File

@@ -132,6 +132,11 @@ jobs:
- name: Run build script
run: npm run build
- name: Warm possible disk caching
env:
NODE_ENV: test
run: ./script/warm-before-tests.mjs
- name: Run tests
env:
DIFF_FILE: get_diff_files.txt

View File

@@ -245,6 +245,15 @@ function initClipboardEvent() {
})
}
function initCopyButtonEvent() {
document.documentElement.addEventListener('click', (evt) => {
const target = evt.target as HTMLElement
const button = target.closest('.js-btn-copy') as HTMLButtonElement
if (!button) return
sendEvent({ type: EventType.navigate, navigate_label: 'copy icon button' })
})
}
function initLinkEvent() {
document.documentElement.addEventListener('click', (evt) => {
const target = evt.target as HTMLElement
@@ -267,6 +276,7 @@ export default function initializeEvents() {
initPageAndExitEvent() // must come first
initLinkEvent()
initClipboardEvent()
initCopyButtonEvent()
initPrintEvent()
// survey event in ./survey.js
// experiment event in ./experiment.js

View File

@@ -1,24 +1,62 @@
import cx from 'classnames'
import { CheckIcon, CopyIcon } from '@primer/octicons-react'
import { Tooltip } from '@primer/react'
import useClipboard from 'components/hooks/useClipboard'
import styles from './CodeBlock.module.scss'
type Props = {
verb?: string
// Only Code samples should have a copy icon - if there's a headingLang it's a code sample
headingLang?: string
codeBlock: string
highlight?: string
}
export function CodeBlock({ verb, codeBlock, highlight }: Props) {
export function CodeBlock({ verb, headingLang, codeBlock, highlight }: Props) {
const [isCopied, setCopied] = useClipboard(codeBlock, {
successDuration: 1400,
})
return (
<pre className={cx(styles.methodCodeBlock, 'rounded-1 border')} data-highlight={highlight}>
<code>
{verb && (
<span className="color-bg-accent-emphasis color-fg-on-emphasis rounded-1 text-uppercase">
{verb}
</span>
)}{' '}
{codeBlock}
</code>
</pre>
<div className="code-extra">
{headingLang && (
<header className="d-flex flex-justify-between flex-items-center p-2 text-small rounded-top-1 border">
{headingLang === 'JavaScript' ? (
<span>
{headingLang} (
<a className="text-underline" href="https://github.com/octokit/core.js#readme">
@octokit/core.js
</a>
)
</span>
) : (
`${headingLang}`
)}
<Tooltip direction="w" aria-label={isCopied ? 'Copied!' : 'Copy to clipboard'}>
<button className="js-btn-copy btn-octicon" onClick={() => setCopied()}>
{isCopied ? <CheckIcon /> : <CopyIcon />}
</button>
</Tooltip>
</header>
)}
<pre
className={cx(
styles.methodCodeBlock,
'd-flex flex-justify-between flex-items-center rounded-1 border'
)}
data-highlight={highlight}
>
<code>
{verb && (
<span className="color-bg-accent-emphasis color-fg-on-emphasis rounded-1 text-uppercase">
{verb}
</span>
)}{' '}
{codeBlock}
</code>
</pre>
</div>
)
}

View File

@@ -18,22 +18,10 @@ export function RestCodeSamples({ slug, xCodeSamples }: Props) {
{xCodeSamples.map((sample, index) => {
const sampleElements: JSX.Element[] = []
if (sample.lang !== 'Ruby') {
sampleElements.push(
sample.lang === 'JavaScript' ? (
<h5 key={`${sample.lang}-${index}`}>
{sample.lang} (
<a className="text-underline" href="https://github.com/octokit/core.js#readme">
@octokit/core.js
</a>
)
</h5>
) : (
<h5 key={`${sample.lang}-${index}`}>{sample.lang}</h5>
)
)
sampleElements.push(
<CodeBlock
key={sample.lang + index}
headingLang={sample.lang}
codeBlock={sample.source}
highlight={sample.lang === 'JavaScript' ? 'javascript' : 'curl'}
></CodeBlock>

View File

@@ -183,6 +183,7 @@ The `github` context contains information about the workflow run and the event t
| `github.action_path` | `string` | The path where an action is located. This property is only supported in composite actions. You can use this path to access files located in the same repository as the action. |
| `github.action_ref` | `string` | For a step executing an action, this is the ref of the action being executed. For example, `v2`. |
| `github.action_repository` | `string` | For a step executing an action, this is the owner and repository name of the action. For example, `actions/checkout`. |
| `github.action_status` | `string` | For a composite action, the current result of the composite action. |
| `github.actor` | `string` | The username of the user that initiated the workflow run. |
| `github.api_url` | `string` | The URL of the {% data variables.product.prodname_dotcom %} REST API. |
| `github.base_ref` | `string` | The `base_ref` or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either `pull_request` or `pull_request_target`. |

View File

@@ -156,7 +156,7 @@ We strongly recommend that actions use environment variables to access the files
| `GITHUB_RUN_ID` | {% data reusables.actions.run_id_description %} For example, `1658821493`. |
| `GITHUB_RUN_NUMBER` | {% data reusables.actions.run_number_description %} For example, `3`. |
| `GITHUB_SERVER_URL`| The URL of the {% data variables.product.product_name %} server. For example: `https://{% data variables.product.product_url %}`.
| `GITHUB_SHA` | The commit SHA that triggered the workflow. For example, `ffac537e6cbbf934b08745a378932722df287a53`. |
| `GITHUB_SHA` | The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see [Events that trigger workflows](/actions/using-workflows/events-that-trigger-workflows). For example, `ffac537e6cbbf934b08745a378932722df287a53`. |
| `GITHUB_WORKFLOW` | The name of the workflow. For example, `My test workflow`. If the workflow file doesn't specify a `name`, the value of this variable is the full path of the workflow file in the repository. |
| `GITHUB_WORKSPACE` | The default working directory on the runner for steps, and the default location of your repository when using the [`checkout`](https://github.com/actions/checkout) action. For example, `/home/runner/work/my-repo-name/my-repo-name`. |
{%- if actions-runner-arch-envvars %}

View File

@@ -22,7 +22,6 @@ shortTitle: Recover an account with 2FA
**Warnings**:
- {% data reusables.two_fa.support-may-not-help %}
- {% data reusables.accounts.you-must-know-your-password %}
{% endwarning %}
@@ -32,7 +31,13 @@ shortTitle: Recover an account with 2FA
Use one of your recovery codes to automatically regain entry into your account. You may have saved your recovery codes to a password manager or your computer's downloads folder. The default filename for recovery codes is `github-recovery-codes.txt`. For more information about recovery codes, see "[Configuring two-factor authentication recovery methods](/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication-recovery-methods#downloading-your-two-factor-authentication-recovery-codes)."
{% data reusables.two_fa.username-password %}
1. Type your username and password to prompt authentication.
{% warning %}
**Warning**: {% data reusables.accounts.you-must-know-your-password %}
{% endwarning %}
{% ifversion fpt or ghec %}
1. Under "Having problems?", click **Use a recovery code or request a reset**.

View File

@@ -31,6 +31,7 @@ includeGuides:
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/tracking-code-scanning-alerts-in-issues-using-task-lists
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning-alerts
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning-with-codeql
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/managing-code-scanning-alerts-for-your-repository
@@ -38,6 +39,7 @@ includeGuides:
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/triaging-code-scanning-alerts-in-pull-requests
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/troubleshooting-the-codeql-workflow
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/viewing-code-scanning-logs
- /code-security/code-scanning/integrating-with-code-scanning/about-integration-with-code-scanning
- /code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning
- /code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github
@@ -45,6 +47,7 @@ includeGuides:
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/configuring-codeql-cli-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/configuring-codeql-runner-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/installing-codeql-cli-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/migrating-from-the-codeql-runner-to-codeql-cli
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/running-codeql-runner-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/troubleshooting-codeql-runner-in-your-ci-system
- /code-security/repository-security-advisories/about-coordinated-disclosure-of-security-vulnerabilities
@@ -58,6 +61,8 @@ includeGuides:
- /code-security/repository-security-advisories/removing-a-collaborator-from-a-repository-security-advisory
- /code-security/repository-security-advisories/withdrawing-a-repository-security-advisory
- /code-security/security-overview/about-the-security-overview
- /code-security/security-overview/filtering-alerts-in-the-security-overview
- /code-security/security-overview/viewing-the-security-overview
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/about-dependabot-version-updates
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/automating-dependabot-with-github-actions
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates

View File

@@ -8,17 +8,17 @@ featuredLinks:
guides:
- /code-security/getting-started/securing-your-repository
- /code-security/getting-started/securing-your-organization
- '{% ifversion fpt %}/code-security/repository-security-advisories/creating-a-repository-security-advisory{% endif %}'
- '{% ifversion ghes or ghae %}/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository{% endif%}'
- '{% ifversion fpt or ghec %}/code-security/repository-security-advisories/creating-a-repository-security-advisory{% endif %}'
- '{% ifversion ghes or ghae %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository{% endif%}'
guideCards:
- '{% ifversion fpt %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-dependabot-security-updates{% endif %}'
- '{% ifversion fpt %}/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/enabling-and-disabling-dependabot-version-updates{% endif %}'
- '{% ifversion fpt %}/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository{% endif %}'
- '{% ifversion ghes %}/code-security/supply-chain-security/understanding-your-software-supply-chain/exploring-the-dependencies-of-a-repository{% endif %}'
- '{% ifversion ghes %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-notifications-for-vulnerable-dependencies{% endif %}'
- '{% ifversion ghes or ghae %}/code-security/secret-security/configuring-secret-scanning-for-your-repositories{% endif %}'
- '{% ifversion ghae %}/code-security/secure-coding/integrating-with-code-scanning/uploading-a-sarif-file-to-github{% endif %}'
- '{% ifversion ghae %}/code-security/secure-coding/using-codeql-code-scanning-with-your-existing-ci-system{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-dependabot-security-updates{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/enabling-and-disabling-dependabot-version-updates{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository{% endif %}'
- '{% ifversion ghes < 3.3 %}/code-security/supply-chain-security/understanding-your-software-supply-chain/exploring-the-dependencies-of-a-repository{% endif %}'
- '{% ifversion ghes < 3.3 %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-notifications-for-vulnerable-dependencies{% endif %}'
- '{% ifversion ghes < 3.3 or ghae %}/code-security/secret-scanning/configuring-secret-scanning-for-your-repositories{% endif %}'
- '{% ifversion ghae %}/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github{% endif %}'
- '{% ifversion ghae %}/code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system{% endif %}'
popular:
- '{% ifversion ghes %}/admin/release-notes{% endif %}'
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/about-alerts-for-vulnerable-dependencies
@@ -26,11 +26,11 @@ featuredLinks:
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/keeping-your-actions-up-to-date-with-dependabot
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/managing-encrypted-secrets-for-dependabot
- '{% ifversion ghae %}/code-security/secret-security/about-secret-scanning{% endif %}'
- '{% ifversion ghae %}/code-security/secret-scanning/about-secret-scanning{% endif %}'
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/troubleshooting-the-detection-of-vulnerable-dependencies
- '{% ifversion ghes or ghae %}/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages{% endif %}'
- '{% ifversion ghes or ghae %}/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/troubleshooting-the-codeql-workflow{% endif %}'
- '{% ifversion ghes or ghae %}/code-security/secure-coding/automatically-scanning-your-code-for-vulnerabilities-and-errors/running-codeql-code-scanning-in-a-container{% endif %}'
- '{% ifversion ghes < 3.3 or ghae %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages{% endif %}'
- '{% ifversion ghes < 3.3 or ghae %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/troubleshooting-the-codeql-workflow{% endif %}'
- '{% ifversion ghes < 3.3 or ghae %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/running-codeql-code-scanning-in-a-container{% endif %}'
changelog:
label: security-and-compliance
versions:

View File

@@ -22,7 +22,11 @@ An outside collaborator is a person who is not a member of your organization, bu
{% data reusables.organizations.outside-collaborators-use-seats %}
{% ifversion fpt %}
Organizations that use {% data variables.product.prodname_ghe_cloud %} can restrict the ability to invite collaborators. For more information, see "[Setting permissions for adding outside collaborators](/enterprise-cloud@latest/organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators)" in the {% data variables.product.prodname_ghe_cloud %} documentation.
{% else %}
An organization owner can restrict the ability to invite collaborators. For more information, see "[Setting permissions for adding outside collaborators](/organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators)."
{% endif %}
{% ifversion ghes %}
Before you can add someone as an outside collaborator on a repository, the person must have a user account on {% data variables.product.product_location %}. If your enterprise uses an external authentication system such as SAML or LDAP, the person you want to add must sign in through that system to create an account. If the person does not have access to the authentication system and built-in authentication is enabled for your enterprise, a site admin can create a user account for the person. For more information, see "[Using built-in authentication](/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/using-built-in-authentication#inviting-users)."
@@ -32,10 +36,6 @@ Before you can add someone as an outside collaborator on a repository, the perso
If your organization requires two-factor authentication, all outside collaborators must enable two-factor authentication before accepting your invitation to collaborate on a repository. For more information, see "[Requiring two-factor authentication in your organization](/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization)."
{% endif %}
{% ifversion fpt %}
To further support your team's collaboration abilities, you can upgrade to {% data variables.product.prodname_ghe_cloud %}, which includes features like protected branches and code owners on private repositories. {% data reusables.enterprise.link-to-ghec-trial %}
{% endif %}
## Adding outside collaborators to a repository
{% ifversion fpt or ghec or ghes > 3.3 or ghae-issue-5974 %}

View File

@@ -22,8 +22,6 @@ You can use this information to help off-board people, gather data for complianc
{% ifversion fpt %}
Organizations that use {% data variables.product.prodname_ghe_cloud %} can also export a CSV list of people who have access to a repository. For more information, see [the {% data variables.product.prodname_ghe_cloud %} documentation](/enterprise-cloud@latest/organizations/managing-access-to-your-organizations-repositories/viewing-people-with-access-to-your-repository).
{% data reusables.enterprise.link-to-ghec-trial %}
{% endif %}
{% ifversion fpt or ghec or ghes > 3.3 or ghae-issue-5974 %}
@@ -44,6 +42,14 @@ You can see a combined overview of teams and people with access to your reposito
{% ifversion ghec or ghes or ghae %}
## Exporting a list of people with access to your repository
{% ifversion ghec %}
{% note %}
**Note:** Only organizations that use {% data variables.product.prodname_ghe_cloud %} can export a list of people with access to a repository. {% data reusables.enterprise.link-to-ghec-trial %}
{% endnote %}
{% endif %}
{% data reusables.repositories.navigate-to-repo %}
{% data reusables.repositories.accessing-repository-graphs %}
{% data reusables.repositories.accessing-repository-people %}

View File

@@ -1,13 +1,11 @@
---
title: Setting permissions for adding outside collaborators
intro: 'To protect your organization''s data and the number of paid licenses used in your organization, you can allow only owners to invite outside collaborators to organization repositories.'
product: '{% data reusables.gated-features.restrict-add-collaborator %}'
redirect_from:
- /articles/restricting-the-ability-to-add-outside-collaborators-to-organization-repositories
- /articles/setting-permissions-for-adding-outside-collaborators
- /github/setting-up-and-managing-organizations-and-teams/setting-permissions-for-adding-outside-collaborators
versions:
fpt: '*'
ghes: '*'
ghae: '*'
ghec: '*'
@@ -17,7 +15,16 @@ topics:
shortTitle: Set collaborator policy
---
Organization owners, and members with admin privileges for a repository, can invite outside collaborators to work on the repository. You can also restrict outside collaborator invite permissions to only organization owners.
By default, anyone with admin access to a repository can invite outside collaborators to work on the repository. You can choose to restrict the ability to invite outside collaborators to organization owners only.
{% ifversion ghec %}
{% note %}
**Note:** Only organizations that use {% data variables.product.prodname_ghe_cloud %} can restrict the ability to invite outside collaborators to organization owners. {% data reusables.enterprise.link-to-ghec-trial %}
{% endnote %}
{% endif %}
{% data reusables.organizations.outside-collaborators-use-seats %}

View File

@@ -67,7 +67,7 @@ For more information on reviewing pull requests in {% data variables.product.pro
{% data reusables.dependency-review.beta %}
If the pull request contains changes to dependencies you can use the dependency review for a manifest or lock file to see what has changed and check whether the changes introduce security vulnerabilities. For more information, see "[Reviewing dependency changes in a pull request](/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request)."
If the pull request contains changes to dependencies you can use the dependency review for a manifest or lock file to see what has changed and check whether the changes introduce security vulnerabilities. For more information, see "[Reviewing dependency changes in a pull request](/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-dependency-changes-in-a-pull-request)."
{% data reusables.repositories.changed-files %}

View File

@@ -322,6 +322,7 @@ Take care to distinguish between product names and product elements. For more in
| Product | Element |
| --- | --- |
| GitHub Actions | an action |
| GitHub Codespaces | a codespace |
| GitHub Packages | a package |
| GitHub Pages | a GitHub Pages site |
@@ -594,7 +595,7 @@ Avoid ending a sentence with a preposition unless the rewritten sentence would s
### Product names
See the “Product names” section of this guide.
See the “[Product names](#product-names)” section of this guide.
### Terms to use or avoid

View File

@@ -2,7 +2,7 @@
security_advisories:
title: 'Fix and disclose a security vulnerability'
description: 'Using repository security advisories to privately fix a reported vulnerability and get a CVE.'
featured_track: '{% ifversion fpt %}true{% else %}false{% endif %}'
featured_track: '{% ifversion fpt or ghec %}true{% else %}false{% endif %}'
guides:
- /code-security/repository-security-advisories/about-coordinated-disclosure-of-security-vulnerabilities
- /code-security/repository-security-advisories/creating-a-repository-security-advisory
@@ -13,32 +13,32 @@ security_advisories:
- /code-security/repository-security-advisories/withdrawing-a-repository-security-advisory
- /code-security/repository-security-advisories/removing-a-collaborator-from-a-repository-security-advisory
# Feature available on dotcom and GHES
# Feature available on dotcom and GHES 3.3+, so articles available on GHAE and earlier GHES hidden to hide the learning track
dependabot_alerts:
title: 'Get notifications for vulnerable dependencies'
description: 'Set up Dependabot to alert you to new vulnerabilities in your dependencies.'
guides:
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/about-alerts-for-vulnerable-dependencies
- '{% ifversion not ghae %}/github/administering-a-repository/managing-repository-settings/managing-security-and-analysis-settings-for-your-repository{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/github/administering-a-repository/managing-repository-settings/managing-security-and-analysis-settings-for-your-repository{% endif %}'
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/viewing-and-updating-vulnerable-dependencies-in-your-repository
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-notifications-for-vulnerable-dependencies
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/managing-pull-requests-for-dependency-updates
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/troubleshooting-the-detection-of-vulnerable-dependencies
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/troubleshooting-dependabot-errors
# Feature available only on dotcom, so articles available hidden to hide the learning track in other versions
# Feature available on dotcom and GHES 3.3+, so articles available on GHAE and earlier GHES hidden to hide the learning track
dependabot_security_updates:
title: 'Get pull requests to update your vulnerable dependencies'
description: 'Set up Dependabot to create pull requests when new vulnerabilities are reported.'
guides:
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/about-dependabot-security-updates
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-dependabot-security-updates
- '{% ifversion fpt %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-notifications-for-vulnerable-dependencies{% endif %}'
- '{% ifversion fpt %}/github/administering-a-repository/managing-repository-settings/managing-security-and-analysis-settings-for-your-repository{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/configuring-notifications-for-vulnerable-dependencies{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/github/administering-a-repository/managing-repository-settings/managing-security-and-analysis-settings-for-your-repository{% endif %}'
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/managing-pull-requests-for-dependency-updates
- '{% ifversion fpt %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/troubleshooting-the-detection-of-vulnerable-dependencies{% endif %}'
- '{% ifversion fpt or ghec or ghes > 3.2 %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/troubleshooting-the-detection-of-vulnerable-dependencies{% endif %}'
# Feature available only on dotcom
# Feature available only on dotcom and GHES 3.3+
dependency_version_updates:
title: 'Keep your dependencies up-to-date'
description: 'Use Dependabot to check for new releases and create pull requests to update your dependencies.'
@@ -54,32 +54,34 @@ dependency_version_updates:
- /code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/managing-pull-requests-for-dependency-updates
- /code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/troubleshooting-dependabot-errors
# Feature available in all versions from GHES 3.0 up
# Feature available in GHEC, GHES 3.0 up, and GHAE. Feature limited on FPT so hidden there.
secret_scanning:
title: 'Scan for secrets'
description: 'Set up secret scanning to guard against accidental check-ins of tokens, passwords, and other secrets to your repository.'
guides:
- /code-security/secret-scanning/about-secret-scanning
- /code-security/secret-scanning/configuring-secret-scanning-for-your-repositories
- /code-security/secret-scanning/defining-custom-patterns-for-secret-scanning
- /code-security/secret-scanning/managing-alerts-from-secret-scanning
- '{% ifversion not fpt %}/code-security/secret-scanning/about-secret-scanning{% endif %}'
- '{% ifversion not fpt %}/code-security/secret-scanning/configuring-secret-scanning-for-your-repositories{% endif %}'
- '{% ifversion not fpt %}/code-security/secret-scanning/defining-custom-patterns-for-secret-scanning{% endif %}'
- '{% ifversion not fpt %}/code-security/secret-scanning/managing-alerts-from-secret-scanning{% endif %}'
- '{% ifversion not fpt %}/code-security/secret-scanning/secret-scanning-patterns{% endif %}'
# Security overview feature available only on dotcom currently, so other articles hidden to hide the learning path in other versions
# Security overview feature available in GHEC and GHES 3.2+, so other articles hidden to hide the learning path in other versions
security_alerts:
title: 'Explore and manage security alerts'
description: 'Learn where to find and resolve security alerts.'
guides:
- /code-security/security-overview/about-the-security-overview
- '{% ifversion fpt %}/code-security/secret-scanning/managing-alerts-from-secret-scanning {% endif %}'
- '{% ifversion fpt %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/managing-code-scanning-alerts-for-your-repository{% endif %}'
- '{% ifversion fpt %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/triaging-code-scanning-alerts-in-pull-requests{% endif %}'
- '{% ifversion fpt %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/viewing-and-updating-vulnerable-dependencies-in-your-repository{% endif %}'
- '{% ifversion ghec or ghes > 3.1 %}/code-security/security-overview/about-the-security-overview {% endif %}'
- '{% ifversion ghec or ghes > 3.1 %}/code-security/security-overview/viewing-the-security-overview {% endif %}'
- '{% ifversion ghec or ghes > 3.1 %}/code-security/secret-scanning/managing-alerts-from-secret-scanning {% endif %}'
- '{% ifversion ghec or ghes > 3.1 %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/managing-code-scanning-alerts-for-your-repository{% endif %}'
- '{% ifversion ghec or ghes > 3.1 %}/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/triaging-code-scanning-alerts-in-pull-requests{% endif %}'
- '{% ifversion ghec or ghes > 3.1 %}/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/viewing-and-updating-vulnerable-dependencies-in-your-repository{% endif %}'
# Feature available in all versions from GHES 2.22 up
code_security_actions:
title: 'Run code scanning with GitHub Actions'
description: 'Check your default branch and every pull request to keep vulnerabilities and errors out of your repository.'
featured_track: '{% ifversion ghae or ghes > 2.22 %}true{% else %}false{% endif %}'
featured_track: '{% ifversion ghae or ghes %}true{% else %}false{% endif %}'
guides:
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning
- /code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/setting-up-code-scanning-for-a-repository
@@ -106,6 +108,5 @@ code_security_ci:
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/about-codeql-code-scanning-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/installing-codeql-cli-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/configuring-codeql-cli-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/running-codeql-runner-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/configuring-codeql-runner-in-your-ci-system
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/migrating-from-the-codeql-runner-to-codeql-cli
- /code-security/code-scanning/using-codeql-code-scanning-with-your-existing-ci-system/troubleshooting-codeql-runner-in-your-ci-system

View File

@@ -19,9 +19,9 @@
- GitHub Actions
# Security policies
- title: Microsoft security policy
- title: Microsoft security policy template
description: Example security policy
href: /microsoft/microsoft.github.io/blob/master/SECURITY.MD
href: https://github.com/microsoft/repo-templates/blob/main/shared/SECURITY.md
tags:
- Security policy
- title: Electron security policy
@@ -50,8 +50,9 @@
versions:
fpt: '*'
ghec: '*'
ghes: '>=3.3'
# Dependabot configuration only relevant to GitHub.com
# Dependabot configuration only relevant to GitHub.com and GHES 3.3+
# Convert "languages" to "package-ecosystems" for Dependabot configurations
- title: Super linter configuration
description: Example Dependabot version updates configuration from the Super linter repository.
@@ -69,6 +70,7 @@
versions:
fpt: '*'
ghec: '*'
ghes: '>=3.3'
- title: Dependabot version update PR
description: Example pull request generated by the Dependabot version updates configuration in the Super linter repository.
@@ -81,3 +83,4 @@
versions:
fpt: '*'
ghec: '*'
ghes: '>=3.3'

View File

@@ -1 +1 @@
If you protect your personal account with two-factor authentication but do not know your password, you will not be able to generate a one-time password to recover your account. {% data variables.product.company_short %} can send a password reset email to a verified address associated with your account. For more information, see "[Updating your {% data variables.product.prodname_dotcom %} access credentials](/authentication/keeping-your-account-and-data-secure/updating-your-github-access-credentials#requesting-a-new-password)."
If you protect your personal account with two-factor authentication but do not know your password, you will not be able to follow these steps to recover your account. {% data variables.product.company_short %} can send a password reset email to a verified address associated with your account. For more information, see "[Updating your {% data variables.product.prodname_dotcom %} access credentials](/authentication/keeping-your-account-and-data-secure/updating-your-github-access-credentials#requesting-a-new-password)."

View File

@@ -5,7 +5,7 @@ Use the `branches` filter when you want to include branch name patterns or when
Use the `tags` filter when you want to include tag name patterns or when you want to both include and exclude tag names patterns. Use the `tags-ignore` filter when you only want to exclude tag name patterns. You cannot use both the `tags` and `tags-ignore` filters for the same event in a workflow.
If you define only `tags`/`tag-ignore` or only `branches`/`branches-ignore`, the workflow won't run for events affecting the undefined Git ref. If you define neither `tags`/`tag-ignore` or `branches`/`branches-ignore`, the workflow will run for events affecting either branches or tags. If you define both `branches`/`branches-ignore` and [`paths`](#onpushpull_requestpull_request_targetpathspaths-ignore), the workflow will only run when both filters are satisfied.
If you define only `tags`/`tags-ignore` or only `branches`/`branches-ignore`, the workflow won't run for events affecting the undefined Git ref. If you define neither `tags`/`tags-ignore` or `branches`/`branches-ignore`, the workflow will run for events affecting either branches or tags. If you define both `branches`/`branches-ignore` and [`paths`](#onpushpull_requestpull_request_targetpathspaths-ignore), the workflow will only run when both filters are satisfied.
The `branches`, `branches-ignore`, `tags`, and `tags-ignore` keywords accept glob patterns that use characters like `*`, `**`, `+`, `?`, `!` and others to match more than one branch or tag name. If a name contains any of these characters and you want a literal match, you need to *escape* each of these special characters with `\`. For more information about glob patterns, see the "[Filter pattern cheat sheet](/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet)."

View File

@@ -1 +0,0 @@
Restricting the ability to add outside collaborators to owners is available with {% data variables.product.prodname_ghe_cloud %}. For more information, see "[GitHub's products](/articles/githubs-products)."

View File

@@ -1,5 +1,5 @@
You can manage permissions and policies for a number of different actions and features in your organization.
For example, to protect your organization's data and number of paid licenses, you can choose to allow only organization owners to invite outside collaborators to organization repositories. You can also choose to allow or prevent the forking of private repositories owned by your organization. For more information, see "[Setting permissions for adding outside collaborators](/organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators)" and "[Managing the forking policy for your organization](/organizations/managing-organization-settings/managing-the-forking-policy-for-your-organization)."
For example, to protect your organization's data, you can restrict repository creation in your organization. You can also choose to allow or prevent the forking of private repositories owned by your organization. For more information, see "[Restricting repository creation in your organization](/organizations/managing-organization-settings/restricting-repository-creation-in-your-organization)" and "[Managing the forking policy for your organization](/organizations/managing-organization-settings/managing-the-forking-policy-for-your-organization)."
For the full list of settings you can configure for your organization, see "[Managing organization settings](/organizations/managing-organization-settings)."

View File

@@ -90,6 +90,7 @@ contribution_cta:
products:
graphql:
reference:
implements: Implements
fields: Fields
arguments: Arguments
name: Name

View File

@@ -14,8 +14,18 @@ export const next = '3.5'
export const nextNext = '3.6'
export const supported = ['3.4', '3.3', '3.2', '3.1']
// This indicates the point where we started treating redirect lookups
// to be a *function* rather than a big *lookup object*.
// This is important distinguish because we need to leverage that
// when dealing with redirects specifically in these archived
// enterprise versions.
// When you're archiving a version, add the new archived number to this
// array and you should never need to touch the `deprecated` array
// on the line just below.
export const deprecatedWithFunctionalRedirects = ['3.0']
export const deprecated = [
'3.0',
...deprecatedWithFunctionalRedirects,
'2.22',
'2.21',
'2.20',

View File

@@ -2,21 +2,32 @@ import { languageKeys } from './languages.js'
import nonEnterpriseDefaultVersion from './non-enterprise-default-version.js'
import { allVersions } from './all-versions.js'
import { latest, supported } from './enterprise-server-releases.js'
import {
latest,
supported,
deprecatedWithFunctionalRedirects,
} from './enterprise-server-releases.js'
const languagePrefixRegex = new RegExp(`^/(${languageKeys.join('|')})/`)
const nonEnterpriseDefaultVersionPrefix = `/${nonEnterpriseDefaultVersion}`
// Return the new URI if there is one, otherwise return undefined.
export default function getRedirect(uri, context) {
const { redirects, userLanguage } = context
const supportedAndRecentlyDeprecated = [...supported, ...deprecatedWithFunctionalRedirects]
export function splitPathByLanguage(uri, userLanguage) {
let language = userLanguage || 'en'
let withoutLanguage = uri
if (languagePrefixRegex.test(uri)) {
language = uri.match(languagePrefixRegex)[1]
withoutLanguage = uri.replace(languagePrefixRegex, '/')
}
return [language, withoutLanguage]
}
// Return the new URI if there is one, otherwise return undefined.
export default function getRedirect(uri, context) {
const { redirects, userLanguage } = context
const [language, withoutLanguage] = splitPathByLanguage(uri, userLanguage)
let destination
@@ -54,7 +65,6 @@ export default function getRedirect(uri, context) {
if (withoutLanguage === '/enterprise-server') {
return basicCorrection
}
// console.log({ basicCorrection })
} else if (withoutLanguage.startsWith('/enterprise-server@latest')) {
// E.g. '/enterprise-server@latest' or '/enterprise-server@latest/3.3/foo'
basicCorrection =
@@ -67,9 +77,9 @@ export default function getRedirect(uri, context) {
}
} else if (
withoutLanguage.startsWith('/enterprise/') &&
supported.includes(withoutLanguage.split('/')[2])
supportedAndRecentlyDeprecated.includes(withoutLanguage.split('/')[2])
) {
// E.g. '/enterprise/3.3' or '/enterprise/3.3/foo'
// E.g. '/enterprise/3.3' or '/enterprise/3.3/foo' or '/enterprise/3.0/foo
// If the URL is without a language, and no redirect is necessary,
// but it has as version prefix, the language has to be there

View File

@@ -440,3 +440,9 @@
- /github/administering-a-repository/managing-alerts-from-secret-scanning
- /code-security/secret-security/managing-alerts-from-secret-scanning
- /code-security/secret-scanning/managing-alerts-from-secret-scanning
/enterprise-cloud@latest/organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators
- /articles/restricting-the-ability-to-add-outside-collaborators-to-organization-repositories
- /articles/setting-permissions-for-adding-outside-collaborators
- /github/setting-up-and-managing-organizations-and-teams/setting-permissions-for-adding-outside-collaborators
- /organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators

View File

@@ -1,3 +1,5 @@
import fs from 'fs'
import os from 'os'
import path from 'path'
import flat from 'flat'
import { get, set } from 'lodash-es'
@@ -5,17 +7,42 @@ import languages from './languages.js'
import dataDirectory from './data-directory.js'
import encodeBracketedParentheses from './encode-bracketed-parentheses.js'
const loadSiteDataFromDir = (dir) => ({
site: {
data: dataDirectory(path.join(dir, 'data'), {
preprocess: (dataString) => encodeBracketedParentheses(dataString.trimEnd()),
ignorePatterns: [/README\.md$/],
}),
},
const TEMP_DIRECTORY = process.env.RUNNER_TEMP || os.tmpdir()
function diskMemoize(prefix, fn) {
const useCache = process.env.NODE_ENV !== 'development'
return (dir) => {
const cacheFileName = `${prefix}.${dir.replace(/[^\w]+/g, '-').toLowerCase() || 'en'}.json`
if (useCache) {
try {
return JSON.parse(fs.readFileSync(cacheFileName, 'utf-8'))
} catch (err) {
if (!(err.code === 'ENOENT' || err instanceof SyntaxError)) throw err
}
}
const result = fn(dir)
if (useCache) {
fs.writeFileSync(cacheFileName, JSON.stringify(result), 'utf-8')
console.log(`Disk-cache miss on ${cacheFileName}`, new Date())
}
return result
}
}
const loadSiteDataFromDir = diskMemoize(path.join(TEMP_DIRECTORY, 'docs-site-data'), (dir) => {
return {
site: {
data: dataDirectory(path.join(dir, 'data'), {
preprocess: (dataString) => encodeBracketedParentheses(dataString.trimEnd()),
ignorePatterns: [/README\.md$/],
}),
},
}
})
export default function loadSiteData() {
// load english site data
// load English site data
const siteData = {
en: loadSiteDataFromDir(languages.en.dir),
}

View File

@@ -4,6 +4,7 @@ import statsd from '../lib/statsd.js'
import {
firstVersionDeprecatedOnNewSite,
lastVersionWithoutArchivedRedirectsFile,
deprecatedWithFunctionalRedirects,
} from '../lib/enterprise-server-releases.js'
import patterns from '../lib/patterns.js'
import versionSatisfiesRange from '../lib/version-satisfies-range.js'
@@ -13,6 +14,7 @@ import got from 'got'
import { readCompressedJsonFileFallbackLazily } from '../lib/read-json-file.js'
import { cacheControlFactory } from './cache-control.js'
import { pathLanguagePrefixed, languagePrefixPathRegex } from '../lib/languages.js'
import getRedirect, { splitPathByLanguage } from '../lib/get-redirect.js'
function splitByLanguage(uri) {
let language = null
@@ -35,6 +37,7 @@ const archivedFrontmatterFallbacks = readCompressedJsonFileFallbackLazily(
)
const cacheControl = cacheControlFactory(60 * 60 * 24 * 365)
const noCacheControl = cacheControlFactory(0)
// Combine all the things you need to make sure the response is
// aggresively cached.
@@ -99,6 +102,39 @@ export default async function archivedEnterpriseVersions(req, res, next) {
const redirectCode = pathLanguagePrefixed(req.path) ? 301 : 302
if (deprecatedWithFunctionalRedirects.includes(requestedVersion)) {
const redirectTo = getRedirect(req.path, req.context)
if (redirectTo) {
if (redirectCode === 301) {
cacheControl(res)
} else {
noCacheControl(res)
}
res.removeHeader('set-cookie')
return res.redirect(redirectCode, redirectTo)
}
const redirectJson = await getRemoteJSON(getProxyPath('redirects.json', requestedVersion), {
retry: retryConfiguration,
// This is allowed to be different compared to the other requests
// we make because downloading the `redirects.json` once is very
// useful because it caches so well.
// And, as of 2021 that `redirects.json` is 10MB so it's more likely
// to time out.
timeout: 1000,
})
const [language, withoutLanguage] = splitPathByLanguage(req.path, req.context.userLanguage)
const newRedirectTo = redirectJson[withoutLanguage]
if (newRedirectTo) {
if (redirectCode === 301) {
cacheControl(res)
} else {
noCacheControl(res)
}
res.removeHeader('set-cookie')
return res.redirect(redirectCode, `/${language}${newRedirectTo}`)
}
}
// redirect language-prefixed URLs like /en/enterprise/2.10 -> /enterprise/2.10
// (this only applies to versions <2.13)
if (
@@ -135,7 +171,10 @@ export default async function archivedEnterpriseVersions(req, res, next) {
}
}
if (versionSatisfiesRange(requestedVersion, `>${lastVersionWithoutArchivedRedirectsFile}`)) {
if (
versionSatisfiesRange(requestedVersion, `>${lastVersionWithoutArchivedRedirectsFile}`) &&
!deprecatedWithFunctionalRedirects.includes(requestedVersion)
) {
const redirectJson = await getRemoteJSON(getProxyPath('redirects.json', requestedVersion), {
retry: retryConfiguration,
// This is allowed to be different compared to the other requests

22
script/warm-before-tests.mjs Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env node
// [start-readme]
//
// It runs the warmServer() function because that function can do things
// like writing to disk as a caching mechanism.
// When jest runs tests, it starts multiple concurrent processes,
// even if it runs it serially (`--runInBand`) so it's highly likely
// that two concurrent processes both attempt to writing to
// the same exact file. By running this script before anything
// begins, we can be certain that files that should have been created
// are created.
//
// [end-readme]
import warmServer from '../lib/warm-server.js'
main()
async function main() {
await warmServer()
}

View File

@@ -17,13 +17,7 @@ const slugger = new GithubSlugger()
const contentDir = path.join(__dirname, '../../content')
describe('category pages', () => {
let siteData
beforeAll(async () => {
// Load the English site data
const allSiteData = await loadSiteData()
siteData = allSiteData.en.site
})
const siteData = loadSiteData().en.site
const walkOptions = {
globs: ['*/index.md', 'enterprise/*/index.md'],

View File

@@ -1,10 +1,7 @@
import loadSiteData from '../../lib/site-data.js'
describe('glossaries', () => {
let glossaries
beforeAll(async () => {
glossaries = (await loadSiteData()).en.site.data.glossaries
})
const glossaries = loadSiteData().en.site.data.glossaries
test('are broken into external, internal, and candidates', async () => {
const keys = Object.keys(glossaries)
@@ -41,7 +38,7 @@ describe('glossaries', () => {
})
test('non-English external glossary is in correct order', async () => {
const vals = (await loadSiteData()).ja.site.data.glossaries.external
const vals = loadSiteData().ja.site.data.glossaries.external
vals.forEach((val, i) => {
expect(val.term.localeCompare(vals[i + 1], 'ja')).toBeGreaterThan(0)
})

View File

@@ -11,17 +11,12 @@ import { jest } from '@jest/globals'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const siteData = loadSiteData()
const pages = (await loadPages()).filter((page) => page.languageCode === 'en')
describe('data references', () => {
jest.setTimeout(60 * 1000)
let data, pages
beforeAll(async () => {
data = await loadSiteData()
pages = await loadPages()
pages = pages.filter((page) => page.languageCode === 'en')
})
test('every data reference found in English content files is defined and has a value', () => {
let errors = []
expect(pages.length).toBeGreaterThan(0)
@@ -30,7 +25,7 @@ describe('data references', () => {
const file = path.join('content', page.relativePath)
const pageRefs = getDataReferences(page.markdown)
pageRefs.forEach((key) => {
const value = get(data.en, key)
const value = get(siteData.en, key)
if (typeof value !== 'string') errors.push({ key, value, file })
})
})
@@ -50,7 +45,7 @@ describe('data references', () => {
const { data: metadata } = frontmatter(fileContents, { filepath: page.fullPath })
const metadataRefs = getDataReferences(JSON.stringify(metadata))
metadataRefs.forEach((key) => {
const value = get(data.en, key)
const value = get(siteData.en, key)
if (typeof value !== 'string') errors.push({ key, value, metadataFile })
})
})
@@ -62,7 +57,7 @@ describe('data references', () => {
test('every data reference found in English reusable files is defined and has a value', async () => {
let errors = []
const allReusables = data.en.site.data.reusables
const allReusables = siteData.en.site.data.reusables
const reusables = Object.values(allReusables)
expect(reusables.length).toBeGreaterThan(0)
@@ -78,7 +73,7 @@ describe('data references', () => {
const reusableRefs = getDataReferences(JSON.stringify(reusablesPerFile))
reusableRefs.forEach((key) => {
const value = get(data.en, key)
const value = get(siteData.en, key)
if (typeof value !== 'string') errors.push({ key, value, reusableFile })
})
})
@@ -90,7 +85,7 @@ describe('data references', () => {
test('every data reference found in English variable files is defined and has a value', async () => {
let errors = []
const allVariables = data.en.site.data.variables
const allVariables = siteData.en.site.data.variables
const variables = Object.values(allVariables)
expect(variables.length).toBeGreaterThan(0)
@@ -106,7 +101,7 @@ describe('data references', () => {
const variableRefs = getDataReferences(JSON.stringify(variablesPerFile))
variableRefs.forEach((key) => {
const value = get(data.en, key)
const value = get(siteData.en, key)
if (typeof value !== 'string') errors.push({ key, value, variableFile })
})
})

View File

@@ -1,21 +1,17 @@
import { fileURLToPath } from 'url'
import path from 'path'
import fs from 'fs'
import { get, isPlainObject, has } from 'lodash-es'
import flat from 'flat'
import walkSync from 'walk-sync'
import { ParseError } from 'liquidjs'
import loadSiteData from '../../lib/site-data.js'
import patterns from '../../lib/patterns.js'
import { liquid } from '../../lib/render-content/index.js'
import walkSync from 'walk-sync'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
describe('siteData module (English)', () => {
let data
beforeAll(async () => {
data = await loadSiteData()
})
const data = loadSiteData()
test('makes an object', async () => {
expect(isPlainObject(data)).toBe(true)
@@ -49,21 +45,6 @@ describe('siteData module (English)', () => {
expect(reusable.includes('任意のページの左上で')).toBe(true)
})
test('backfills missing translated site data with English values', async () => {
const newFile = path.join(__dirname, '../../data/newfile.yml')
fs.writeFileSync(newFile, 'newvalue: bar')
try {
const data = loadSiteData()
expect(get(data, 'en.site.data.newfile.newvalue')).toEqual('bar')
expect(get(data, 'ja.site.data.newfile.newvalue')).toEqual('bar')
} finally {
// If an error is thrown above, it will still "bubble up"
// to the jest reporter, but we still always need to clean up
// the temporary file.
fs.unlinkSync(newFile)
}
})
test('all Liquid tags are valid', async () => {
const dataMap = flat(data)
for (const key in dataMap) {

View File

@@ -25,6 +25,7 @@ import allowedVersionOperators from '../../lib/liquid-tags/ifversion-supported-o
import semver from 'semver'
import { jest } from '@jest/globals'
import { getDiffFiles } from '../helpers/diff-files.js'
import loadSiteData from '../../lib/site-data.js'
jest.useFakeTimers('legacy')
@@ -410,6 +411,9 @@ if (
describe('lint markdown content', () => {
if (mdToLint.length < 1) return
const siteData = loadSiteData()
describe.each(mdToLint)('%s', (markdownRelPath, markdownAbsPath) => {
let content,
ast,
@@ -453,12 +457,14 @@ describe('lint markdown content', () => {
}
})
const context = { site: siteData.en.site }
// visit is not async-friendly so we need to do an async map to parse the YML snippets
yamlScheduledWorkflows = (
await Promise.all(
yamlScheduledWorkflows.map(async (snippet) => {
// If we don't parse the Liquid first, yaml loading chokes on {% raw %} tags
const rendered = await renderContent.liquid.parseAndRender(snippet)
const rendered = await renderContent.liquid.parseAndRender(snippet, context)
const parsed = yaml.load(rendered)
return parsed.on.schedule
})
@@ -1031,6 +1037,9 @@ describe('lint GHAE release notes', () => {
describe('lint learning tracks', () => {
if (learningTracksToLint.length < 1) return
const siteData = loadSiteData()
describe.each(learningTracksToLint)('%s', (yamlRelPath, yamlAbsPath) => {
let dictionary
let dictionaryError = false
@@ -1066,7 +1075,7 @@ describe('lint learning tracks', () => {
const productVersions = getApplicableVersions(data.versions, productTocPath)
const featuredTracks = {}
const context = { enterpriseServerVersions }
const context = { enterpriseServerVersions, site: siteData.en.site }
// For each of the product's versions, render the learning track data and look for a featured track.
await Promise.all(

View File

@@ -1,9 +1,11 @@
import supertest from 'supertest'
import { describe, jest, test } from '@jest/globals'
import createApp from '../../lib/app.js'
import enterpriseServerReleases from '../../lib/enterprise-server-releases.js'
import { get, getDOM } from '../helpers/supertest.js'
import { SURROGATE_ENUMS } from '../../middleware/set-fastly-surrogate-key.js'
import supertest from 'supertest'
import { jest } from '@jest/globals'
import { PREFERRED_LOCALE_COOKIE_NAME } from '../../middleware/detect-language.js'
jest.useFakeTimers('legacy')
@@ -89,6 +91,73 @@ describe('enterprise deprecation', () => {
})
})
// Starting with the deprecation of 3.0, it's the first time we deprecate
// enterprise versions since redirects is a *function* rather than a
// lookup in a big object.
describe('recently deprecated redirects', () => {
test('basic enterprise 3.0 redirects', async () => {
const res = await get('/enterprise/3.0')
expect(res.statusCode).toBe(302)
expect(res.headers.location).toBe('/en/enterprise-server@3.0')
expect(res.headers['set-cookie']).toBeUndefined()
// Deliberately no cache control because it is user-dependent
expect(res.headers['cache-control']).toBe('private, no-store')
})
test('basic enterprise 3.0 redirects by cookie', async () => {
const res = await get('/enterprise/3.0', {
headers: {
Cookie: `${PREFERRED_LOCALE_COOKIE_NAME}=ja`,
},
})
expect(res.statusCode).toBe(302)
expect(res.headers.location).toBe('/ja/enterprise-server@3.0')
})
test('already languaged enterprise 3.0 redirects', async () => {
const res = await get('/en/enterprise/3.0')
expect(res.statusCode).toBe(301)
expect(res.headers.location).toBe('/en/enterprise-server@3.0')
// 301 redirects are safe to cache aggressively
expect(res.headers['set-cookie']).toBeUndefined()
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=\d+/)
})
test('redirects enterprise-server 3.0 with actual redirect without language', async () => {
const res = await get(
'/enterprise-server@3.0/github/getting-started-with-github/githubs-products'
)
expect(res.statusCode).toBe(302)
expect(res.headers['set-cookie']).toBeUndefined()
// Deliberately no cache control because it is user-dependent
expect(res.headers['cache-control']).toBe('private, no-store')
// This is based on
// https://github.com/github/help-docs-archived-enterprise-versions/blob/master/3.0/redirects.json
expect(res.headers.location).toBe(
'/en/enterprise-server@3.0/get-started/learning-about-github/githubs-products'
)
})
test('redirects enterprise-server 3.0 with actual redirect with language', async () => {
const res = await get(
'/ja/enterprise-server@3.0/github/getting-started-with-github/githubs-products'
)
expect(res.statusCode).toBe(301)
expect(res.headers['set-cookie']).toBeUndefined()
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=\d+/)
// This is based on
// https://github.com/github/help-docs-archived-enterprise-versions/blob/master/3.0/redirects.json
expect(res.headers.location).toBe(
'/ja/enterprise-server@3.0/get-started/learning-about-github/githubs-products'
)
})
test('follow redirects enterprise-server 3.0 with actual redirect without language', async () => {
const res = await get(
'/enterprise-server@3.0/github/getting-started-with-github/githubs-products',
{ followAllRedirects: true }
)
expect(res.statusCode).toBe(200)
})
})
describe('deprecation banner', () => {
test('renders a deprecation warning banner on oldest supported Enterprise version', async () => {
const $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)

View File

@@ -1,6 +1,36 @@
import getRedirect from '../../lib/get-redirect.js'
import { describe, expect, test } from '@jest/globals'
import getRedirect, { splitPathByLanguage } from '../../lib/get-redirect.js'
import { latest } from '../../lib/enterprise-server-releases.js'
describe('splitPathByLanguage', () => {
test('basic', () => {
const [language, withoutLanguage] = splitPathByLanguage('/foo/')
expect(language).toBe('en')
expect(withoutLanguage).toBe('/foo/')
})
test('already has /en in it', () => {
const [language, withoutLanguage] = splitPathByLanguage('/en/foo/')
expect(language).toBe('en')
expect(withoutLanguage).toBe('/foo/')
})
test('basic with different fallback', () => {
const [language, withoutLanguage] = splitPathByLanguage('/foo/', 'ja')
expect(language).toBe('ja')
expect(withoutLanguage).toBe('/foo/')
})
test('already has /en different fallback', () => {
const [language, withoutLanguage] = splitPathByLanguage('/en/foo/', 'ja')
expect(language).toBe('en')
expect(withoutLanguage).toBe('/foo/')
})
test('unrecognized prefix is ignored', () => {
const [language, withoutLanguage] = splitPathByLanguage('/sv/foo/')
expect(language).toBe('en')
expect(withoutLanguage).toBe('/sv/foo/')
})
})
describe('getRedirect basics', () => {
it('should sometimes not correct the version prefix', () => {
// This essentially tests legacy entries that come from the
@@ -162,4 +192,15 @@ describe('getRedirect basics', () => {
ctx.userLanguage = null
expect(getRedirect('/foo', ctx)).toBe(`/en/bar`)
})
it('should work for some deprecated enterprise-server URLs too', () => {
// Starting with enterprise-server 3.0, we have made redirects become
// a *function* rather than a lookup on a massive object.
const ctx = {
pages: {},
redirects: {},
}
expect(getRedirect('/enterprise/3.0', ctx)).toBe('/en/enterprise-server@3.0')
expect(getRedirect('/enterprise/3.0/foo', ctx)).toBe('/en/enterprise-server@3.0/foo')
})
})

View File

@@ -191,11 +191,7 @@ describe('liquid template parser', () => {
// Create a fake req so we can test the feature versions middleware
const req = { language: 'en', query: {} }
let siteData
beforeAll(async () => {
const allSiteData = await loadSiteData()
siteData = allSiteData.en.site
})
const siteData = loadSiteData().en.site
test('does not render in FPT because feature is not available in FPT', async () => {
req.context = {