Merge branch 'main' into fix-inconsistencies
This commit is contained in:
@@ -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.
|
||||
2
.github/allowed-actions.js
vendored
2
.github/allowed-actions.js
vendored
@@ -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',
|
||||
|
||||
2
.github/workflows/link-check-dotcom.yml
vendored
2
.github/workflows/link-check-dotcom.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/link-check-ghae.yml
vendored
2
.github/workflows/link-check-ghae.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/link-check-ghes.yml
vendored
2
.github/workflows/link-check-ghes.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/openapi-schema-check.yml
vendored
2
.github/workflows/openapi-schema-check.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -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
|
||||
|
||||
@@ -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. 🚂`
|
||||
})
|
||||
|
||||
6
.github/workflows/workflow-lint.yml
vendored
6
.github/workflows/workflow-lint.yml
vendored
@@ -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"]'
|
||||
|
||||
2
Procfile
2
Procfile
@@ -1,3 +1 @@
|
||||
web: NODE_ENV=production node server.mjs
|
||||
|
||||
release: NODE_ENV=production script/release-heroku
|
||||
|
||||
118
components/GenericError.tsx
Normal file
118
components/GenericError.tsx
Normal 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>© {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>
|
||||
)
|
||||
}
|
||||
@@ -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`}
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ topics:
|
||||
- Accounts
|
||||
children:
|
||||
- /quickstart
|
||||
- /onboarding
|
||||
- /learning-about-github
|
||||
- /signing-up-for-github
|
||||
- /using-github
|
||||
|
||||
@@ -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 %}
|
||||
@@ -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)."
|
||||
@@ -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 %}
|
||||
@@ -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)"
|
||||
@@ -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 %}
|
||||
14
content/get-started/onboarding/index.md
Normal file
14
content/get-started/onboarding/index.md
Normal 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
|
||||
---
|
||||
@@ -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)."
|
||||
1
data/reusables/getting-started/actions.md
Normal file
1
data/reusables/getting-started/actions.md
Normal 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)."
|
||||
@@ -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)."
|
||||
1
data/reusables/getting-started/api.md
Normal file
1
data/reusables/getting-started/api.md
Normal 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)."
|
||||
@@ -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)."
|
||||
@@ -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)."
|
||||
1
data/reusables/getting-started/contact-support.md
Normal file
1
data/reusables/getting-started/contact-support.md
Normal 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)."
|
||||
1
data/reusables/getting-started/creating-organizations.md
Normal file
1
data/reusables/getting-started/creating-organizations.md
Normal 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)."
|
||||
1
data/reusables/getting-started/creating-teams.md
Normal file
1
data/reusables/getting-started/creating-teams.md
Normal 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)."
|
||||
@@ -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.
|
||||
@@ -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)."
|
||||
@@ -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)."
|
||||
@@ -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)."
|
||||
@@ -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)."
|
||||
3
data/reusables/getting-started/learning-lab.md
Normal file
3
data/reusables/getting-started/learning-lab.md
Normal 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)."
|
||||
@@ -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)."
|
||||
1
data/reusables/getting-started/managing-org-members.md
Normal file
1
data/reusables/getting-started/managing-org-members.md
Normal 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)."
|
||||
5
data/reusables/getting-started/managing-org-policies.md
Normal file
5
data/reusables/getting-started/managing-org-policies.md
Normal 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)."
|
||||
3
data/reusables/getting-started/managing-repo-changes.md
Normal file
3
data/reusables/getting-started/managing-repo-changes.md
Normal 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)."
|
||||
3
data/reusables/getting-started/managing-team-settings.md
Normal file
3
data/reusables/getting-started/managing-team-settings.md
Normal 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)."
|
||||
1
data/reusables/getting-started/marketplace.md
Normal file
1
data/reusables/getting-started/marketplace.md
Normal 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)."
|
||||
4
data/reusables/getting-started/open-source-projects.md
Normal file
4
data/reusables/getting-started/open-source-projects.md
Normal 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 %}
|
||||
@@ -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)."
|
||||
1
data/reusables/getting-started/packages.md
Normal file
1
data/reusables/getting-started/packages.md
Normal 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)."
|
||||
@@ -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 %}.
|
||||
1
data/reusables/getting-started/requiring-2fa.md
Normal file
1
data/reusables/getting-started/requiring-2fa.md
Normal 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)."
|
||||
@@ -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)."
|
||||
@@ -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)."
|
||||
1
data/reusables/getting-started/sponsors.md
Normal file
1
data/reusables/getting-started/sponsors.md
Normal 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)."
|
||||
@@ -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)."
|
||||
1
data/reusables/github-ae/initialize-enterprise.md
Normal file
1
data/reusables/github-ae/initialize-enterprise.md
Normal 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
1
next-env.d.ts
vendored
@@ -1,2 +1,3 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
182
pages/404.tsx
182
pages/404.tsx
@@ -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>© {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
|
||||
|
||||
158
pages/500.tsx
158
pages/500.tsx
@@ -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>© {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
10
pages/_error.tsx
Normal 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
|
||||
@@ -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.
|
||||
|
||||
38
script/enterprise-server-deprecations/remove-redirects.js
Executable file
38
script/enterprise-server-deprecations/remove-redirects.js
Executable 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))
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -13,3 +13,7 @@
|
||||
.rotate-180 {
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
|
||||
.min-h-screen {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user