1
0
mirror of synced 2026-01-08 12:01:53 -05:00

Merge branch 'main' into fix-inconsistencies

This commit is contained in:
PSJ
2021-07-22 09:14:55 +05:30
committed by GitHub
70 changed files with 986 additions and 1189 deletions

View File

@@ -37,21 +37,15 @@ In your `docs-internal` checkout:
- [ ] Create a new branch: `git checkout -b deprecate-<version>`.
- [ ] Edit `lib/enterprise-server-releases.js` by moving the number to be deprecated into the `deprecated` array.
- [ ] Run `script/enterprise-server-deprecations/remove-static-files.js` and commit results.
- [ ] Manually remove entries for the deprecated version from `lib/redirects/static/developer-docs-routes-for-supported-versions.json`.
- **Note**: These entries only go up to 2.21. We can remove this step once 2.21 is deprecated.
- [ ] Run `script/enterprise-server-deprecations/remove-redirects.js` and commit results.
- [ ] Open a new PR. Make sure to check the following:
- [ ] Tests are passing.
- [ ] The deprecated version renders on staging as expected.
- [ ] The new oldest supported version renders on staging as expected. Also check the banner text.
- [ ] When the PR is approved, merge it in to complete the deprecation.
## Step 5: Remove outdated Liquid markup and frontmatter
The following steps are somewhat optional and can be completed at any time. They do not have user impact; they just clear out old Liquid statements for the deprecated version, which makes things easier for content writers.
In your `docs-internal` checkout:
- [ ] Create a new branch: `git checkout -b remove-<version>-markup`
- [ ] Run the script: `script/remove-deprecated-enterprise-version-markup.js --release <number>`.
- [ ] Spot check a few changes. Content, frontmatter, and data files should all have been updated.
- [ ] Open a PR with the results. The diff may be large and complex, so make sure to get a review from `@github/docs-content`.
- [ ] Debug any test failures or unexpected results.
- [ ] Remove the outdated Liquid markup and frontmatter. It's recommended to create a topic branch off of your `deprecate-<version>` branch to isolate the changes for review.
- [ ] In your `docs-internal` checkout, from your `deprecate-<version>` branch: `git checkout -b remove-<version>-markup`
- [ ] Run the script: `script/enterprise-server-deprecations/remove-version-markup.js --release <number>`.
- [ ] Spot check a few changes. Content, frontmatter, and data files should all have been updated.
- [ ] Open a PR with the results. The diff may be large and complex, so make sure to get a review from `@github/docs-content`.
- [ ] Debug any test failures or unexpected results.
- [ ] When the PR is approved, merge it in to complete the deprecation.

View File

@@ -14,7 +14,7 @@ export default [
'andymckay/labeler@22d5392de2b725cea4b284df5824125054049d84',
'crowdin/github-action@fd9429dd63d6c0f8a8cb4b93ad8076990bd6e688',
'crykn/copy_folder_to_another_repo_action@0282e8b9fef06de92ddcae9fe6cb44df6226646c',
'cschleiden/actions-linter@0ff16d6ac5103cca6c92e6cbc922b646baaea5be',
'cschleiden/actions-linter@caffd707beda4fc6083926a3dff48444bc7c24aa', // uses github-actions-parser v0.23.0
'dawidd6/action-delete-branch@47743101a121ad657031e6704086271ca81b1911',
'docker://chinthakagodawita/autoupdate-action:v1',
'dorny/paths-filter@eb75a1edc117d3756a18ef89958ee59f9500ba58',

View File

@@ -13,7 +13,7 @@ on:
jobs:
build:
runs-on: ${{ fromJson('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything

View File

@@ -13,7 +13,7 @@ on:
jobs:
build:
runs-on: ${{ fromJson('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything

View File

@@ -13,7 +13,7 @@ on:
jobs:
build:
runs-on: ${{ fromJson('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything

View File

@@ -14,7 +14,7 @@ on:
jobs:
check-schema-versions:
if: ${{ github.repository == 'github/docs-internal' }}
runs-on: ${{ fromJson('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
- name: Checkout repository code
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f

View File

@@ -20,7 +20,7 @@ jobs:
test:
# Run on self-hosted if the private repo or ubuntu-latest if the public repo
# See pull # 17442 in the private repo for context
runs-on: ${{ fromJson('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
timeout-minutes: 60
strategy:
fail-fast: false

View File

@@ -87,7 +87,7 @@ jobs:
# and no review exists,leave a REQUEST_CHANGES review
- name: Request pull request changes
# Check for no reviews or reviews that aren't CHANGES_REQUESTED
if: ${{ steps.filter.outputs.notAllowed == 'true' && (!steps.requested-change.outputs.result || fromJson(steps.requested-change.outputs.result).state != 'CHANGES_REQUESTED') }}
if: ${{ steps.filter.outputs.notAllowed == 'true' && (!steps.requested-change.outputs.result || fromJSON(steps.requested-change.outputs.result).state != 'CHANGES_REQUESTED') }}
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
with:
github-token: ${{secrets.GITHUB_TOKEN}}
@@ -126,7 +126,7 @@ jobs:
- name: Dismiss pull request review
# Check that unallowed files aren't modified and that a
# CHANGES_REQUESTED review already exists
if: ${{ steps.filter.outputs.notAllowed == 'false' && steps.requested-change.outputs.result && fromJson(steps.requested-change.outputs.result).state == 'CHANGES_REQUESTED' }}
if: ${{ steps.filter.outputs.notAllowed == 'false' && steps.requested-change.outputs.result && fromJSON(steps.requested-change.outputs.result).state == 'CHANGES_REQUESTED' }}
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
with:
github-token: ${{secrets.GITHUB_TOKEN}}
@@ -134,6 +134,6 @@ jobs:
await github.pulls.dismissReview({
...context.repo,
pull_number: context.payload.number,
review_id: ${{fromJson(steps.requested-change.outputs.result).id}},
review_id: ${{fromJSON(steps.requested-change.outputs.result).id}},
message: `✨Looks like you reverted all files we don't accept contributions for. 🙌 A member of the docs team will review your PR soon. 🚂`
})

View File

@@ -11,9 +11,11 @@ on:
- main
paths:
- '.github/workflows/*.yml'
- '.github/workflows/*.yaml'
pull_request:
paths:
- '.github/workflows/*.yml'
- '.github/workflows/*.yaml'
jobs:
lint:
@@ -24,6 +26,6 @@ jobs:
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
- name: Run linter
uses: cschleiden/actions-linter@0ff16d6ac5103cca6c92e6cbc922b646baaea5be
uses: cschleiden/actions-linter@caffd707beda4fc6083926a3dff48444bc7c24aa
with:
workflows: '[".github/workflows/*.yml", "!.github/workflows/staging-deploy-pr.yml", "!.github/workflows/staging-undeploy-pr.yml"]'
workflows: '[".github/workflows/*.yml", ".github/workflows/*.yaml", "!.github/workflows/remove-from-fr-board.yaml"]'

View File

@@ -1,3 +1 @@
web: NODE_ENV=production node server.mjs
release: NODE_ENV=production script/release-heroku

118
components/GenericError.tsx Normal file
View File

@@ -0,0 +1,118 @@
import Head from 'next/head'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { MarkGithubIcon, CommentDiscussionIcon } from '@primer/octicons-react'
import { useVersion } from 'components/hooks/useVersion'
export function GenericError() {
const { isEnterprise } = useVersion()
return (
<div className="min-h-screen d-flex flex-column">
<Head>
<title>GitHub Documentation</title>
</Head>
<SimpleHeader />
<div className="container-xl p-responsive py-9 width-full flex-1">
<article className="markdown-body col-md-10 col-lg-7 mx-auto">
<h1>Ooops!</h1>
<p className="lead-mktg">It looks like something went wrong.</p>
<p className="lead-mktg">
We track these errors automatically, but if the problem persists please feel free to
contact us.
</p>
<a
id="contact-us"
href={
isEnterprise
? 'https://enterprise.github.com/support'
: 'https://support.github.com/contact'
}
className="btn btn-outline mt-2"
>
<CommentDiscussionIcon size="small" className="octicon mr-1" />
Contact support
</a>
</article>
</div>
<SimpleFooter />
</div>
)
}
export const SimpleHeader = () => {
const router = useRouter()
return (
<div className="border-bottom color-border-secondary no-print">
<header className="container-xl p-responsive py-3 position-relative d-flex width-full">
<div
className="d-flex flex-items-center"
style={{ zIndex: 3 }}
id="github-logo-mobile"
role="banner"
>
<Link href={`/${router.locale}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a aria-hidden="true" tabIndex={-1}>
<MarkGithubIcon size={32} className="color-icon-primary" />
</a>
</Link>
<Link href={`/${router.locale}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a className="h4-mktg color-text-primary no-underline no-wrap pl-2">GitHub Docs</a>
</Link>
</div>
</header>
</div>
)
}
export const SimpleFooter = () => {
return (
<footer className="py-6 text-small">
<div className="container-xl d-flex px-3 px-md-6 flex-justify-center">
<ul className="d-flex list-style-none flex-wrap flex-justify-center">
<li className="d-flex mr-xl-3 color-text-secondary">
<MarkGithubIcon className="mr-2 mr-xl-3" size={20} />
<span>&copy; {new Date().getFullYear()} GitHub, Inc.</span>
</li>
<li className="ml-3">
<a href="/github/site-policy/github-terms-of-service">Terms</a>
</li>
<li className="ml-3">
<a href="/github/site-policy/github-privacy-statement">Privacy </a>
</li>
<li className="ml-3">
<a href="https://github.com/security">Security</a>
</li>
<li className="ml-3">
<a href="https://www.githubstatus.com/">Status</a>
</li>
<li className="ml-3">
<a href="/">Help</a>
</li>
<li className="ml-3">
<a href="https://support.github.com">Contact GitHub</a>
</li>
<li className="ml-3">
<a href="https://github.com/pricing">Pricing</a>
</li>
<li className="ml-3">
<a href="/developers">Developer API</a>
</li>
<li className="ml-3">
<a href="https://services.github.com/">Training</a>
</li>
<li className="ml-3">
<a href="https://github.com/about">About</a>
</li>
</ul>
</div>
</footer>
)
}

View File

@@ -35,7 +35,7 @@ export const Survey = () => {
}
return (
<form className="f5" onSubmit={submit} ref={formRef} data-testid="survey-form">
<form className="f5 js-survey" onSubmit={submit} ref={formRef} data-testid="survey-form">
<h2 className="mb-1 f4">
{t`able_to_find`}

View File

@@ -13,7 +13,7 @@ export const CodeExampleCard = ({ example }: Props) => {
href={`https://github.com/${example.href}`}
>
<div className="p-4">
<h4>{example.title}</h4>
<h4 dangerouslySetInnerHTML={{ __html: example.title }} />
<p className="mt-2 mb-4 color-text-tertiary">{example.description}</p>
<div className="d-flex flex-wrap">
{example.tags.map((tag) => {

View File

@@ -9,7 +9,10 @@ export const ArticleCard = ({ card, typeLabel }: Props) => {
return (
<div data-testid="article-card" className="d-flex col-12 col-md-4 pr-0 pr-md-6 pr-lg-8">
<a className="no-underline d-flex flex-column py-3 border-bottom" href={card.href}>
<h4 className="h4 color-text-primary mb-1">{card.title}</h4>
<h4
className="h4 color-text-primary mb-1"
dangerouslySetInnerHTML={{ __html: card.title }}
/>
<div className="h6 text-uppercase" data-testid="article-card-type">
{typeLabel}
</div>

View File

@@ -13,7 +13,7 @@ redirect_from:
Before you can initialize your enterprise, you must purchase {% data variables.product.product_name %}. For more information, contact {% data variables.contact.contact_enterprise_sales %}.
After you purchase {% data variables.product.product_name %}, we'll ask you to provide an email address and username for the person you want to initialize the enterprise. Your dedicated technical account manager in {% data variables.contact.enterprise_support %} will create an account for the enterprise owner and send the enterprise owner an email to log into {% data variables.product.product_name %} and complete the initialization. Make sure the information you provide matches the intended enterprise owner's information in the IdP. For more information about enterprise owners, see "[Roles in an enterprise](/github/setting-up-and-managing-your-enterprise/roles-in-an-enterprise#enterprise-owner)."
{% data reusables.github-ae.initialize-enterprise %} Make sure the information you provide matches the intended enterprise owner's information in the IdP. For more information about enterprise owners, see "[Roles in an enterprise](/github/setting-up-and-managing-your-enterprise/roles-in-an-enterprise#enterprise-owner)."
{% note %}

View File

@@ -45,6 +45,7 @@ topics:
- Accounts
children:
- /quickstart
- /onboarding
- /learning-about-github
- /signing-up-for-github
- /using-github

View File

@@ -0,0 +1,80 @@
---
title: Getting started with GitHub AE
intro: 'Get started with setting up and configuring {% data variables.product.product_name %} for {% data variables.product.product_location %}.'
versions:
ghae: '*'
---
This guide will walk you through setting up, configuring, and managing settings for {% data variables.product.product_location %} on {% data variables.product.product_name %} as an enterprise owner.
## Part 1: Setting up {% data variables.product.product_name %}
To get started with {% data variables.product.product_name %}, you can create your enterprise account, initialize {% data variables.product.product_name %}, configure an IP allow list, configure user authentication and provisioning, and manage billing for {% data variables.product.product_location %}.
### 1. Creating your {% data variables.product.product_name %} enterprise account
You will first need to purchase {% data variables.product.product_name %}. For more information, contact [{% data variables.product.prodname_dotcom %}'s Sales team](https://enterprise.github.com/contact).
{% data reusables.github-ae.initialize-enterprise %}
### 2. Initializing {% data variables.product.product_name %}
After {% data variables.product.company_short %} creates the owner account for {% data variables.product.product_location %} on {% data variables.product.product_name %}, you will receive an email to sign in and complete the initialization. During initialization, you, as the enterprise owner, will name {% data variables.product.product_location %}, configure SAML SSO, create policies for all organizations in {% data variables.product.product_location %}, and configure a support contact for your enterprise members. For more information, see "[Initializing {% data variables.product.prodname_ghe_managed %}](/admin/configuration/configuring-your-enterprise/initializing-github-ae)."
### 3. Restricting network traffic
You can configure an allow list for specific IP addresses to restrict access to assets owned by organizations in your enterprise account. For more information, see "[Restricting network traffic to your enterprise](/admin/configuration/configuring-your-enterprise/restricting-network-traffic-to-your-enterprise)."
### 4. Managing identity and access for {% data variables.product.product_location %}
You can centrally manage access to {% data variables.product.product_location %} on {% data variables.product.product_name %} from an identity provider (IdP) using SAML single sign-on (SSO) for user authentication and System for Cross-domain Identity Management (SCIM) for user provisioning. Once you configure provisioning, you can assign or unassign users to the application from the IdP, creating or disabling user accounts in the enterprise. For more information, see "[About identity and access management for your enterprise](/admin/authentication/managing-identity-and-access-for-your-enterprise/about-identity-and-access-management-for-your-enterprise)."
### 5. Managing billing for {% data variables.product.product_location %}
Owners of the subscription for {% data variables.product.product_location %} on {% data variables.product.product_name %} can view billing details for {% data variables.product.product_name %} in the Azure portal. For more information, see "[Managing billing for your enterprise](/admin/overview/managing-billing-for-your-enterprise)."
## Part 2: Organizing and managing enterprise members
As an enterprise owner for {% data variables.product.product_name %}, you can manage settings on user, repository, team, and organization levels. You can manage members of {% data variables.product.product_location %}, create and manage organizations, set policies for repository management, and create and manage teams.
### 1. Managing members of {% data variables.product.product_location %}
{% data reusables.getting-started.managing-enterprise-members %}
### 2. Creating organizations
{% data reusables.getting-started.creating-organizations %}
### 3. Adding members to organizations
{% data reusables.getting-started.adding-members-to-organizations %}
### 4. Creating teams
{% data reusables.getting-started.creating-teams %}
### 5. Setting organization and repository permission levels
{% data reusables.getting-started.setting-org-and-repo-permissions %}
### 6. Enforcing repository management policies
{% data reusables.getting-started.enforcing-repo-management-policies %}
## Part 3: Building securely
To increase the security of {% data variables.product.product_location %}, you can monitor {% data variables.product.product_location %} and configure security and analysis features for your organizations.
### 1. Monitoring {% data variables.product.product_location %}
You can monitor {% data variables.product.product_location %} with your activity dashboard and audit logging. For more information, see "[Monitoring activity in your enterprise](/admin/user-management/monitoring-activity-in-your-enterprise)."
### 2. Configuring security features for your organizations
{% data reusables.getting-started.configuring-security-features %}
## Part 4: Customizing and automating work on {% data variables.product.product_location %}
You can customize and automate work in organizations in {% data variables.product.product_location %} with the {% data variables.product.prodname_dotcom %} API, {% data variables.product.prodname_actions %}, and {% data variables.product.prodname_pages %}.
### 1. Using the {% data variables.product.prodname_dotcom %} API
{% data reusables.getting-started.api %}
### 2. Building {% data variables.product.prodname_actions %}
{% data reusables.getting-started.actions %}
For more information on enabling and configuring {% data variables.product.prodname_actions %} for {% data variables.product.product_name %}, see "[Getting started with {% data variables.product.prodname_actions %} for {% data variables.product.prodname_ghe_managed %}](/admin/github-actions/using-github-actions-in-github-ae/getting-started-with-github-actions-for-github-ae)."
### 3. Using {% data variables.product.prodname_pages %}
{% data reusables.getting-started.github-pages-enterprise %}
## Part 5: Using {% data variables.product.prodname_dotcom %}'s learning and support resources
Your enterprise members can learn more about Git and {% data variables.product.prodname_dotcom %} with our learning resources, and you can get the support you need with {% data variables.product.prodname_dotcom %} Enterprise Support.
### 1. Learning with {% data variables.product.prodname_learning %}
{% data reusables.getting-started.learning-lab-enterprise %}
### 2. Working with {% data variables.product.prodname_dotcom %} Enterprise Support
{% data reusables.getting-started.contact-support-enterprise %}

View File

@@ -0,0 +1,176 @@
---
title: Getting started with GitHub Enterprise Cloud
intro: 'Get started with setting up and managing your {% data variables.product.prodname_ghe_cloud %} organization or enterprise account'
versions:
fpt: '*'
---
This guide will walk you through setting up, configuring and managing your {% data variables.product.prodname_ghe_cloud %} account as an organization or enterprise owner.
## Part 1: Choosing your account type
{% data variables.product.prodname_dotcom %} provides two types of Enterprise products:
- **{% data variables.product.prodname_ghe_cloud %}**
- **{% data variables.product.prodname_ghe_server %}**
The main difference between the products is that {% data variables.product.prodname_ghe_cloud %} is hosted by {% data variables.product.prodname_dotcom %}, while {% data variables.product.prodname_ghe_server %} is self-hosted.
Within the {% data variables.product.prodname_ghe_cloud %} product, there are two different types of account that you can use:
- A single organization account
- An enterprise account that contains multiple organizations
In either scenario, your users will use their own self-created user account and you'll invite them to join.
### 1. Understanding the differences between an organization account and enterprise account
Both organization and enterprise accounts are available with {% data variables.product.prodname_ghe_cloud %}. An organization is a shared account where groups of people can collaborate across many projects at once, and owners and administrators can manage access to data and projects. An enterprise account enables collaboration between multiple organizations, and allows owners to centrally manage policy, billing and security for these organizations. For more information on the differences, see "[Organizations and enterprise accounts](/organizations/collaborating-with-groups-in-organizations/about-organizations#organizations-and-enterprise-accounts)."
If you choose an enterprise account, keep in mind that some policies can be set only at an organization level, while others can be enforced for all organizations in an enterprise.
Once you choose the account type you would like, you can proceed to setting up your account. In each of the sections in this guide, proceed to either the single organization or enterprise account section based on your account type.
## Part 2: Setting up your account
To get started with {% data variables.product.prodname_ghe_cloud %}, you will want to create your organization or enterprise account and set up and view billing settings, subscriptions and usage.
### Setting up a single organization account with {% data variables.product.prodname_ghe_cloud %}
#### 1. About organizations
Organizations are shared accounts where groups of people can collaborate across many projects at once. With {% data variables.product.prodname_ghe_cloud %}, owners and administrators can manage their organization with sophisticated user authentication and management, as well as escalated support and security options. For more information, see "[About organizations](/organizations/collaborating-with-groups-in-organizations/about-organizations)."
#### 2. Creating or upgrading an organization account
To use an organization account with {% data variables.product.prodname_ghe_cloud %}, you will first need to create an organization. When prompted to choose a plan, select "Enterprise". For more information, see "[Creating a new organization from scratch](/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch)."
Alternatively, if you have an existing organization account that you would like to upgrade, follow the steps in "[Upgrading your {% data variables.product.prodname_dotcom %} subscription](/billing/managing-billing-for-your-github-account/upgrading-your-github-subscription#upgrading-your-organizations-subscription)."
#### 3. Setting up and managing billing
When you choose to use an organization account with {% data variables.product.prodname_ghe_cloud %}, you'll first have access to a [14-day trial](/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud). If you don't purchase {% data variables.product.prodname_enterprise %} or {% data variables.product.prodname_team %} before your trial ends, your organization will be downgraded to {% data variables.product.prodname_free_user %} and lose access to any advanced tooling and features that are only included with paid products. For more information, see "[Finishing your trial](/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud#finishing-your-trial)."
Your organization's billing settings page allows you to manage settings like your payment method and billing cycle, view information about your subscription, and upgrade your storage and {% data variables.product.prodname_actions %} minutes. For more information on managing your billing settings, see "[Managing your {% data variables.product.prodname_dotcom %} billing settings](/billing/managing-your-github-billing-settings)."
Only organization members with the *owner* or *billing manager* role can access or change billing settings for your organization. A billing manager is a user who manages the billing settings for your organization and does not use a paid license in your organization's subscription. For more information on adding a billing manager to your organization, see "[Adding a billing manager to your organization](/organizations/managing-peoples-access-to-your-organization-with-roles/adding-a-billing-manager-to-your-organization)."
### Setting up an enterprise account with {% data variables.product.prodname_ghe_cloud %}
{% note %}
To get an enterprise account created for you, contact [{% data variables.product.prodname_dotcom %}'s Sales team](https://enterprise.github.com/contact).
{% endnote %}
#### 1. About enterprise accounts
An enterprise account allows you to centrally manage policy and settings for multiple {% data variables.product.prodname_dotcom %} organizations, including member access, billing and usage and security. For more information, see "[About enterprise accounts](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-account/about-enterprise-accounts)."
#### 2. Adding organizations to your enterprise account
You can create new organizations to manage within your enterprise account. For more information, see "[Adding organizations to your enterprise](/github/setting-up-and-managing-your-enterprise/managing-organizations-in-your-enterprise-account/adding-organizations-to-your-enterprise-account)."
Contact your {% data variables.product.prodname_dotcom %} sales account representative if you want to transfer an existing organization to your enterprise account.
#### 3. Viewing the subscription and usage for your enterprise account
You can view your current subscription, license usage, invoices, payment history, and other billing information for your enterprise account at any time. Both enterprise owners and billing managers can access and manage billing settings for enterprise accounts. For more information, see "[Viewing the subscription and usage for your enterprise account](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-account/viewing-the-subscription-and-usage-for-your-enterprise-account)."
## Part 3: Managing your organization or enterprise members and teams with {% data variables.product.prodname_ghe_cloud %}
### Managing members and teams in your organization
You can set permissions and member roles, create and manage teams, and give people access to repositories in your organization.
#### 1. Managing members of your organization
{% data reusables.getting-started.managing-org-members %}
#### 2. Organization permissions and roles
{% data reusables.getting-started.org-permissions-and-roles %}
#### 3. About and creating teams
{% data reusables.getting-started.about-and-creating-teams %}
#### 4. Managing team settings
{% data reusables.getting-started.managing-team-settings %}
#### 5. Giving people and teams access to repositories, project boards and apps
{% data reusables.getting-started.giving-access-to-repositories-projects-apps %}
### Managing members of an enterprise account
Managing members of an enterprise is separate from managing members or teams in an organization. It is important to note that enterprise owners or administrators cannot access organization-level settings or manage members for organizations in their enterprise unless they are made an organization owner. For more information, see the above section, "[Managing members and teams in your organization](#managing-members-and-teams-in-your-organization)."
#### 1. Assigning roles in an enterprise
By default, everyone in an enterprise is a member of the enterprise. There are also administrative roles, including enterprise owner and billing manager, that have different levels of access to enterprise settings and data. For more information, see "[Roles in an enterprise](/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/roles-in-an-enterprise)."
#### 2. Inviting people to manage your enterprise
You can invite people to manage your enterprise as enterprise owners or billing managers, as well as remove those who no longer need access. For more information, see "[Inviting people to manage your enterprise](/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/inviting-people-to-manage-your-enterprise)."
You can also grant enterprise members the ability to manage support tickets in the support portal. For more information, see "[Managing support entitlements for your enterprise](/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/managing-support-entitlements-for-your-enterprise)."
#### 3. Viewing people in your enterprise
To audit access to enterprise-owned resources or user license usage, you can view every enterprise administrator, enterprise member, and outside collaborator in your enterprise. You can see the organizations that a member belongs to and the specific repositories that an outside collaborator has access to. For more information, see "[Viewing people in your enterprise](/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/viewing-people-in-your-enterprise)."
## Part 4: Managing security with {% data variables.product.prodname_ghe_cloud %}
### Managing security for a single organization
You can help keep your organization secure by requiring two-factor authentication, configuring security features, reviewing your organization's audit log and integrations, and enabling SAML single sign-on and team synchronization.
#### 1. Requiring two-factor authentication
{% data reusables.getting-started.requiring-2fa %}
#### 2. Configuring security features for your organization
{% data reusables.getting-started.configuring-security-features %}
#### 3. Reviewing your organization's audit log and integrations
{% data reusables.getting-started.reviewing-org-audit-log-and-integrations %}
#### 4. Enabling and enforcing SAML single sign-on for your organization
If you manage your applications and the identities of your organization members with an identity provider (IdP), you can configure SAML single-sign-on (SSO) to control and secure access to organization resources like repositories, issues and pull requests. When members of your organization access organization resources that use SAML SSO, {% data variables.product.prodname_dotcom %} will redirect them to your IdP to authenticate. For more information, see "[About identity and access management with SAML single sign-on](/organizations/managing-saml-single-sign-on-for-your-organization/about-identity-and-access-management-with-saml-single-sign-on)."
Organization owners can choose to disable, enable but not enforce, or enable and enforce SAML SSO. For more information, see "[Enabling and testing SAML single sign-on for your organization](/organizations/managing-saml-single-sign-on-for-your-organization/enabling-and-testing-saml-single-sign-on-for-your-organization)" and "[Enforcing SAML single sign-on for your organization](/organizations/managing-saml-single-sign-on-for-your-organization/enforcing-saml-single-sign-on-for-your-organization)."
#### 5. Managing team synchronization for your organization
Organization owners can enable team synchronization between your identity provider (IdP) and {% data variables.product.prodname_dotcom %} to allow organization owners and team maintainers to connect teams in your organization with IdP groups. For more information, see "[Managing team synchronization for your organization](/organizations/managing-saml-single-sign-on-for-your-organization/managing-team-synchronization-for-your-organization)."
### Managing security for an enterprise account with multiple organizations
To manage security for your enterprise, you can require two-factor authentication, manage allowed IP addresses, enable SAML single sign-on and team synchronization at an enterprise level, and sign up for and enforce GitHub Advanced Security features.
#### 1. Requiring two-factor authentication and managing allowed IP addresses for organizations in your enterprise account
Enterprise owners can require that organization members, billing managers, and outside collaborators in all organizations owned by an enterprise account use two-factor authentication to secure their personal accounts. Before doing so, we recommend notifying all who have access to organizations in your enterprise. You can also configure an allow list for specific IP addresses to restrict access to assets owned by organizations in your enterprise account.
For more information on enforcing two-factor authentication and allowed IP address lists, see "[Enforcing security settings in your enterprise account](/github/setting-up-and-managing-your-enterprise/setting-policies-for-organizations-in-your-enterprise-account/enforcing-security-settings-in-your-enterprise-account#managing-allowed-ip-addresses-for-organizations-in-your-enterprise-account)."
#### 2. Enabling and enforcing SAML single sign-on for organizations in your enterprise account
You can centrally manage access to your enterprise's resources, organization membership and team membership using your IdP and SAM single sign-on (SSO). Enterprise owners can enable SAML SSO across all organizations owned by an enterprise account. For more information, see "[About identity and access management for your enterprise account](/github/setting-up-and-managing-your-enterprise/configuring-identity-and-access-management-for-your-enterprise-account/about-identity-and-access-management-for-your-enterprise-account)."
#### 3. Managing team synchronization
You can enable and manage team sychronization between an identity provider (IdP) and {% data variables.product.prodname_dotcom %} to allow organizations owned by your enterprise account to manage team membership with IdP groups. For more information, see "[Managing team synchronization for organizations in your enterprise account](/github/setting-up-and-managing-your-enterprise/configuring-identity-and-access-management-for-your-enterprise-account/managing-team-synchronization-for-organizations-in-your-enterprise-account)."
#### 4. Enforcing policies for Advanced Security features in your enterprise account
If you have a GitHub Advanced Security license for your enterprise account, you can enforce policies to manage {% data variables.product.prodname_dotcom %} Advanced Security features for organizations owned by an enterprise account. For more information, see "[Enforcing policies for Advanced Security in your enterprise account](/github/setting-up-and-managing-your-enterprise/setting-policies-for-organizations-in-your-enterprise-account/enforcing-policies-for-advanced-security-in-your-enterprise-account)."
## Part 5: Managing organization and enterprise level policies and settings
### Managing settings for a single organization
To manage and moderate your organization, you can set organization policies, manage permissions for repository changes, and use organization-level community health files.
#### 1. Managing organization policies
{% data reusables.getting-started.managing-org-policies %}
#### 2. Managing repository changes
{% data reusables.getting-started.managing-repo-changes %}
#### 3. Using organization-level community health files and moderation tools
{% data reusables.getting-started.using-org-community-files-and-moderation-tools %}
### Managing settings for an enterprise account
To manage and moderate your enterprise, you can set policies for organizations within the enterprise, view audit logs, configure webhooks, and restrict email notifications.
#### 1. Managing policies for organizations in your enterprise account
You can choose to enforce a number of policies for all organizations owned by your enterprise, or choose to allow these policies to be set in each organization. Types of policies you can enforce include repository management, project board, and team policies. For more information, see "[Set organization policies](/github/setting-up-and-managing-your-enterprise/setting-policies-for-organizations-in-your-enterprise-account)."
#### 2. Viewing audit logs, configuring webhooks, and restricting email notifications for your enterprise
You can view actions from all of the organizations owned by your enterprise account in the enterprise audit log. You can also configure webhooks to receive events from organizations owned by your enterprise account. For more information, see "[Viewing the audit logs for organizations in your enterprise account](/github/setting-up-and-managing-your-enterprise/managing-organizations-in-your-enterprise-account/viewing-the-audit-logs-for-organizations-in-your-enterprise-account)" and "[Configuring webooks for organization events in your enterprise](/github/setting-up-and-managing-your-enterprise/managing-organizations-in-your-enterprise-account/configuring-webhooks-for-organization-events-in-your-enterprise-account)."
You can also restrict email notifications for your enterprise account so that enterprise members can only use an email address in a verified or approved domain to receive notifications. For more information, see "[Restricting email notifications for your enterprise account](/github/setting-up-and-managing-your-enterprise/setting-policies-for-organizations-in-your-enterprise-account/restricting-email-notifications-for-your-enterprise-account)."
## Part 6: Customizing and automating your organization or enterprise's work on {% data variables.product.prodname_dotcom %}
Members of your organization or enterprise can use tools from the {% data variables.product.prodname_marketplace %}, the {% data variables.product.product_name %} API, and existing {% data variables.product.product_name %} features to customize and automate your work.
### 1. Using {% data variables.product.prodname_marketplace %}
{% data reusables.getting-started.marketplace %}
### 2. Using the {% data variables.product.prodname_dotcom %} API
{% data reusables.getting-started.api %}
### 3. Building {% data variables.product.prodname_actions %}
{% data reusables.getting-started.actions %}
### 4. Publishing and managing {% data variables.product.prodname_registry %}
{% data reusables.getting-started.packages %}
### 5. Using {% data variables.product.prodname_pages %}
{% data variables.product.prodname_pages %} is a static site hosting service that takes HTML, CSS, and JavaScript files straight from a repository and publishes a website. You can manage the publication of {% data variables.product.prodname_pages %} sites at the organization level. For more information, see "[Managing the publication of {% data variables.product.prodname_pages %} sites for your organization](/organizations/managing-organization-settings/managing-the-publication-of-github-pages-sites-for-your-organization)" and "[About {% data variables.product.prodname_pages %}](/pages/getting-started-with-github-pages/about-github-pages)."
## Part 7: Participating in {% data variables.product.prodname_dotcom %}'s community
Members of your organization or enterprise can use GitHub's learning and support resources to get the help they need. You can also support the open source community.
### 1. Learning with {% data variables.product.prodname_learning %}
Members of your organization or enterprise can learn new skills by completing fun, realistic projects in your very own GitHub repository with [{% data variables.product.prodname_learning %}](https://lab.github.com/). Each course is a hands-on lesson created by the GitHub community and taught by the friendly Learning Lab bot.
For more information, see "[Git and {% data variables.product.prodname_dotcom %} learning resources](/github/getting-started-with-github/quickstart/git-and-github-learning-resources)."
### 2. Supporting the open source community
{% data reusables.getting-started.sponsors %}
### 3. Contacting {% data variables.contact.github_support %}
{% data reusables.getting-started.contact-support %}
{% data variables.product.prodname_ghe_cloud %} allows you to submit priority support requests with a target eight-hour response time. For more information, see "[{% data variables.product.prodname_ghe_cloud %} support](/github/working-with-github-support/github-enterprise-cloud-support)."

View File

@@ -0,0 +1,114 @@
---
title: Getting started with GitHub Enterprise Server
intro: 'Get started with setting up and managing {% data variables.product.product_location %}.'
versions:
ghes: '*'
---
This guide will walk you through setting up, configuring and managing {% data variables.product.product_location %} as an enterprise administrator.
{% data variables.product.company_short %} provides two ways to deploy {% data variables.product.prodname_enterprise %}.
- **{% data variables.product.prodname_ghe_cloud %}**
- **{% data variables.product.prodname_ghe_server %}**
{% data variables.product.company_short %} hosts {% data variables.product.prodname_ghe_cloud %}. You can deploy and host {% data variables.product.prodname_ghe_server %} in your own datacenter or a supported cloud provider.
For an overview of how {% data variables.product.product_name %} works, see "[System overview](/admin/overview/system-overview)."
## Part 1: Installing {% data variables.product.product_name %}
To get started with {% data variables.product.product_name %}, you will need to create your enterprise account, install the instance, use the Management Console for initial setup, configure your instance, and manage billing.
### 1. Creating your enterprise account
Before you install {% data variables.product.product_name %}, you can create an enterprise account on {% data variables.product.prodname_dotcom_the_website %} by contacting [{% data variables.product.prodname_dotcom %}'s Sales team](https://enterprise.github.com/contact). An enterprise account on {% data variables.product.prodname_dotcom_the_website %} is useful for billing and for shared features with {% data variables.product.prodname_dotcom_the_website %} via {% data variables.product.prodname_github_connect %}. For more information, see "[About enterprise accounts](/admin/overview/about-enterprise-accounts)."
### 2. Installing {% data variables.product.product_name %}
To get started with {% data variables.product.product_name %}, you will need to install the appliance on a virtualization platform of your choice. For more information, see "[Setting up a {% data variables.product.prodname_ghe_server %} instance](/admin/installation/setting-up-a-github-enterprise-server-instance)."
### 3. Using the Management Console
You will use the Management Console to walk through the initial setup process when first launching {% data variables.product.product_location %}. You can also use the Management Console to manage instance settings such as the license, domain, authentication, and TLS. For more information, see "[Accessing the management console](/admin/configuration/configuring-your-enterprise/accessing-the-management-console)."
### 4. Configuring {% data variables.product.product_location %}
In addition to the Management Console, you can use the site admin dashboard and the administrative shell (SSH) to manage {% data variables.product.product_location %}. For example, you can configure applications and rate limits, view reports, use command-line utilities. For more information, see "[Configuring your enterprise](/admin/configuration/configuring-your-enterprise)."
You can use the default network settings used by {% data variables.product.product_name %} via the dynamic host configuration protocol (DHCP), or you can also configure the network settings using the virtual machine console. You can also configure a proxy server or firewall rules. For more information, see "[Configuring network settings](/admin/configuration/configuring-network-settings)."
### 5. Configuring high availability
You can configure {% data variables.product.product_location %} for high availability to minimize the impact of hardware failures and network outages. For more information, see "[Configuring high availability](/admin/enterprise-management/configuring-high-availability)."
### 6. Setting up a staging instance
You can set up a staging instance to test modifications, plan for disaster recovery, and try out updates before applying them to {% data variables.product.product_location %}. For more information, see "[Setting up a staging instance](/admin/installation/setting-up-a-github-enterprise-server-instance/setting-up-a-staging-instance)."
### 7. Designating backups and disaster recovery
To protect your production data, you can configure automated backups of {% data variables.product.product_location %} with {% data variables.product.prodname_enterprise_backup_utilities %}. For more information, see "[Configuring backups on your appliance](/admin/configuration/configuring-your-enterprise/configuring-backups-on-your-appliance)."
### 8. Managing billing for your enterprise
Billing for all the organizations and {% data variables.product.product_name %} instances connected to your enterprise account is aggregated into a single bill charge for all of your paid {% data variables.product.prodname_dotcom %}.com services. Enterprise owners and billing managers can access and manage billing settings for enterprise accounts. For more information, see "[Managing billing for your enterprise](/admin/overview/managing-billing-for-your-enterprise)."
## Part 2: Organizing and managing your team
As an enterprise owner or administrator, you can manage settings on user, repository, team and organization levels. You can manage members of your enterprise, create and manage organizations, set policies for repository management, and create and manage teams.
### 1. Managing members of {% data variables.product.product_location %}
{% data reusables.getting-started.managing-enterprise-members %}
### 2. Creating organizations
{% data reusables.getting-started.creating-organizations %}
### 3. Adding members to organizations
{% data reusables.getting-started.adding-members-to-organizations %}
### 4. Creating teams
{% data reusables.getting-started.creating-teams %}
### 5. Setting organization and repository permission levels
{% data reusables.getting-started.setting-org-and-repo-permissions %}
### 6. Enforcing repository management policies
{% data reusables.getting-started.enforcing-repo-management-policies %}
## Part 3: Building securely
To increase the security of {% data variables.product.product_location %}, you can configure authentication for enterprise members, use tools and audit logging to stay in compliance, configure security and analysis features for your organizations, and optionally enable {% data variables.product.prodname_GH_advanced_security %}.
### 1. Authenticating enterprise members
You can use {% data variables.product.product_name %}'s built-in authentication method, or you can choose between an established authentication provider, such as CAS, LDAP, or SAML, to integrate your existing accounts and centrally manage user access to {% data variables.product.product_location %}. For more information, see "[Authenticating users for {% data variables.product.product_location %}](/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance)."
You can also require two-factor authentication for each of your organizations. For more information, see "[Requiring two factor authentication for an organization](/admin/user-management/managing-organizations-in-your-enterprise/requiring-two-factor-authentication-for-an-organization)."
### 2. Staying in compliance
You can implement required status checks and commit verifications to enforce your organization's compliance standards and automate compliance workflows. You can also use the audit log for your organization to review actions performed by your team. For more information, see "[Enforcing policy with pre-receive hooks](/admin/policies/enforcing-policy-with-pre-receive-hooks)" and "[Audit logging](/admin/user-management/monitoring-activity-in-your-enterprise/audit-logging)."
### 3. Configuring security features for your organizations
{% data reusables.getting-started.configuring-security-features %}
### 4. Enabling {% data variables.product.prodname_GH_advanced_security %} features
You can upgrade your {% data variables.product.product_name %} license to include {% data variables.product.prodname_GH_advanced_security %}. This provides extra features that help users find and fix security problems in their code, such as code and secret scanning. For more information, see "[{% data variables.product.prodname_GH_advanced_security %} for your enterprise](/admin/advanced-security/enabling-github-advanced-security-for-your-enterprise)."
## Part 4: Customizing and automating your enterprise's work on {% data variables.product.prodname_dotcom %}
You can customize and automate work in organizations in your enterprise with {% data variables.product.prodname_dotcom %} and {% data variables.product.prodname_oauth_apps %}, {% data variables.product.prodname_dotcom %} API, {% data variables.product.prodname_actions %}, {% data variables.product.prodname_registry %} , and {% data variables.product.prodname_pages %}.
### 1. Building {% data variables.product.prodname_github_apps %} and {% data variables.product.prodname_oauth_apps %}
You can build integrations with the {% data variables.product.prodname_dotcom %} API, such as {% data variables.product.prodname_github_apps %} or {% data variables.product.prodname_oauth_apps %}, for use in organizations in your enterprise to complement and extend your workflows. For more information, see "[About apps](/developers/apps/getting-started-with-apps/about-apps)."
### 2. Using the {% data variables.product.prodname_dotcom %} API
{% data reusables.getting-started.api %}
### 3. Building {% data variables.product.prodname_actions %}
{% data reusables.getting-started.actions %}
For more information on enabling and configuring {% data variables.product.prodname_actions %} on {% data variables.product.product_name %}, see "[Getting started with {% data variables.product.prodname_actions %} for {% data variables.product.prodname_ghe_server %}](/admin/github-actions/enabling-github-actions-for-github-enterprise-server/getting-started-with-github-actions-for-github-enterprise-server)."
### 4. Publishing and managing {% data variables.product.prodname_registry %}
{% data reusables.getting-started.packages %}
For more information on enabling and configuring {% data variables.product.prodname_registry %} for {% data variables.product.product_location %}, see "[Getting started with {% data variables.product.prodname_registry %} for your enterprise](/admin/packages/getting-started-with-github-packages-for-your-enterprise)."
### 5. Using {% data variables.product.prodname_pages %}
{% data reusables.getting-started.github-pages-enterprise %}
## Part 5: Connecting with other {% data variables.product.prodname_dotcom %} resources
You can use {% data variables.product.prodname_github_connect %} and {% data variables.product.prodname_insights %} to share resources and understand and improve your processes.
### 1. Enabling {% data variables.product.prodname_github_connect %}
If you are the owner of both a {% data variables.product.product_name %} instance and a {% data variables.product.prodname_ghe_cloud %} organization or enterprise account, you can enable {% data variables.product.prodname_github_connect %}. {% data variables.product.prodname_github_connect %} allows you to share specific workflows and features between {% data variables.product.product_location %} and {% data variables.product.prodname_ghe_cloud %}, such as unified search and contributions. For more information, see "[Connecting {% data variables.product.prodname_ghe_server %} to {% data variables.product.prodname_ghe_cloud %}](/admin/configuration/managing-connections-between-github-enterprise-server-and-github-enterprise-cloud/connecting-github-enterprise-server-to-github-enterprise-cloud)."
### 2. Using {% data variables.product.prodname_insights %}
{% data variables.product.prodname_insights %} is a standalone application that provides analytic reports and metrics based on data from {% data variables.product.product_location %}. You can use these reports to understand and improve your software delivery process. For more information, see "[About {% data variables.product.prodname_insights %}](/insights/installing-and-configuring-github-insights/installing-and-updating-github-insights/about-github-insights)."
## Part 6: Using {% data variables.product.prodname_dotcom %}'s learning and support resources
Your enterprise members can learn more about Git and {% data variables.product.prodname_dotcom %} with our learning resources, and you can get the support you need when setting up and managing {% data variables.product.product_location %} with {% data variables.product.prodname_dotcom %} Enterprise Support.
### 1. Learning with {% data variables.product.prodname_learning %}
{% data reusables.getting-started.learning-lab-enterprise %}
### 2. Working with {% data variables.product.prodname_dotcom %} Enterprise Support
{% data reusables.getting-started.contact-support-enterprise %}

View File

@@ -0,0 +1,96 @@
---
title: Getting started with GitHub Team
intro: 'With {% data variables.product.prodname_team %} groups of people can collaborate across many projects at the same time in an organization account.'
versions:
fpt: '*'
---
This guide will walk you through setting up, configuring and managing your {% data variables.product.prodname_team %} account as an organization owner.
## Part 1: Configuring your {% data variables.product.product_name %} account
As the first steps in starting with {% data variables.product.prodname_team %}, you will need to create a user account or log into your existing account on {% data variables.product.prodname_dotcom %}, create an organization, and set up billing.
### 1. About organizations
Organizations are shared accounts where businesses and open-source projects can collaborate across many projects at once. Owners and administrators can manage member access to the organization's data and projects with sophisticated security and administrative features. For more information on the features of organizations, see "[About organizations](/organizations/collaborating-with-groups-in-organizations/about-organizations#terms-of-service-and-data-protection-for-organizations)."
### 2. Creating an organization and signing up for {% data variables.product.prodname_team %}
Before creating an organization, you will need to create a user account or log in to your existing {% data variables.product.prodname_dotcom %} account. For more information, see "[Signing up for a new {% data variables.product.prodname_dotcom %} account](/get-started/signing-up-for-github/signing-up-for-a-new-github-account)."
Once your user account is set up, you can create an organization and pick a plan. This is where you can choose a {% data variables.product.prodname_team %} subscription for your organization. For more information, see "[Creating a new organization from scratch](/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch)."
### 3. Managing billing for an organization
You must manage billing settings, payment method, and paid features and products for each of your personal accounts and organizations separately. You can switch between settings for your different accounts using the context switcher in your settings. For more information, see "[Switching between settings for your different accounts](/billing/managing-your-github-billing-settings/about-billing-on-github#switching-between-settings-for-your-different-accounts)."
Your organization's billing settings page allows you to manage settings like your payment method, billing cycle and billing email, or view information such as your subscription, billing date and payment history. You can also view and upgrade your storage and GitHub Actions minutes. For more information on managing your billing settings, see "[Managing your {% data variables.product.prodname_dotcom %} billing settings](/billing/managing-your-github-billing-settings)."
Only organization members with the *owner* or *billing manager* role can access or change billing settings for your organization. A billing manager is someone who manages the billing settings for your organization and does not use a paid license in your organization's subscription. For more information on adding a billing manager to your organization, see "[Adding a billing manager to your organization](/organizations/managing-peoples-access-to-your-organization-with-roles/adding-a-billing-manager-to-your-organization)."
## Part 2: Adding members and setting up teams
After creating your organization, you can invite members and set permissions and roles. You can also create different levels of teams and set customized levels of permissions for your organization's repositories, project boards, and apps.
### 1. Managing members of your organization
{% data reusables.getting-started.managing-org-members %}
### 2. Organization permissions and roles
{% data reusables.getting-started.org-permissions-and-roles %}
### 3. About and creating teams
{% data reusables.getting-started.about-and-creating-teams %}
### 4. Managing team settings
{% data reusables.getting-started.managing-team-settings %}
### 5. Giving people and teams access to repositories, project boards and apps
{% data reusables.getting-started.giving-access-to-repositories-projects-apps %}
## Part 3: Managing security for your organization
You can help to make your organization more secure by recommending or requiring two-factor authentication for your organization members, configuring security features, and reviewing your organization's audit log and integrations.
### 1. Requiring two-factor authentication
{% data reusables.getting-started.requiring-2fa %}
### 2. Configuring security features for your organization
{% data reusables.getting-started.configuring-security-features %}
### 3. Reviewing your organization's audit log and integrations
{% data reusables.getting-started.reviewing-org-audit-log-and-integrations %}
## Part 4: Setting organization level policies
### 1. Managing organization policies
{% data reusables.getting-started.managing-org-policies %}
### 2. Managing repository changes
{% data reusables.getting-started.managing-repo-changes %}
### 3. Using organization-level community health files and moderation tools
{% data reusables.getting-started.using-org-community-files-and-moderation-tools %}
## Part 5: Customizing and automating your work on {% data variables.product.product_name %}
{% data reusables.getting-started.customizing-and-automating %}
### 1. Using {% data variables.product.prodname_marketplace %}
{% data reusables.getting-started.marketplace %}
### 2. Using the {% data variables.product.prodname_dotcom %} API
{% data reusables.getting-started.api %}
### 3. Building {% data variables.product.prodname_actions %}
{% data reusables.getting-started.actions %}
### 4. Publishing and managing {% data variables.product.prodname_registry %}
{% data reusables.getting-started.packages %}
## Part 6: Participating in {% data variables.product.prodname_dotcom %}'s community
{% data reusables.getting-started.participating-in-community %}
### 1. Contributing to open source projects
{% data reusables.getting-started.open-source-projects %}
### 2. Interacting with the {% data variables.product.prodname_gcf %}
{% data reusables.support.ask-and-answer-forum %}
### 3. Learning with {% data variables.product.prodname_learning %}
{% data reusables.getting-started.learning-lab %}
### 4. Supporting the open source community
{% data reusables.getting-started.sponsors %}
### 5. Contacting {% data variables.contact.github_support %}
{% data reusables.getting-started.contact-support %}
## Further reading
- "[Getting started with your GitHub account](/get-started/onboarding/getting-started-with-your-github-account)"

View File

@@ -0,0 +1,194 @@
---
title: Getting started with your GitHub account
intro: 'With a user account on {% data variables.product.prodname_dotcom %}, you can import or create repositories, collaborate with others, and connect with the {% data variables.product.prodname_dotcom %} community.'
versions:
fpt: '*'
ghes: '*'
ghae: '*'
---
This guide will walk you through setting up your {% data variables.product.prodname_dotcom %} account and getting started with {% data variables.product.prodname_dotcom %}'s features for collaboration and community.
## Part 1: Configuring your {% data variables.product.prodname_dotcom %} account
{% ifversion fpt %}
The first steps in starting with {% data variables.product.product_name %} are to create an account, choose a product that fits your needs best, verify your email, set up two-factor authentication, and view your profile.
{% elsif ghes %}
The first steps in starting with {% data variables.product.product_name %} are to access your account, set up two-factor authentication, and view your profile.
{% elsif ghae %}
The first steps in starting with {% data variables.product.product_name %} are to access your account and view your profile.
{% endif %}
{% ifversion fpt %}There are several types of accounts on {% data variables.product.prodname_dotcom %}. {% endif %} Every person who uses {% data variables.product.product_name %} has their own user account, which can be part of multiple organizations and teams. Your user account is your identity on {% data variables.product.product_location %} and represents you as an individual.
{% ifversion fpt %}
### 1. Creating an account
To sign up for a {% data variables.product.prodname_dotcom %} account, navigate to https://github.com/ and follow the prompts.
To keep your {% data variables.product.prodname_dotcom %} account secure you should use a strong and unique password. For more information, see "[Creating a strong password](/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-strong-password)."
### 2. Choosing your {% data variables.product.prodname_dotcom %} product
You can choose {% data variables.product.prodname_free_user %} or {% data variables.product.prodname_pro %} to get access to different features for your personal account. You can upgrade at any time if you are unsure at first which product you want.
For more information on all of {% data variables.product.prodname_dotcom %}'s plans, see "[{% data variables.product.prodname_dotcom %}'s products](/get-started/learning-about-github/githubs-products)."
### 3. Verifying your email address
To ensure you can use all the features in your {% data variables.product.product_name %} plan, verify your email address after signing up for a new account. For more information, see "[Verifying your email address](/github/getting-started-with-github/signing-up-for-github/verifying-your-email-address)."
{% endif %}
{% ifversion ghes %}
### 1. Accessing your account
The administrator of your {% data variables.product.product_name %} instance will notify you about how to authenticate and access your account. The process varies depending on the authentication mode they have configured for the instance.
{% endif %}
{% ifversion ghae %}
### 1. Accessing your account
You will receive an email notification once your enterprise owner for {% data variables.product.product_name %} has set up your account, allowing you to authenticate with SAML single sign-on (SSO) and access your account.
{% endif %}
{% ifversion fpt or ghes %}
### {% ifversion fpt %}4.{% else %}2.{% endif %} Configuring two-factor authentication
Two-factor authentication, or 2FA, is an extra layer of security used when logging into websites or apps. We strongly urge you to configure 2FA for the safety of your account. For more information, see "[About two-factor authentication](/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa/about-two-factor-authentication)."
{% endif %}
### {% ifversion fpt %}5.{% elsif ghes %}3.{% else %}2.{% endif %} Viewing your {% data variables.product.product_name %} profile and contribution graph
Your {% data variables.product.product_name %} profile tells people the story of your work through the repositories and gists you've pinned, the organization memberships you've chosen to publicize, the contributions you've made, and the projects you've created. For more information, see "[About your profile](/github/setting-up-and-managing-your-github-profile/customizing-your-profile/about-your-profile)" and "[Viewing contributions on your profile](/github/setting-up-and-managing-your-github-profile/managing-contribution-graphs-on-your-profile/viewing-contributions-on-your-profile)."
## Part 2: Using {% data variables.product.product_name %}'s tools and processes
To best use {% data variables.product.product_name %}, you'll need to set up Git. Git is responsible for everything {% data variables.product.prodname_dotcom %}-related that happens locally on your computer. To effectively collaborate on {% data variables.product.product_name %}, you'll write in issues and pull requests using {% data variables.product.prodname_dotcom %} Flavored Markdown.
### 1. Learning Git
{% data variables.product.prodname_dotcom %}'s collaborative approach to development depends on publishing commits from your local repository to {% data variables.product.product_name %} for other people to view, fetch, and update using Git. For more information about Git, see the "[Git Handbook](https://guides.github.com/introduction/git-handbook/)" guide. For more information about how Git is used on {% data variables.product.product_name %}, see "[{% data variables.product.prodname_dotcom %} flow](/get-started/quickstart/github-flow)."
### 2. Setting up Git
If you plan to use Git locally on your computer, whether through the command line, an IDE or text editor, you will need to install and set up Git. For more information, see "[Set up Git](/get-started/quickstart/set-up-git)."
If you prefer to use a visual interface, you can download and use {% data variables.product.prodname_desktop %}. {% data variables.product.prodname_desktop %} comes packaged with Git, so there is no need to install Git separately. For more information, see "[Getting started with {% data variables.product.prodname_desktop %}](/desktop/installing-and-configuring-github-desktop/overview/getting-started-with-github-desktop)."
Once you install Git, you can connect to {% data variables.product.product_name %} repositories from your local computer, whether your own repository or another user's fork. When you connect to a {% data variables.product.product_name %} repository from Git, you'll need to authenticate with {% data variables.product.product_name %} using either HTTPS or SSH. For more information, see "[About remote repositories](/get-started/getting-started-with-git/about-remote-repositories)."
### 3. Choosing how to interact with {% data variables.product.product_name %}
Everyone has their own unique workflow for interacting with {% data variables.product.prodname_dotcom %}; the interfaces and methods you use depend on your preference and what works best for your needs.
For more information about how to authenticate to {% data variables.product.product_name %} with each of these methods, see "[About authentication to {% data variables.product.prodname_dotcom %}](/github/authenticating-to-github/keeping-your-account-and-data-secure/about-authentication-to-github)."
| **Method** | **Description** | **Use cases** |
| ------------- | ------------- | ------------- |
| Browse to {% data variables.product.prodname_dotcom_the_website %} | If you don't need to work with files locally, {% data variables.product.product_name %} lets you complete most Git-related actions directly in the browser, from creating and forking repositories to editing files and opening pull requests.| This method is useful if you want a visual interface and need to do quick, simple changes that don't require working locally. |
| {% data variables.product.prodname_desktop %} | {% data variables.product.prodname_desktop %} extends and simplifies your {% data variables.product.prodname_dotcom_the_website %} workflow, using a visual interface instead of text commands on the command line. For more information on getting started with {% data variables.product.prodname_desktop %}, see "[Getting started with {% data variables.product.prodname_desktop %}](/desktop/installing-and-configuring-github-desktop/overview/getting-started-with-github-desktop)." | This method is best if you need or want to work with files locally, but prefer using a visual interface to use Git and interact with {% data variables.product.product_name %}. |
| IDE or text editor | You can set a default text editor, like [Atom](https://atom.io/) or [Visual Studio Code](https://code.visualstudio.com/) to open and edit your files with Git, use extensions, and view the project structure. For more information, see "[Associating text editors with Git](/github/using-git/associating-text-editors-with-git)." | This is convenient if you are working with more complex files and projects and want everything in one place, since text editors or IDEs often allow you to directly access the command line in the editor. |
| Command line, with or without {% data variables.product.prodname_cli %} | For the most granular control and customization of how you use Git and interact with {% data variables.product.product_name %}, you can use the command line. For more information on using Git commands, see "[Git cheatsheet](/github/getting-started-with-github/quickstart/git-cheatsheet)."<br/><br/> {% data variables.product.prodname_cli %} is a separate command-line tool you can install that brings pull requests, issues, {% data variables.product.prodname_actions %}, and other {% data variables.product.prodname_dotcom %} features to your terminal, so you can do all your work in one place. For more information, see "[{% data variables.product.prodname_cli %}](/github/getting-started-with-github/using-github/github-cli)." | This is most convenient if you are already working from the command line, allowing you to avoid switching context, or if you are more comfortable using the command line. |
| {% data variables.product.prodname_dotcom %} API | {% data variables.product.prodname_dotcom %} has a REST API and GraphQL API that you can use to interact with {% data variables.product.product_name %}. For more information, see "[Getting started with the API](/github/extending-github/getting-started-with-the-api)." | The {% data variables.product.prodname_dotcom %} API would be most helpful if you wanted to automate common tasks, back up your data, or create integrations that extend {% data variables.product.prodname_dotcom %}. |
### 4. Writing on {% data variables.product.product_name %}
To make your communication clear and organized in issues and pull requests, you can use {% data variables.product.prodname_dotcom %} Flavored Markdown for formatting, which combines an easy-to-read, easy-to-write syntax with some custom functionality. For more information, see "[About writing and formatting on {% data variables.product.prodname_dotcom %}](/github/writing-on-github/about-writing-and-formatting-on-github)."
You can learn {% data variables.product.prodname_dotcom %} Flavored Markdown with the "[Communicating using Markdown](https://lab.github.com/githubtraining/communicating-using-markdown)" course on {% data variables.product.prodname_learning %}.
### 5. Searching on {% data variables.product.product_name %}
Our integrated search allows you to find what you are looking for among the many repositories, users and lines of code on {% data variables.product.product_name %}. You can search globally across all of {% data variables.product.product_name %} or limit your search to a particular repository or organization. For more information about the types of searches you can do on {% data variables.product.product_name %}, see "[About searching on {% data variables.product.prodname_dotcom %}](/github/searching-for-information-on-github/getting-started-with-searching-on-github/about-searching-on-github)."
Our search syntax allows you to construct queries using qualifiers to specify what you want to search for. For more information on the search syntax to use in search, see "[Searching on {% data variables.product.prodname_dotcom %}](/github/searching-for-information-on-github/searching-on-github)."
### 6. Managing files on {% data variables.product.product_name %}
With {% data variables.product.product_name %}, you can create, edit, move and delete files in your repository or any repository you have write access to. You can also track the history of changes in a file line by line. For more information, see "[Managing files on {% data variables.product.prodname_dotcom %}](/github/managing-files-in-a-repository/managing-files-on-github)."
## Part 3: Collaborating on {% data variables.product.product_name %}
Any number of people can work together in repositories across {% data variables.product.product_name %}. You can configure settings, create project boards, and manage your notifications to encourage effective collaboration.
### 1. Working with repositories
#### Creating a repository
A repository is like a folder for your project. You can have any number of public and private repositories in your user account. Repositories can contain folders and files, images, videos, spreadsheets, and data sets, as well as the revision history for all files in the repository. For more information, see "[About repositories](/github/creating-cloning-and-archiving-repositories/about-repositories)."
When you create a new repository, you should initialize the repository with a README file to let people know about your project. For more information, see "[Creating a new repository](/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/creating-a-new-repository)."
#### Cloning a repository
You can clone an existing repository from {% data variables.product.product_name %} to your local computer, making it easier to add or remove files, fix merge conflicts, or make complex commits. Cloning a repository pulls down a full copy of all the repository data that {% data variables.product.prodname_dotcom %} has at that point in time, including all versions of every file and folder for the project. For more information, see "[Cloning a repository](/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github/cloning-a-repository)."
#### Forking a repository
A fork is a copy of a repository that you manage, where any changes you make will not affect the original repository unless you submit a pull request to the project owner. Most commonly, forks are used to either propose changes to someone else's project or to use someone else's project as a starting point for your own idea. For more information, see "[Working with forks](/github/collaborating-with-pull-requests/working-with-forks)."
### 2. Importing your projects
If you have existing projects you'd like to move over to {% data variables.product.product_name %} you can import projects using the {% data variables.product.prodname_dotcom %} Importer, the command line, or external migration tools. For more information, see "[Importing source code to {% data variables.product.prodname_dotcom %}](/github/importing-your-projects-to-github/importing-source-code-to-github)."
### 3. Managing collaborators and permissions
You can collaborate on your project with others using your repository's issues, pull requests, and project boards. You can invite other people to your repository as collaborators from the **Collaborators** tab in the repository settings. For more information, see "[Inviting collaborators to a personal repository](/github/setting-up-and-managing-your-github-user-account/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository)."
You are the owner of any repository you create in your user account and have full control of the repository. Collaborators have write access to your repository, limiting what they have permission to do. For more information, see "[Permission levels for a user account repository](/github/setting-up-and-managing-your-github-user-account/managing-user-account-settings/permission-levels-for-a-user-account-repository)."
### 4. Managing repository settings
As the owner of a repository you can configure several settings, including the repository's visibility, topics, and social media preview. For more information, see "[Managing repository settings](/github/administering-a-repository/managing-repository-settings)."
### 5. Setting up your project for healthy contributions
{% ifversion fpt %}
To encourage collaborators in your repository, you need a community that encourages people to use, contribute to, and evangelize your project. For more information, see "[Building Welcoming Communities](https://opensource.guide/building-community/)" in the Open Source Guides.
By adding files like contributing guidelines, a code of conduct, and a license to your repository you can create an environment where it's easier for collaborators to make meaningful, useful contributions. For more information, see "[Setting up your project for healthy contributions](/communities/setting-up-your-project-for-healthy-contributions)."
{% endif %}
{% ifversion ghes or ghae %}
By adding files like contributing guidelines, a code of conduct, and support resources to your repository you can create an environment where it's easier for collaborators to make meaningful, useful contributions. For more information, see "[Setting up your project for healthy contributions](/communities/setting-up-your-project-for-healthy-contributions)."
{% endif %}
### 6. Using GitHub Issues and project boards
You can use GitHub Issues to organize your work with issues and pull requests and manage your workflow with project boards. For more information, see "[About issues](/issues/tracking-your-work-with-issues/about-issues)" and "[About project boards](/issues/organizing-your-work-with-project-boards/managing-project-boards/about-project-boards)."
### 7. Managing notifications
Notifications provide updates about the activity on {% data variables.product.product_name %} you've subscribed to or participated in. If you're no longer interested in a conversation, you can unsubscribe, unwatch, or customize the types of notifications you'll receive in the future. For more information, see "[About notifications](/github/managing-subscriptions-and-notifications-on-github/setting-up-notifications/about-notifications)."
### 8. Working with {% data variables.product.prodname_pages %}
You can use {% data variables.product.prodname_pages %} to create and host a website directly from a {% data variables.product.product_name %} repository. For more information, see "[About {% data variables.product.prodname_pages %}](/pages/getting-started-with-github-pages/about-github-pages)."
{% ifversion fpt %}
### 9. Using {% data variables.product.prodname_discussions %}
You can enable {% data variables.product.prodname_discussions %} for your repository to help build a community around your project. Maintainers, contributors and visitors can use discussions to share announcements, ask and answer questions, and participate in conversations around goals. For more information, see "[About discussions](/discussions/collaborating-with-your-community-using-discussions/about-discussions)."
{% endif %}
## Part 4: Customizing and automating your work on {% data variables.product.product_name %}
{% data reusables.getting-started.customizing-and-automating %}
{% ifversion fpt %}
### 1. Using {% data variables.product.prodname_marketplace %}
{% data reusables.getting-started.marketplace %}
{% endif %}
### {% ifversion fpt %}2.{% else %}1.{% endif %} Using the {% data variables.product.prodname_dotcom %} API
{% data reusables.getting-started.api %}
### {% ifversion fpt %}3.{% else %}2.{% endif %} Building {% data variables.product.prodname_actions %}
{% data reusables.getting-started.actions %}
### {% ifversion fpt %}4.{% else %}3.{% endif %} Publishing and managing {% data variables.product.prodname_registry %}
{% data reusables.getting-started.packages %}
## Part 5: Building securely on {% data variables.product.product_name %}
{% data variables.product.product_name %} has a variety of security features that help keep code and secrets secure in repositories. Some features are available for all repositories, while others are only available for public repositories and repositories with a {% data variables.product.prodname_GH_advanced_security %} license. For an overview of {% data variables.product.product_name %} security features, see "[{% data variables.product.prodname_dotcom %} security features](/code-security/getting-started/github-security-features)."
### 1. Securing your repository
As a repository administrator, you can secure your repositories by configuring repository security settings. These include managing access to your repository, setting a security policy, and managing dependencies. For public repositories, and for private repositories owned by organizations where {% data variables.product.prodname_GH_advanced_security %} is enabled, you can also configure code and secret scanning to automatically identify vulnerabilities and ensure tokens and keys are not exposed.
For more information on steps you can take to secure your repositories, see "[Securing your repository](/code-security/getting-started/securing-your-repository)."
{% ifversion fpt %}
### 2. Managing your dependencies
A large part of building securely is maintaining your project's dependencies to ensure that all packages and applications you depend on are updated and secure. You can manage your repository's dependencies on {% data variables.product.product_name %} by exploring the dependency graph for your repository, using Dependabot to automatically raise pull requests to keep your dependencies up-to-date, and receiving Dependabot alerts and security updates for vulnerable dependencies.
For more information, see "[Securing your software supply chain](/code-security/supply-chain-security)."
{% endif %}
## Part 6: Participating in {% data variables.product.prodname_dotcom %}'s community
{% data reusables.getting-started.participating-in-community %}
### 1. Contributing to open source projects
{% data reusables.getting-started.open-source-projects %}
### 2. Interacting with {% data variables.product.prodname_gcf %}
{% data reusables.support.ask-and-answer-forum %}
### 3. Learning with {% data variables.product.prodname_learning %}
{% data reusables.getting-started.learning-lab %}
{% ifversion fpt %}
### 4. Supporting the open source community
{% data reusables.getting-started.sponsors %}
### 5. Contacting {% data variables.contact.github_support %}
{% data reusables.getting-started.contact-support %}
## Further reading
- "[Getting started with {% data variables.product.prodname_team %}](/get-started/onboarding/getting-started-with-github-team)"
{% endif %}

View File

@@ -0,0 +1,14 @@
---
title: Onboarding
intro: ''
versions:
free-pro-team: '*'
enterprise-server: '*'
github-ae: '*'
children:
- /getting-started-with-your-github-account
- /getting-started-with-github-team
- /getting-started-with-github-enterprise-cloud
- /getting-started-with-github-enterprise-server
- /getting-started-with-github-ae
---

View File

@@ -0,0 +1,3 @@
Teams are groups of organization members that you can create to reflect your company or group's structure with cascading access permissions and mentions. Organization members can send notifications to a team or request reviews, and teams can be visible or secret. For more information, see "[About teams](/organizations/organizing-members-into-teams/about-teams)."
You can create independent teams or have multiple levels of nested teams to reflect your group or company's hierarchy. For more information, see "[Creating a team](/organizations/organizing-members-into-teams/creating-a-team)."

View File

@@ -0,0 +1 @@
With {% data variables.product.prodname_actions %}, you can automate and customize {% data variables.product.product_location %}'s development workflow on {% data variables.product.product_name %}. You can create your own actions, and use and customize actions shared by the {% data variables.product.prodname_dotcom %} community. For more information, see "[Learn {% data variables.product.prodname_actions %}](/actions/learn-github-actions)."

View File

@@ -0,0 +1 @@
You can add members to organizations in {% data variables.product.product_location %} as long as you are an organization owner in the organizations you want to manage. You can also configure visibility of organization membership. For more information, see "[Adding people to your organization](/organizations/managing-membership-in-your-organization/adding-people-to-your-organization)" and "[Configuring visibility for organization membership](/admin/user-management/managing-organizations-in-your-enterprise/configuring-visibility-for-organization-membership)."

View File

@@ -0,0 +1 @@
There are two versions of the {% data variables.product.prodname_dotcom %} API: the REST API and the GraphQL API. You can use the {% data variables.product.prodname_dotcom %} APIs to automate common tasks, [back up your data](/github/creating-cloning-and-archiving-repositories/archiving-a-github-repository/backing-up-a-repository), or {% ifversion fpt %}[create integrations](/github/customizing-your-github-workflow/exploring-integrations/about-integrations){% else %}create integrations{% endif %} that extend {% data variables.product.product_name %}. For more information, see "[About {% data variables.product.prodname_dotcom %}'s APIs](/developers/overview/about-githubs-apis)."

View File

@@ -0,0 +1 @@
To keep {% ifversion ghes or ghae %}the organizations in {% data variables.product.product_location %}{% else %}your organization{% endif %} secure, you can use a variety of {% data variables.product.prodname_dotcom %} security features, including security policies, dependency graphs, secret scanning and Dependabot security and version updates. For more information, see "[Securing your organization](/code-security/getting-started/securing-your-organization)" and "[Managing security and analysis settings for your organization](/organizations/keeping-your-organization-secure/managing-security-and-analysis-settings-for-your-organization)."

View File

@@ -0,0 +1 @@
{% data variables.product.product_name %} includes access to {% data variables.contact.enterprise_support %}. {% data variables.contact.enterprise_support %} can help you troubleshoot issues that come up on {% data variables.product.product_name %}. {% ifversion ghes %}You can also choose to sign up for {% data variables.product.prodname_dotcom %} Premium Support for additional features. {% endif %}For more information, see "[About {% data variables.contact.enterprise_support %}](/admin/enterprise-support/overview/about-github-enterprise-support)."

View File

@@ -0,0 +1 @@
{% data variables.contact.github_support %} can help you troubleshoot issues you run into while using {% data variables.product.prodname_dotcom %}. For more information, see “[About {% data variables.contact.github_support %}](/github/working-with-github-support/about-github-support)."

View File

@@ -0,0 +1 @@
You can create new organizations in {% data variables.product.product_location %} to reflect your company or group's structure. For more information, see "[Creating a new organization from scratch](/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch)."

View File

@@ -0,0 +1 @@
Teams are groups of organization members that can be granted permissions to specific repositories as a group. You can create individual teams or multiple levels of nested teams in each of your organizations. For more information, see "[Creating teams](/organizations/organizing-members-into-teams/creating-a-team)" and "[Adding people to teams](/organizations/organizing-members-into-teams/adding-organization-members-to-a-team)."

View File

@@ -0,0 +1 @@
You can use tools from the {% data variables.product.prodname_marketplace %}, the {% data variables.product.product_name %} API, and existing {% data variables.product.product_name %} features to customize and automate your work.

View File

@@ -0,0 +1 @@
As an enterprise owner, you can set repository management policies for all organizations in {% data variables.product.product_location %}, or allow policies to be set separately in each organization. For more information, see "[Enforcing repository management policies in your enterprise](/admin/policies/enforcing-policies-for-your-enterprise/enforcing-repository-management-policies-in-your-enterprise)."

View File

@@ -0,0 +1 @@
{% data variables.product.prodname_pages %} is a static site hosting service that takes HTML, CSS, and JavaScript files straight from a repository and publishes a website. You can enable or disable {% data variables.product.prodname_pages %} for your enterprise members at the organization level. For more information, see "[Configuring {% data variables.product.prodname_pages %} for your enterprise](/admin/configuration/configuring-your-enterprise/configuring-github-pages-for-your-enterprise)" and "[About {% data variables.product.prodname_pages %}](/pages/getting-started-with-github-pages/about-github-pages)."

View File

@@ -0,0 +1,3 @@
You can give organization members, teams, and outside collaborators different levels of access to repositories owned by your organization with granular permission levels. For more information, see "[Repository permission levels for an organization](/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization)."
You can also customize access to your organization's project boards and allow individual organization members to manage your organization's {% data variables.product.prodname_github_apps %}. For more information, see "[Managing access to your organization's project boards](/organizations/managing-access-to-your-organizations-project-boards)" and "[Managing access to your organization's apps](/organizations/managing-access-to-your-organizations-apps)."

View File

@@ -0,0 +1,3 @@
Your enterprise members can learn new skills by completing fun, realistic projects in their very own GitHub repository with [{% data variables.product.prodname_learning %}](https://lab.github.com/). Each course is a hands-on lesson created by the GitHub community and taught by the friendly Learning Lab bot.
For more information, see “[Git and {% data variables.product.prodname_dotcom %} learning resources](/github/getting-started-with-github/quickstart/git-and-github-learning-resources)."

View File

@@ -0,0 +1,3 @@
You can learn new skills by completing fun, realistic projects in your very own GitHub repository with [{% data variables.product.prodname_learning %}](https://lab.github.com/). Each course is a hands-on lesson created by the GitHub community and taught by the friendly Learning Lab bot.
For more information, see “[Git and {% data variables.product.prodname_dotcom %} learning resources](/github/getting-started-with-github/quickstart/git-and-github-learning-resources)."

View File

@@ -0,0 +1 @@
You can manage settings and audit activity for the members of {% data variables.product.product_location %}. You can {% ifversion ghes %}promote an enterprise member to be a site administrator, {% endif %}manage dormant users, view the audit log for user activity, and customize messages that enterprise members will see. For more information, see "[Managing users in your enterprise](/admin/user-management/managing-users-in-your-enterprise)."

View File

@@ -0,0 +1 @@
You can invite anyone to be a member of your organization, as long as they have a personal account on {% data variables.product.prodname_dotcom %}. You can also remove members and reinstate former members. For more information, see "[Managing membership in your organization](/organizations/managing-membership-in-your-organization)."

View File

@@ -0,0 +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 the full list of settings you can configure for your organization, see "[Managing organization settings](/organizations/managing-organization-settings)."

View File

@@ -0,0 +1,3 @@
You can configure permissions for creating, transferring and deleting repositories in your organization, including which types members can create. For more information, see "[Restricting repository creation in your organization](/organizations/managing-organization-settings/restricting-repository-creation-in-your-organization)" and "[Setting permissions for deleting or transferring repositories](/organizations/managing-organization-settings/setting-permissions-for-deleting-or-transferring-repositories)."
You can also restrict or grant the ability to change repository visibility. For more information, see "[Restricting repository visibility changes in your organization](/organizations/managing-organization-settings/restricting-repository-visibility-changes-in-your-organization)."

View File

@@ -0,0 +1,3 @@
You can designate a "team maintainer" to manage team settings and discussions, among other privileges. For more information, see "[Giving "team maintainer" permissions to an organization member](/organizations/managing-peoples-access-to-your-organization-with-roles/giving-team-maintainer-permissions-to-an-organization-member)."
You can manage code review assignments for your team, change team visibility, manage scheduled reminders for your team, and more in your team's settings. For more information, see "[Organizing members into teams](/organizations/organizing-members-into-teams)."

View File

@@ -0,0 +1 @@
{% data variables.product.prodname_marketplace %} contains integrations that add functionality and improve your workflow. You can discover, browse, and install free and paid tools, including {% data variables.product.prodname_github_app %}s, {% data variables.product.prodname_oauth_app %}s, and {% data variables.product.prodname_actions %}, in [{% data variables.product.prodname_marketplace %}](https://github.com/marketplace). For more information, see "[About {% data variables.product.prodname_marketplace %}](/github/customizing-your-github-workflow/exploring-integrations/about-github-marketplace)."

View File

@@ -0,0 +1,4 @@
Contributing to open source projects on {% data variables.product.prodname_dotcom %} can be a rewarding way to learn, teach, and build experience in just about any skill you can imagine. For more information, see “[How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)" in the Open Source Guides.
You can find personalized recommendations for projects and good first issues based on your past contributions, stars, and other activities in [Explore](https://github.com/explore).{% ifversion fpt %} For more information, see “[Finding ways to contribute to open source on GitHub](/github/getting-started-with-github/finding-ways-to-contribute-to-open-source-on-github)."
{% endif %}

View File

@@ -0,0 +1 @@
Each person in your organization has a role that defines their level of access to the organization. The member role is the default, and you can assign owner and billing manager roles as well as "team maintainer" permissions. For more information, see "[Permission levels for an organization](/organizations/managing-peoples-access-to-your-organization-with-roles/permission-levels-for-an-organization)."

View File

@@ -0,0 +1 @@
{% data variables.product.prodname_registry %} is a software package hosting service that allows you to host your software packages privately or publicly and use packages as dependencies in your projects. For more information, see “[Introduction to {% data variables.product.prodname_registry %}](/packages/learn-github-packages/introduction-to-github-packages)."

View File

@@ -0,0 +1 @@
There are many ways to participate in the {% data variables.product.prodname_dotcom %} community. You can contribute to open source projects, interact with people in the {% data variables.product.prodname_gcf %}, or learn with {% data variables.product.prodname_learning %}.

View File

@@ -0,0 +1 @@
You can view whether your organization members have two-factor authentication enabled and choose to require two-factor authentication in your organization. For more information, see "[Requiring two-factor authentication in your organization](/organizations/keeping-your-organization-secure/requiring-two-factor-authentication-in-your-organization)."

View File

@@ -0,0 +1,3 @@
The audit log for your organization allows you, as an organization owner, to review the actions performed by members of the organization within the last 90 days. For more information, see "[Reviewing the audit log for your organization](/organizations/keeping-your-organization-secure/reviewing-the-audit-log-for-your-organization)."
You can also review and configure the permission levels for your organization's installed integrations. For more information, see "[Reviewing your organization's installed integrations](/organizations/keeping-your-organization-secure/reviewing-your-organizations-installed-integrations)."

View File

@@ -0,0 +1,3 @@
We recommend giving a limited number of members in each organization an organization owner role, which provides complete administrative access for that organization. For more information, see "[Permission levels for an organization](/organizations/managing-peoples-access-to-your-organization-with-roles/permission-levels-for-an-organization)."
For organizations where you have admin permissions, you can also customize access to each repository with granular permission levels. For more information, see "[Repository permissions levels for an organization](/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization)."

View File

@@ -0,0 +1 @@
{% data variables.product.prodname_sponsors %} allows you to make a monthly recurring payment to a developer or organization who designs, creates, or maintains open source projects you depend on. For more information, see “[About {% data variables.product.prodname_sponsors %}](/sponsors/getting-started-with-github-sponsors/about-github-sponsors)."

View File

@@ -0,0 +1,3 @@
You can create default community health files, such as a CONTRIBUTING.md file, a CODE_OF_CONDUCT.md file, or even issue and pull request templates, for your organization. These default files will be used for any repository owned by your organization that does not contain its own file of that type. For more information, see "[Creating a default community health file](/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file)."
{% data variables.product.prodname_dotcom %} offers multiple tools for moderating and managing your community. For more information, see "[Tools for moderating your community](/communities/setting-up-your-project-for-healthy-contributions/about-community-management-and-moderation#tools-for-moderating-your-community)."

View File

@@ -0,0 +1 @@
After you purchase {% data variables.product.product_name %}, we'll ask you to provide an email address and username for the person you want to initialize the enterprise. Your dedicated technical account manager in {% data variables.contact.enterprise_support %} will create an account for the enterprise owner and send the enterprise owner an email to log into {% data variables.product.product_name %} and complete the initialization.

View File

@@ -1 +1 @@
You can connect with developers around the world in the [{% data variables.product.prodname_gcf %}](https://github.community) to ask and answer questions, learn, and interact directly with {% data variables.product.product_name %} staff.
You can connect with developers around the world in [{% data variables.product.prodname_gcf %}](https://github.community) to ask and answer questions, learn, and interact directly with {% data variables.product.product_name %} staff.

View File

@@ -1,138 +0,0 @@
import createRedisClient from './redis/create-client.js'
import InMemoryRedis from 'redis-mock'
import { promisify } from 'util'
const { CI, NODE_ENV, REDIS_URL } = process.env
// Do not use real a Redis client for CI, tests, or if the REDIS_URL is not provided
const useRealRedis = !CI && NODE_ENV !== 'test' && !!REDIS_URL
class RedisAccessor {
constructor({
databaseNumber = 0,
prefix = null,
allowSetFailures = false,
allowGetFailures = false,
name = null,
} = {}) {
const redisClient = useRealRedis
? createRedisClient({
url: REDIS_URL,
db: databaseNumber,
name: name || 'redis-accessor',
})
: InMemoryRedis.createClient()
this._client = redisClient
this._prefix = prefix ? prefix.replace(/:+$/, '') + ':' : ''
// Allow for graceful failures if a Redis SET operation fails?
this._allowSetFailures = allowSetFailures === true
// Allow for graceful failures if a Redis GET operation fails?
this._allowGetFailures = allowGetFailures === true
}
/** @private */
prefix(key) {
if (typeof key !== 'string' || !key) {
throw new TypeError(`Key must be a non-empty string but was: ${JSON.stringify(key)}`)
}
return this._prefix + key
}
static translateSetArguments(options = {}) {
const setArgs = []
const defaults = {
newOnly: false,
existingOnly: false,
expireIn: null, // No expiration
rollingExpiration: true,
}
const opts = { ...defaults, ...options }
if (opts.newOnly === true) {
if (opts.existingOnly === true) {
throw new TypeError('Misconfiguration: entry cannot be both new and existing')
}
setArgs.push('NX')
} else if (opts.existingOnly === true) {
setArgs.push('XX')
}
if (Number.isFinite(opts.expireIn)) {
const ttl = Math.round(opts.expireIn)
if (ttl < 1) {
throw new TypeError('Misconfiguration: cannot set a TTL of less than 1 millisecond')
}
setArgs.push('PX')
setArgs.push(ttl)
}
// otherwise there is no expiration
if (opts.rollingExpiration === false) {
if (opts.newOnly === true) {
throw new TypeError('Misconfiguration: cannot keep an existing TTL on a new entry')
}
setArgs.push('KEEPTTL')
}
return setArgs
}
async set(key, value, options = {}) {
const setAsync = promisify(this._client.set).bind(this._client)
const fullKey = this.prefix(key)
if (typeof value !== 'string' || !value) {
throw new TypeError(`Value must be a non-empty string but was: ${JSON.stringify(value)}`)
}
// Handle optional arguments
const setArgs = this.constructor.translateSetArguments(options)
try {
const result = await setAsync(fullKey, value, ...setArgs)
return result === 'OK'
} catch (err) {
const errorText = `Failed to set value in Redis.
Key: ${fullKey}
Error: ${err.message}`
if (this._allowSetFailures === true) {
// Allow for graceful failure
console.error(errorText)
return false
}
throw new Error(errorText)
}
}
async get(key) {
const getAsync = promisify(this._client.get).bind(this._client)
const fullKey = this.prefix(key)
try {
const value = await getAsync(fullKey)
return value
} catch (err) {
const errorText = `Failed to get value from Redis.
Key: ${fullKey}
Error: ${err.message}`
if (this._allowGetFailures === true) {
// Allow for graceful failure
console.error(errorText)
return null
}
throw new Error(errorText)
}
}
}
export default RedisAccessor

View File

@@ -1,9 +1,7 @@
import fs from 'fs'
import path from 'path'
import { liquid } from '../lib/render-content/index.js'
import FailBot from '../lib/failbot.js'
import loadSiteData from '../lib/site-data.js'
import builtAssets from '../lib/built-asset-urls.js'
import { nextApp } from './next.js'
function shouldLogException(error) {
const IGNORED_ERRORS = [
@@ -54,15 +52,7 @@ export default async function handleError(error, req, res, next) {
// Special handling for when a middleware calls `next(404)`
if (error === 404) {
// Again, we can remove this once the 404/500 pages are ready
return res
.status(404)
.send(
await liquid.parseAndRender(
fs.readFileSync(path.join(process.cwd(), './layouts/error-404.html'), 'utf8'),
req.context
)
)
return nextApp.render404(req, res)
}
// If the error contains a status code, just send that back. This is usually
@@ -75,15 +65,9 @@ export default async function handleError(error, req, res, next) {
console.error('500 error!', req.path)
console.error(error)
}
// Again, we can remove this once the 404/500 pages are ready
res
.status(500)
.send(
await liquid.parseAndRender(
fs.readFileSync(path.join(process.cwd(), './layouts/error-500.html'), 'utf8'),
req.context
)
)
res.statusCode = 500
nextApp.renderError(error, req, res, req.path)
// Report to Failbot AFTER responding to the user
await logException(error, req)

View File

@@ -1,59 +1,9 @@
import fs from 'fs'
import path from 'path'
import { get } from 'lodash-es'
import { liquid } from '../lib/render-content/index.js'
import patterns from '../lib/patterns.js'
import getMiniTocItems from '../lib/get-mini-toc-items.js'
import Page from '../lib/page.js'
import statsd from '../lib/statsd.js'
import RedisAccessor from '../lib/redis-accessor.js'
import { isConnectionDropped } from './halt-on-dropped-connection.js'
import { nextHandleRequest } from './next.js'
const { HEROKU_RELEASE_VERSION } = process.env
const pageCacheDatabaseNumber = 1
const pageCache = new RedisAccessor({
databaseNumber: pageCacheDatabaseNumber,
prefix: (HEROKU_RELEASE_VERSION ? HEROKU_RELEASE_VERSION + ':' : '') + 'rp',
// Allow for graceful failures if a Redis SET operation fails
allowSetFailures: true,
// Allow for graceful failures if a Redis GET operation fails
allowGetFailures: true,
name: 'page-cache',
})
// a list of query params that *do* alter the rendered page, and therefore should be cached separately
const cacheableQueries = ['learn']
function modifyOutput(req, text) {
return addColorMode(req, addCsrf(req, text))
}
function addCsrf(req, text) {
return text.replace('$CSRFTOKEN$', req.csrfToken())
}
function addColorMode(req, text) {
let colorMode = 'auto'
let darkTheme = 'dark'
let lightTheme = 'light'
try {
const cookieValue = JSON.parse(decodeURIComponent(req.cookies.color_mode))
colorMode = encodeURIComponent(cookieValue.color_mode) || colorMode
darkTheme = encodeURIComponent(cookieValue.dark_theme.name) || darkTheme
lightTheme = encodeURIComponent(cookieValue.light_theme.name) || lightTheme
} catch (e) {
// do nothing
}
return text
.replace('$COLORMODE$', colorMode)
.replace('$DARKTHEME$', darkTheme)
.replace('$LIGHTTHEME$', lightTheme)
}
import { nextApp, nextHandleRequest } from './next.js'
export default async function renderPage(req, res, next) {
const page = req.context.page
@@ -64,65 +14,17 @@ export default async function renderPage(req, res, next) {
`\nTried to redirect to ${req.context.redirectNotFound}, but that page was not found.\n`
)
}
return res
.status(404)
// We can get rid of reading the layout for 404 once we have the 404 page up and running
.send(modifyOutput(req, await liquid.parseAndRender(fs.readFileSync(path.join(process.cwd(), './layouts/error-404.html'), 'utf8'), req.context)))
return nextApp.render404(req, res)
}
// Just finish fast without all the details like Content-Length
if (req.method === 'HEAD') {
return res.status(200).end()
}
// Remove any query string (?...) and/or fragment identifier (#...)
const { pathname, searchParams } = new URL(req.originalUrl, 'https://docs.github.com')
for (const queryKey in req.query) {
if (!cacheableQueries.includes(queryKey)) {
searchParams.delete(queryKey)
}
}
const originalUrl = pathname + ([...searchParams].length > 0 ? `?${searchParams}` : '')
// Is the request for JSON debugging info?
const isRequestingJsonForDebugging = 'json' in req.query && process.env.NODE_ENV !== 'production'
// Is in an airgapped session?
const isAirgapped = Boolean(req.cookies.AIRGAP)
// Is the request for the GraphQL Explorer page?
const isGraphQLExplorer = req.context.currentPathWithoutLanguage === '/graphql/overview/explorer'
// Serve from the cache if possible
const isCacheable =
// Skip for CI
!process.env.CI &&
// Skip for tests
process.env.NODE_ENV !== 'test' &&
// Skip for HTTP methods other than GET
req.method === 'GET' &&
// Skip for JSON debugging info requests
!isRequestingJsonForDebugging &&
// Skip for airgapped sessions
!isAirgapped &&
// Skip for the GraphQL Explorer page
!isGraphQLExplorer
if (isCacheable) {
// Stop processing if the connection was already dropped
if (isConnectionDropped(req, res)) return
const cachedHtml = await pageCache.get(originalUrl)
if (cachedHtml) {
// Stop processing if the connection was already dropped
if (isConnectionDropped(req, res)) return
console.log(`Serving from cached version of ${originalUrl}`)
statsd.increment('page.sent_from_cache')
return res.send(modifyOutput(req, cachedHtml))
}
}
// add page context
const context = Object.assign({}, req.context, { page })

1
next-env.d.ts vendored
View File

@@ -1,2 +1,3 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />

View File

@@ -1,158 +1,44 @@
import { useRouter } from 'next/router'
import { SimpleHeader, SimpleFooter } from 'components/GenericError'
import Head from 'next/head'
import Link from 'next/link'
import {
MarkGithubIcon,
GitPullRequestIcon,
PeopleIcon,
CommentDiscussionIcon,
} from '@primer/octicons-react'
import { CommentDiscussionIcon } from '@primer/octicons-react'
import { useVersion } from 'components/hooks/useVersion'
import { AllProductsLink } from 'components/product/AllProductsLink'
export default function Custom404() {
const router = useRouter()
const { currentVersion, isEnterprise } = useVersion()
const contribution_href = router.locale
? `https://github.com/github/docs/edit/main/content/`
: 'https://github.com/github/docs'
const Custom404 = () => {
const { isEnterprise } = useVersion()
return (
<div className="d-lg-flex error-404">
<div className="min-h-screen d-flex flex-column">
<Head>
<title>Ooops!</title>
<title>404 - Page not found</title>
</Head>
<div className="sidebar d-none d-lg-block color-bg-tertiary position-sticky top-0 overflow-y-auto root">
<div
className="d-flex flex-items-center p-4 position-sticky top-0 color-bg-tertiary"
style={{ zIndex: 3 }}
id="github-logo"
role="banner"
>
<Link href={`/${router.locale}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a className="color-text-primary" aria-hidden="true" tabIndex={-1}>
<MarkGithubIcon size={32} />
</a>
</Link>
<Link href={`/${router.locale}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a className="h4-mktg color-text-primary no-underline no-wrap pl-2 flex-auto">
GitHub Docs
</a>
</Link>
</div>
<nav>
<ul className="sidebar-products mt-4">
{currentVersion !== 'homepage' && <AllProductsLink />}
</ul>
</nav>
<SimpleHeader />
<div className="container-xl p-responsive py-6 width-full flex-1">
<article className="markdown-body col-md-10 col-lg-7 mx-auto">
<h1>Ooops!</h1>
<p className="lead-mktg">It looks like this page doesn't exist.</p>
<p className="lead-mktg">
We track these errors automatically, but if the problem persists please feel free to
contact us.
</p>
<a
id="contact-us"
href={
isEnterprise
? 'https://enterprise.github.com/support'
: 'https://support.github.com/contact'
}
className="btn btn-outline mt-2"
>
<CommentDiscussionIcon size="small" className="octicon mr-1" />
Contact support
</a>
</article>
</div>
<main className="width-full">
<div className="container-xl p-responsive py-6">
<article className="markdown-body col-md-10 col-lg-7 mx-auto">
<h1>Ooops</h1>
<div className="lead-mktg mb-5">It looks like this page doesn't exist.</div>
<div className="col-lg-12 mt-6">
<h3 className="mb-3">Need help?</h3>
</div>
</article>
</div>
<section className="mt-lg-9 py-7 px-3 px-md-6 no-print color-bg-tertiary">
<div className="container-xl gutter-lg-spacious clearfix">
<div className="col-12 col-lg-6 col-xl-4 mb-6 mb-xl-0 float-left">
<div className="f5 contribution">
<h2 className="f4">Help us make these docs great!</h2>
<p className="color-text-secondary f6">
All GitHub docs are open source. See something that's wrong or unclear? Submit a
pull request.
</p>
<a className="btn btn-outline" href={contribution_href}>
<GitPullRequestIcon size="small" className="octicon mr-1" />
Make a contribution
</a>
<p className="color-text-secondary f6 mt-2">
Or,{' '}
<a
href="https://github.com/github/docs/blob/main/CONTRIBUTING.md"
target="_blank"
rel="noopener"
>
learn how to contribute.
</a>
</p>
</div>
</div>
<div className="col-12 col-lg-12 col-xl-4 float-left">
<div>
<h3 className="mb-2 f4">Still need help?</h3>
<a
id="ask-community"
href="https://github.community"
className="btn btn-outline mr-4 mt-2"
>
<PeopleIcon size="small" className="octicon mr-1" />
Ask the GitHub community
</a>
<a
id="contact-us"
href={
isEnterprise
? 'https://enterprise.github.com/support'
: 'https://support.github.com/contact'
}
className="btn btn-outline mt-2"
>
<CommentDiscussionIcon size="small" className="octicon mr-1" />
Contact support
</a>
</div>
</div>
</div>
</section>
<footer className="py-6 text-small">
<div className="container-xl d-flex px-3 px-md-6">
<ul className="d-flex list-style-none flex-wrap flex-justify-center flex-xl-justify-start">
<li className="d-flex mr-xl-3 color-text-secondary">
<MarkGithubIcon className="mr-2 mr-xl-3" size={20} />
<span>&copy; {new Date().getFullYear()} GitHub, Inc.</span>
</li>
<li className="ml-3">
<a href="/github/site-policy/github-terms-of-service">Terms</a>
</li>
<li className="ml-3">
<a href="/github/site-policy/github-privacy-statement">Privacy </a>
</li>
<li className="ml-3">
<a href="https://github.com/security">Security</a>
</li>
<li className="ml-3">
<a href="https://www.githubstatus.com/">Status</a>
</li>
<li className="ml-3">
<a href="/">Help</a>
</li>
<li className="ml-3">
<a href="https://support.github.com">Contact GitHub</a>
</li>
<li className="ml-3">
<a href="https://github.com/pricing">Pricing</a>
</li>
<li className="ml-3">
<a href="/developers">Developer API</a>
</li>
<li className="ml-3">
<a href="https://services.github.com/">Training</a>
</li>
<li className="ml-3">
<a href="https://github.com/about">About</a>
</li>
</ul>
</div>
</footer>
</main>
<SimpleFooter />
</div>
)
}
export default Custom404

View File

@@ -1,159 +1,5 @@
import { useRouter } from 'next/router'
import Head from 'next/head'
import Link from 'next/link'
import {
MarkGithubIcon,
GitPullRequestIcon,
PeopleIcon,
CommentDiscussionIcon,
} from '@primer/octicons-react'
import { useVersion } from 'components/hooks/useVersion'
import { GenericError } from 'components/GenericError'
export default function Custom500() {
const router = useRouter()
const { isEnterprise } = useVersion()
const contribution_href = router.locale
? `https://github.com/github/docs/edit/main/content/`
: 'https://github.com/github/docs'
return (
<div>
<Head>
<title>GitHub Documentation</title>
</Head>
<div className="border-bottom color-border-secondary no-print">
<header className="container-xl px-3 px-md-6 pt-3 pb-2 position-relative d-flex flex-justify-between width-full">
<div
className="d-flex flex-items-center d-lg-none"
style={{ zIndex: 3 }}
id="github-logo-mobile"
role="banner"
>
<Link href={`/${router.locale}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a aria-hidden="true" tabIndex={-1}>
<MarkGithubIcon size={32} className="color-icon-primary" />
</a>
</Link>
<Link href={`/${router.locale}`}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a className="h4-mktg color-text-primary no-underline no-wrap pl-2">GitHub Docs</a>
</Link>
</div>
<div className="width-full">
<div className="d-inline-block width-full d-md-flex" style={{ zIndex: 1 }}>
<div className="float-right d-md-none position-relative" style={{ zIndex: 3 }}>
<div className="d-md-inline-block"></div>
</div>
</div>
</div>
</header>
</div>
<div className="container-xl p-responsive py-9">
<article className="markdown-body col-md-10 col-lg-7 mx-auto">
<h1>Ooops!</h1>
<div className="lead-mktg mb-5">
It looks like something went wrong. We track these errors automatically, but if the
problem persists please feel free to contact us.
</div>
</article>
</div>
<section className="mt-lg-9 py-7 px-3 px-md-6 no-print color-bg-tertiary">
<div className="container-xl gutter-lg-spacious clearfix">
<div className="col-12 col-lg-6 col-xl-4 mb-6 mb-xl-0 float-left">
<div className="f5 contribution">
<h2 className="f4">Help us make these docs great!</h2>
<p className="color-text-secondary f6">
All GitHub docs are open source. See something that's wrong or unclear? Submit a
pull request.
</p>
<a className="btn btn-outline" href={contribution_href}>
<GitPullRequestIcon size="small" className="octicon mr-1" />
Make a contribution
</a>
<p className="color-text-secondary f6 mt-2">
Or,{' '}
<a
href="https://github.com/github/docs/blob/main/CONTRIBUTING.md"
target="_blank"
rel="noopener"
>
learn how to contribute.
</a>
</p>
</div>
</div>
<div className="col-12 col-lg-12 col-xl-4 float-left">
<div>
<h3 className="mb-2 f4">Still need help?</h3>
<a
id="ask-community"
href="https://github.community"
className="btn btn-outline mr-4 mt-2"
>
<PeopleIcon size="small" className="octicon mr-1" />
Ask the GitHub community
</a>
<a
id="contact-us"
href={
isEnterprise
? 'https://enterprise.github.com/support'
: 'https://support.github.com/contact'
}
className="btn btn-outline mt-2"
>
<CommentDiscussionIcon size="small" className="octicon mr-1" />
Contact support
</a>
</div>
</div>
</div>
</section>
<footer className="py-6 text-small">
<div className="container-xl d-flex px-3 px-md-6">
<ul className="d-flex list-style-none flex-wrap flex-justify-center flex-xl-justify-start">
<li className="d-flex mr-xl-3 color-text-secondary">
<MarkGithubIcon className="mr-2 mr-xl-3" size={20} />
<span>&copy; {new Date().getFullYear()} GitHub, Inc.</span>
</li>
<li className="ml-3">
<a href="/github/site-policy/github-terms-of-service">Terms</a>
</li>
<li className="ml-3">
<a href="/github/site-policy/github-privacy-statement">Privacy </a>
</li>
<li className="ml-3">
<a href="https://github.com/security">Security</a>
</li>
<li className="ml-3">
<a href="https://www.githubstatus.com/">Status</a>
</li>
<li className="ml-3">
<a href="/">Help</a>
</li>
<li className="ml-3">
<a href="https://support.github.com">Contact GitHub</a>
</li>
<li className="ml-3">
<a href="https://github.com/pricing">Pricing</a>
</li>
<li className="ml-3">
<a href="/developers">Developer API</a>
</li>
<li className="ml-3">
<a href="https://services.github.com/">Training</a>
</li>
<li className="ml-3">
<a href="https://github.com/about">About</a>
</li>
</ul>
</div>
</footer>
</div>
)
return <GenericError />
}

10
pages/_error.tsx Normal file
View File

@@ -0,0 +1,10 @@
import { NextPage } from 'next'
import { GenericError } from 'components/GenericError'
type Props = {}
const ErrorPage: NextPage<Props> = () => {
return <GenericError />
}
export default ErrorPage

View File

@@ -338,13 +338,6 @@ Run this script to manually purge the Fastly cache for all language variants of
---
### [`purge-redis-pages.js`](purge-redis-pages.js)
Run this script to manually purge the Redis rendered page cache. This will typically only be run by Heroku during the deployment process, as triggered via our Procfile's "release" phase configuration.
---
### [`reconcile-category-dirs-with-ids.js`](reconcile-category-dirs-with-ids.js)
An automated test checks for discrepancies between category directory names and slugified category titles as IDs.

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env node
import fs from 'fs'
import path from 'path'
import program from 'commander'
import readJsonFile from '../../lib/read-json-file.js'
import { deprecated } from '../../lib/enterprise-server-releases.js'
const DEVELOPER_REDIRECTS_FILEPATH = 'lib/redirects/static/developer.json'
const developerRedirects = readJsonFile(`./${DEVELOPER_REDIRECTS_FILEPATH}`)
// [start-readme]
//
// Run this script after an Enterprise deprecation to remove redirects
// for the deprecated version. See the Enterprise deprecation issue template for instructions.
//
// [end-readme]
program
.description(
'Remove developer redirects for deprecated versions. The redirects for deprecated versions live in the respective directory in the github/help-docs-archived-enterprise-versions repository.'
)
.option('-r, --release <NUMBER>', 'Enterprise Server release number. Example: 2.19. Default: latest deprecated release number.')
.parse(process.argv)
// Default to latest deprecated release
const release = program.opts().release || deprecated[0]
const supportedRedirects = {}
Object.keys(developerRedirects).forEach(elem => {
const includesVersion = elem.includes(`enterprise/${release}`)
|| elem.includes(`enterprise-server@${release}`)
if ( includesVersion ) return
supportedRedirects[elem] = developerRedirects[elem]
})
fs.writeFileSync(path.join(process.cwd(), DEVELOPER_REDIRECTS_FILEPATH), JSON.stringify(supportedRedirects, null, 2))

View File

@@ -71,7 +71,6 @@ function groupTokens (tokens, tagName, endTagName, newArray = []) {
const startIndex = tokens.findIndex(token => token.conditional === tagName)
// The end tag name is currently in a separate token, but we want to group it with the start tag and content.
const endIndex = tokens.findIndex(token => token.conditional === endTagName)
// Once all tags are grouped and removed from `tokens`, this findIndex will not find anything,
// so we can return the grouped result at this point.
if (startIndex === -1) return newArray
@@ -123,7 +122,12 @@ function handleNestedTags (condBlockArr, endIndex, tagName, endTagName, tokens)
}
function hasUnhandledNestedTags (condBlockArr, tagName, endTagName) {
const startTags = condBlockArr.filter(t => t.conditional === tagName)
const startTags = condBlockArr.filter(t => {
// some blocks that start with ifversion still have if tags nested inside
return tagName === 'ifversion'
? t.conditional === tagName || t.conditional === 'if'
: t.conditional === tagName
})
const endTags = condBlockArr.filter(t => t.conditional === endTagName)
const hasMoreStartTagsThanEndTags = startTags.length > endTags.length

View File

@@ -1,185 +0,0 @@
#!/usr/bin/env node
import xDotenv from 'dotenv'
import { promisify } from 'util'
import createRedisClient from '../lib/redis/create-client.js'
// [start-readme]
//
// Run this script to manually "soft purge" the Redis rendered page cache
// by shortening the expiration window of entries.
// This will typically only be run by Heroku during the deployment process,
// as triggered via our Procfile's "release" phase configuration.
//
// [end-readme]
xDotenv.config()
const { REDIS_URL, HEROKU_RELEASE_VERSION, HEROKU_PRODUCTION_APP } = process.env
const isHerokuProd = HEROKU_PRODUCTION_APP === 'true'
const pageCacheDatabaseNumber = 1
const keyScanningPattern = HEROKU_RELEASE_VERSION ? '*:rp:*' : 'rp:*'
const scanSetSize = 250
const startTime = Date.now()
const expirationDuration = 30 * 60 * 1000 // 30 minutes
const expirationTimestamp = startTime + expirationDuration // 30 minutes from now
// print keys to be purged without actually purging
const dryRun = ['-d', '--dry-run'].includes(process.argv[2])
// verify environment variables
if (!REDIS_URL) {
if (isHerokuProd) {
console.error('Error: you must specify the REDIS_URL environment variable.\n')
process.exit(1)
} else {
console.warn('Warning: you did not specify a REDIS_URL environment variable. Exiting...\n')
process.exit(0)
}
}
console.log({
HEROKU_RELEASE_VERSION,
HEROKU_PRODUCTION_APP,
})
purgeRenderedPageCache()
function purgeRenderedPageCache() {
const redisClient = createRedisClient({
url: REDIS_URL,
db: pageCacheDatabaseNumber,
// These commands ARE important, so let's make sure they are all accounted for
enable_offline_queue: true,
})
let iteration = 0
let potentialKeyCount = 0
let totalKeyCount = 0
// Promise wrappers
const scanAsync = promisify(redisClient.scan).bind(redisClient)
const quitAsync = promisify(redisClient.quit).bind(redisClient)
// Run it!
return scan()
//
// Define other subroutines
//
async function scan(cursor = '0') {
try {
// [0]: Update the cursor position for the next scan
// [1]: Get the SCAN result for this iteration
const [nextCursor, keys] = await scanAsync(
cursor,
'MATCH',
keyScanningPattern,
'COUNT',
scanSetSize.toString()
)
console.log(`\n[Iteration ${iteration++}] Received ${keys.length} keys...`)
if (dryRun) {
console.log(
`DRY RUN! This iteration might have set TTL for up to ${
keys.length
} keys:\n - ${keys.join('\n - ')}`
)
}
// NOTE: It is possible for a SCAN cursor iteration to return 0 keys when
// using a MATCH because it is applied after the elements are retrieved
//
// Remember: more or less than COUNT or no keys may be returned
// See http://redis.io/commands/scan#the-count-option
// Also, SCAN may return the same key multiple times
// See http://redis.io/commands/scan#scan-guarantees
// Additionally, you should always have the code that uses the keys
// before the code checking the cursor.
if (keys.length > 0) {
if (dryRun) {
potentialKeyCount += keys.length
} else {
totalKeyCount += await updateTtls(keys)
}
}
// From <http://redis.io/commands/scan>:
// 'An iteration starts when the cursor is set to 0,
// and terminates when the cursor returned by the server is 0.'
if (nextCursor === '0') {
const dryRunTrailer = dryRun ? ` (potentially up to ${potentialKeyCount})` : ''
console.log(`\nDone purging keys; affected total: ${totalKeyCount}${dryRunTrailer}`)
console.log(`Time elapsed: ${Date.now() - startTime} ms`)
// Close the connection
await quitAsync()
return
}
// Tail recursion
return scan(nextCursor)
} catch (error) {
console.error('An unexpected error occurred!\n' + error.stack)
console.error('\nAborting...')
process.exit(1)
}
}
// Find existing TTLs to ensure we aren't extending the TTL if it's already set
async function getTtls(keys) {
const pttlPipeline = redisClient.batch()
keys.forEach((key) => pttlPipeline.pttl(key))
const pttlPipelineExecAsync = promisify(pttlPipeline.exec).bind(pttlPipeline)
const pttlResults = await pttlPipelineExecAsync()
if (pttlResults == null || pttlResults.length === 0) {
throw new Error('PTTL results were empty')
}
return pttlResults
}
async function updateTtls(keys) {
const pttlResults = await getTtls(keys)
// Find pertinent keys to have TTLs set
let updatingKeyCount = 0
const pexpireAtPipeline = redisClient.batch()
keys.forEach((key, i) => {
// Only operate on -1 values or those later than our desired expiration timestamp
const pttl = pttlResults[i]
// A TTL of -1 means the entry was not configured with any TTL (expiration)
// currently and will remain as a permanent entry unless a TTL is added
const needsShortenedTtl = pttl === -1 || pttl > expirationDuration
const isOldKey = !HEROKU_RELEASE_VERSION || !key.startsWith(`${HEROKU_RELEASE_VERSION}:`)
if (needsShortenedTtl && isOldKey) {
pexpireAtPipeline.pexpireat(key, expirationTimestamp)
updatingKeyCount += 1
}
})
console.log(`Purging ${updatingKeyCount} keys...`)
// Only update TTLs if there are records worth updating
if (updatingKeyCount === 0) return
// Set all the TTLs
const pexpireAtPipelineExecAsync = promisify(pexpireAtPipeline.exec).bind(pexpireAtPipeline)
const pexpireAtResults = await pexpireAtPipelineExecAsync()
if (pttlResults == null || pttlResults.length === 0) {
throw new Error('PEXPIREAT results were empty')
}
// Count only the entries whose TTLs were successfully updated
const updatedResults = pexpireAtResults.filter((result) => result === 1)
return updatedResults.length
}
}

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env bash
# [start-readme]
#
# Light Bash wrapper for the Heroku release command, which sometimes fails
# unexpectedly in staging environments when a Node installation is missing
#
# [end-readme]
# Check for node but don't fail immediately if it's not present
./script/check-for-node
EXIT_STATUS=$?
# If node is missing...
if [[ "$EXIT_STATUS" -ne "0" ]]; then
# Fail hard if this is our Heroku production app or if Redis is configured
if [[ "$HEROKU_PRODUCTION_APP" == "true" || -n "$REDIS_URL" ]]; then
echo "Error: cannot execute the release script without Node.js, which is fatal."
echo "Exiting..."
exit $EXIT_STATUS
# Otherwise succeed with only a warning
else
echo "Warning: although Node.js is missing, it is non-critical."
echo "Exiting..."
exit 0
fi
else
# Execute the release script and exit with its status
node script/purge-redis-pages.js
exit $?
fi

View File

@@ -13,3 +13,7 @@
.rotate-180 {
transform: rotateX(180deg);
}
.min-h-screen {
min-height: 100vh;
}

View File

@@ -46,8 +46,8 @@ describe('browser search', () => {
expect(hits.length).toBeGreaterThan(5)
await page.setViewport(initialViewport)
})
it('works on 404 error page', async () => {
// 404 page is statically generated with next, so search is not available, but may possibly be brought back
it.skip('works on 404 error page', async () => {
await page.goto('http://localhost:4001/en/404')
await page.click('#search-input-container input[type="search"]')
await page.type('#search-input-container input[type="search"]', 'actions')

View File

@@ -2,7 +2,6 @@ import lodash from 'lodash-es'
import enterpriseServerReleases from '../../lib/enterprise-server-releases.js'
import { get, getDOM, head, post } from '../helpers/supertest.js'
import { describeViaActionsOnly } from '../helpers/conditional-runs.js'
import path from 'path'
import { loadPages } from '../../lib/page-data.js'
import builtAssets from '../../lib/built-asset-urls.js'
import CspParse from 'csp-parse'
@@ -178,7 +177,7 @@ describe('server', () => {
const $ = await getDOM('/not-a-real-page')
expect($('h1').text()).toBe('Ooops!')
expect($.text().includes("It looks like this page doesn't exist.")).toBe(true)
expect($.text().includes('Still need help?')).toBe(true)
expect($.text().includes('We track these errors automatically, but if the problem persists please feel free to contact us.')).toBe(true)
expect($.res.statusCode).toBe(404)
})
@@ -201,11 +200,8 @@ describe('server', () => {
test('renders a 500 page when errors are thrown', async () => {
const $ = await getDOM('/_500')
expect($('h1').text()).toBe('Ooops!')
expect($('code').text().startsWith('Error: Intentional error')).toBe(true)
expect($('code').text().includes(path.join('node_modules', 'express', 'lib', 'router'))).toBe(
true
)
expect($.text().includes('Still need help?')).toBe(true)
expect($.text().includes("It looks like something went wrong.")).toBe(true)
expect($.text().includes("We track these errors automatically, but if the problem persists please feel free to contact us.")).toBe(true)
expect($.res.statusCode).toBe(500)
})

View File

@@ -1,359 +0,0 @@
import { jest } from '@jest/globals'
import redisMock from 'redis-mock'
import RedisAccessor from '../../lib/redis-accessor.js'
const { RedisClient: InMemoryRedis } = redisMock
describe('RedisAccessor', () => {
test('is a constructor', async () => {
expect(typeof RedisAccessor).toBe('function')
const instance = new RedisAccessor()
expect(instance).toBeInstanceOf(RedisAccessor)
})
test('has expected instance properties', async () => {
const instance = new RedisAccessor()
expect(Object.keys(instance).sort()).toEqual([
'_allowGetFailures',
'_allowSetFailures',
'_client',
'_prefix',
])
})
test('has expected static methods', async () => {
expect(typeof RedisAccessor.translateSetArguments).toBe('function')
})
describe('#_allowGetFailures property', () => {
test('defaults to false', async () => {
const instance = new RedisAccessor()
expect(instance._allowGetFailures).toBe(false)
})
test('is expected value', async () => {
const instance = new RedisAccessor({ allowGetFailures: true })
expect(instance._allowGetFailures).toBe(true)
})
})
describe('#_allowSetFailures property', () => {
test('defaults to false', async () => {
const instance = new RedisAccessor()
expect(instance._allowSetFailures).toBe(false)
})
test('is expected value', async () => {
const instance = new RedisAccessor({ allowSetFailures: true })
expect(instance._allowSetFailures).toBe(true)
})
})
describe('#_client property', () => {
test('is expected Redis client', async () => {
const instance = new RedisAccessor()
expect(instance._client).toBeInstanceOf(InMemoryRedis)
})
})
describe('#_prefix property', () => {
test('defaults to empty string', async () => {
const instance = new RedisAccessor()
expect(instance._prefix).toBe('')
})
test('is expected value', async () => {
const instance = new RedisAccessor({ prefix: 'myPrefix' })
expect(instance._prefix).toBe('myPrefix:')
})
test('removes a trailing colon', async () => {
const instance = new RedisAccessor({ prefix: 'myPrefix:' })
expect(instance._prefix).toBe('myPrefix:')
})
test('removes multiple trailing colons', async () => {
const instance = new RedisAccessor({ prefix: 'myPrefix::' })
expect(instance._prefix).toBe('myPrefix:')
})
})
describe('#prefix method', () => {
test('returns prefixed key', async () => {
const prefix = 'myPrefix'
const instance = new RedisAccessor({ prefix })
expect(instance.prefix('myKey')).toBe('myPrefix:myKey')
})
test('returns original key if no prefix is configured', async () => {
const instance = new RedisAccessor()
expect(instance.prefix('myKey')).toBe('myKey')
})
test('throws if no key is provided', async () => {
const instance = new RedisAccessor()
expect(() => instance.prefix()).toThrow(
new TypeError('Key must be a non-empty string but was: undefined')
)
})
})
describe('.translateSetArguments method', () => {
test('defaults to an empty list of arguments if no options are given', async () => {
expect(RedisAccessor.translateSetArguments()).toEqual([])
})
test('adds argument "NX" if option `newOnly` is set to true', async () => {
expect(RedisAccessor.translateSetArguments({ newOnly: true })).toEqual(['NX'])
})
test('adds argument "XX" if option `existingOnly` is set to true', async () => {
expect(RedisAccessor.translateSetArguments({ existingOnly: true })).toEqual(['XX'])
})
test('adds argument "PX n" if option `expireIn` is provided with a positive finite integer', async () => {
expect(RedisAccessor.translateSetArguments({ expireIn: 20 })).toEqual(['PX', 20])
})
test('adds argument "PX n" with rounded integer if option `expireIn` is provided with a positive finite non-integer', async () => {
expect(RedisAccessor.translateSetArguments({ expireIn: 20.5 })).toEqual(['PX', 21])
expect(RedisAccessor.translateSetArguments({ expireIn: 29.1 })).toEqual(['PX', 29])
})
test('adds argument "KEEPTTL" if option `rollingExpiration` is set to false', async () => {
expect(RedisAccessor.translateSetArguments({ rollingExpiration: false })).toEqual(['KEEPTTL'])
})
test('adds expected arguments if multiple options are configured', async () => {
expect(
RedisAccessor.translateSetArguments({
newOnly: true,
expireIn: 20,
})
).toEqual(['NX', 'PX', 20])
expect(
RedisAccessor.translateSetArguments({
existingOnly: true,
expireIn: 20,
})
).toEqual(['XX', 'PX', 20])
expect(
RedisAccessor.translateSetArguments({
existingOnly: true,
expireIn: 20,
rollingExpiration: false,
})
).toEqual(['XX', 'PX', 20, 'KEEPTTL'])
expect(
RedisAccessor.translateSetArguments({
existingOnly: true,
rollingExpiration: false,
})
).toEqual(['XX', 'KEEPTTL'])
})
test('throws a misconfiguration error if options `newOnly` and `existingOnly` are both set to true', async () => {
expect(() =>
RedisAccessor.translateSetArguments({ newOnly: true, existingOnly: true })
).toThrowError(new TypeError('Misconfiguration: entry cannot be both new and existing'))
})
test('throws a misconfiguration error if option `expireIn` is set to a finite number that rounds to less than 1', async () => {
const misconfigurationError = new TypeError(
'Misconfiguration: cannot set a TTL of less than 1 millisecond'
)
expect(() => RedisAccessor.translateSetArguments({ expireIn: 0 })).toThrowError(
misconfigurationError
)
expect(() => RedisAccessor.translateSetArguments({ expireIn: -1 })).toThrowError(
misconfigurationError
)
expect(() => RedisAccessor.translateSetArguments({ expireIn: 0.4 })).toThrowError(
misconfigurationError
)
})
test('throws a misconfiguration error if option `rollingExpiration` is set to false but `newOnly` is set to true', async () => {
expect(() =>
RedisAccessor.translateSetArguments({ newOnly: true, rollingExpiration: false })
).toThrowError(new TypeError('Misconfiguration: cannot keep an existing TTL on a new entry'))
})
})
describe('#set method', () => {
test('resolves to true if value was successfully set', async () => {
const instance = new RedisAccessor()
expect(await instance.set('myKey', 'myValue')).toBe(true)
})
test('resolves to false if value was not set', async () => {
const instance = new RedisAccessor()
instance._client.set = jest.fn((...args) => args.pop()(null, 'NOT_OK'))
expect(await instance.set('myKey', 'myValue')).toBe(false)
})
test('sends expected key/value to Redis with #_client.set', async () => {
const instance = new RedisAccessor()
const setSpy = jest.spyOn(instance._client, 'set')
await instance.set('myKey', 'myValue')
expect(setSpy.mock.calls.length).toBe(1)
expect(setSpy.mock.calls[0].slice(0, 2)).toEqual(['myKey', 'myValue'])
})
test('resolves to false if Redis replies with an error and `allowSetFailures` option is set to true', async () => {
// Temporarily override `console.error`
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation()
const instance = new RedisAccessor({ prefix: 'myPrefix', allowSetFailures: true })
instance._client.set = jest.fn((...args) => args.pop()(new Error('Redis ReplyError')))
const result = await instance.set('myKey', 'myValue')
expect(result).toBe(false)
expect(consoleErrorSpy).toBeCalledWith(
`Failed to set value in Redis.
Key: myPrefix:myKey
Error: Redis ReplyError`
)
// Restore `console.error`
consoleErrorSpy.mockRestore()
})
test('rejects if Redis replies with an error and `allowSetFailures` option is not set to true', async () => {
// Temporarily override `console.error`
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation()
const instance = new RedisAccessor({ prefix: 'myPrefix' })
instance._client.set = jest.fn((...args) => args.pop()(new Error('Redis ReplyError')))
await expect(instance.set('myKey', 'myValue')).rejects.toThrowError(
new Error(`Failed to set value in Redis.
Key: myPrefix:myKey
Error: Redis ReplyError`)
)
expect(consoleErrorSpy).not.toBeCalled()
// Restore `console.error`
consoleErrorSpy.mockRestore()
})
test('rejects if value is an empty string', async () => {
const instance = new RedisAccessor()
await expect(instance.set('myKey', '')).rejects.toThrow(
new TypeError('Value must be a non-empty string but was: ""')
)
})
test('rejects if value is a non-string value', async () => {
const instance = new RedisAccessor()
await expect(instance.set('myKey', true)).rejects.toThrow(
new TypeError('Value must be a non-empty string but was: true')
)
})
test('invokes .translateSetArguments before sending values to Redis', async () => {
const argSpy = jest.spyOn(RedisAccessor, 'translateSetArguments')
const instance = new RedisAccessor()
const setSpy = jest.spyOn(instance._client, 'set')
await instance.set('myKey', 'myValue', { expireIn: 20 })
expect(argSpy).toBeCalled()
expect(setSpy.mock.calls.length).toBe(1)
expect(setSpy.mock.calls[0].slice(0, 4)).toEqual(['myKey', 'myValue', 'PX', 20])
argSpy.mockRestore()
})
})
describe('#get method', () => {
test('resolves to expected value if matching entry exists in Redis', async () => {
const instance = new RedisAccessor()
await instance.set('myKey', 'myValue')
const result = await instance.get('myKey')
expect(result).toBe('myValue')
})
test('resolves to null if no matching entry exists in Redis', async () => {
const instance = new RedisAccessor()
const result = await instance.get('fakeKey')
expect(result).toBe(null)
})
test('retrieves matching entry from Redis with #_client.get', async () => {
const instance = new RedisAccessor()
let callbackSpy
const originalGet = instance._client.get.bind(instance._client)
instance._client.get = jest.fn((...args) => {
const realCallback = args.pop()
callbackSpy = jest.fn((error, value) => {
realCallback(error, value)
})
return originalGet(...args, callbackSpy)
})
await instance.set('myKey', 'myValue')
await instance.get('myKey')
expect(instance._client.get.mock.calls.length).toBe(1)
expect(instance._client.get.mock.calls[0].slice(0, 1)).toEqual(['myKey'])
expect(callbackSpy).toHaveBeenCalledWith(null, 'myValue')
})
test('resolves to null if Redis replies with an error and `allowGetFailures` option is set to true', async () => {
// Temporarily override `console.error`
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation()
const instance = new RedisAccessor({ prefix: 'myPrefix', allowGetFailures: true })
instance._client.get = jest.fn((...args) => args.pop()(new Error('Redis ReplyError')))
const result = await instance.get('myKey', 'myValue')
expect(result).toBe(null)
expect(consoleErrorSpy).toBeCalledWith(
`Failed to get value from Redis.
Key: myPrefix:myKey
Error: Redis ReplyError`
)
// Restore `console.error`
consoleErrorSpy.mockRestore()
})
test('rejects if Redis replies with an error and `allowGetFailures` option is not set to true', async () => {
// Temporarily override `console.error`
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation()
const instance = new RedisAccessor({ prefix: 'myPrefix' })
instance._client.get = jest.fn((...args) => args.pop()(new Error('Redis ReplyError')))
await expect(instance.get('myKey')).rejects.toThrowError(
new Error(`Failed to get value from Redis.
Key: myPrefix:myKey
Error: Redis ReplyError`)
)
expect(consoleErrorSpy).not.toBeCalled()
// Restore `console.error`
consoleErrorSpy.mockRestore()
})
})
})