1
0
mirror of synced 2025-12-23 03:44:00 -05:00

Merge branch 'main' into andrekolodochka-patch-2

This commit is contained in:
Laura Coursen
2021-10-01 09:41:56 -05:00
16955 changed files with 445791 additions and 94102 deletions

View File

@@ -119,6 +119,7 @@ async function run() {
const statusID = findFieldID('Status', data)
const featureID = findFieldID('Feature', data)
const contributorTypeID = findFieldID('Contributor type', data)
const sizeTypeID = findFieldID('Size', data)
const authorID = findFieldID('Author', data)
// Get the ID of the single select values that we want to set
@@ -169,6 +170,8 @@ async function run() {
reviewDueDateID: reviewDueDateID,
contributorTypeID: contributorTypeID,
contributorType: contributorType,
sizeTypeID: sizeTypeID,
sizeType: '', // Although we aren't populating size, we are passing the variable so that we can use the shared mutation function
featureID: featureID,
authorID: authorID,
headers: {

View File

@@ -186,6 +186,8 @@ export function generateUpdateProjectNextItemFieldMutation({
$reviewDueDateID: ID!
$contributorTypeID: ID!
$contributorType: String!
$sizeTypeID: ID!
$sizeType: String!
$featureID: ID!
$authorID: ID!
) {
@@ -211,6 +213,11 @@ export function generateUpdateProjectNextItemFieldMutation({
fieldID: '$contributorTypeID',
value: '$contributorType',
})}
${generateMutationToUpdateField({
item: item,
fieldID: '$sizeTypeID',
value: '$sizeType',
})}
${generateMutationToUpdateField({
item: item,
fieldID: '$featureID',

View File

@@ -12,7 +12,7 @@ async function run() {
// Get info about the docs-content review board project
const data = await graphql(
`
query ($organization: String!, $projectNumber: Int!) {
query ($organization: String!, $projectNumber: Int!, $id: ID!) {
organization(login: $organization) {
projectNext(number: $projectNumber) {
id
@@ -25,9 +25,22 @@ async function run() {
}
}
}
item: node(id: $id) {
__typename
... on PullRequest {
files(first: 100) {
nodes {
additions
deletions
path
}
}
}
}
}
`,
{
id: process.env.ITEM_NODE_ID,
organization: process.env.ORGANIZATION,
projectNumber: parseInt(process.env.PROJECT_NUMBER),
headers: {
@@ -46,6 +59,7 @@ async function run() {
const statusID = findFieldID('Status', data)
const featureID = findFieldID('Feature', data)
const contributorTypeID = findFieldID('Contributor type', data)
const sizeTypeID = findFieldID('Size', data)
const authorID = findFieldID('Author', data)
// Get the ID of the single select values that we want to set
@@ -53,22 +67,115 @@ async function run() {
const hubberTypeID = findSingleSelectID('Hubber or partner', 'Contributor type', data)
const docsMemberTypeID = findSingleSelectID('Docs team', 'Contributor type', data)
const osContributorTypeID = findSingleSelectID('OS contributor', 'Contributor type', data)
const sizeXS = findSingleSelectID('XS', 'Size', data)
const sizeS = findSingleSelectID('S', 'Size', data)
const sizeM = findSingleSelectID('M', 'Size', data)
const sizeL = findSingleSelectID('L', 'Size', data)
// Add the PR to the project
const newItemID = await addItemToProject(process.env.PR_NODE_ID, projectID)
const newItemID = await addItemToProject(process.env.ITEM_NODE_ID, projectID)
// If the item is a PR, determine the feature and size
let feature = ''
let sizeType = '' // You don't need to use a field ID if you want the value to be empty
if (data.item.__typename === 'PullRequest') {
// Get the
// - number of files changed
// - total number of additions/deletions
// - affected docs sets (not considering changes to data/assets)
let numFiles = 0
let numChanges = 0
let features = new Set([])
const files = data.item.files.nodes.forEach((node) => {
numFiles += 1
numChanges += node.additions
numChanges += node.deletions
// To determine the feature, we are only looking at `content/*` paths
// and then pulling out the second part of the path, which corresponds to the docs set
const pathComponents = node.path.split('/')
if (pathComponents[0] === 'content') {
features.add(pathComponents[1])
}
})
// Determine the size
if (numFiles < 5 && numChanges < 25) {
sizeType = sizeXS
} else if (numFiles < 5 && numChanges < 25) {
sizeType = sizeS
} else if (numFiles < 5 && numChanges < 25) {
sizeType = sizeM
} else {
sizeType = sizeL
}
// Set the feature
feature = Array.from(features).join()
}
// If this is the OS repo, determine if this is a first time contributor
// If yes, set the author to 'first time contributor' instead of to the author login
let firstTimeContributor
if (process.env.REPO === 'github/docs') {
const contributorData = await graphql(
`
query ($author: String!) {
user(login: $author) {
contributionsCollection {
pullRequestContributionsByRepository {
contributions {
totalCount
}
repository {
nameWithOwner
}
}
issueContributionsByRepository {
contributions {
totalCount
}
repository {
nameWithOwner
}
}
}
}
}
`,
{
author: process.env.AUTHOR_LOGIN,
headers: {
authorization: `token ${process.env.TOKEN}`,
},
}
)
const prCount =
contributorData.user.contributionsCollection.pullRequestContributionsByRepository.filter(
(item) => item.repository.nameWithOwner === 'github/docs'
)[0].contributions.totalCount
const issueCount =
contributorData.user.contributionsCollection.issueContributionsByRepository.filter(
(item) => item.repository.nameWithOwner === 'github/docs'
)[0].contributions.totalCount
if (prCount + issueCount <= 1) {
firstTimeContributor = true
}
}
const turnaround = process.env.REPO === 'github/docs' ? 3 : 2
// Generate a mutation to populate fields for the new project item
const updateProjectNextItemMutation = generateUpdateProjectNextItemFieldMutation({
item: newItemID,
author: process.env.AUTHOR_LOGIN,
turnaround: 2,
author: firstTimeContributor ? 'first time contributor' : process.env.AUTHOR_LOGIN,
turnaround: turnaround,
feature: feature,
})
// Determine which variable to use for the contributor type
let contributorType
if (await isDocsTeamMember(process.env.AUTHOR_LOGIN)) {
contributorType = docsMemberTypeID
} else if (process.env.PR_REPO === 'github/docs') {
} else if (process.env.REPO === 'github/docs') {
contributorType = osContributorTypeID
} else {
contributorType = hubberTypeID
@@ -84,6 +191,8 @@ async function run() {
reviewDueDateID: reviewDueDateID,
contributorTypeID: contributorTypeID,
contributorType: contributorType,
sizeTypeID: sizeTypeID,
sizeType: sizeType,
featureID: featureID,
authorID: authorID,
headers: {

View File

@@ -13,7 +13,7 @@ jobs:
transfer-issue:
name: Transfer issue
runs-on: ubuntu-latest
if: github.event.label.name == 'rest-description' && github.repository == 'github/docs'
if: (github.event.label.name == 'rest-description' || github.event.label.name == 'graphql-description') && github.repository == 'github/docs'
steps:
- name: Check if this run was triggered by a member of the docs team
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
@@ -57,7 +57,7 @@ jobs:
OLD_ISSUE: ${{ github.event.issue.html_url }}
- name: Comment on the old issue
run: gh issue comment $OLD_ISSUE --body "Thank you for opening this issue! Updates to the REST API description must be made internally. I have copied your issue to an internal issue, so I will close this issue."
run: gh issue comment $OLD_ISSUE --body "Thank you for opening this issue! Updates to the REST/GraphQL API description must be made internally. I have copied your issue to an internal issue, so I will close this issue."
env:
GITHUB_TOKEN: ${{secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES}}
OLD_ISSUE: ${{ github.event.issue.html_url }}

View File

@@ -0,0 +1,68 @@
name: OS Ready for review
# **What it does**: Adds pull requests and issues in the docs repository to the docs-content review board when the "waiting for review" label is added
# **Why we have it**: So that contributors in the OS repo can easily get reviews from the docs-content team, and so that writers can see when a PR is ready for review
# **Who does it impact**: Writers working in the docs repository
permissions:
contents: read
on:
pull_request:
types: [labeled]
issues:
types: [labeled]
jobs:
request_doc_review:
name: Request a review from the docs-content team
if: github.event.label.name == 'waiting for review' && github.repository == 'github/docs'
runs-on: ubuntu-latest
steps:
- name: Exit if not triggered by a docs team member
env:
GITHUB_TOKEN: ${{ secrets.DOCUBOT_READORG_REPO_WORKFLOW_SCOPES }}
run: |
members="$( gh api graphql -f query='
query {
organization(login: "github") {
team(slug: "docs") {
members {
nodes {
login
}
}
}
}
}
' --jq '.data.organization.team.members.nodes | [(.[].login)]')"
isMember=$(echo ${members[@]} | grep -ow $GITHUB_ACTOR | wc -w)
if [ $isMember -eq 0 ]
then
echo "$GITHUB_ACTOR is not a docs team member. exiting..."
exit 1
fi
- name: Check out repo content
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
- name: Setup Node
uses: actions/setup-node@38d90ce44d5275ad62cc48384b3d8a58c500bb5f
with:
node-version: 16.x
cache: npm
- name: Install dependencies
run: npm install @octokit/graphql
- name: Run script
run: |
node .github/actions-scripts/ready-for-docs-review.js
env:
TOKEN: ${{ secrets.DOCS_BOT_FR }}
PROJECT_NUMBER: 2936
ORGANIZATION: 'github'
ITEM_NODE_ID: ${{ github.event.pull_request.node_id || github.event.issue.node_id }}
AUTHOR_LOGIN: ${{ github.event.pull_request.user.login || github.event.issue.user.login }}
REPO: ${{ github.repository }}

View File

@@ -27,6 +27,10 @@ jobs:
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
with:
persist-credentials: 'false'
lfs: 'true'
- name: Check out LFS objects
run: git lfs checkout
- name: Setup node
uses: actions/setup-node@38d90ce44d5275ad62cc48384b3d8a58c500bb5f

View File

@@ -33,9 +33,9 @@ jobs:
TOKEN: ${{ secrets.DOCS_BOT_FR }}
PROJECT_NUMBER: 2936
ORGANIZATION: 'github'
PR_NODE_ID: ${{ github.event.pull_request.node_id }}
ITEM_NODE_ID: ${{ github.event.pull_request.node_id }}
AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
PR_REPO: ${{ github.event.pull_request.base.repo.full_name }}
REPO: ${{ github.event.pull_request.base.repo.full_name }}
# Since the projects API is still in beta, use the old workflow if something fails
# so that we don't miss these PRs

View File

@@ -136,12 +136,15 @@ jobs:
target_url: ACTIONS_RUN_LOG
})
- if: ${{ github.repository == 'github/docs-internal' }}
name: Check out repo's default branch
- name: Check out repo's default branch
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
with:
# To prevent issues with cloning early access content later
persist-credentials: 'false'
lfs: 'true'
- name: Check out LFS objects
run: git lfs checkout
- if: ${{ github.repository == 'github/docs-internal' }}
name: Setup node to clone early access
@@ -171,24 +174,25 @@ jobs:
name: pr_build
path: ./
- if: ${{ github.repository == 'github/docs-internal' }}
name: Extract user-changes to temp directory
- name: Extract user-changes to temp directory
run: |
tar -x --file=app.tar -C "$RUNNER_TEMP/"
rm app.tar
# Append early access content into the temp directory
- if: ${{ github.repository == 'github/docs-internal' }}
name: Merge in the early access content
# Move the LFS content into the temp directory in chunks (destructively)
- name: Move the LFS objects
run: |
rsync -aiR \
assets/images/early-access \
content/early-access \
data/early-access \
"$RUNNER_TEMP/"
git lfs ls-files --name-only | xargs -n 1 -I {} sh -c 'mkdir -p "$RUNNER_TEMP/$(dirname {})"; mv {} "$RUNNER_TEMP/$(dirname {})/"'
# Move the early access content into the temp directory (destructively)
- if: ${{ github.repository == 'github/docs-internal' }}
name: Create an updated archive
name: Move the early access content
run: |
mv assets/images/early-access "$RUNNER_TEMP/assets/images/"
mv content/early-access "$RUNNER_TEMP/content/"
mv data/early-access "$RUNNER_TEMP/data/"
- name: Create an updated archive
run: tar -c --file app.tar "$RUNNER_TEMP/"
# Create "app.tar.gz" and delete "app.tar"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -37,7 +37,7 @@ export function Link(props: Props) {
}
return (
<NextLink href={href || ''} locale={locale || false}>
<NextLink href={locale ? `/${locale}${href}` : href || ''} locale={locale || false}>
{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}
<a rel={isExternal ? 'noopener' : ''} {...restProps} />
</NextLink>

View File

@@ -171,7 +171,7 @@ export function Search({
)}
>
{results.length > 0 ? (
<ol data-testid="search-results" className="d-block mt-2">
<ol data-testid="search-results" className="d-block mt-4">
{results.map(({ url, breadcrumbs, heading, title, content }, index) => {
const isActive = index === activeHit
return (

View File

@@ -0,0 +1,126 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import { Dropdown, Heading, Details, Box, Text, useDetails } from '@primer/components'
import { ArrowRightIcon, ChevronDownIcon } from '@primer/octicons-react'
import { Link } from 'components/Link'
import { useMainContext } from 'components/context/MainContext'
import { useVersion } from 'components/hooks/useVersion'
import { useTranslation } from 'components/hooks/useTranslation'
type Props = {
hideLabel?: boolean
variant?: 'default' | 'compact' | 'inline'
popoverVariant?: 'inline' | 'dropdown'
}
export const VersionPicker = ({ variant = 'default', popoverVariant, hideLabel }: Props) => {
const router = useRouter()
const { currentVersion } = useVersion()
const { allVersions, page, enterpriseServerVersions } = useMainContext()
const { getDetailsProps, setOpen } = useDetails({ closeOnOutsideClick: true })
const { t } = useTranslation('pages')
if (page.permalinks && page.permalinks.length <= 1) {
return null
}
return (
<>
{!hideLabel && (
<Heading as="span" fontSize={1} className="d-none d-xl-inline-block mb-1">
{t('article_version')}
</Heading>
)}
<div>
<Details
{...getDetailsProps()}
className={cx(
'position-relative details-reset',
variant === 'inline' ? 'd-block' : 'd-inline-block'
)}
data-testid="article-version-picker"
>
{(variant === 'compact' || variant === 'inline') && (
<summary
className="d-block btn btn-invisible color-text-primary"
aria-haspopup="true"
aria-label="Toggle version list"
>
{variant === 'inline' ? (
<div className="d-flex flex-items-center flex-justify-between">
<Text>{allVersions[currentVersion].versionTitle}</Text>
<ChevronDownIcon size={24} className="arrow ml-md-1" />
</div>
) : (
<>
<Text>{allVersions[currentVersion].versionTitle}</Text>
<Dropdown.Caret />
</>
)}
</summary>
)}
{variant === 'default' && (
<summary aria-haspopup="true" className="btn btn-sm">
<Text>{allVersions[currentVersion].versionTitle}</Text>
<Dropdown.Caret />
</summary>
)}
{popoverVariant === 'inline' ? (
<Box py="2">
{(page.permalinks || []).map((permalink) => {
return (
<Dropdown.Item key={permalink.href} onClick={() => setOpen(false)}>
<Link href={permalink.href}>{permalink.pageVersionTitle}</Link>
</Dropdown.Item>
)
})}
<Box mt={1}>
<Link
onClick={() => {
setOpen(false)
}}
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap"
>
{t('all_enterprise_releases')}{' '}
<ArrowRightIcon verticalAlign="middle" size={15} className="mr-2" />
</Link>
</Box>
</Box>
) : (
<Dropdown.Menu direction="sw" style={{ width: 'unset' }}>
{(page.permalinks || []).map((permalink) => {
return (
<Dropdown.Item key={permalink.href} onClick={() => setOpen(false)}>
<Link href={permalink.href}>{permalink.pageVersionTitle}</Link>
</Dropdown.Item>
)
})}
<Box
borderColor="border.default"
borderTopWidth={1}
borderTopStyle="solid"
mt={2}
pt={2}
pb={1}
>
<Link
onClick={() => {
setOpen(false)
}}
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap"
>
{t('all_enterprise_releases')}{' '}
<ArrowRightIcon verticalAlign="middle" size={15} className="mr-2" />
</Link>
</Box>
</Dropdown.Menu>
)}
</Details>
</div>
</>
)
}

View File

@@ -1,44 +0,0 @@
@import "@primer/css/layout/index.scss";
@import "@primer/css/support/variables/layout.scss";
@import "@primer/css/marketing/support/variables.scss";
.container {
max-width: 720px;
@include breakpoint(xl) {
max-width: none;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: minmax(500px, 720px) minmax(220px, 1fr);
grid-template-areas:
"top right-sidebar"
"bottom right-sidebar";
column-gap: $spacer-6;
}
@include breakpoint(xl) {
column-gap: $spacer-9;
}
}
.sidebar {
grid-area: right-sidebar;
}
.sidebarContent {
@include breakpoint(xl) {
position: sticky;
top: $spacer-4;
max-height: calc(100vh - #{$spacer-4});
overflow-y: auto;
padding-bottom: $spacer-4;
}
}
.head {
grid-area: top;
}
.content {
grid-area: bottom;
}

View File

@@ -1,30 +1,78 @@
import React from 'react'
import cx from 'classnames'
import styles from './ArticleGridLayout.module.scss'
import styled from 'styled-components'
import { Box, themeGet } from '@primer/components'
type Props = {
head?: React.ReactNode
intro?: React.ReactNode
topperSidebar?: React.ReactNode
topper?: React.ReactNode
toc?: React.ReactNode
children?: React.ReactNode
className?: string
}
export const ArticleGridLayout = ({ head, toc, children, className }: Props) => {
export const ArticleGridLayout = ({
intro,
topperSidebar,
topper,
toc,
children,
className,
}: Props) => {
return (
<div className={cx(styles.container, className)}>
{/* head */}
{head && <div className={styles.head}>{head}</div>}
{/* toc */}
<Container className={className}>
{topper && <Box gridArea="topper">{topper}</Box>}
{topperSidebar && <Box gridArea="topper-sidebar">{topperSidebar}</Box>}
{toc && (
<div className={cx(styles.sidebar, 'border-bottom border-xl-0 pb-4 mb-5 pb-xl-0 mb-xl-0')}>
<div className={styles.sidebarContent}>{toc}</div>
</div>
<SidebarContent
gridArea="sidebar"
alignSelf="flex-start"
className="border-bottom border-xl-0 pb-4 mb-5 pb-xl-0 mb-xl-0"
>
{toc}
</SidebarContent>
)}
{/* content */}
<div data-search="article-body" className={styles.content}>
{intro && <Box gridArea="intro">{intro}</Box>}
<Box gridArea="content" data-search="article-body">
{children}
</div>
</div>
</Box>
</Container>
)
}
const Container = styled(Box)`
max-width: 720px;
display: grid;
grid-template-areas:
'topper'
'topper-sidebar'
'intro'
'sidebar'
'content';
row-gap: ${themeGet('space.2')};
@media (min-width: ${themeGet('breakpoints.3')}) {
max-width: none;
grid-template-rows: auto 1fr;
grid-template-columns: minmax(500px, 720px) minmax(220px, 1fr);
grid-template-areas:
'topper topper-sidebar'
'intro sidebar'
'content sidebar';
column-gap: ${themeGet('space.9')};
row-gap: 0;
}
`
const SidebarContent = styled(Box)`
@media (min-width: ${themeGet('breakpoints.3')}) {
position: sticky;
padding-top: ${themeGet('space.4')};
top: 0;
max-height: calc(100vh - ${themeGet('space.4')});
overflow-y: auto;
padding-bottom: ${themeGet('space.4')};
}
`

View File

@@ -1,12 +1,12 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import { Heading } from '@primer/components'
import { ZapIcon, InfoIcon } from '@primer/octicons-react'
import { Callout } from 'components/ui/Callout'
import { Link } from 'components/Link'
import { DefaultLayout } from 'components/DefaultLayout'
import { ArticleTopper } from 'components/article/ArticleTopper'
import { ArticleTitle } from 'components/article/ArticleTitle'
import { useArticleContext } from 'components/context/ArticleContext'
import { useTranslation } from 'components/hooks/useTranslation'
@@ -14,6 +14,8 @@ import { LearningTrackNav } from './LearningTrackNav'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import { Lead } from 'components/ui/Lead'
import { ArticleGridLayout } from './ArticleGridLayout'
import { VersionPicker } from 'components/VersionPicker'
import { Breadcrumbs } from 'components/Breadcrumbs'
// Mapping of a "normal" article to it's interactive counterpart
const interactiveAlternatives: Record<string, { href: string }> = {
@@ -44,12 +46,11 @@ export const ArticlePage = () => {
return (
<DefaultLayout>
<div className="container-xl px-3 px-md-6 my-4 my-lg-4">
<ArticleTopper />
<div className="container-xl px-3 px-md-6 my-4">
<ArticleGridLayout
className="mt-7"
head={
topper={<Breadcrumbs />}
topperSidebar={<VersionPicker />}
intro={
<>
<ArticleTitle>{title}</ArticleTitle>
@@ -124,11 +125,11 @@ export const ArticlePage = () => {
)}
{miniTocItems.length > 1 && (
<>
<h2 id="in-this-article" className="f5 mb-2">
<Heading as="h2" fontSize={1} id="in-this-article" className="mb-1">
<a className="Link--primary" href="#in-this-article">
{t('miniToc')}
</a>
</h2>
</Heading>
<ul className="list-style-none pl-0 f5 mb-0">
{miniTocItems.map((item) => {
return (

View File

@@ -4,7 +4,7 @@ type Props = {
export const ArticleTitle = ({ children }: Props) => {
return (
<div className="d-flex flex-items-baseline flex-justify-between">
<h1 className="my-4 border-bottom-0">{children}</h1>
<h1 className="mt-4 border-bottom-0">{children}</h1>
</div>
)
}

View File

@@ -1,18 +0,0 @@
import { Breadcrumbs } from 'components/Breadcrumbs'
import { ArticleVersionPicker } from 'components/article/ArticleVersionPicker'
export const ArticleTopper = () => {
return (
<div className="d-lg-flex flex-justify-between">
<div className="d-block d-lg-none mb-2">
<ArticleVersionPicker />
</div>
<div className="d-flex flex-items-center">
<Breadcrumbs />
</div>
<div className="d-none d-lg-block">
<ArticleVersionPicker />
</div>
</div>
)
}

View File

@@ -1,52 +0,0 @@
import { useRouter } from 'next/router'
import { Dropdown } from '@primer/components'
import { Link } from 'components/Link'
import { useMainContext } from 'components/context/MainContext'
import { useVersion } from 'components/hooks/useVersion'
import { useTranslation } from 'components/hooks/useTranslation'
export const ArticleVersionPicker = () => {
const router = useRouter()
const { currentVersion } = useVersion()
const { allVersions, page, enterpriseServerVersions } = useMainContext()
const { t } = useTranslation('pages')
if (page.permalinks && page.permalinks.length <= 1) {
return null
}
return (
<Dropdown
css={`
ul {
width: unset;
}
`}
data-testid="article-version-picker"
>
<summary className="btn btn-outline p-2 outline-none">
<span className="d-md-none d-xl-inline-block">{t('article_version')}</span>{' '}
{allVersions[currentVersion].versionTitle}
<Dropdown.Caret />
</summary>
<Dropdown.Menu direction="sw">
{(page.permalinks || []).map((permalink) => {
return (
<Dropdown.Item key={permalink.href}>
<Link href={permalink.href}>{permalink.pageVersionTitle}</Link>
</Dropdown.Item>
)
})}
<div className="pb-1">
<Link
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap"
>
See all Enterprise releases
</Link>
</div>
</Dropdown.Menu>
</Dropdown>
)
}

View File

@@ -6,7 +6,7 @@ type Props = {
}
export function LearningTrackNav({ track }: Props) {
const { t } = useTranslation('learning_track_nav')
const { prevGuide, nextGuide, trackName } = track
const { prevGuide, nextGuide, trackName, trackProduct } = track
return (
<div
data-testid="learning-track-nav"
@@ -17,7 +17,7 @@ export function LearningTrackNav({ track }: Props) {
<>
<span className="f6 color-text-secondary">{t('prevGuide')}</span>
<a
href={`${prevGuide.href}?learn=${trackName}`}
href={`${prevGuide.href}?learn=${trackName}&learnProduct=${trackProduct}`}
className="text-bold color-text-secondary"
>
{prevGuide.title}
@@ -31,7 +31,7 @@ export function LearningTrackNav({ track }: Props) {
<>
<span className="f6 color-text-secondary">{t('nextGuide')}</span>
<a
href={`${nextGuide.href}?learn=${trackName}`}
href={`${nextGuide.href}?learn=${trackName}&learnProduct=${trackProduct}`}
className="text-bold color-text-secondary text-right f4"
>
{nextGuide.title}

View File

@@ -2,6 +2,7 @@ import { createContext, useContext } from 'react'
export type LearningTrack = {
trackName?: string
trackProduct?: string
prevGuide?: { href: string; title: string }
nextGuide?: { href: string; title: string }
}

View File

@@ -62,10 +62,6 @@ export type MainContextT = {
article?: BreadcrumbT
}
activeProducts: Array<ProductT>
community_redirect: {
name: string
href: string
}
currentProduct?: ProductT
currentLayoutName: string
isHomepageVersion: boolean
@@ -114,7 +110,6 @@ export const getMainContext = (req: any, res: any): MainContextT => {
return {
breadcrumbs: req.context.breadcrumbs || {},
activeProducts: req.context.activeProducts,
community_redirect: req.context.page?.community_redirect || {},
currentProduct: req.context.productMap[req.context.currentProduct] || null,
currentLayoutName: req.context.currentLayoutName,
isHomepageVersion: req.context.page?.documentType === 'homepage',

View File

@@ -3,6 +3,7 @@ import pick from 'lodash/pick'
export type FeaturedTrack = {
trackName: string
trackProduct: string
title: string
description: string
guides?: Array<{ href: string; page?: { type: string }; title: string; intro: string }>
@@ -47,14 +48,14 @@ export const getProductSubLandingContextFromRequest = (req: any): ProductSubLand
title: req.context.productMap[req.context.currentProduct].name,
featuredTrack: page.featuredTrack
? {
...pick(page.featuredTrack, ['title', 'description', 'trackName']),
...pick(page.featuredTrack, ['title', 'description', 'trackName', 'trackProduct']),
guides: (page.featuredTrack?.guides || []).map((guide: any) => {
return pick(guide, ['title', 'intro', 'href', 'page.type'])
}),
}
: null,
learningTracks: (page.learningTracks || []).map((track: any) => ({
...pick(track, ['title', 'description', 'trackName']),
...pick(track, ['title', 'description', 'trackName', 'trackProduct']),
guides: (track.guides || []).map((guide: any) => {
return pick(guide, ['title', 'intro', 'href', 'page.type'])
}),

View File

@@ -38,7 +38,6 @@ export const useTocLandingContext = (): TocLandingContextT => {
}
export const getTocLandingContextFromRequest = (req: any): TocLandingContextT => {
const isEarlyAccess = req.context.page?.documentType === 'early-access'
return {
title: req.context.page.titlePlainText,
productCallout: req.context.page.product || '',
@@ -49,7 +48,7 @@ export const getTocLandingContextFromRequest = (req: any): TocLandingContextT =>
variant: req.context.genericTocFlat ? 'expanded' : 'compact',
featuredLinks: getFeaturedLinksFromReq(req),
renderedPage: isEarlyAccess ? req.context.renderedPage : '',
renderedPage: req.context.renderedPage,
currentLearningTrack: req.context.currentLearningTrack,
}
}

View File

@@ -1,93 +0,0 @@
import cx from 'classnames'
import { useRouter } from 'next/router'
import { Dropdown, Details, useDetails } from '@primer/components'
import { ChevronDownIcon } from '@primer/octicons-react'
import { Link } from 'components/Link'
import { useMainContext } from 'components/context/MainContext'
import { useVersion } from 'components/hooks/useVersion'
type Props = {
variant?: 'inline'
}
export const HomepageVersionPicker = ({ variant }: Props) => {
const router = useRouter()
const { currentVersion } = useVersion()
const { getDetailsProps } = useDetails({})
const { allVersions, page, enterpriseServerVersions } = useMainContext()
if (page.permalinks && page.permalinks.length <= 1) {
return null
}
const label = allVersions[currentVersion].versionTitle
if (variant === 'inline') {
return (
<Details {...getDetailsProps()} className="details-reset">
<summary className="outline-none" aria-label="Toggle language list">
<div className="d-flex flex-items-center flex-justify-between py-2">
<span>{label}</span>
<ChevronDownIcon size={24} className="arrow ml-md-1" />
</div>
</summary>
<div>
{(page.permalinks || []).map((permalink) => {
return (
<Link
key={permalink.href}
href={permalink.href}
className={cx(
'd-block py-2',
permalink.href === router.asPath
? 'color-text-link text-underline active'
: 'Link--primary no-underline'
)}
>
{permalink.pageVersionTitle}
</Link>
)
})}
<Link
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary no-wrap"
>
See all Enterprise releases
</Link>
</div>
</Details>
)
}
return (
<Dropdown
css={`
ul {
width: unset;
}
`}
>
<summary>
{label}
<Dropdown.Caret />
</summary>
<Dropdown.Menu direction="sw">
{(page.permalinks || []).map((permalink) => {
return (
<Dropdown.Item key={permalink.href}>
<Link href={permalink.href}>{permalink.pageVersionTitle}</Link>
</Dropdown.Item>
)
})}
<div className="pb-1">
<Link
href={`/${router.locale}/${enterpriseServerVersions[0]}/admin/all-releases`}
className="f6 no-underline color-text-tertiary pl-3 pr-2 no-wrap"
>
See all Enterprise releases
</Link>
</div>
</Dropdown.Menu>
</Dropdown>
)
}

View File

@@ -1,7 +1,8 @@
import { DefaultLayout } from 'components/DefaultLayout'
import { TableOfContents } from 'components/landing/TableOfContents'
import { useTocLandingContext } from 'components/context/TocLandingContext'
import { ArticleTopper } from 'components/article/ArticleTopper'
import { VersionPicker } from 'components/VersionPicker'
import { Breadcrumbs } from 'components/Breadcrumbs'
import { ArticleTitle } from 'components/article/ArticleTitle'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import { ArticleList } from 'components/landing/ArticleList'
@@ -9,7 +10,7 @@ import { useTranslation } from 'components/hooks/useTranslation'
import { ArticleGridLayout } from 'components/article/ArticleGridLayout'
import { Callout } from 'components/ui/Callout'
import { Lead } from 'components/ui/Lead'
import { LearningTrackNav } from '../article/LearningTrackNav'
import { LearningTrackNav } from 'components/article/LearningTrackNav'
export const TocLanding = () => {
const {
@@ -26,10 +27,8 @@ export const TocLanding = () => {
return (
<DefaultLayout>
<div className="container-xl px-3 px-md-6 my-4 my-lg-4">
<ArticleTopper />
<ArticleGridLayout className="mt-7">
<div className="container-xl px-3 px-md-6 my-4">
<ArticleGridLayout topper={<Breadcrumbs />} topperSidebar={<VersionPicker />}>
<ArticleTitle>{title}</ArticleTitle>
{introPlainText && <Lead>{introPlainText}</Lead>}
@@ -59,7 +58,7 @@ export const TocLanding = () => {
)}
{renderedPage && (
<div id="article-contents">
<div id="article-contents" className="mb-5">
<MarkdownContent>{renderedPage}</MarkdownContent>
</div>
)}

View File

@@ -7,18 +7,29 @@ import { useMainContext } from 'components/context/MainContext'
export const Support = () => {
const { isEnterprise } = useVersion()
const { t } = useTranslation('support')
const { community_redirect } = useMainContext()
const { relativePath } = useMainContext()
let updatedCommunityLink = ''
if (
relativePath?.startsWith('codespaces') ||
relativePath?.startsWith('discussions') ||
relativePath?.startsWith('sponsors')
) {
const product = relativePath.substring(0, relativePath.indexOf('/'))
updatedCommunityLink = `https://github.com/github/feedback/discussions/categories/${product}-feedback`
}
return (
<div>
<h3 className="mb-2 f4">{t`still_need_help`}</h3>
<a
id="ask-community"
href={community_redirect.href || 'https://github.community/'}
href={updatedCommunityLink === '' ? 'https://github.community/' : updatedCommunityLink}
className="btn btn-outline mr-4 mt-2"
>
<PeopleIcon size="small" className="octicon mr-1" />
{Object.keys(community_redirect).length === 0 ? t`ask_community` : community_redirect.name}
{updatedCommunityLink === '' ? t`ask_community` : 'Provide GitHub Feedback'}
</a>
<a
id="contact-us"

View File

@@ -2,7 +2,6 @@ import { useState } from 'react'
import cx from 'classnames'
import { useRouter } from 'next/router'
import { MarkGithubIcon, ThreeBarsIcon, XIcon } from '@primer/octicons-react'
import { ButtonOutline } from '@primer/components'
import { Link } from 'components/Link'
import { useMainContext } from 'components/context/MainContext'
@@ -10,8 +9,8 @@ import { LanguagePicker } from './LanguagePicker'
import { HeaderNotifications } from 'components/page-header/HeaderNotifications'
import { ProductPicker } from 'components/page-header/ProductPicker'
import { useTranslation } from 'components/hooks/useTranslation'
import { HomepageVersionPicker } from 'components/landing/HomepageVersionPicker'
import { Search } from 'components/Search'
import { VersionPicker } from 'components/VersionPicker'
export const Header = () => {
const router = useRouter()
@@ -31,25 +30,23 @@ export const Header = () => {
<div className="border-bottom color-border-secondary no-print">
{error !== '404' && <HeaderNotifications />}
<header
className="container-xl px-3 px-md-6 pt-3 pb-3 position-relative"
style={{ zIndex: 2 }}
>
<header className={cx('container-xl px-3 px-md-6 pt-3 pb-3 position-relative z-3')}>
{/* desktop header */}
<div className="d-none d-lg-flex flex-justify-end" data-testid="desktop-header">
<div
className="d-none d-lg-flex flex-justify-end flex-items-center"
data-testid="desktop-header"
>
{showVersionPicker && (
<div className="py-2 mr-4">
<HomepageVersionPicker />
<div className="mr-2">
<VersionPicker hideLabel={true} variant="compact" />
</div>
)}
<div className="py-2">
<LanguagePicker />
</div>
{/* <!-- GitHub.com homepage and 404 page has a stylized search; Enterprise homepages do not --> */}
{relativePath !== 'index.md' && error !== '404' && (
<div className="d-inline-block ml-4">
<div className="d-inline-block ml-3">
<Search updateSearchParams={updateSearchParams} isOverlay={true} />
</div>
)}
@@ -72,14 +69,14 @@ export const Header = () => {
</div>
<div>
<ButtonOutline
<button
className="btn"
data-testid="mobile-menu-button"
css
onClick={() => setIsMenuOpen(!isMenuOpen)}
aria-label="Navigation Menu"
>
{isMenuOpen ? <XIcon size="small" /> : <ThreeBarsIcon size="small" />}
</ButtonOutline>
</button>
</div>
</div>
@@ -87,31 +84,33 @@ export const Header = () => {
<div className="relative">
<div
className={cx(
'width-full position-absolute left-0 right-0 color-shadow-large color-bg-primary px-3 px-md-6 pb-3',
'width-full position-absolute left-0 right-0 color-shadow-large color-bg-primary px-2 px-md-4 pb-3',
isMenuOpen ? 'd-block' : 'd-none'
)}
>
<div className="mt-3 mb-2">
<h4 className="f5 text-normal color-text-secondary">{t('explore_by_product')}</h4>
<h4 className="f5 text-normal color-text-secondary ml-3">
{t('explore_by_product')}
</h4>
<ProductPicker />
</div>
{/* <!-- Versions picker that only appears in the header on landing pages --> */}
{showVersionPicker && (
<div className="border-top py-2">
<HomepageVersionPicker variant="inline" />
</div>
<>
<div className="border-top my-2 mx-3" />
<VersionPicker hideLabel={true} variant="inline" popoverVariant={'inline'} />
</>
)}
{/* <!-- Language picker - 'English', 'Japanese', etc --> */}
<div className="border-top py-2">
<div className="border-top my-2 mx-3" />
<LanguagePicker variant="inline" />
</div>
{/* <!-- GitHub.com homepage and 404 page has a stylized search; Enterprise homepages do not --> */}
{relativePath !== 'index.md' && error !== '404' && (
<div className="pt-3 border-top">
<div className="my-2 pt-3 mx-3">
<Search updateSearchParams={updateSearchParams} />
</div>
)}

View File

@@ -1,6 +1,5 @@
import cx from 'classnames'
import { useRouter } from 'next/router'
import { Dropdown, Details, useDetails } from '@primer/components'
import { Box, Dropdown, Details, Text, useDetails } from '@primer/components'
import { ChevronDownIcon } from '@primer/octicons-react'
import { Link } from 'components/Link'
@@ -12,39 +11,32 @@ type Props = {
export const LanguagePicker = ({ variant }: Props) => {
const router = useRouter()
const { languages } = useLanguages()
const { getDetailsProps } = useDetails({})
const { getDetailsProps, setOpen } = useDetails({ closeOnOutsideClick: true })
const locale = router.locale || 'en'
const langs = Object.values(languages)
const selectedLang = languages[locale]
if (variant === 'inline') {
return (
<Details {...getDetailsProps()} className="details-reset">
<summary className="outline-none" aria-label="Toggle language list">
<div className="d-flex flex-items-center flex-justify-between py-2">
<span>{selectedLang.nativeName || selectedLang.name}</span>
<Details {...getDetailsProps()} data-testid="language-picker">
<summary
className="d-block btn btn-invisible color-text-primary"
aria-label="Toggle language list"
>
<div className="d-flex flex-items-center flex-justify-between">
<Text>{selectedLang.nativeName || selectedLang.name}</Text>
<ChevronDownIcon size={24} className="arrow ml-md-1" />
</div>
</summary>
<div>
<Box mt={1}>
{langs.map((lang) => {
if (lang.wip) {
return null
}
return (
<Link
key={lang.code}
href={router.asPath}
locale={lang.code}
disableClientTransition={true}
className={cx(
'd-block py-2',
lang.code === router.locale
? 'color-text-link text-underline active'
: 'Link--primary no-underline'
)}
>
<Dropdown.Item onClick={() => setOpen(false)} key={lang.code}>
<Link href={router.asPath} locale={lang.code}>
{lang.nativeName ? (
<>
{lang.nativeName} ({lang.name})
@@ -53,35 +45,29 @@ export const LanguagePicker = ({ variant }: Props) => {
lang.name
)}
</Link>
</Dropdown.Item>
)
})}
</div>
</Box>
</Details>
)
}
return (
<Dropdown
css={`
ul {
width: unset;
}
`}
data-testid="language-picker"
>
<summary>
{selectedLang.nativeName || selectedLang.name}
<Details {...getDetailsProps()} data-testid="language-picker" className="position-relative">
<summary className="d-block btn btn-invisible color-text-primary">
<Text>{selectedLang.nativeName || selectedLang.name}</Text>
<Dropdown.Caret />
</summary>
<Dropdown.Menu direction="sw">
<Dropdown.Menu direction="sw" style={{ width: 'unset' }}>
{langs.map((lang) => {
if (lang.wip) {
return null
}
return (
<Dropdown.Item key={lang.code}>
<Link href={router.asPath} locale={lang.code} disableClientTransition={true}>
<Dropdown.Item key={lang.code} onClick={() => setOpen(false)}>
<Link href={router.asPath} locale={lang.code}>
{lang.nativeName ? (
<>
{lang.nativeName} ({lang.name})
@@ -94,6 +80,6 @@ export const LanguagePicker = ({ variant }: Props) => {
)
})}
</Dropdown.Menu>
</Dropdown>
</Details>
)
}

View File

@@ -1,43 +1,37 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import { Link } from 'components/Link'
import { useMainContext } from 'components/context/MainContext'
import { ChevronDownIcon, LinkExternalIcon } from '@primer/octicons-react'
import { Details, useDetails } from '@primer/components'
import { Box, Dropdown, Details, useDetails } from '@primer/components'
// Product Picker - GitHub.com, Enterprise Server, etc
export const ProductPicker = () => {
const router = useRouter()
const { activeProducts, currentProduct } = useMainContext()
const { getDetailsProps } = useDetails({})
const { getDetailsProps, setOpen } = useDetails({ closeOnOutsideClick: true })
return (
<Details {...getDetailsProps()} className="details-reset">
<summary
className="color-text-link outline-none"
className="d-block color-text-primary btn btn-invisible"
role="button"
aria-label="Toggle products list"
>
<div id="current-product" className="d-flex flex-items-center flex-justify-between py-2">
{/* <!-- Product switcher - GitHub.com, Enterprise Server, etc -->
<!-- 404 and 500 error layouts are not real pages so we need to hardcode the name for those --> */}
<div
data-testid="current-product"
data-current-product-path={currentProduct?.href}
className="d-flex flex-items-center flex-justify-between"
>
<span>{currentProduct?.name || 'All Products'}</span>
<ChevronDownIcon size={24} className="arrow ml-md-1" />
</div>
</summary>
<div id="homepages" style={{ zIndex: 6 }}>
<Box data-testid="product-picker-list" py="2" style={{ zIndex: 6 }}>
{activeProducts.map((product) => {
return (
<Link
key={product.id}
href={`${product.external ? '' : `/${router.locale}`}${product.href}`}
className={cx(
'd-block py-2',
product.id === currentProduct?.id
? 'color-text-link text-underline active'
: 'Link--primary no-underline'
)}
>
<Dropdown.Item key={product.id} onClick={() => setOpen(false)}>
<Link href={`${product.external ? '' : `/${router.locale}`}${product.href}`}>
{product.name}
{product.external && (
<span className="ml-1">
@@ -45,9 +39,10 @@ export const ProductPicker = () => {
</span>
)}
</Link>
</Dropdown.Item>
)
})}
</div>
</Box>
</Details>
)
}

View File

@@ -31,17 +31,16 @@ export const CodeLanguagePicker = ({ variant }: Props) => {
}
return (
<SelectMenu css className="position-relative">
<Button as="summary" css>
<SelectMenu className="position-relative">
<Button as="summary">
{currentLanguage.label} <Dropdown.Caret />
</Button>
<SelectMenu.Modal css style={{ minWidth: 300 }} align="right">
<SelectMenu.Header css>Programming Language</SelectMenu.Header>
<SelectMenu.Modal style={{ minWidth: 300 }} align="right">
<SelectMenu.Header>Programming Language</SelectMenu.Header>
<SelectMenu.List>
{codeLanguages.map((language) => (
<SelectMenu.Item
key={language.id}
css
as="a"
href={`${routePath}?langId=${language.id}`}
selected={language.id === currentLanguage.id}

View File

@@ -3,7 +3,7 @@ import { Box, Text } from '@primer/components'
export function LoadingIndicator() {
return (
<Box display="flex" flexDirection="column" alignItems="center" py={4}>
<img width="120px" src="/playground/loading.gif" alt="bouncing octocat" />
<img width="120px" src="/assets/images/playground/loading.gif" alt="bouncing octocat" />
<Text fontFamily="mono" fontSize={1} color="gray.8">
Loading...
</Text>

View File

@@ -33,7 +33,9 @@ export const LearningTrack = ({ track }: Props) => {
<a
className="d-inline-flex btn no-wrap mt-3 mt-md-0 flex-items-center flex-justify-center"
role="button"
href={`${track?.guides && track?.guides[0].href}?learn=${track?.trackName}`}
href={`${track?.guides && track?.guides[0].href}?learn=${
track?.trackName
}&learnProduct=${track?.trackProduct}`}
>
<span>{t('start')}</span>
<ArrowRightIcon size={20} className="ml-2" />
@@ -44,7 +46,7 @@ export const LearningTrack = ({ track }: Props) => {
<div key={guide.href + track?.trackName}>
<a
className="Box-row d-flex flex-items-center color-text-primary no-underline"
href={`${guide.href}?learn=${track?.trackName}`}
href={`${guide.href}?learn=${track?.trackName}&learnProduct=${track?.trackProduct}`}
>
<div
className="color-bg-tertiary d-inline-flex mr-4 circle flex-items-center flex-justify-center"

View File

@@ -16,7 +16,7 @@ export const SubLandingHero = () => {
const guideItems = featuredTrack?.guides?.map((guide) => (
<li className="px-2 d-flex flex-shrink-0" key={guide.href} style={{ width: cardWidth }}>
<Link
href={`${guide.href}?learn=${featuredTrack.trackName}`}
href={`${guide.href}?learn=${featuredTrack.trackName}&learnProduct=${featuredTrack.trackProduct}`}
className="d-inline-block Box p-5 color-bg-primary color-border-primary no-underline"
>
<div className="d-flex flex-justify-between flex-items-center">
@@ -71,7 +71,7 @@ export const SubLandingHero = () => {
<Link
className="d-inline-flex flex-items-center flex-justify-center btn px-4 py-2 f5 no-underline text-bold"
role="button"
href={`${featuredTrack.guides[0].href}?learn=${featuredTrack.trackName}`}
href={`${featuredTrack.guides[0].href}?learn=${featuredTrack.trackName}&learnProduct=${featuredTrack.trackProduct}`}
>
{t(`start_path`)}
<ArrowRightIcon size={20} className="ml-2" />

View File

@@ -52,6 +52,14 @@ When you sign up for an account, {% data variables.product.product_name %} provi
You can change the name that is displayed on your profile. This name may also be displayed next to comments you make on private repositories owned by an organization. For more information, see "[Managing the display of member names in your organization](/articles/managing-the-display-of-member-names-in-your-organization)."
{% ifversion fpt %}
{% note %}
**Note:** If you're a member of an {% data variables.product.prodname_emu_enterprise %}, any changes to your profile name must be made through your identity provider instead of {% data variables.product.prodname_dotcom_the_website %}. {% data reusables.enterprise-accounts.emu-more-info-account %}
{% endnote %}
{% endif %}
{% data reusables.user_settings.access_settings %}
2. Under "Name", type the name you want to be displayed on your profile.
![Name field in profile settings](/assets/images/help/profile/name-field.png)

View File

@@ -23,6 +23,8 @@ Repositories owned by an organization can grant more granular access. For more i
{% ifversion fpt %}
If you're a member of an {% data variables.product.prodname_emu_enterprise %}, you can only invite other members of your enterprise to collaborate with you. {% data reusables.enterprise-accounts.emu-more-info-account %}
{% note %}
**Note:** {% data variables.product.company_short %} limits the number of people who can be invited to a repository within a 24-hour period. If you exceed this limit, either wait 24 hours or create an organization to collaborate with more people.

View File

@@ -17,7 +17,9 @@ shortTitle: Add an email address
{% note %}
**Note**: {% data reusables.user_settings.no-verification-disposable-emails %}
**Notes**:
- {% data reusables.user_settings.no-verification-disposable-emails %}
- If you're a member of an {% data variables.product.prodname_emu_enterprise %}, you cannot make changes to your email address on {% data variables.product.prodname_dotcom_the_website %}. {% data reusables.enterprise-accounts.emu-more-info-account %}
{% endnote %}

View File

@@ -30,6 +30,12 @@ After changing your username, your old username becomes available for anyone els
- [@mentions](/articles/basic-writing-and-formatting-syntax/#mentioning-people-and-teams) using your old username
- Links to [gists](/articles/creating-gists) that include your old username
{% ifversion fpt %}
If you're a member of an {% data variables.product.prodname_emu_enterprise %}, you cannot make changes to your username. {% data reusables.enterprise-accounts.emu-more-info-account %}
{% endif %}
## Repository references
After you change your username, {% data variables.product.product_name %} will automatically redirect references to your repositories.

View File

@@ -14,7 +14,15 @@ shortTitle: Manage theme settings
For choice and flexibility in how and when you use {% data variables.product.product_name %}, you can configure theme settings to change how {% data variables.product.product_name %} looks to you. You can choose from themes that are light or dark, or you can configure {% data variables.product.product_name %} to follow your system settings.
You may want to use a dark theme to reduce power consumption on certain devices, to reduce eye strain in low-light conditions, or because you prefer how the theme looks.{% ifversion fpt or ghae-issue-4618 %} People with visual impairment may benefit from the dark high contrast theme, with greater contrast between foreground and background elements.{% endif %}
You may want to use a dark theme to reduce power consumption on certain devices, to reduce eye strain in low-light conditions, or because you prefer how the theme looks.
{% ifversion fpt or ghae-issue-4618 %} If you have low vision, you may benefit from a high contrast theme, with greater contrast between foreground and background elements.{% endif %}{% ifversion fpt or ghae-issue-4619 %} If you have colorblindness, you may benefit from our light and dark colorblind themes.
{% note %}
**Note:** The colorblind themes are currently in public beta. For more information on enabling features in public beta, see "[Exploring early access releases with feature preview](/get-started/using-github/exploring-early-access-releases-with-feature-preview)."
{% endnote %}{% endif %}
{% data reusables.user_settings.access_settings %}
1. In the user settings sidebar, click **Appearance**.
@@ -26,6 +34,8 @@ You may want to use a dark theme to reduce power consumption on certain devices,
{% ifversion fpt or ghae-issue-4618 %}![Radio buttons for the choice of a single theme](/assets/images/help/settings/theme-choose-a-single-theme-highcontrast.png){% else %}![Radio buttons for the choice of a single theme](/assets/images/help/settings/theme-choose-a-single-theme.png){% endif %}
- If you chose to follow your system settings, click a day theme and a night theme.
{% ifversion fpt or ghae-issue-4618 %}![Buttons for the choice of a theme to sync with the system setting](/assets/images/help/settings/theme-choose-a-day-and-night-theme-to-sync-highcontrast.png){% else %}![Buttons for the choice of a theme to sync with the system setting](/assets/images/help/settings/theme-choose-a-day-and-night-theme-to-sync.png){% endif %}
{% ifversion fpt or ghae-issue-4619 %}
- If you would like to choose a theme which is currently in public beta, you will first need to enable it with feature preview. For more information, see "[Exploring early access releases with feature preview](/get-started/using-github/exploring-early-access-releases-with-feature-preview)."{% endif %}
## Further reading

View File

@@ -78,6 +78,7 @@ The `github` context contains information about the workflow run and the event t
| `github.repository_owner` | `string` | The repository owner's name. For example, `Codertocat`. |
| `github.run_id` | `string` | {% data reusables.github-actions.run_id_description %} |
| `github.run_number` | `string` | {% data reusables.github-actions.run_number_description %} |
| `github.run_attempt` | `string` | A unique number for each attempt of a particular workflow run in a repository. This number begins at 1 for the workflow run's first attempt, and increments with each re-run. |
| `github.server_url` | `string` | Returns the URL of the GitHub server. For example: `https://github.com`. |
| `github.sha` | `string` | The commit SHA that triggered the workflow run. |
| `github.token` | `string` | A token to authenticate on behalf of the GitHub App installed on your repository. This is functionally equivalent to the `GITHUB_TOKEN` secret. For more information, see "[Authenticating with the GITHUB_TOKEN](/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token)." |

View File

@@ -84,7 +84,7 @@ The following table shows which toolkit functions are available within a workflo
| `core.setOutput` | `set-output` |
| `core.setSecret` | `add-mask` |
| `core.startGroup` | `group` |
| `core.warning` | `warning file` |
| `core.warning` | `warning` |
{% ifversion ghes < 3.0 %}
## Setting an environment variable

View File

@@ -29,6 +29,9 @@ If you can't access {% data variables.product.product_name %}, contact your loca
{% data reusables.saml.dotcom-saml-explanation %} Organization owners can invite your user account on {% data variables.product.prodname_dotcom %} to join their organization that uses SAML SSO, which allows you to contribute to the organization and retain your existing identity and contributions on {% data variables.product.prodname_dotcom %}.
If you're a member of an {% data variables.product.prodname_emu_enterprise %}, you will use a new account that is provisioned for you. {% data reusables.enterprise-accounts.emu-more-info-account %}
When you access resources within an organization that uses SAML SSO, {% data variables.product.prodname_dotcom %} will redirect you to the organization's SAML IdP to authenticate. After you successfully authenticate with your account on the IdP, the IdP redirects you back to {% data variables.product.prodname_dotcom %}, where you can access the organization's resources.
{% data reusables.saml.outside-collaborators-exemption %}

View File

@@ -27,6 +27,10 @@ You can access your resources in {% data variables.product.product_name %} in a
You can authenticate to {% data variables.product.product_name %} in your browser {% ifversion ghae %}using your IdP. For more information, see "[About authentication with SAML single sign-on](/github/authenticating-to-github/about-authentication-with-saml-single-sign-on)."{% else %}in different ways.
- {% ifversion fpt %}
If you're a member of an {% data variables.product.prodname_emu_enterprise %}, you will authenticate to {% data variables.product.product_name %} in your browser using your IdP. For more information, see "[Authenticating as a managed user](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users#authenticating-as-a-managed-user)". If you're not a member of an {% data variables.product.prodname_emu_enterprise %}, you will authenticate using your browser on {% data variables.product.prodname_dotcom_the_website %}.
{% endif %}
- **Username and password only**
- You'll create a password when you create your user account on {% data variables.product.product_name %}. We recommend that you use a password manager to generate a random and unique password. For more information, see "[Creating a strong password](/github/authenticating-to-github/creating-a-strong-password)."
- **Two-factor authentication (2FA)** (recommended)

View File

@@ -38,8 +38,7 @@ A token with no assigned scopes can only access public information. To use your
{% data reusables.user_settings.access_settings %}
{% data reusables.user_settings.developer_settings %}
{% data reusables.user_settings.personal_access_tokens %}
4. Click **Generate new token**.
![Generate new token button](/assets/images/help/settings/generate_new_token.png)
{% data reusables.user_settings.generate_new_token %}
5. Give your token a descriptive name.
![Token description field](/assets/images/help/settings/token_description.png){% ifversion fpt or ghes > 3.2 or ghae-issue-4374 %}
6. To give your token an expiration, select the **Expiration** drop-down menu, then click a default or use the calendar picker.

View File

@@ -79,34 +79,6 @@ You can use a fallback number regardless of whether you've configured authentica
After setup, the backup device will receive a confirmation SMS.
## Adding a fallback authentication method with Recover Accounts Elsewhere
You can generate an extra authentication credential for your account and store it with a partner recovery provider.
### About Recover Accounts Elsewhere
With Recover Accounts Elsewhere, you can add an extra security factor to your {% data variables.product.product_name %} account in case you lose access to your two-factor authentication method or recovery codes.
Recover Accounts Elsewhere lets you associate your {% data variables.product.product_name %} account with your Facebook account. You can store an authentication credential in the form of an _account recovery token_ for your {% data variables.product.product_name %} account with Facebook.
If you lose access to your {% data variables.product.product_name %} account because you no longer have access to your two-factor authentication method or recovery codes, you can retrieve your account recovery token from the recovery provider to help prove that you're the owner of your {% data variables.product.product_name %} account.
After you retrieve your token, {% data variables.contact.contact_support %} may be able to disable two-factor authentication for your account. Then, you can provide or reset your password to regain access to your account.
When you generate or retrieve an account recovery token, an event is added to your account's audit log. For more information, see "[Reviewing your security log](/articles/reviewing-your-security-log)."
### Generating and storing an account recovery token
You can generate an account recovery token and store it with a partner recovery provider.
1. Sign in to your Facebook account, then return to {% data variables.product.product_name %}.
{% data reusables.user_settings.access_settings %}
{% data reusables.user_settings.security %}
4. To generate a new token, under "Recovery tokens," click **Store new token**. ![Button for storing a new recovery token](/assets/images/help/settings/store-new-recovery-token.png)
5. Read the information about account recovery tokens, then click **Connect with https://www.facebook.com**. ![Button for connecting a recovery token with Facebook](/assets/images/help/settings/connect-recovery-token-with-facebook.png)
6. After you're redirected to Facebook, read the information about turning on account recovery with Facebook before you click **Save as [_YOUR NAME_]**. (If you save multiple tokens within a short period of time, Facebook may skip this confirmation step after you save your first token.)
![Facebook page with button for turning on account recovery](/assets/images/help/settings/security-turn-on-rae-facebook.png)
{% endif %}
## Further reading

View File

@@ -27,6 +27,12 @@ We strongly recommend using a time-based one-time password (TOTP) application to
{% endwarning %}
{% ifversion fpt %}
If you're a member of an {% data variables.product.prodname_emu_enterprise %}, you cannot configure 2FA for your {% data variables.product.prodname_managed_user %} account. 2FA should be configured through your identity provider.
{% endif %}
## Configuring two-factor authentication using a TOTP mobile app
A time-based one-time password (TOTP) application automatically generates an authentication code that changes after a certain period of time. We recommend using cloud-based TOTP apps such as:

View File

@@ -78,6 +78,12 @@ You can use your two-factor authentication credentials or two-factor authenticat
## Authenticating with an account recovery token
{% warning %}
**Warning:** Account recovery tokens are deprecated and will be disabled on **December 1st, 2021**. Please ensure you have configured other two-factor recovery methods. For more information, see "[Configuring two-factor authentication recovery methods](/articles/configuring-two-factor-authentication-recovery-methods)."
{% endwarning %}
If you lose access to the two-factor authentication methods for your {% data variables.product.product_name %} account, you can retrieve your account recovery token from a partner recovery provider and ask {% data variables.product.prodname_dotcom %} Support to review it.
If you don't have access to your two-factor authentication methods or recovery codes and you've stored an account recovery token with Facebook using Recover Accounts Elsewhere, you may be able to use your token to regain access to your account.

View File

@@ -1,11 +1,11 @@
---
title: About dependency review
intro: 'Dependency review lets you catch vulnerable dependencies before you introduce them to your environment, and provides information on license, dependents, and age of dependencies.'
product: '{% data reusables.gated-features.dependency-review %}'
shortTitle: Dependency review
versions:
fpt: '*'
ghes: '>= 3.2'
product: '{% data reusables.gated-features.dependency-review %}'
type: overview
topics:
- Advanced Security

View File

@@ -15,6 +15,5 @@ children:
- /forwarding-ports-in-your-codespace
- /changing-the-machine-type-for-your-codespace
- /using-codespaces-in-visual-studio-code
- /web-based-editor
---

View File

@@ -30,11 +30,7 @@ A typical workflow for updating a file using {% data variables.product.prodname_
## Creating or switching branches
1. If the current branch is not shown in the status bar, at the bottom of your codespace, right-click the status bar and select **Source control**.
1. Click the branch name in the status bar.
![The branch in the status bar](/assets/images/help/codespaces/branch-in-status-bar.png)
1. In the drop-down, either click the branch you want to switch to, or enter the name for a new branch and click **Create new branch**.
![Choose from the branch menu](/assets/images/help/codespaces/create-new-branch.png)
{% data reusables.codespaces.create-or-switch-branch %}
{% tip %}
@@ -70,21 +66,11 @@ If the fetch operation detects new changes on the remote repository, you'll see
## Committing your changes
{% data reusables.codespaces.source-control-display-dark %}
1. To stage your changes, click **+** next to the file you've changed, or next to **Changes** if you've changed multiple files and you want to stage them all.
![Source control side bar with staging button highlighted](/assets/images/help/codespaces/codespaces-commit-stage.png)
1. Type a commit message describing the change you've made.
![Source control side bar with a commit message](/assets/images/help/codespaces/codespaces-commit-commit-message.png)
1. To commit your staged changes, click the check mark at the top the source control side bar.
![Click the check mark icon](/assets/images/help/codespaces/codespaces-commit-checkmark-icon.png)
{% data reusables.codespaces.source-control-commit-changes %}
## Raising a pull request
1. After you've committed changes to your local copy of the repository, click the **Create Pull Request** icon.
![Source control side bar with staging button highlighted](/assets/images/help/codespaces/codespaces-commit-pr-button.png)
1. Check that the local branch and repository you're merging from, and the remote branch and repository you're merging into, are correct. Then give the pull request a title and a description.
![Source control side bar with staging button highlighted](/assets/images/help/codespaces/codespaces-commit-pr.png)
1. Click **Create**.
{% data reusables.codespaces.source-control-pull-request %}
## Pushing changes to your remote repository

View File

@@ -24,9 +24,6 @@ featuredLinks:
- /codespaces/setting-up-your-codespace/personalizing-codespaces-for-your-account
popularHeading: Set up your project
product_video: 'https://www.youtube-nocookie.com/embed/_W9B7qc9lVc'
community_redirect:
name: Provide GitHub Feedback
href: 'https://github.com/github/feedback/discussions/categories/codespaces-feedback'
redirect_from:
- /github/developing-online-with-github-codespaces
- /github/developing-online-with-codespaces
@@ -44,6 +41,7 @@ children:
- /managing-codespaces-for-your-organization
- /codespaces-reference
- /troubleshooting
- /the-githubdev-web-based-editor
- /guides
---

View File

@@ -0,0 +1,106 @@
---
title: The github.dev web-based editor
intro: Use the github.dev {% data variables.product.prodname_serverless %} from your repository or pull request to create and commit changes.
versions:
fpt: '*'
type: how_to
miniTocMaxHeadingLevel: 3
topics:
- Codespaces
- Visual Studio Code
- Developer
shortTitle: Web-based editor
redirect_from:
- /codespaces/developing-in-codespaces/web-based-editor
---
{% note %}
**Note:** The github.dev {% data variables.product.prodname_serverless %} is currently in beta preview. You can provide feedback [in our Discussions](https://github.co/browser-editor-feedback).
{% endnote %}
## About the {% data variables.product.prodname_serverless %}
The {% data variables.product.prodname_serverless %} introduces a lightweight editing experience that runs entirely in your browser. With the {% data variables.product.prodname_serverless %}, you can navigate files and source code repositories from {% data variables.product.prodname_dotcom %}, and make and commit code changes. You can open any repository, fork, or pull request in the editor.
The {% data variables.product.prodname_serverless %} is available to everyone for free on {% data variables.product.prodname_dotcom_the_website %}.
The {% data variables.product.prodname_serverless %} provides many of the benefits of {% data variables.product.prodname_vscode %}, such as search, syntax highlighting, and a source control view. You can also use Settings Sync to share your own {% data variables.product.prodname_vscode %} settings with the editor. For more information, see "[Settings Sync](https://code.visualstudio.com/docs/editor/settings-sync)" in the {% data variables.product.prodname_vscode %} documentation.
The {% data variables.product.prodname_serverless %} runsentirely in your browsers sandbox. The editor doesnt clone the repository, but instead uses the [GitHub Repositories extension](https://code.visualstudio.com/docs/editor/github#_github-repositories-extension) to carry out most of the functionality that you will use. Your work is saved in the browsers local storage until you commit it. You should commit your changes regularly to ensure that they're always accessible.
## Opening the {% data variables.product.prodname_serverless %}
You can open any {% data variables.product.prodname_dotcom %} repository in the {% data variables.product.prodname_serverless %} in the following ways:
- Press `.` while browsing any repository or pull request on {% data variables.product.prodname_dotcom %}.
- Change the URL from "github.com" to "github.dev".
## {% data variables.product.prodname_codespaces %} and the {% data variables.product.prodname_serverless %}
Both the {% data variables.product.prodname_serverless %} and {% data variables.product.prodname_codespaces %} allow you to edit your code straight from your repository. However, both have slightly different benefits, depending on your use case.
|| {% data variables.product.prodname_serverless %} | {% data variables.product.prodname_codespaces %}|
|-|----------------|---------|
| **Cost** | Free. | Costs for compute and storage. For information on pricing, see "[Codespaces pricing](/en/billing/managing-billing-for-github-codespaces/about-billing-for-codespaces#codespaces-pricing)."|
| **Availability** | Available to everyone on GitHub.com. | Available for organizations using GitHub Team or GitHub Enterprise Cloud. |
| **Start up** | The {% data variables.product.prodname_serverless %} opens instantly with a key-press and you can start using it right away, without having to wait for additional configuration or installation. | When you create or resume a codespace, the codespace is assigned a VM and the container is configured based on the contents of a `devcontainer.json` file. This set up may take a few minutes to create the environment. For more information, see "[Creating a Codespace](/codespaces/developing-in-codespaces/creating-a-codespace)." |
| **Compute** | There is no associated compute, so you wont be able to build and run your code or use the integrated terminal. | With {% data variables.product.prodname_codespaces %}, you get the power of dedicated VM on which you can run and debug your application.|
| **Terminal access** | None. | {% data variables.product.prodname_codespaces %} provides a common set of tools by default, meaning that you can use the Terminal exactly as you would in your local environment.|
| **Extensions** | Only a subset of extensions that can run in the web will appear in the ExtensionsView and can be installed. For more information, see "[Using extensions](#using-extensions)."| With Codespaces, you can use most extensions from the Visual Studio Code Marketplace.|
### Continue working on {% data variables.product.prodname_codespaces %}
You can start your workflow in the {% data variables.product.prodname_serverless %} and continue working on a codespace, provided you have [access to {% data variables.product.prodname_codespaces %}](/codespaces/developing-in-codespaces/creating-a-codespace#access-to-codespaces). If you try to access the Run and Debug View or the Terminal, you'll be notified that they are not available in the {% data variables.product.prodname_serverless %}.
To continue your work in a codespace, click **Continue Working on…** and select **Create New Codespace** to create a codespace on your current branch. Before you choose this option, you must commit any changes.
![A screenshot that shows the "Continue Working on" button in the UI](/assets/images/help/codespaces/codespaces-continue-working.png)
## Using source control
When you use the {% data variables.product.prodname_serverless %}, all actions are managed through the Source Control View, which is located in the Activity Bar on the left hand side. For more information on the Source Control View, see "[Version Control](https://code.visualstudio.com/docs/editor/versioncontrol)" in the {% data variables.product.prodname_vscode %} documentation.
Because the web-based editor uses the GitHub Repositories extension to power its functionality, you can switch branches without needing to stash changes. For more information, see "[GitHub Repositories](https://code.visualstudio.com/docs/editor/github#_github-repositories-extension)" in the {% data variables.product.prodname_vscode %} documentation.
### Create a new branch
{% data reusables.codespaces.create-or-switch-branch %}
Any uncommited changes you have made in your old branch will be available on your new branch.
### Commit your changes
{% data reusables.codespaces.source-control-commit-changes %}
5. Once you have committed your changes, they will automatically be pushed to your branch on {% data variables.product.prodname_dotcom %}.
### Create a pull request
{% data reusables.codespaces.source-control-pull-request %}
### Working with an existing pull request
You can use the {% data variables.product.prodname_serverless %} to work with an existing pull request.
1. Browse to the pull request you'd like to open in the {% data variables.product.prodname_serverless %}.
2. Press `.` to open the pull request in the {% data variables.product.prodname_serverless %}.
3. Once you have made any changes, commit them using the steps in [Commit your changes](#commit-your-changes). Your changes will be committed directly to the branch, it's not necessary to push the changes.
## Using extensions
The {% data variables.product.prodname_serverless %} supports {% data variables.product.prodname_vscode %} extensions that have been specifically created or updated to run in the web. These extensions are known as "web extensions". To learn how you can create a web extension or update your existing extension to work for the web, see "[Web extensions](https://code.visualstudio.com/api/extension-guides/web-extensions)" in the {% data variables.product.prodname_vscode %} documentation.
Extensions that can run in the {% data variables.product.prodname_serverless %} will appear in the ExtensionsView and can be installed. If you use Settings Sync, any compatible extensions are also installed automatically. For information, see "[Settings Sync](https://code.visualstudio.com/docs/editor/settings-sync)" in the {% data variables.product.prodname_vscode %} documentation.
## Troubleshooting
If you have issues opening the {% data variables.product.prodname_serverless %}, try the following:
- Make sure you are signed in to {% data variables.product.prodname_dotcom %}.
- Disable any ad blockers.
- Use a non-incognito window in your browser to open the {% data variables.product.prodname_serverless %}.
### Known limitations
- The {% data variables.product.prodname_serverless %} is currently supported in Chrome (and various other Chromium-based browsers), Edge, Firefox, and Safari. We recommend that you use the latest versions of these browsers.
- Some keybindings may not work, depending on the browser you are using. These keybinding limitations are documented in the "[Known limitations and adaptations](https://code.visualstudio.com/docs/remote/codespaces#_known-limitations-and-adaptations)" section of the {% data variables.product.prodname_vscode %} documentation.

View File

@@ -31,7 +31,7 @@ Different server-to-server request rate limits apply to {% data variables.produc
### {% data variables.product.prodname_ghe_cloud %} server-to-server rate limits
{% data variables.product.prodname_github_apps %} that are installed on an organization or repository owned by a {% data variables.product.prodname_ghe_cloud %} account and make server-to-server requests have a rate limit of 15,000 requests per hour.
{% data variables.product.prodname_github_apps %} that are installed on an organization or repository owned by a {% data variables.product.prodname_ghe_cloud %} account and make server-to-server requests have a rate limit of 15,000 requests per hour per organization for organization installations or per repository for repository installations.
{% endif %}

View File

@@ -2,7 +2,7 @@
title: Collaborating with maintainers using discussions
shortTitle: Collaborating with maintainers
intro: 'You can contribute to the goals, plans, health, and community for a project on {% data variables.product.product_name %} by communicating with the maintainers of the project in a discussion.'
permissions: People with read permissions to a repository can start and participate in discussions in the repository.
permissions: 'People with read access to a repository can start and participate in discussions in the repository. {% data reusables.enterprise-accounts.emu-permission-interact %}'
versions:
fpt: '*'
---

View File

@@ -1,7 +1,7 @@
---
title: Participating in a discussion
intro: 'You can converse with the community and maintainers in a forum within the repository for a project on {% data variables.product.product_name %}.'
permissions: People with read permissions to a repository can participate in discussions in the repository.
permissions: 'People with read access to a repository can participate in discussions in the repository. {% data reusables.enterprise-accounts.emu-permission-interact %}'
versions:
fpt: '*'
shortTitle: Participate in discussion

View File

@@ -26,9 +26,6 @@ changelog:
examples_source: data/product-examples/discussions/community-examples.yml
product_video: 'https://www.youtube-nocookie.com/embed/IpBw2SJkFyk'
layout: product-landing
community_redirect:
name: Provide GitHub Feedback
href: 'https://github.com/github/feedback/discussions/categories/discussions-feedback'
versions:
fpt: '*'
children:

View File

@@ -1,6 +1,7 @@
---
title: Finding ways to contribute to open source on GitHub
intro: 'You can find ways to contribute to open source projects on {% data variables.product.product_name %} that are relevant to you.'
permissions: '{% data reusables.enterprise-accounts.emu-permission-interact %}'
redirect_from:
- /articles/where-can-i-find-open-source-projects-to-work-on/
- /articles/finding-interesting-projects-on-github/

View File

@@ -1,6 +1,7 @@
---
title: Following people
intro: 'You can follow people on {% data variables.product.product_name %} to receive notifications about their activity{% ifversion fpt %} and discover projects in their communities{% endif %}.'
permissions: '{% data reusables.enterprise-accounts.emu-permission-follow %}'
redirect_from:
- /articles/following-people
- /github/getting-started-with-github/following-people

View File

@@ -35,6 +35,8 @@ Organization members can have *owner*{% ifversion fpt %}, *billing manager*,{% e
*Enterprise owners* have ultimate power over the enterprise account and can take every action in the enterprise account. *Billing managers* can manage your enterprise account's billing settings. Members and outside collaborators of organizations owned by your enterprise account are automatically members of the enterprise account, although they have no access to the enterprise account itself or its settings. For more information, see "[Roles in an enterprise](/github/setting-up-and-managing-your-enterprise/roles-in-an-enterprise)."
If an enterprise uses {% data variables.product.prodname_emus %}, members are provisioned as new user accounts on {% data variables.product.prodname_dotcom %} and are fully managed by the identity provider. The {% data variables.product.prodname_managed_users %} have read-only access to repositories that are not a part of their enterprise and cannot interact with users that are not also members of the enterprise. Within the organizations owned by the enterprise, the {% data variables.product.prodname_managed_users %} can be granted the same granular access levels available for regular organizations. For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
{% data reusables.gated-features.enterprise-accounts %}
{% endif %}

View File

@@ -101,6 +101,7 @@ In addition to the features available with {% data variables.product.prodname_te
- 50GB {% data variables.product.prodname_registry %} storage
- Access control for {% data variables.product.prodname_pages %} sites. For more information, see <a href="/pages/getting-started-with-github-pages/changing-the-visibility-of-your-github-pages-site" class="dotcom-only">Changing the visibility of your {% data variables.product.prodname_pages %} site</a>"
- A service level agreement for 99.9% monthly uptime
- The option to configure your enterprise for {% data variables.product.prodname_emus %}, so you can provision and manage members with your identity provider and restrict your member's contributions to just your enterprise. For more information, see "<a href="/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users" class="dotcom-only">About {% data variables.product.prodname_emus %}</a>."
- The option to centrally manage policy and billing for multiple {% data variables.product.prodname_dotcom_the_website %} organizations with an enterprise account. For more information, see "<a href="/articles/about-enterprise-accounts" class="dotcom-only">About enterprise accounts</a>."
You can set up a trial to evaluate {% data variables.product.prodname_ghe_cloud %}. For more information, see "<a href="/articles/setting-up-a-trial-of-github-enterprise-cloud" class="dotcom-only">Setting up a trial of {% data variables.product.prodname_ghe_cloud %}</a>."

View File

@@ -63,6 +63,14 @@ Every person who uses {% data variables.product.product_location %} has their ow
{% endif %}
{% ifversion fpt %}
### {% data variables.product.prodname_emus %}
With {% data variables.product.prodname_emus %}, instead of using your personal account, members of an {% data variables.product.prodname_emu_enterprise %} are provisioned accounts using the enterprise's identity provider (IdP). {% data variables.product.prodname_managed_users_caps %} authenticate using their IdP instead of a {% data variables.product.prodname_dotcom_the_website %} username and password.
{% data variables.product.prodname_managed_users_caps %} can only interact with users, repositories, and organizations that are part of their enterprise. {% data variables.product.prodname_managed_users_caps %} have read-only access to the rest of {% data variables.product.prodname_dotcom_the_website %}. For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
{% endif %}
## Organization accounts
Organizations are shared accounts where groups of people 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.

View File

@@ -18,16 +18,19 @@ This guide will walk you through setting up, configuring and managing your {% da
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:
With {% data variables.product.prodname_ghe_cloud %}, you have the option of using {% data variables.product.prodname_emus %}. {% data reusables.enterprise-accounts.emu-short-summary %}
If you choose to let your members create and manage their own user accounts instead, there are two types of accounts you can use with {% data variables.product.prodname_ghe_cloud %}:
- 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.
@@ -86,6 +89,11 @@ You can set permissions and member roles, create and manage teams, and give peop
### 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)."
If your enterprise uses {% data variables.product.prodname_emus %}, your members are fully managed through your identity provider. Adding members, making changes to their membership, and assigning roles is all managed using your IdP. For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
If your enterprise does not use {% data variables.product.prodname_emus %}, follow the steps below.
#### 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
@@ -97,6 +105,10 @@ To audit access to enterprise-owned resources or user license usage, you can vie
## Part 4: Managing security with {% data variables.product.prodname_ghe_cloud %}
* [Managing security for a single organization](#managing-security-for-a-single-organization)
* [Managing security for an {% data variables.product.prodname_emu_enterprise %}](#managing-security-for-an-enterprise-with-managed-users)
* [Managing security for an enterprise account without {% data variables.product.prodname_managed_users %}](#managing-security-for-an-enterprise-account-without-managed-users)
### 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
@@ -113,8 +125,28 @@ Organization owners can choose to disable, enable but not enforce, or enable and
#### 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
### Managing security for an {% data variables.product.prodname_emu_enterprise %}
With {% data variables.product.prodname_emus %}, access and identity is managed centrally through your identity provider. Two-factor authentication and other login requirements should be enabled and enforced on your IdP.
#### 1. Enabling and SAML single sign-on and provisioning in your {% data variables.product.prodname_emu_enterprise %}
In an {% data variables.product.prodname_emu_enterprise %}, all members are provisioned and managed by your identity provider. You must enable SAML SSO and SCIM provisioning before you can start using your enterprise. For more information on configuring SAML SSO and provisioning for an {% data variables.product.prodname_emu_enterprise %}, see "[Configuring SAML single sign-on for Enterprise Managed Users](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-saml-single-sign-on-for-enterprise-managed-users)."
#### 2. Managing teams in your {% data variables.product.prodname_emu_enterprise %} with your identity provider
You can connect teams in your organizations to security groups in your identity provider, managing membership of your teams and access to repositories through your IdP. For more information, see "[Managing team memberships with identity provider groups](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/managing-team-memberships-with-identity-provider-groups)."
#### 3. Managing allowed IP addresses for organizations in your {% data variables.product.prodname_emu_enterprise %}
You can configure an allow list for specific IP addresses to restrict access to assets owned by organizations in your {% data variables.product.prodname_emu_enterprise %}. For more information, 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)."
#### 4. Enforcing policies for Advanced Security features in your {% data variables.product.prodname_emu_enterprise %}
{% data reusables.getting-started.enterprise-advanced-security %}
### Managing security for an enterprise account without {% data variables.product.prodname_managed_users %}
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.
@@ -126,7 +158,7 @@ You can centrally manage access to your enterprise's resources, organization mem
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)."
{% data reusables.getting-started.enterprise-advanced-security %}
## Part 5: Managing organization and enterprise level policies and settings

View File

@@ -6,6 +6,7 @@ redirect_from:
- /github/getting-started-with-github/be-social
- /github/getting-started-with-github/quickstart/be-social
intro: 'You can interact with people, repositories, and organizations on {% data variables.product.prodname_dotcom %}. See what others are working on and who they''re connecting with from your personal dashboard.'
permissions: '{% data reusables.enterprise-accounts.emu-permission-interact %}'
versions:
fpt: '*'
ghes: '*'

View File

@@ -7,6 +7,7 @@ redirect_from:
- /github/getting-started-with-github/fork-a-repo
- /github/getting-started-with-github/quickstart/fork-a-repo
intro: A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project.
permissions: '{% data reusables.enterprise-accounts.emu-permission-fork %}'
versions:
fpt: '*'
ghes: '*'

View File

@@ -5,7 +5,7 @@ redirect_from:
- /github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork
- /articles/creating-a-pull-request-from-a-fork
- /github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork
permissions: Anyone with write access to a repository can create a pull request from a user-owned fork.
permissions: 'Anyone with write access to a repository can create a pull request from a user-owned fork. {% data reusables.enterprise-accounts.emu-permission-propose %}'
versions:
fpt: '*'
ghes: '*'

View File

@@ -1,6 +1,7 @@
---
title: Creating a pull request
intro: 'Create a pull request to propose and collaborate on changes to a repository. These changes are proposed in a *branch*, which ensures that the default branch only contains finished and approved work.'
permissions: 'Anyone with read access to a repository can create a pull request. {% data reusables.enterprise-accounts.emu-permission-propose %}'
redirect_from:
- /github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request
- /articles/creating-a-pull-request
@@ -12,7 +13,7 @@ versions:
topics:
- Pull requests
---
Anyone with read permissions to a repository can create a pull request, but you must have write permissions to create a branch. If you want to create a new branch for your pull request and don't have write permissions to the repository, you can fork the repository first. For more information, see "[Creating a pull request from a fork](/articles/creating-a-pull-request-from-a-fork)" and "[About forks](/articles/about-forks)."
If you want to create a new branch for your pull request and do not have write permissions to the repository, you can fork the repository first. For more information, see "[Creating a pull request from a fork](/articles/creating-a-pull-request-from-a-fork)" and "[About forks](/articles/about-forks)."
You can specify which branch you'd like to merge your changes into when you create your pull request. Pull requests can only be opened between two branches that are different.

View File

@@ -1,10 +1,10 @@
---
title: Reviewing dependency changes in a pull request
intro: 'If a pull request contains changes to dependencies, you can view a summary of what has changed and whether there are known vulnerabilities in any of the dependencies.'
product: '{% data reusables.gated-features.dependency-review %}'
versions:
fpt: '*'
ghes: '>= 3.2'
product: '{% data reusables.gated-features.dependency-review %}'
type: how_to
topics:
- Pull requests
@@ -38,18 +38,19 @@ Dependency review allows you to "shift left". You can use the provided predictiv
1. If the pull request contains many files, use the **File filter** drop-down menu to collapse all files that don't record dependencies. This will make it easier to focus your review on the dependency changes.
![The file filter menu](/assets/images/help/pull_requests/file-filter-menu-json.png)
The dependency review provides a clearer view of what has changed in large lock files, where the source diff is not rendered by default.
{% note %}
**Note:** Dependency review rich diffs are not available for committed static JavaScript files like `jquery.js`.
{% endnote %}
1. On the right of the header for a manifest or lock file, display the dependency review by clicking the **{% octicon "file" aria-label="The rich diff icon" %}** rich diff button.
![The rich diff button](/assets/images/help/pull_requests/dependency-review-rich-diff.png)
{% note %}
**Note:** The dependency review provides a clearer view of what has changed in large lock files, where the source diff is not rendered by default.
{% endnote %}
1. Check the dependencies listed in the dependency review.
2. Check the dependencies listed in the dependency review.
![Vulnerability warnings in a dependency review](/assets/images/help/pull_requests/dependency-review-vulnerability.png)

View File

@@ -19,6 +19,12 @@ Forking a repository is similar to copying a repository, with two major differen
{% data reusables.repositories.you-can-fork %}
{% ifversion fpt %}
If you're a member of a {% data variables.product.prodname_emu_enterprise %}, there are further restrictions on the repositories you can fork. {% data reusables.enterprise-accounts.emu-forks %} For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
{% endif %}
{% data reusables.repositories.desktop-fork %}
Deleting a fork will not delete the original upstream repository. You can make any changes you want to your fork—add collaborators, rename files, generate {% data variables.product.prodname_pages %}—with no effect on the original.{% ifversion fpt %} You cannot restore a deleted forked repository. For more information, see "[Restoring a deleted repository](/articles/restoring-a-deleted-repository)."{% endif %}

View File

@@ -20,6 +20,12 @@ If you use Azure AD as your IDP, you can use team synchronization to manage team
{% data reusables.saml.switching-from-org-to-enterprise %} For more information, see "[Switching your SAML configuration from an organization to an enterprise account](/github/setting-up-and-managing-your-enterprise/configuring-identity-and-access-management-for-your-enterprise-account/switching-your-saml-configuration-from-an-organization-to-an-enterprise-account)."
## About {% data variables.product.prodname_emus %}
{% data reusables.enterprise-accounts.emu-short-summary %}
Configuring {% data variables.product.prodname_emus %} for SAML single-sign on and user provisioning involves following a different process than you would for an enterprise that isn't using {% data variables.product.prodname_managed_users %}. If your enterprise uses {% data variables.product.prodname_emus %}, see "[Configuring SAML single sign-on for Enterprise Managed Users](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-saml-single-sign-on-for-enterprise-managed-users)."
## Supported IdPs
We test and officially support the following IdPs. For SAML SSO, we offer limited support for all identity providers that implement the SAML 2.0 standard. For more information, see the [SAML Wiki](https://wiki.oasis-open.org/security) on the OASIS website.
@@ -31,4 +37,3 @@ Azure Active Directory (Azure AD) | {% octicon "check-circle-fill" aria-label="T
OneLogin | {% octicon "check-circle-fill" aria-label="The check icon" %} | |
PingOne | {% octicon "check-circle-fill" aria-label="The check icon" %} | |
Shibboleth | {% octicon "check-circle-fill" aria-label="The check icon" %} | |

View File

@@ -15,6 +15,8 @@ shortTitle: Configure SAML with Okta
---
{% data reusables.enterprise-accounts.user-provisioning-release-stage %}
{% data reusables.enterprise-accounts.emu-saml-note %}
## About SAML with Okta
You can control access to your enterprise account in {% data variables.product.product_name %} and other web applications from one central interface by configuring the enterprise account to use SAML SSO with Okta, an Identity Provider (IdP).

View File

@@ -12,6 +12,9 @@ redirect_from:
- /github/setting-up-and-managing-your-enterprise/enabling-saml-single-sign-on-for-organizations-in-your-enterprise-account
shortTitle: Enforce SAML
---
{% data reusables.enterprise-accounts.emu-saml-note %}
## About SAML single sign-on for enterprise accounts
{% data reusables.saml.dotcom-saml-explanation %} 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)."

View File

@@ -11,6 +11,9 @@ redirect_from:
- /github/setting-up-and-managing-your-enterprise/managing-team-synchronization-for-organizations-in-your-enterprise-account
shortTitle: Manage team synchronization
---
{% data reusables.enterprise-accounts.emu-scim-note %}
## About team synchronization for enterprise accounts
If you use Azure AD as your IdP, you can enable team synchronization for your enterprise account to allow organization owners and team maintainers to synchronize teams in the organizations owned by your enterprise accounts with IdP groups.

View File

@@ -10,6 +10,8 @@ topics:
shortTitle: Switching from organization
---
{% data reusables.enterprise-accounts.emu-saml-note %}
## About SAML single sign-on for enterprise accounts
{% data reusables.saml.dotcom-saml-explanation %} {% data reusables.saml.about-saml-enterprise-accounts %}

View File

@@ -14,6 +14,7 @@ topics:
children:
- /managing-your-enterprise-account
- /managing-users-in-your-enterprise
- /managing-your-enterprise-users-with-your-identity-provider
- /managing-organizations-in-your-enterprise-account
- /configuring-identity-and-access-management-for-your-enterprise-account
- /setting-policies-for-organizations-in-your-enterprise-account

View File

@@ -1,6 +1,6 @@
---
title: Adding organizations to your enterprise account
intro: You can create new organizations to manage within your enterprise account.
intro: You can create new organizations or invite existing organizations to manage within your enterprise account.
product: '{% data reusables.gated-features.enterprise-accounts %}'
redirect_from:
- /articles/adding-organizations-to-your-enterprise-account
@@ -12,9 +12,9 @@ topics:
- Enterprise
shortTitle: Add organizations
---
Enterprise owners can create new organizations within an enterprise account's settings.
Enterprise owners can create new organizations within an enterprise account's settings or invite existing organizations to join an enterprise account.
To add an organization to your enterprise account, you must create the organization from within the enterprise account settings. If you want to transfer an existing organization to your enterprise account, contact your {% data variables.product.prodname_dotcom %} sales account representative.
To add an organization to your enterprise account, you must create the organization from within the enterprise account settings.
## Creating an organization in your enterprise account
@@ -31,3 +31,20 @@ Enterprise owners who create an organization owned by the enterprise account aut
5. Under "Invite owners", type the username of a person you'd like to invite to become an organization owner, then click **Invite**.
![Organization owner search field and Invite button](/assets/images/help/business-accounts/invite-org-owner.png)
6. Click **Finish**.
## Inviting an organization to join your enterprise account
Enterprise owners can invite existing organizations to join their enterprise account. If the organization you want to invite is already owned by another enterprise, you will not be able to issue an invitation until the previous enterprise gives up ownership of the organization.
{% data reusables.enterprise-accounts.access-enterprise %}
2. On the **Organizations** tab, above the list of organizations, click **Invite organization**.
![Invite organization](/assets/images/help/business-accounts/enterprise-account-invite-organization.png)
3. Under "Organization name", start typing the name of the organization you want to invite and select it when it appears in the drop-down list.
![Search for organization](/assets/images/help/business-accounts/enterprise-account-search-for-organization.png)
4. Click **Invite organization**.
5. The organization owners will receive an email inviting them to join the organization. At least one owner needs to accept the invitation before the process can continue. You can cancel or resend the invitation at any time before an owner approves it.
![Cancel or resend](/assets/images/help/business-accounts/enterprise-account-invitation-sent.png)
6. Once an organization owner has approved the invitation, you can view its status in the list of pending invitations.
![Pending invitation](/assets/images/help/business-accounts/enterprise-account-pending.png)
7. Click **Approve** to complete the transfer, or **Cancel** to cancel it.
![Approve invitation](/assets/images/help/business-accounts/enterprise-account-transfer-approve.png)

View File

@@ -28,6 +28,12 @@ If you want to manage owners and billing managers for an enterprise account on {
{% endif %}
{% ifversion fpt %}
If your enterprise uses {% data variables.product.prodname_emus %}, enterprise owners can only be added or removed through your identity provider. For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
{% endif %}
{% tip %}
**Tip:** For more information on managing users within an organization owned by your enterprise account, see "[Managing membership in your organization](/articles/managing-membership-in-your-organization)" and "[Managing people's access to your organization with roles](/articles/managing-peoples-access-to-your-organization-with-roles)."

View File

@@ -20,7 +20,14 @@ Everyone in an enterprise is a member of the enterprise. You can also assign adm
{% data reusables.enterprise-accounts.enterprise-administrators %}
For more information about adding people to your enterprise, see "{% ifversion fpt %}[Inviting people to manage your enterprise](/github/setting-up-and-managing-your-enterprise/inviting-people-to-manage-your-enterprise){% else %}[Authentication](/admin/authentication){% endif %}".
{% ifversion fpt %}
If your enterprise does not use {% data variables.product.prodname_emus %}, you can invite someone to an administrative role using a user account on {% data variables.product.product_name %} that they control. For more information, see "[Inviting people to manage your enterprise](/github/setting-up-and-managing-your-enterprise/inviting-people-to-manage-your-enterprise)".
In an enterprise using {% data variables.product.prodname_emus %}, new owners and members must be provisioned through your identity provider. Enterprise owners and organization owners cannot add new members or owners to the enterprise using {% data variables.product.prodname_dotcom %}. You can select a member's enterprise role using your IdP and it cannot be changed on {% data variables.product.prodname_dotcom %}. You can select a member's role in an organization on {% data variables.product.prodname_dotcom %}. For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
{% else %}
For more information about adding people to your enterprise, see "[Authentication](/admin/authentication)".
{% endif %}
## Enterprise owner

View File

@@ -17,10 +17,14 @@ shortTitle: View & manage SAML access
When you enable SAML single sign-on for your enterprise account, each enterprise member can link their external identity on your identity provider (IdP) to their existing {% data variables.product.product_name %} account. {% data reusables.saml.about-saml-access-enterprise-account %}
If your enterprise is uses {% data variables.product.prodname_emus %}, your members will use accounts provisioned through your IdP. {% data variables.product.prodname_managed_users_caps %} will not use their existing user account on {% data variables.product.product_name %}. For more information, see "[About {% data variables.product.prodname_emus %}](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users)."
## Viewing and revoking a linked identity
{% data reusables.saml.about-linked-identities %}
If your enterprise uses {% data variables.product.prodname_emus %}, you will not be able to deprovision or remove user accounts from the enterprise on {% data variables.product.product_name %}. Any changes you need to make to your enterprise's {% data variables.product.prodname_managed_users %} should be made through your IdP.
{% data reusables.identity-and-permissions.revoking-identity-team-sync %}
{% data reusables.enterprise-accounts.access-enterprise %}

View File

@@ -0,0 +1,84 @@
---
title: About Enterprise Managed Users
shortTitle: About managed users
intro: You can centrally manage identity and access for your enterprise members on {% data variables.product.prodname_dotcom %} from your identity provider.
product: '{% data reusables.gated-features.emus %}'
redirect_from:
- /early-access/github/articles/get-started-with-managed-users-for-your-enterprise
versions:
fpt: '*'
topics:
- Accounts
- Enterprise
---
## About {% data variables.product.prodname_emus %}
With {% data variables.product.prodname_emus %}, you can control the user accounts of your enterprise members through your identity provider (IdP). You can simplify authentication with SAML single sign-on (SSO) and provision, update, and deprovision user accounts for your enterprise members. Users assigned to the {% data variables.product.prodname_emu_idp_application %} application in your IdP are provisioned as new user accounts on {% data variables.product.prodname_dotcom %} and added to your enterprise. You control usernames, profile data, team membership, and repository access from your IdP.
In your IdP, you can give each {% data variables.product.prodname_managed_user %} the role of user, enterprise owner, or billing manager. {% data variables.product.prodname_managed_users_caps %} can own organizations within your enterprise and can add other {% data variables.product.prodname_managed_users %} to the organizations and teams within. For more information, see "[Roles in an enterprise](/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/roles-in-an-enterprise)" and "[About organizations](/organizations/collaborating-with-groups-in-organizations/about-organizations)."
You can also manage team membership within an organization in your enterprise directly through your IdP, allowing you to manage repository access using groups in your IdP. Organization membership can be managed manually or updated automatically as {% data variables.product.prodname_managed_users %} are added to teams within the organization. For more information, see "[Managing team memberships with identity provider groups](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/managing-team-memberships-with-identity-provider-groups)."
You can grant {% data variables.product.prodname_managed_users %} access and the ability to contribute to repositories within your enterprise, but {% data variables.product.prodname_managed_users %} cannot create public content or collaborate with other users, organizations, and enterprises on the rest of {% data variables.product.prodname_dotcom %}. The {% data variables.product.prodname_managed_users %} provisioned for your enterprise cannot be invited to organizations or repositories outside of the enterprise, nor can the {% data variables.product.prodname_managed_users %} be invited to other enterprises. Outside collaborators are not supported by {% data variables.product.prodname_emus %}.
The usernames of your enterprise's {% data variables.product.prodname_managed_users %} and their profile information, such as display names and email addresses, are set by through your IdP and cannot be changed by the users themselves. For more information, see "[Usernames and profile information](#usernames-and-profile-information)."
{% data reusables.enterprise-accounts.emu-forks %}
Enterprise owners can audit all of the {% data variables.product.prodname_managed_users %}' actions on {% data variables.product.prodname_dotcom %}.
To use {% data variables.product.prodname_emus %}, you need a separate type of enterprise account with {% data variables.product.prodname_emus %} enabled. For more information about creating this account, see "[About enterprises with managed users](#about-enterprises-with-managed-users)."
## Identity provider support
{% data variables.product.prodname_emus %} supports the following IdPs:
{% data reusables.enterprise-accounts.emu-supported-idps %}
## Abilities and restrictions of {% data variables.product.prodname_managed_users %}
{% data variables.product.prodname_managed_users_caps %} can only contribute to private and internal repositories within their enterprise and private repositories owned by their user account. {% data variables.product.prodname_managed_users_caps %} have read-only access to the wider {% data variables.product.prodname_dotcom %} community.
* {% data variables.product.prodname_managed_users_caps %} cannot create issues or pull requests in, comment or add reactions to, nor star, watch, or fork repositories outside of the enterprise.
* {% data variables.product.prodname_managed_users_caps %} cannot push code to repositories outside of the enterprise.
* {% data variables.product.prodname_managed_users_caps %} and the content they create is only visible to other members of the enterprise.
* {% data variables.product.prodname_managed_users_caps %} cannot follow users outside of the enterprise.
* {% data variables.product.prodname_managed_users_caps %} cannot create gists or comment on gists.
* {% data variables.product.prodname_managed_users_caps %} cannot install {% data variables.product.prodname_github_apps %} on their user accounts.
* Other {% data variables.product.prodname_dotcom %} users cannot see, mention, or invite a {% data variables.product.prodname_managed_user %} to collaborate.
* {% data variables.product.prodname_managed_users_caps %} can only own private repositories and {% data variables.product.prodname_managed_users %} can only invite other enterprise members to collaborate on their owned repositories.
* Only private and internal repositories can be created in organizations owned by an {% data variables.product.prodname_emu_enterprise %}, depending on organization and enterprise repository visibility settings.
## About enterprises with managed users
To use {% data variables.product.prodname_emus %}, you need a separate type of enterprise account with {% data variables.product.prodname_emus %} enabled. To try out {% data variables.product.prodname_emus %} or to discuss options for migrating from your existing enterprise, please contact [{% data variables.product.prodname_dotcom %}'s Sales team](https://enterprise.github.com/contact).
Your contact on the GitHub Sales team will work with you to create your new {% data variables.product.prodname_emu_enterprise %}. You'll need to provide the email address for the user who will set up your enterprise and a short code that will be used as the suffix for your enterprise members' usernames. {% data reusables.enterprise-accounts.emu-shortcode %} For more information, see "[Usernames and profile information](#usernames-and-profile-information)."
After we create your enterprise, you will receive an email from {% data variables.product.prodname_dotcom %} inviting you to choose a password for your enterprise's setup user, which will be the first owner in the enterprise. The setup user is only used to configure SAML single sign-on and SCIM provisioning integration for the enterprise. It will no longer have access to administer the enterprise account once SAML is successfully enabled.
The setup user's username is your enterprise's shortcode suffixed with `_admin`. After you log in to your setup user, you can get started by configuring SAML SSO for your enterprise. For more information, see "[Configuring SAML single sign-on for Enterprise Managed Users](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-saml-single-sign-on-for-enterprise-managed-users)."
{% note %}
{% data reusables.enterprise-accounts.emu-password-reset-session %}
{% endnote %}
## Authenticating as a {% data variables.product.prodname_managed_user %}
{% data variables.product.prodname_managed_users_caps %} must authenticate through their identity provider.
To authenticate, {% data variables.product.prodname_managed_users %} must visit their IdP application portal or **https://github.com/enterprises/ENTERPRISE_NAME**, replacing **ENTERPRISE_NAME** with your enterprise's name.
## Usernames and profile information
When your {% data variables.product.prodname_emu_enterprise %} is created, you will choose a short code that will be used as the suffix for your enterprise member's usernames. {% data reusables.enterprise-accounts.emu-shortcode %} The setup user who configures SAML SSO has a username in the format of **@<em>SHORT-CODE</em>_admin**.
When you provision a new user from your identity provider, the new {% data variables.product.prodname_managed_user %} will have a {% data variables.product.product_name %} username in the format of **@<em>IDP-USERNAME</em>_<em>SHORT-CODE</em>**. When using Azure Active Directory (Azure AD), _IDP-USERNAME_ is formed by normalizing the characters preceding the `@` character in the UPN (User Principal Name) provided by Azure AD. When using Okta, _IDP-USERNAME_ is the normalized username attribute provided by Okta.
The username of the new account provisioned on {% data variables.product.product_name %}, including underscore and short code, must not exceed 39 characters.
The profile name and email address of a {% data variables.product.prodname_managed_user %} is also provided by the IdP. {% data variables.product.prodname_managed_users_caps %} cannot change their profile name or email address on {% data variables.product.prodname_dotcom %}.

View File

@@ -0,0 +1,33 @@
---
title: Auditing activity in your enterprise
shortTitle: Auditing activity
intro: 'You can audit the activity of the {% data variables.product.prodname_managed_users %} in your enterprise, viewing information about what actions were performed, by which user, and when they took place.'
permissions: 'Enterprise owners can access the audit log.'
product: '{% data reusables.gated-features.emus %}'
versions:
fpt: '*'
topics:
- Accounts
- Enterprise
---
## About the audit log
The audit log allows enterprise owners to quickly review or export the actions performed by both owners and members of your enterprise. Each audit log entry shows information about the event.
- The organization an action was performed in
- The user who performed the action
- Which repository an action was performed in
- The action that was performed
- Which country the action took place in
- The date and time the action occurred
## Accessing the audit log
You can also access the audit log for your enterprise from the REST API. For more information, see "[GitHub Enterprise administration](/rest/reference/enterprise-admin#get-the-audit-log-for-an-enterprise)" in the API documentation.
{% data reusables.enterprise-accounts.access-enterprise %}
{% data reusables.enterprise-accounts.settings-tab %}
{% data reusables.enterprise-accounts.audit-log-tab %}
1. Optionally, above the list of events, select the **Export Git Events** or **Export** drop-down menu and choose options for exporting events from the audit log.
!["Export Git Events" and "Export" drop-down menus for the enterprise audit log](/assets/images/help/enterprises/audit-log-export-drop-down-menus.png)

View File

@@ -0,0 +1,117 @@
---
title: Configuring SAML single sign-on for Enterprise Managed Users
shortTitle: SAML for managed users
intro: 'You can automatically manage access to your enterprise account on {% data variables.product.prodname_dotcom %} by configuring Security Assertion Markup Language (SAML) single sign-on (SSO).'
product: '{% data reusables.gated-features.emus %}'
versions:
fpt: '*'
topics:
- Accounts
- Enterprise
---
## About SAML single sign-on for {% data variables.product.prodname_emus %}
With {% data variables.product.prodname_emus %}, your enterprise uses SAML SSO to authenticate all members. Instead of signing in to {% data variables.product.prodname_dotcom %} with a {% data variables.product.prodname_dotcom %} username and password, members of your enterprise will sign in through your IdP.
{% data variables.product.prodname_emus %} supports the following IdPs:
{% data reusables.enterprise-accounts.emu-supported-idps %}
After you configure SAML SSO, we recommend storing your recovery codes so you can recover access to your enterprise in the event that your identity provider is unavailable. For more information, see "[Saving your recovery codes](#saving-your-recovery-codes)."
## Configuring SAML single sign-on for {% data variables.product.prodname_emus %}
To configure SAML SSO for your {% data variables.product.prodname_emu_enterprise %}, you must configure an application on your IdP and then configure your enterprise on GitHub.com. After you configure SAML SSO, you can configure user provisioning.
To install and configure the {% data variables.product.prodname_emu_idp_application %} application on your IdP, you must have a tenant and administrative access on a supported IdP.
{% note %}
{% data reusables.enterprise-accounts.emu-password-reset-session %}
{% endnote %}
1. [Configuring your identity provider](#configuring-your-identity-provider)
2. [Configuring your enterprise](#configuring-your-enterprise)
3. [Enabling provisioning](#enabling-provisioning)
### Configuring your identity provider
To configure your IdP, follow the instructions they provide for configuring the {% data variables.product.prodname_emu_idp_application %} application on your IdP.
1. To install the {% data variables.product.prodname_emu_idp_application %} application, click the link for your IdP below:
- [{% data variables.product.prodname_emu_idp_application %} application on Azure Active Directory](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/aad.githubenterprisemanageduser?tab=Overview)
- [{% data variables.product.prodname_emu_idp_application %} application on Okta](https://www.okta.com/integrations/github-enterprise-managed-user)
1. To configure the {% data variables.product.prodname_emu_idp_application %} application and your IdP, click the link below and follow the instructions provided by your IdP:
- [Azure Active Directory tutorial for {% data variables.product.prodname_emus %}](https://docs.microsoft.com/en-us/azure/active-directory/saas-apps/github-enterprise-managed-user-tutorial)
- [Okta documentation for {% data variables.product.prodname_emus %}](https://saml-doc.okta.com/SAML_Docs/How-to-Configure-SAML-2.0-for-GitHub-Enterprise-Managed-User.html)
1. So you can test and configure your enterprise, assign yourself or the user that will be configuring SAML SSO on {% data variables.product.prodname_dotcom %} to the {% data variables.product.prodname_emu_idp_application %} application on your IdP.
1. To enable you to continue configuring your enterprise on {% data variables.product.prodname_dotcom %}, locate and note the following information from the application you installed on your IdP:
| Value | Other names | Description |
| :- | :- | :- |
| IdP Sign-On URL | Login URL, IdP URL | Application's URL on your IdP |
| IdP Identifier URL | Issuer | IdP's identifier to service providers for SAML authentication |
| Signing certificate, Base64-encoded | Public certificate | Public certificate that IdP uses to sign authentication requests |
### Configuring your enterprise
After you install and configure the {% data variables.product.prodname_emu_idp_application %} application on your identity provider, you can configure your enterprise.
1. Sign into {% data variables.product.prodname_dotcom_the_website %} as the setup user for your new enterprise with the username **@<em>SHORT-CODE</em>_admin**.
{% data reusables.enterprise-accounts.access-enterprise %}
{% data reusables.enterprise-accounts.settings-tab %}
{% data reusables.enterprise-accounts.security-tab %}
1. Under "SAML single sign-on", select **Require SAML authentication**.
![Checkbox for enabling SAML SSO](/assets/images/help/business-accounts/enable-saml-auth-enterprise.png)
1. Under **Sign on URL**, type the HTTPS endpoint of your IdP for single sign-on requests that you noted while configuring your IdP.
![Field for the URL that members will be forwarded to when signing in](/assets/images/help/saml/saml_sign_on_url_business.png)
1. Under **Issuer**, type your SAML issuer URL that you noted while configuring your IdP, to verify the authenticity of sent messages.
![Field for the SAML issuer's name](/assets/images/help/saml/saml_issuer.png)
1. Under **Public Certificate**, paste the certificate that you noted while configuring your IdP, to verify SAML responses.
![Field for the public certificate from your identity provider](/assets/images/help/saml/saml_public_certificate.png)
1. To verify the integrity of the requests from your SAML issuer, click {% octicon "pencil" aria-label="The edit icon" %}. Then, in the "Signature Method" and "Digest Method" drop-downs, choose the hashing algorithm used by your SAML issuer.
![Drop-downs for the Signature Method and Digest method hashing algorithms used by your SAML issuer](/assets/images/help/saml/saml_hashing_method.png)
1. Before enabling SAML SSO for your enterprise, to ensure that the information you've entered is correct, click **Test SAML configuration**. ![Button to test SAML configuration before enforcing](/assets/images/help/saml/saml_test.png)
1. Click **Save**.
{% note %}
**Note:** When you require SAML SSO for your enterprise, the setup user will no longer have access to the enterprise but will remain signed in to GitHub. Only {% data variables.product.prodname_managed_users %} provisioned by your IdP will have access to the enterprise.
{% endnote %}
1. To ensure you can still access your enterprise in the event that your identity provider is ever unavailable in the future, click **Download**, **Print**, or **Copy** to save your recovery codes.
![Button to test SAML configuration before enforcing](/assets/images/help/saml/saml_recovery_code_options.png)
### Enabling provisioning
After you enable SAML SSO, enable provisioning. For more information, see "[Configuring SCIM provisioning for enterprise managed users](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-scim-provisioning-for-enterprise-managed-users)."
## Saving your recovery codes
In the event that your identity provider is unavailable, you can use the setup user and a recovery code to sign in and access your enterprise. If you did not save your recovery codes when you configured SAML SSO, you can still access them from your enterprise's settings.
{% data reusables.enterprise-accounts.access-enterprise %}
{% data reusables.enterprise-accounts.settings-tab %}
{% data reusables.enterprise-accounts.security-tab %}
1. Under "Require SAML authentication", click **Save your recovery codes**.
![Button to test SAML configuration before enforcing](/assets/images/help/enterprises/saml-recovery-codes-link.png)
2. To save your recovery codes, click **Download**, **Print**, or **Copy**.
![Button to test SAML configuration before enforcing](/assets/images/help/saml/saml_recovery_code_options.png)

View File

@@ -0,0 +1,80 @@
---
title: Configuring SCIM provisioning for Enterprise Managed Users with Okta
shortTitle: Set up provisioning with Okta
intro: 'You can provision new users and manage their membership of your enterprise and teams using Okta as your identity provider.'
product: '{% data reusables.gated-features.emus %}'
versions:
fpt: '*'
redirect_from:
- /early-access/github/articles/configuring-provisioning-for-managed-users-with-okta
topics:
- Accounts
- Enterprise
---
## About provisioning with Okta
You can use {% data variables.product.prodname_emus %} with Okta as your identity provider to provision new accounts, manage enterprise membership, and manage team memberships for organizations in your enterprise. For more information about provisioning for {% data variables.product.prodname_emus %}, see "[Configuring SCIM provisioning for enterprise managed users](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-scim-provisioning-for-enterprise-managed-users)."
Before you can configure provisioning with Okta, you must configure SAML single-sign on. For more information, see "[Configuring SAML single sign-on for Enterprise Managed Users](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-saml-single-sign-on-for-enterprise-managed-users)."
To configure provisioning with Okta, you must set your enterprise's name in the {% data variables.product.prodname_emu_idp_application %} application and enter your setup user's personal access token. You can then start provisioning users in Okta.
## Supported features
{% data variables.product.prodname_emus %} supports many provisioning features in Okta.
| Feature | Description |
| --- | --- |
| Push New Users | Users that are assigned to the {% data variables.product.prodname_emu_idp_application %} application in Okta are automatically created in the enterprise on {% data variables.product.product_name %}. |
| Push Profile Update | Updates made to the user's profile in Okta will be pushed to {% data variables.product.product_name %}. |
| Push Groups | Groups in Okta that are assigned to the {% data variables.product.prodname_emu_idp_application %} application as Push Groups are automatically created in the enterprise on {% data variables.product.product_name %}. |
| Push User Deactivation | Unassigning the user from the {% data variables.product.prodname_emu_idp_application %} application in Okta will disable the user on {% data variables.product.product_name %}. The user will not be able to sign in, but the user's information is maintained. |
| Reactivate Users | Users in Okta whose Okta accounts are reactivated and who are assigned back to the {% data variables.product.prodname_emu_idp_application %} application will be enabled. |
{% note %}
**Note:** {% data variables.product.prodname_emus %} does not support modifications to usernames.
{% endnote %}
## Setting your enterprise name
After your {% data variables.product.prodname_emu_enterprise %} has been created, you can begin to configure provisioning by setting your enterprise name in Okta.
1. Navigate to your {% data variables.product.prodname_emu_idp_application %} application on Okta.
1. Click the **Sign On** tab.
1. To make changes, click **Edit**.
1. Under "Advanced Sign-on Settings", in the "Enterprise Name" text box, type your enterprise name. For example, if you access your enterprise at `https://github.com/enterprises/octoinc`, your enterprise name would be "octoinc".
![Screenshot of the Enterprise Name field on Okta](/assets/images/help/enterprises/okta-emu-enterprise-name.png)
1. To save your enterprise name, click **Save**.
## Configuring provisioning
After setting your enterprise name, you can proceed to configure provisioning settings.
To configure provisioning, the setup user with the **@<em>SHORT-CODE</em>_admin** username will need to provide a personal access token with the **admin:enterprise** scope. For more information on creating a new token, see "[Creating a personal access token](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/configuring-scim-provisioning-for-enterprise-managed-users#creating-a-personal-access-token)."
1. Navigate to your {% data variables.product.prodname_emu_idp_application %} application on Okta.
1. Click the **Provisioning** tab.
1. In the settings menu, click **Integration**.
1. To make changes, click **Edit**.
1. Select **Enable API integration**.
1. In the "API Token" field, enter the personal access token with the **admin:enterprise** scope belonging to the setup user.
![Screenshot showing the API Token field on Okta](/assets/images/help/enterprises/okta-emu-token.png)
1. Click **Test API Credentials**. If the test is successful, a verification message will appear at the top of the screen.
1. To save the token, click **Save**.
1. In the settings menu, click **To App**.
![Screenshot showing the To App menu item on Okta](/assets/images/help/enterprises/okta-emu-to-app-menu.png)
1. To the right of "Provisioning to App", to allow changes to be made, click **Edit**.
1. Select **Enable** for **Create Users**, **Update User Attributes**, and **Deactivate Users**.
![Screenshot showing provisioning options on Okta](/assets/images/help/enterprises/okta-emu-provisioning-to-app.png)
1. To finish configuring provisioning, click **Save**.
## Assigning users
After you have configured SAML SSO and provisioning, you will be able provision new users on {% data variables.product.prodname_dotcom_the_website %} by assigning users to the {% data variables.product.prodname_emu_idp_application %} application. You can also automatically manage organization membership by assigning groups to the application as push groups and connecting the push groups to teams in your organizations. For more information about managing teams, see "[Managing team memberships with identity provider groups](/github/setting-up-and-managing-your-enterprise/managing-your-enterprise-users-with-your-identity-provider/managing-team-memberships-with-identity-provider-groups)."
When assigning users, you can use the "Roles" attribute in the {% data variables.product.prodname_emu_idp_application %} application to set a user's role in your enterprise on {% data variables.product.product_name %}. For more information on roles, see "[Roles in an enterprise](/github/setting-up-and-managing-your-enterprise/managing-users-in-your-enterprise/roles-in-an-enterprise)."
![Screenshot showing the role options for provisioned user on Okta](/assets/images/help/enterprises/okta-emu-user-role.png)

Some files were not shown because too many files have changed in this diff Show More