1
0
mirror of synced 2025-12-22 11:26:57 -05:00

Merge branch 'main' into sophietheking-6776

This commit is contained in:
Sophie
2022-04-25 15:25:27 +02:00
committed by GitHub
2980 changed files with 52575 additions and 38993 deletions

View File

@@ -13,7 +13,7 @@ module.exports = {
babelOptions: { configFile: './.babelrc' },
sourceType: 'module',
},
ignorePatterns: ['tmp/*', '!/.*', '/.next/'],
ignorePatterns: ['tmp/*', '!/.*', '/.next/', 'script/bookmarklets/*'],
rules: {
'import/no-extraneous-dependencies': ['error', { packageDir: '.' }],
},

View File

@@ -40,7 +40,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo content
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -79,7 +79,7 @@ jobs:
- if: ${{ env.IS_PUBLIC_BUILD == 'true' }}
name: Check out main branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
ref: 'main'
persist-credentials: 'false'
@@ -87,7 +87,7 @@ jobs:
- if: ${{ env.IS_INTERNAL_BUILD == 'true' }}
name: Check out PR code
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
ref: ${{ env.COMMIT_REF }}
# To prevent issues with cloning early access content later
@@ -139,7 +139,7 @@ jobs:
- if: ${{ env.IS_INTERNAL_BUILD == 'true' }}
name: Clone docs-early-access
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
repository: github/docs-early-access
token: ${{ secrets.DOCUBOT_REPO_PAT }}
@@ -152,7 +152,7 @@ jobs:
- if: ${{ env.IS_PUBLIC_BUILD == 'true' }}
name: Check out user code to temp directory
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
path: ./user-code
ref: ${{ env.COMMIT_REF }}

View File

@@ -39,7 +39,7 @@ jobs:
creds: ${{ secrets.NONPROD_AZURE_CREDENTIALS }}
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Get preview app info
env:

View File

@@ -49,7 +49,7 @@ jobs:
uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
ref: ${{ github.sha }}
# To prevent issues with cloning early access content later
@@ -66,7 +66,7 @@ jobs:
cache: npm
- name: Clone docs-early-access
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
repository: github/docs-early-access
token: ${{ secrets.DOCUBOT_REPO_PAT }}

View File

@@ -32,7 +32,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
lfs: true
@@ -54,7 +54,7 @@ jobs:
run: npm ci --include=optional
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -26,7 +26,7 @@ jobs:
REPORT_REPOSITORY: github/docs-content
steps:
- name: Check out repo's default branch
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
with:
@@ -35,7 +35,7 @@ jobs:
- name: npm ci
run: npm ci
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -39,7 +39,7 @@ jobs:
exit 1 # prevents further steps from running
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
@@ -50,9 +50,20 @@ jobs:
- name: Install Node.js dependencies
run: npm ci
- name: Run broken github/github link check
- name: Build server
run: npm run build
- name: Start server in the background
env:
WAF_TOKEN: ${{ secrets.WAF_TOKEN }}
NODE_ENV: production
PORT: 4000
run: |
node server.mjs &
sleep 5
curl --retry-connrefused --retry 3 -I http://localhost:4000/
- name: Run broken github/github link check
run: |
script/check-github-github-links.js > broken_github_github_links.md

View File

@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -30,7 +30,7 @@ jobs:
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- uses: github/codeql-action/init@1ed1437484560351c5be56cf73a48a279d116b78
with:
languages: javascript # comma separated list of values from {go, python, javascript, java, cpp, csharp} (not YET ruby, sorry!)

View File

@@ -49,7 +49,7 @@ jobs:
PR_NUMBER: ${{ github.event.pull_request.number }}
steps:
- name: check out repo content
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Get preview app info
env:
@@ -74,7 +74,7 @@ jobs:
run: .github/actions-scripts/content-changes-table-comment.js
- name: Find content directory changes comment
uses: peter-evans/find-comment@d2dae40ed151c634e4189471272b57e76ec19ba8
uses: peter-evans/find-comment@1769778a0c5bd330272d749d12c036d65e70d39d
id: findComment
with:
issue-number: ${{ github.event.pull_request.number }}

View File

@@ -55,7 +55,7 @@ jobs:
- run: git config --global user.email "67483024+docubot@users.noreply.github.com"
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
fetch-depth: 0
lfs: true

View File

@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -20,7 +20,7 @@ jobs:
steps:
- name: Check out repo content
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -36,7 +36,7 @@ jobs:
exit 1 # prevents further steps from running
- name: Checkout repository code
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.DOCUBOT_REPO_PAT }}
@@ -63,7 +63,7 @@ jobs:
run: $GITHUB_WORKSPACE/.github/actions-scripts/enterprise-search-label.js
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -27,7 +27,7 @@ jobs:
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -45,7 +45,7 @@ jobs:
uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
# To prevent issues with cloning early access content later
persist-credentials: 'false'
@@ -56,7 +56,7 @@ jobs:
- if: ${{ env.ENABLE_EARLY_ACCESS }}
name: Clone docs-early-access
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
repository: github/docs-early-access
token: ${{ secrets.DOCUBOT_REPO_PAT }}

View File

@@ -16,7 +16,7 @@ jobs:
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Install dependencies
run: npm ci

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository code
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -31,7 +31,7 @@ jobs:
add-labels: 'github-openapi-bot'
- name: Checkout repository code
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
# actions/checkout by default will leave you in a detached head state
# so we need to specify the PR head ref explicitly since we're making

View File

@@ -39,7 +39,7 @@ jobs:
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
- name: Checkout repository code
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo on head ref
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
ref: ${{ github.head_ref }}
# Need to specify a PAT here because otherwise GITHUB_TOKEN is used

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
# Using a PAT is necessary so that the new commit will trigger the
# CI in the PR. (Events from GITHUB_TOKEN don't trigger new workflows.)

View File

@@ -44,7 +44,7 @@ jobs:
exit 1
- name: Check out repo content
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
@@ -30,7 +30,7 @@ jobs:
run: npm ci --include=optional
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo content
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561

View File

@@ -25,7 +25,7 @@ jobs:
echo 'The repo is currently frozen! Exiting this workflow.'
exit 1 # prevents further steps from running
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
with:

View File

@@ -98,7 +98,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
# Set up npm and run npm ci to run husky to get githooks for LFS
- name: Setup node
@@ -120,7 +120,7 @@ jobs:
github_token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }}
- name: Create pull request
uses: repo-sync/pull-request@9152b1c4aeeab247ba2ce12c5d7e693d287bf1b9
uses: repo-sync/pull-request@65785d95a5a466e46a9d0708933a3bd51bbf9dde
env:
GITHUB_TOKEN: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }}
with:

View File

@@ -26,10 +26,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout docs-internal
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: checkout public site-policy
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
repository: github/site-policy
token: ${{ secrets.API_TOKEN_SITEPOLICY }}

View File

@@ -51,7 +51,7 @@ jobs:
exit 1 # prevents further steps from running
# Check out internal docs repository
- name: checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
token: ${{ secrets.DOCS_BOT_FR }}
@@ -65,7 +65,7 @@ jobs:
run: npm ci
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
@@ -38,7 +38,7 @@ jobs:
run: npm ci
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -46,7 +46,7 @@ jobs:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
# Not all test suites need the LFS files. So instead, we opt to
# NOT clone them initially and instead, include them manually
@@ -87,7 +87,7 @@ jobs:
- name: Check out docs-early-access too, if internal repo
if: ${{ github.repository == 'github/docs-internal' }}
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
repository: github/docs-early-access
token: ${{ secrets.DOCUBOT_REPO_PAT }}
@@ -132,7 +132,7 @@ jobs:
run: npm ci
- name: Cache nextjs build
uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed
uses: actions/cache@48af2dc4a9e8278b89d7fa154b955c30c6aaab09
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}

View File

@@ -30,9 +30,7 @@ jobs:
if: github.repository == 'github/docs-internal' && github.event.pull_request.user.login != 'Octomerger'
runs-on: ubuntu-latest
outputs:
notAllowed: ${{ steps.filter.outputs.notAllowed }}
notAllowedSearchSyncLabel: ${{ steps.filter.outputs.notAllowedSearchSyncLabel }}
count: 0
steps:
- name: Get files changed
uses: dorny/paths-filter@eb75a1edc117d3756a18ef89958ee59f9500ba58
@@ -55,7 +53,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.DOCUBOT_REPO_PAT }}

View File

@@ -32,7 +32,7 @@ jobs:
echo 'The repo is currently frozen! Exiting this workflow.'
exit 1 # prevents further steps from running
- name: Checkout
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
- name: Setup Node
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561
with:

View File

@@ -1,3 +1,4 @@
translations/
includes/
data/release-notes/
script/bookmarklets/

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -88,10 +88,7 @@ export const DefaultLayout = (props: Props) => {
<SidebarNav />
{/* Need to set an explicit height for sticky elements since we also
set overflow to auto */}
<div
className="flex-column flex-1 overflow-auto print-overflow-visible"
style={{ height: '100vh' }}
>
<div className="flex-column flex-1">
<Header />
<main id="main-content" style={{ scrollMarginTop: '5rem' }}>
<DeprecationBanner />
@@ -103,7 +100,7 @@ export const DefaultLayout = (props: Props) => {
<SupportSection />
<SmallFooter />
<ScrollButton
className="position-fixed bottom-0 mb-4 right-0 mr-4"
className="position-fixed bottom-0 mb-4 right-0 mr-4 z-1"
ariaLabel={t('scroll_to_top')}
/>
</footer>

View File

@@ -26,7 +26,7 @@ const SUPPORTED_LANGUAGES = ['json', 'javascript', 'curl']
// </pre>
//
const CODE_ELEMENTS_PARENT_SELECTOR = '[data-highlight]'
const CODE_SELECTOR = 'pre code'
const CODE_SELECTOR = 'div code' || 'pre code'
export default function ClientSideHighlightJS() {
const { asPath } = useRouter()

View File

@@ -0,0 +1,37 @@
import { createContext, useContext } from 'react'
export type MiniTocItem = {
platform: string
contents: string & { title: string; href: string }
items?: MiniTocItem[]
}
export type RestContextT = {
title: string
intro: string
renderedPage: string | JSX.Element[]
miniTocItems: Array<MiniTocItem>
}
export const RestContext = createContext<RestContextT | null>(null)
export const useRestContext = (): RestContextT => {
const context = useContext(RestContext)
if (!context) {
throw new Error('"useRestContext" may only be used inside "RestContext.Provider"')
}
return context
}
export const getRestContextFromRequest = (req: any): RestContextT => {
const page = req.context.page
return {
title: page.titlePlainText,
intro: page.intro,
renderedPage: req.context.renderedPage || '',
miniTocItems: req.context.miniTocItems || [],
}
}

View File

@@ -1,3 +1,7 @@
import { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
import dynamic from 'next/dynamic'
import { DefaultLayout } from 'components/DefaultLayout'
import { TableOfContents } from 'components/landing/TableOfContents'
import { useTocLandingContext } from 'components/context/TocLandingContext'
@@ -10,6 +14,13 @@ import { Callout } from 'components/ui/Callout'
import { Lead } from 'components/ui/Lead'
import { LearningTrackNav } from 'components/article/LearningTrackNav'
const ClientSideRedirectExceptions = dynamic(
() => import('components/article/ClientsideRedirectExceptions'),
{
ssr: false,
}
)
export const TocLanding = () => {
const {
title,
@@ -23,8 +34,38 @@ export const TocLanding = () => {
} = useTocLandingContext()
const { t } = useTranslation('toc')
const { asPath } = useRouter()
// We have some one-off redirects for rest api docs
// currently those are limited to the repos page, but
// that will grow soon as we restructure the rest api docs.
// This is a workaround to updating the hardcoded links
// directly in the REST API code in a separate repo, which
// requires many file changes and teams to sign off.
// While the organization is turbulent, we can do this.
// Once it's more settled, we can refactor the rest api code
// to leverage the OpenAPI urls rather than hardcoded urls.
// The code below determines if we should bother loading this redirecting
// component at all.
// The reason this isn't done at the server-level is because there you
// can't possibly access the URL hash. That's only known in client-side
// code.
const [loadClientsideRedirectExceptions, setLoadClientsideRedirectExceptions] = useState(false)
useEffect(() => {
const { hash } = window.location
// Today, Jan 2022, it's known explicitly what the pathname.
// In the future there might be more.
// Hopefully, we can some day delete all of this and no longer
// be dependent on the URL hash to do the redirect.
if (hash && asPath.startsWith('/rest')) {
setLoadClientsideRedirectExceptions(true)
}
}, [])
return (
<DefaultLayout>
{/* Doesn't matter *where* this is included because it will
never render anything. It always just return null. */}
{loadClientsideRedirectExceptions && <ClientSideRedirectExceptions />}
<div className="container-xl px-3 px-md-6 my-4">
<ArticleGridLayout>
<ArticleTitle>{title}</ArticleTitle>

View File

@@ -43,7 +43,7 @@ export const RestBanner = () => {
>
const newRestPagesText = pages.map((page, i) => [
<React.Fragment key={page}>
<Link href={`/${router.locale}/rest/reference/${page}`}>
<Link href={`/${router.locale}/rest/${page}`}>
{restRepoCategoryExceptionsTitles[page]}
</Link>
{i < pages.length - 1 && ', '}
@@ -60,7 +60,7 @@ export const RestBanner = () => {
noticeString = (
<React.Fragment>
If you can't find what you're looking for, you might try the{' '}
<Link href={`/${router.locale}/rest/reference/actions`}>Actions</Link> REST API page.
<Link href={`/${router.locale}/rest/actions`}>Actions</Link> REST API page.
</React.Fragment>
)
}

View File

@@ -1,4 +1,14 @@
.codeBlock {
max-height: 32rem;
overflow: auto;
padding: 1rem;
margin-bottom: 1rem;
line-height: 1.45;
background-color: var(--color-canvas-subtle);
white-space: pre-wrap;
word-break: break-all;
code {
background-color: transparent;
}
}

View File

@@ -31,7 +31,7 @@ export function CodeBlock({ verb, headingLang, codeBlock, highlight }: Props) {
</Tooltip>
</header>
)}
<pre className={cx(styles.codeBlock, 'rounded-1 border')} data-highlight={highlight}>
<div className={cx(styles.codeBlock, 'rounded-1 border')} data-highlight={highlight}>
<code>
{verb && (
<>
@@ -43,7 +43,7 @@ export function CodeBlock({ verb, headingLang, codeBlock, highlight }: Props) {
)}
{codeBlock}
</code>
</pre>
</div>
</div>
)
}

View File

@@ -1,18 +1,13 @@
import React, { useState, useEffect } from 'react'
import cx from 'classnames'
import { useRouter } from 'next/router'
import dynamic from 'next/dynamic'
import { DefaultLayout } from 'components/DefaultLayout'
import { useMainContext } from 'components/context/MainContext'
import { MarkdownContent } from 'components/ui/MarkdownContent'
import { Lead } from 'components/ui/Lead'
import { MiniTocItem } from 'components/context/ArticleContext'
import { RestCategoryOperationsT } from './types'
import { useRestContext } from 'components/context/RestContext'
import { Operation } from './types'
import { RestOperation } from './RestOperation'
import { ChevronDownIcon, ChevronUpIcon, SearchIcon } from '@primer/octicons-react'
import { useTranslation } from 'components/hooks/useTranslation'
import { ActionList } from '@primer/react'
const ClientSideHighlightJS = dynamic(() => import('components/article/ClientSideHighlightJS'), {
ssr: false,
@@ -26,24 +21,12 @@ const ClientSideRedirectExceptions = dynamic(
)
export type StructuredContentT = {
descriptions: any
introContent: string
restOperations: RestCategoryOperationsT
miniTocItems?: MiniTocItem[]
restOperations: Operation[]
}
export const RestReferencePage = ({
descriptions,
introContent,
restOperations,
miniTocItems,
}: StructuredContentT) => {
const { t } = useTranslation('pages')
export const RestReferencePage = ({ restOperations }: StructuredContentT) => {
const { asPath } = useRouter()
const { page } = useMainContext()
const subcategories = Object.keys(restOperations)
const [collapsed, setCollapsed] = useState({} as Record<number, boolean>)
const { title, intro, renderedPage } = useRestContext()
// We have some one-off redirects for rest api docs
// currently those are limited to the repos page, but
// that will grow soon as we restructure the rest api docs.
@@ -60,17 +43,13 @@ export const RestReferencePage = ({
// code.
const [loadClientsideRedirectExceptions, setLoadClientsideRedirectExceptions] = useState(false)
useEffect(() => {
const { hash, pathname } = window.location
const { hash } = window.location
// Today, Jan 2022, it's known explicitly what the pathname.
// In the future there might be more.
// Hopefully, we can some day delete all of this and no longer
// be dependent on the URL hash to do the redirect.
if (
hash &&
(pathname.endsWith('/rest/reference/repos') ||
pathname.endsWith('/rest/reference/enterprise-admin') ||
pathname.endsWith('/rest/reference/deployments'))
) {
if (hash && asPath.startsWith('/rest')) {
setLoadClientsideRedirectExceptions(true)
}
}, [])
@@ -110,113 +89,31 @@ export const RestReferencePage = ({
// consecutive one does.
}, [asPath])
// Resetting the collapsed array when we move to another REST page
useEffect(() => {
setCollapsed({})
}, [asPath])
const handleClick = (param: number) => {
setCollapsed((prevState) => {
return { ...prevState, [param]: !prevState[param] }
})
}
const renderTocItem = (item: MiniTocItem, index: number) => {
return (
<ActionList.Item
as="li"
key={item.contents}
className={item.platform}
sx={{
listStyle: 'none',
padding: '2px',
':hover': {
bg: 'var(--color-canvas-inset)',
},
}}
>
<div className={cx('lh-condensed d-block width-full')}>
<div className="d-inline-flex" dangerouslySetInnerHTML={{ __html: item.contents }} />
{item.items && item.items.length > 0 && (
<button
className="background-transparent border-0 ml-1"
onClick={() => handleClick(index)}
>
{!collapsed[index] ? <ChevronDownIcon /> : <ChevronUpIcon />}
</button>
)}
{collapsed[index] && item.items && item.items.length > 0 ? (
<ul className="ml-3">{item.items.map(renderTocItem)}</ul>
) : null}
</div>
</ActionList.Item>
)
}
return (
<DefaultLayout>
{/* Doesn't matter *where* this is included because it will
never render anything. It always just return null. */}
{loadClientsideRedirectExceptions && <ClientSideRedirectExceptions />}
{lazyLoadHighlightJS && <ClientSideHighlightJS />}
<div className="container-xl px-3 px-md-6 my-4 mx-xl-12 mx-lg-12">
<h1>{page.title}</h1>
{page.introPlainText && (
<div className={'px-3 px-md-6 my-4 mx-xl-12 mx-lg-12'}>
<h1 className="mb-3">{title}</h1>
{intro && (
<Lead data-testid="lead" data-search="lead" className="markdown-body">
{page.introPlainText}
{intro}
</Lead>
)}
<div className="my-3 d-flex">
<div className="pr-3 mt-1">
<Circle className="color-fg-on-emphasis color-bg-emphasis">
<SearchIcon className="" size={15} />
</Circle>
</div>
<div id="article-contents">
<h3>{t('miniToc')}</h3>
{miniTocItems && (
<ActionList
key={page.title}
items={miniTocItems.map((items, i) => {
return {
key: page.title + i,
text: page.title,
renderItem: () => <ul>{renderTocItem(items, i)}</ul>,
}
})}
/>
)}
</div>
</div>
<div key={`restCategory-introContent`}>
<div dangerouslySetInnerHTML={{ __html: introContent }} />
</div>
<MarkdownContent>
{subcategories.map((subcategory, index) => (
<div key={`${subcategory}-${index}`}>
<div dangerouslySetInnerHTML={{ __html: descriptions[subcategory] }} />
{restOperations[subcategory].map((operation, index) => (
<RestOperation
key={`${subcategory}-${operation.title}-${index}`}
operation={operation}
/>
))}
</div>
))}
<MarkdownContent>{renderedPage}</MarkdownContent>
{restOperations &&
restOperations.length > 0 &&
restOperations.map((operation, index) => (
<RestOperation
key={`restOperation-${operation.title}-${index}`}
operation={operation}
/>
))}
</MarkdownContent>
</div>
</DefaultLayout>
)
}
const Circle = ({ className, children }: { className?: string; children?: React.ReactNode }) => {
return (
<div
className={cx('circle d-flex flex-justify-center flex-items-center', className)}
style={{ width: 24, height: 24 }}
>
{children}
</div>
)
}

View File

@@ -69,7 +69,3 @@ export interface ChildParameter {
description: string
type: string
}
export interface RestCategoryOperationsT {
[subcategory: string]: Operation[]
}

View File

@@ -0,0 +1,124 @@
import cx from 'classnames'
import { useState, SyntheticEvent } from 'react'
import { ChevronDownIcon } from '@primer/octicons-react'
import { ActionList } from '@primer/react'
import { Link } from 'components/Link'
import { ProductTreeNode } from 'components/context/MainContext'
import { EventType, sendEvent } from 'components/lib/events'
import styles from './SidebarProduct.module.scss'
type SectionProps = {
routePath: string
page: ProductTreeNode
title: string
defaultOpen: boolean
}
export const ProductCollapsibleSection = (props: SectionProps) => {
const { routePath, defaultOpen, title, page } = props
const [isOpen, setIsOpen] = useState(defaultOpen)
const onToggle = (e: SyntheticEvent) => {
const newIsOpen = (e.target as HTMLDetailsElement).open
setIsOpen(newIsOpen)
sendEvent({
type: EventType.navigate,
navigate_label: `details ${newIsOpen ? 'open' : 'close'}: ${title}`,
})
}
// The lowest level page link displayed in the tree
const renderTerminalPageLink = (page: ProductTreeNode) => {
const title = page.renderedShortTitle || page.renderedFullTitle
const isCurrent = routePath === page.href
return {
text: title,
renderItem: () => (
<ActionList.Item
data-testid="sidebar-article"
data-is-current-page={isCurrent}
as="li"
className={cx(
'position-relative',
styles.sidebarArticle,
isCurrent && ['text-bold', styles.sidebarArticleActive]
)}
sx={{
padding: '2px 0',
':hover': {
borderRadius: 0,
},
}}
>
<Link
href={page.href}
className={cx(
'd-block pl-6 pr-5 py-1 no-underline width-full',
isCurrent ? 'color-fg-accent' : 'color-fg-default'
)}
>
{title}
</Link>
</ActionList.Item>
),
}
}
return (
<details open={defaultOpen} onToggle={onToggle} className="details-reset">
<summary className="outline-none">
<div className="d-flex flex-justify-between">
<div className="pl-4 pr-1 py-2 f5 d-block flex-auto mr-3 color-fg-default no-underline text-bold">
{title}
</div>
<span style={{ marginTop: 7 }} className="flex-shrink-0 pr-3">
<ChevronDownIcon className={cx('opacity-60', isOpen && 'rotate-180')} />
</span>
</div>
</summary>
{
<>
{/* <!-- some pages have nested child pages (formerly known as a mapTopic) --> */}
{page.childPages[0]?.page.documentType === 'mapTopic' ? (
<ul className="list-style-none position-relative">
{page.childPages.map((childPage, i) => {
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive = routePath.includes(childPage.href)
const isCurrent = routePath === childPage.href
return (
<li key={childPage.href + i} data-is-current-page={isCurrent}>
<details
open={isActive}
onToggle={(e) => e.stopPropagation()}
className="details-reset"
>
<summary>
<div className={cx('pl-4 pr-5 py-2 no-underline')}>{childTitle}</div>
</summary>
<div data-testid="sidebar-article-group" className="pb-0">
<ActionList
{...{ as: 'ul' }}
items={childPage.childPages.map((cp) => {
return renderTerminalPageLink(cp)
})}
></ActionList>
</div>
</details>
</li>
)
})}
</ul>
) : page.childPages[0]?.page.documentType === 'article' ? (
<div data-testid="sidebar-article-group" className="pb-0">
<ActionList {...{ as: 'ul' }} items={page.childPages.map(renderTerminalPageLink)} />
</div>
) : null}
</>
}
</details>
)
}

View File

@@ -0,0 +1,206 @@
import { useRouter } from 'next/router'
import cx from 'classnames'
import { useState, useEffect, SyntheticEvent, ReactElement } from 'react'
import { ChevronDownIcon } from '@primer/octicons-react'
import { ActionList } from '@primer/react'
import { Link } from 'components/Link'
import { ProductTreeNode } from 'components/context/MainContext'
import { EventType, sendEvent } from 'components/lib/events'
import { MiniTocItem, useRestContext } from 'components/context/RestContext'
import styles from './SidebarProduct.module.scss'
type SectionProps = {
routePath: string
page: ProductTreeNode
title: string
defaultOpen: boolean
isStandaloneCategory: boolean
}
type ConditionalLinkTypes = {
condition: boolean
wrapper: Function
children: ReactElement
}
export const RestCollapsibleSection = (props: SectionProps) => {
const router = useRouter()
const { routePath, defaultOpen, title, page, isStandaloneCategory } = props
const [isOpen, setIsOpen] = useState(defaultOpen)
const [currentAnchor, setCurrentAnchor] = useState('')
const onToggle = (e: SyntheticEvent) => {
const newIsOpen = (e.target as HTMLDetailsElement).open
setIsOpen(newIsOpen)
sendEvent({
type: EventType.navigate,
navigate_label: `details ${newIsOpen ? 'open' : 'close'}: ${title}`,
})
}
useEffect(() => {
if (!currentAnchor) {
setCurrentAnchor(window.location.hash)
}
const hashChangeHandler = () => {
setCurrentAnchor(window.location.hash)
}
window.addEventListener('hashchange', hashChangeHandler)
return () => {
window.removeEventListener('hashchange', hashChangeHandler)
}
}, [])
const miniTocItems =
router.query.productId === 'rest' ||
// These pages need the Article Page mini tocs instead of the Rest Pages
router.asPath.includes('/rest/guides') ||
router.asPath.includes('/rest/overview')
? []
: useRestContext().miniTocItems
// This wrapper solves the issue of having standalone categories not
// link to the new page. We want standalone categories to have links
// just like maptopics/subcategories.
const ConditionalLinkWrapper = ({ condition, wrapper, children }: ConditionalLinkTypes) =>
condition ? wrapper(children) : children
const renderRestAnchorLink = (miniTocItem: MiniTocItem) => {
const miniTocAnchor = miniTocItem.contents.href
const title = miniTocItem.contents.title
const isCurrent = currentAnchor === miniTocAnchor
return {
text: title,
renderItem: () => (
<ActionList.Item
data-is-current-page={isCurrent}
as="li"
className={cx(
'position-relative',
styles.sidebarArticle,
isCurrent && ['text-bold', styles.sidebarArticleActive]
)}
sx={{
padding: '2px 0',
':hover': {
borderRadius: 0,
},
}}
>
<a
className={cx(
'd-block pl-6 pr-5 py-1 no-underline width-full',
isCurrent ? 'color-fg-accent' : 'color-fg-default'
)}
href={miniTocAnchor}
>
{title}
</a>
</ActionList.Item>
),
}
}
return (
<details open={defaultOpen} onToggle={onToggle} className="details-reset">
<summary className="outline-none">
<ConditionalLinkWrapper
condition={isStandaloneCategory}
wrapper={(children: ReactElement) => (
<Link href={page.href} className="color-fg-default no-underline text-bold">
{children}
</Link>
)}
>
<div className="d-flex flex-justify-between">
<div className="pl-4 pr-1 py-2 f5 d-block flex-auto mr-3 color-fg-default no-underline text-bold">
{title}
</div>
<span style={{ marginTop: 7 }} className="flex-shrink-0 pr-3">
<ChevronDownIcon className={cx('opacity-60', isOpen && 'rotate-180')} />
</span>
</div>
</ConditionalLinkWrapper>
</summary>
{
<>
{/* <!-- Render the maptopic level subcategory operation links e.g. --> */}
<ul className="list-style-none position-relative">
{page.childPages.length <= 0 ? (
<div data-testid="sidebar-article-group" className="pb-0">
{miniTocItems.length > 0 && (
<ActionList
{...{ as: 'ul' }}
items={miniTocItems.map((item) => {
return renderRestAnchorLink(item)
})}
></ActionList>
)}
</div>
) : (
page.childPages.map((childPage, i) => {
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive = routePath.includes(childPage.href)
const isCurrent = routePath === childPage.href
// At this point we have the mini-toc data for the current page
// so we render this list of operation links.
if (routePath === childPage.href) {
return (
<li key={childPage.href + i} data-is-current-page={isCurrent}>
<details
open={isActive}
onToggle={(e) => e.stopPropagation()}
className="details-reset"
>
<summary>
<div
data-testid="sidebar-rest-subcategory"
className={cx('pl-4 pr-5 py-2 no-underline')}
>
{childTitle}
</div>
</summary>
<div className="pb-0">
{miniTocItems.length > 0 && (
<ActionList
{...{ as: 'ul' }}
items={miniTocItems.map((item) => {
return renderRestAnchorLink(item)
})}
></ActionList>
)}
</div>
</details>
</li>
)
} else {
// We're not on the current page so don't have any minitoc
// data so just render a link to the category page.
return (
<li key={childTitle} data-testid="sidebar-article-group" className="pb-0">
<Link
href={childPage.href}
className={cx(
'd-block pl-4 pr-5 py-1 no-underline width-full',
isCurrent ? 'color-fg-accent' : 'color-fg-default'
)}
>
{childTitle}
</Link>
</li>
)
}
})
)}
</ul>
</>
}
</details>
)
}

View File

@@ -9,7 +9,7 @@ import { SidebarHomepage } from './SidebarHomepage'
export const SidebarNav = () => {
const router = useRouter()
const { error, relativePath } = useMainContext()
const { error, currentProduct } = useMainContext()
const { t } = useTranslation('header')
return (
@@ -40,7 +40,7 @@ export const SidebarNav = () => {
</Link>
</div>
<nav>
{error === '404' || relativePath === 'index.md' ? <SidebarHomepage /> : <SidebarProduct />}
{error === '404' || currentProduct === null ? <SidebarHomepage /> : <SidebarProduct />}
</nav>
</div>
)

View File

@@ -1,18 +1,19 @@
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import cx from 'classnames'
import { useState, useEffect, SyntheticEvent } from 'react'
import { ChevronDownIcon } from '@primer/octicons-react'
import { ActionList } from '@primer/react'
import { Link } from 'components/Link'
import { ProductTreeNode, useMainContext } from 'components/context/MainContext'
import { useMainContext } from 'components/context/MainContext'
import { AllProductsLink } from 'components/sidebar/AllProductsLink'
import { EventType, sendEvent } from 'components/lib/events'
import styles from './SidebarProduct.module.scss'
import { RestCollapsibleSection } from './RestCollapsibleSection'
import { ProductCollapsibleSection } from './ProductCollapsibleSection'
import { useTranslation } from 'components/hooks/useTranslation'
export const SidebarProduct = () => {
const router = useRouter()
const { currentProductTree } = useMainContext()
const { currentProduct, currentProductTree } = useMainContext()
const { t } = useTranslation(['products'])
useEffect(() => {
const activeArticle = document.querySelector('[data-is-current-page=true]')
@@ -28,13 +29,134 @@ export const SidebarProduct = () => {
return null
}
const productTitle = currentProductTree.renderedShortTitle || currentProductTree.renderedFullTitle
// remove query string and hash
const routePath = `/${router.locale}${router.asPath.split('?')[0].split('#')[0]}`
const hasExactCategory = !!currentProductTree.childPages.find(({ href }) =>
const hasExactCategory = !!currentProductTree?.childPages.find(({ href }) =>
routePath.includes(href)
)
const productTitle = currentProductTree.renderedShortTitle || currentProductTree.renderedFullTitle
const productSection = () => (
<li className="my-3" data-testid="product-sidebar-items">
<ul className="list-style-none">
{currentProductTree &&
currentProductTree.childPages.map((childPage, i) => {
const isStandaloneCategory = childPage.page.documentType === 'article'
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive =
routePath.includes(childPage.href + '/') || routePath === childPage.href
const defaultOpen = hasExactCategory ? isActive : false
return (
<li
key={childPage.href + i}
data-is-active-category={isActive}
data-is-current-page={isActive && isStandaloneCategory}
className={cx('py-1', isActive && 'color-bg-inset')}
>
{isStandaloneCategory ? (
<Link
href={childPage.href}
className="pl-4 pr-2 py-2 d-block flex-auto mr-3 color-fg-default no-underline text-bold"
>
{childTitle}
</Link>
) : (
<ProductCollapsibleSection
defaultOpen={defaultOpen}
routePath={routePath}
title={childTitle}
page={childPage}
/>
)}
</li>
)
})}
</ul>
</li>
)
const restSection = () => {
const conceptualPages = currentProductTree.childPages.filter(
(page) => page.href.includes('guides') || page.href.includes('overview')
)
const restPages = currentProductTree.childPages.filter(
(page) => !page.href.includes('guides') && !page.href.includes('overview')
)
return (
<>
<li className="my-3" data-testid="rest-sidebar-items">
<ul className="list-style-none">
{conceptualPages.map((childPage, i) => {
const isStandaloneCategory = childPage.page.documentType === 'article'
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive =
routePath.includes(childPage.href + '/') || routePath === childPage.href
const defaultOpen = hasExactCategory ? isActive : false
return (
<li
key={childPage.href + i}
data-is-active-category={isActive}
data-is-current-page={isActive && isStandaloneCategory}
className={cx('py-1', isActive && 'color-bg-inset')}
>
<ProductCollapsibleSection
defaultOpen={defaultOpen}
routePath={routePath}
title={childTitle}
page={childPage}
/>
</li>
)
})}
</ul>
</li>
<div className="my-3">
<div
role="separator"
aria-hidden="true"
data-view-component="true"
className="ActionList-sectionDivider mx-4"
></div>
<span data-testid="rest-sidebar-reference" className={cx('f6 pl-4 pb-1 color-fg-muted')}>
{t('rest.reference.api_reference')}
</span>
</div>
<li className="my-3">
<ul className="list-style-none">
{restPages.map((childPage, i) => {
const isStandaloneCategory = childPage.page.documentType === 'article'
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive =
routePath.includes(childPage.href + '/') || routePath === childPage.href
const defaultOpen = hasExactCategory ? isActive : false
return (
<li
data-testid="rest-sidebar-items"
key={childPage.href + i}
data-is-active-category={isActive}
data-is-current-page={isActive && isStandaloneCategory}
className={cx('py-1', isActive && 'color-bg-inset')}
>
<RestCollapsibleSection
defaultOpen={defaultOpen}
routePath={routePath}
title={childTitle}
page={childPage}
isStandaloneCategory={isStandaloneCategory}
/>
</li>
)
})}
</ul>
</li>
</>
)
}
return (
<ul data-testid="sidebar" className={styles.container}>
<AllProductsLink />
@@ -49,160 +171,9 @@ export const SidebarProduct = () => {
{productTitle}
</Link>
</li>
<li className="my-3">
<ul className="list-style-none">
{currentProductTree.childPages.map((childPage, i) => {
const isStandaloneCategory = childPage.page.documentType === 'article'
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive =
routePath.includes(childPage.href + '/') || routePath === childPage.href
const defaultOpen = hasExactCategory ? isActive : false
return (
<li
key={childPage.href + i}
data-is-active-category={isActive}
data-is-current-page={isActive && isStandaloneCategory}
className={cx('py-1', isActive && 'color-bg-inset')}
>
{isStandaloneCategory ? (
<Link
href={childPage.href}
className="pl-4 pr-2 py-2 d-block flex-auto mr-3 color-fg-default no-underline text-bold"
>
{childTitle}
</Link>
) : (
<CollapsibleSection
defaultOpen={defaultOpen}
routePath={routePath}
title={childTitle}
page={childPage}
/>
)}
</li>
)
})}
</ul>
</li>
{currentProduct && currentProduct.id === 'rest' ? restSection() : productSection()}
</>
)}
</ul>
)
}
type SectionProps = {
routePath: string
page: ProductTreeNode
title: string
defaultOpen: boolean
}
const CollapsibleSection = (props: SectionProps) => {
const { routePath, defaultOpen, title, page } = props
const [isOpen, setIsOpen] = useState(defaultOpen)
const onToggle = (e: SyntheticEvent) => {
const newIsOpen = (e.target as HTMLDetailsElement).open
setIsOpen(newIsOpen)
sendEvent({
type: EventType.navigate,
navigate_label: `details ${newIsOpen ? 'open' : 'close'}: ${title}`,
})
}
// The lowest level page link displayed in the tree
const renderTerminalPageLink = (page: ProductTreeNode) => {
const title = page.renderedShortTitle || page.renderedFullTitle
const isCurrent = routePath === page.href
return {
text: title,
renderItem: () => (
<ActionList.Item
data-testid="sidebar-article"
data-is-current-page={isCurrent}
as="li"
className={cx(
'position-relative',
styles.sidebarArticle,
isCurrent && ['text-bold', styles.sidebarArticleActive]
)}
sx={{
padding: '2px 0',
':hover': {
borderRadius: 0,
},
}}
>
<Link
href={page.href}
className={cx(
'd-block pl-6 pr-5 py-1 no-underline width-full',
isCurrent ? 'color-fg-accent' : 'color-fg-default'
)}
>
{title}
</Link>
</ActionList.Item>
),
}
}
return (
<details open={defaultOpen} onToggle={onToggle} className="details-reset">
<summary className="outline-none">
<div className="d-flex flex-justify-between">
<div className="pl-4 pr-1 py-2 f5 d-block flex-auto mr-3 color-fg-default no-underline text-bold">
{title}
</div>
<span style={{ marginTop: 7 }} className="flex-shrink-0 pr-3">
<ChevronDownIcon className={cx('opacity-60', isOpen && 'rotate-180')} />
</span>
</div>
</summary>
{
<>
{/* <!-- some pages have nested child pages (formerly known as a mapTopic) --> */}
{page.childPages[0]?.page.documentType === 'mapTopic' ? (
<ul className="list-style-none position-relative">
{page.childPages.map((childPage, i) => {
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
const isActive = routePath.includes(childPage.href)
const isCurrent = routePath === childPage.href
return (
<li key={childPage.href + i} data-is-current-page={isCurrent}>
<details
open={isActive}
onToggle={(e) => e.stopPropagation()}
className="details-reset"
>
<summary>
<div className={cx('pl-4 pr-5 py-2 no-underline')}>{childTitle}</div>
</summary>
<div data-testid="sidebar-article-group" className="pb-0">
<ActionList
{...{ as: 'ul' }}
items={childPage.childPages.map((cp) => {
return renderTerminalPageLink(cp)
})}
></ActionList>
</div>
</details>
</li>
)
})}
</ul>
) : page.childPages[0]?.page.documentType === 'article' ? (
<div data-testid="sidebar-article-group" className="pb-0">
<ActionList {...{ as: 'ul' }} items={page.childPages.map(renderTerminalPageLink)} />
</div>
) : null}
</>
}
</details>
)
}

View File

@@ -12,7 +12,8 @@
[class~="code-extra"] {
margin-top: 1.5rem;
pre {
pre,
div {
margin-top: 0 !important;
border-top-left-radius: 0 !important;
border-top-right-radius: 0 !important;

View File

@@ -336,7 +336,11 @@ Just add a hyphen on either the left, right, or both sides to indicate that ther
## Links and image paths
Local links must start with a product ID (like `/actions` or `/admin`), and image paths must start with `/assets`. The links to Markdown pages undergo some transformations on the server side to match the current page's language and version. The handling for these transformations lives in [`lib/render-content/plugins/rewrite-local-links`](lib/render-content/plugins/rewrite-local-links.js).
Links to docs in the `docs-internal` repository must start with a product ID (like `/actions` or `/admin`) and contain the entire filepath, but not the file extension. For example, `/actions/creating-actions/about-custom-actions`.
Image paths must start with `/assets` and contain the entire filepath including the file extension. For example, `/assets/images/help/settings/settings-account-delete.png`.
The links to Markdown pages undergo some transformations on the server side to match the current page's language and version. The handling for these transformations lives in [`lib/render-content/plugins/rewrite-local-links`](lib/render-content/plugins/rewrite-local-links.js).
For example, if you include the following link in a content file:
@@ -364,6 +368,12 @@ Sometimes you want to link to a Dotcom-only article in Enterprise content and yo
Sometimes the canonical home of content moves outside the docs site. None of the links included in [`lib/redirects/external-sites.json`](/lib/redirects/external-sites.json) get rewritten. See [`contributing/redirects.md`](/contributing/redirects.md) for more info about this type of redirect.
### Legacy filepaths and redirects for links
Our docs contain links that use legacy filepaths such as `/article/article-name` or `/github/article-name`. Our docs also contain links that refer to articles by past names. Both of these link types function properly because of redirects, but they are bugs.
When you add a link to an article, use the current filepath and article name.
### Index pages
Index pages are the Table of Contents files for the docs site. Every product, category, and map topic subdirectory has an `index.md` that serves as the landing page. Each `index.md` must contain a `children` frontmatter property with a list of relative links to the child pages of the product, category, or map topic.

View File

@@ -16,7 +16,7 @@ topics:
shortTitle: Organization's profile
---
You can optionally choose to add a description, location, website, and email address for your organization, and pin important repositories.{% ifversion fpt or ghec or ghes > 3.3 or ghae-issue-4749 %} You can customize your organization's profile by adding a README.md file. For more information, see "[Customizing your organization's profile](/organizations/collaborating-with-groups-in-organizations/customizing-your-organizations-profile)."{% endif %}
You can optionally choose to add a description, location, website, and email address for your organization, and pin important repositories.{% ifversion fpt or ghec or ghes > 3.3 or ghae-issue-4749 %} You can customize your organization's public profile by adding a README.md file. For more information, see "[Customizing your organization's profile](/organizations/collaborating-with-groups-in-organizations/customizing-your-organizations-profile)."{% endif %}
{% ifversion fpt %}
Organizations that use {% data variables.product.prodname_ghe_cloud %} can confirm their organization's identity and display a "Verified" badge on their organization's profile page by verifying the organization's domains with {% data variables.product.product_name %}. For more information, see "[Verifying or approving a domain for your organization](/organizations/managing-organization-settings/verifying-or-approving-a-domain-for-your-organization)" in the {% data variables.product.prodname_ghe_cloud %} documenatation.

View File

@@ -17,5 +17,6 @@ children:
- /personalizing-your-profile
- /managing-your-profile-readme
- /pinning-items-to-your-profile
- /setting-your-profile-to-private
---

View File

@@ -151,7 +151,7 @@ You can disable some of the badges for {% data variables.product.prodname_dotcom
{% data reusables.user-settings.access_settings %}
2. Under "Profile settings", deselect the badge you want you disable.
![Checkbox to no longer display a badge on your profile](/assets/images/help/profile/profile-badge-settings.png)
3. Click **Update preferences**.
{% data reusables.user-settings.update-preferences %}
{% endif %}

View File

@@ -0,0 +1,62 @@
---
title: Setting your profile to private
intro: A private profile displays only limited information, and hides some activity.
versions:
fpt: '*'
topics:
- Profiles
shortTitle: Set profile to private
---
## About private profiles
{% note %}
**Note:** Private profiles are currently in beta and are subject to change.
{% endnote %}
To hide parts of your profile page, you can make your profile private. This also hides your activity in various social features on {% data variables.product.prodname_dotcom_the_website %}. A private profile hides information from all users, and there is currently no option to allow specified users to see your activity.
After making your profile private, you can still view all your information when you visit your own profile.
Private profiles cannot receive sponsorships under [{% data variables.product.prodname_sponsors %}](/sponsors/getting-started-with-github-sponsors/about-github-sponsors). To be eligible for {% data variables.product.prodname_sponsors %}, your profile cannot be private.
## Differences between private and public profiles
When your profile is private, the following content is hidden from your profile page:
- Achievements and highlights.
- Activity overview and activity feed.
- Contribution graph.
- Follower and following counts.
- Follow and Sponsor buttons.
- Organization memberships.
- Stars, projects, packages, and sponsoring tabs.
{% note %}
**Note**: When your profile is private, some optional fields are still publicly visible, such as the README, biography, and profile photo.
{% endnote %}
## Changes to reporting on your activities
By making your profile private, you will not remove or hide past activity; this setting only applies to your activity while the private setting is enabled.
When your profile is private, your {% data variables.product.prodname_dotcom_the_website %} activity will not appear in the following locations:
- Activity feeds for other users.
- Discussions leaderboards.
- The [Trending](https://github.com/trending) page.
{% note %}
**Note**: Your activity on public repositories will still be publicly visible to anyone viewing those repositories, and some activity data may still be available through the {% data variables.product.prodname_dotcom %} API.
{% endnote %}
## Changing your profile's privacy settings
{% data reusables.user-settings.access_settings %}
1. Under "Contributions & Activity", select the checkbox next to **Make profile private and hide activity**.
{% data reusables.user-settings.update-preferences %}

View File

@@ -65,7 +65,7 @@ jobs:
java-version: '11'
distribution: 'adopt'
- name: Build with Maven
run: mvn --batch-mode --update-snapshots verify
run: mvn --batch-mode --update-snapshots package
```
This workflow performs the following steps:

View File

@@ -82,7 +82,7 @@ Before you begin, you'll create a repository on {% ifversion ghae %}{% data vari
- run: echo Hello ${{ inputs.who-to-greet }}.
shell: bash
- id: random-number-generator
run: echo "::set-output name=random-id::$(echo $RANDOM)"
run: echo "::set-output name=random-number::$(echo $RANDOM)"
shell: bash
- run: echo "${{ github.action_path }}" >> $GITHUB_PATH
shell: bash

View File

@@ -28,6 +28,14 @@ You can add self-hosted runners at various levels in the management hierarchy:
{% data reusables.actions.self-hosted-runner-architecture %} {% data reusables.actions.runner-app-open-source %} When a new version is released, the runner application automatically updates itself when a job is assigned to the runner, or within a week of release if the runner hasn't been assigned any jobs.
{% ifversion ghes %}
{% note %}
**Note:** {% data reusables.actions.upgrade-runners-before-upgrade-ghes %}
{% endnote %}
{% endif %}
{% data reusables.actions.self-hosted-runner-auto-removal %}
For more information about installing and using self-hosted runners, see "[Adding self-hosted runners](/github/automating-your-workflow-with-github-actions/adding-self-hosted-runners)" and "[Using self-hosted runners in a workflow](/github/automating-your-workflow-with-github-actions/using-self-hosted-runners-in-a-workflow)."
@@ -45,7 +53,7 @@ For more information about installing and using self-hosted runners, see "[Addin
- Use free minutes on your {% data variables.product.prodname_dotcom %} plan, with per-minute rates applied after surpassing the free minutes.
**Self-hosted runners:**{% endif %}
- Receive automatic updates for the self-hosted runner application only{% ifversion fpt or ghec or ghes > 3.2 %}, though you may disable automatic updates of the runner. For more information about controlling runner software updates on self-hosted runners, see "[Autoscaling with self-hosted runners](/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#controlling-runner-software-updates-on-self-hosted-runners)."{% else %}.{% endif %} You are responsible for updating the operating system and all other software.
- Receive automatic updates for the self-hosted runner application only{% ifversion fpt or ghec or ghes > 3.4 or ghae-issue-6143 %}, though you may disable automatic updates of the runner. For more information about controlling runner software updates on self-hosted runners, see "[Autoscaling with self-hosted runners](/actions/hosting-your-own-runners/autoscaling-with-self-hosted-runners#controlling-runner-software-updates-on-self-hosted-runners)."{% else %}.{% endif %} You are responsible for updating the operating system and all other software.
- Can use cloud services or local machines that you already pay for.
- Are customizable to your hardware, operating system, software, and security requirements.
- Don't need to have a clean instance for every job execution.

View File

@@ -54,6 +54,8 @@ The {% data variables.product.prodname_actions %} service will then automaticall
{% endnote %}
{% ifversion fpt or ghec or ghes > 3.4 or ghae-issue-6143 %}
## Controlling runner software updates on self-hosted runners
By default, self-hosted runners will automatically perform a software update whenever a new version of the runner software is available. If you use ephemeral runners in containers then this can lead to repeated software updates when a new runner version is released. Turning off automatic updates allows you to update the runner version on the container image directly on your own schedule.
@@ -76,6 +78,8 @@ For instructions on how to install the latest runner version, see the installati
{% endnote %}
{% endif %}
## Using webhooks for autoscaling
You can create your own autoscaling environment by using payloads received from the [`workflow_job`](/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job) webhook. This webhook is available at the repository, organization, and enterprise levels, and the payload for this event contains an `action` key that corresponds to the stages of a workflow job's life-cycle; for example when jobs are `queued`, `in_progress`, and `completed`. You must then create your own scaling automation in response to these webhook payloads.

View File

@@ -258,3 +258,11 @@ User=runner-user
```
{% endlinux %}
{% ifversion ghes %}
## Resolving runners that are offline after an upgrade of {% data variables.product.product_location %}
{% data reusables.actions.upgrade-runners-before-upgrade-ghes %}
If your runners are offline for this reason, manually update the runners. For more information, see the installation instructions for [the latest release](https://github.com/actions/runner/releases/latest) in the actions/runner repository.
{% endif %}

View File

@@ -57,6 +57,8 @@ In order to use property dereference syntax, the property name must:
- start with `a-Z` or `_`.
- be followed by `a-Z` `0-9` `-` or `_`.
If you attempt to dereference a non-existent property, it will evaluate to an empty string.
### Determining when to use contexts
{% data reusables.actions.using-context-or-environment-variables %}

View File

@@ -50,9 +50,7 @@ You can configure a {% data variables.product.prodname_actions %} _workflow_ to
### Workflows
A workflow is a configurable automated process that will run one or more jobs. Workflows are defined by a YAML file checked in to your repository and will run when triggered by an event in your repository, or they can be triggered manually, or at a defined schedule.
You can have multiple workflows in a repository, each of which can perform a different set of steps. For example, you can have one workflow to build and test pull requests, another workflow to deploy your application every time a release is created, and still another workflow that adds a label every time someone opens a new issue.
{% data reusables.actions.about-workflows-long %}
{% ifversion fpt or ghes > 3.3 or ghae-issue-4757 or ghec %}You can reference a workflow within another workflow, see "[Reusing workflows](/actions/learn-github-actions/reusing-workflows)."{% endif %}
@@ -86,173 +84,7 @@ For more information, see "[Creating actions](/actions/creating-actions)."
{% data reusables.actions.about-runners %} Each runner can run a single job at a time. {% ifversion ghes or ghae %} You must host your own runners for {% data variables.product.product_name %}. {% elsif fpt or ghec %}{% data variables.product.company_short %} provides Ubuntu Linux, Microsoft Windows, and macOS runners to run your workflows; each workflow run executes in a fresh, newly-provisioned virtual machine. If you need a different operating system or require a specific hardware configuration, you can host your own runners.{% endif %} For more information{% ifversion fpt or ghec %} about self-hosted runners{% endif %}, see "[Hosting your own runners](/actions/hosting-your-own-runners)."
## Create an example workflow
{% data variables.product.prodname_actions %} uses YAML syntax to define the workflow. Each workflow is stored as a separate YAML file in your code repository, in a directory called `.github/workflows`.
You can create an example workflow in your repository that automatically triggers a series of commands whenever code is pushed. In this workflow, {% data variables.product.prodname_actions %} checks out the pushed code, installs the software dependencies, and runs `bats -v`.
1. In your repository, create the `.github/workflows/` directory to store your workflow files.
1. In the `.github/workflows/` directory, create a new file called `learn-github-actions.yml` and add the following code.
```yaml
name: learn-github-actions
on: [push]
jobs:
check-bats-version:
runs-on: ubuntu-latest
steps:
- uses: {% data reusables.actions.action-checkout %}
- uses: {% data reusables.actions.action-setup-node %}
with:
node-version: '14'
- run: npm install -g bats
- run: bats -v
```
1. Commit these changes and push them to your {% data variables.product.prodname_dotcom %} repository.
Your new {% data variables.product.prodname_actions %} workflow file is now installed in your repository and will run automatically each time someone pushes a change to the repository. For details about a workflow's execution history, see "[Viewing the workflow's activity](/actions/learn-github-actions/introduction-to-github-actions#viewing-the-workflows-activity)."
## Understanding the workflow file
To help you understand how YAML syntax is used to create a workflow file, this section explains each line of the introduction's example:
<table>
<tr>
<td>
```yaml
name: learn-github-actions
```
</td>
<td>
<em>Optional</em> - The name of the workflow as it will appear in the Actions tab of the {% data variables.product.prodname_dotcom %} repository.
</td>
</tr>
<tr>
<td>
```yaml
on: [push]
```
</td>
<td>
Specifies the trigger for this workflow. This example uses the <code>push</code> event, so a workflow run is triggered every time someone pushes a change to the repository or merges a pull request. This is triggered by a push to every branch; for examples of syntax that runs only on pushes to specific branches, paths, or tags, see <a href="https://docs.github.com/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore">"Workflow syntax for {% data variables.product.prodname_actions %}."</a>
</td>
</tr>
<tr>
<td>
```yaml
jobs:
```
</td>
<td>
Groups together all the jobs that run in the <code>learn-github-actions</code> workflow.
</td>
</tr>
<tr>
<td>
```yaml
check-bats-version:
```
</td>
<td>
Defines a job named <code>check-bats-version</code>. The child keys will define properties of the job.
</td>
</tr>
<tr>
<td>
```yaml
runs-on: ubuntu-latest
```
</td>
<td>
Configures the job to run on the latest version of an Ubuntu Linux runner. This means that the job will execute on a fresh virtual machine hosted by GitHub. For syntax examples using other runners, see <a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on">"Workflow syntax for {% data variables.product.prodname_actions %}."</a>
</td>
</tr>
<tr>
<td>
```yaml
steps:
```
</td>
<td>
Groups together all the steps that run in the <code>check-bats-version</code> job. Each item nested under this section is a separate action or shell script.
</td>
</tr>
<tr>
<td>
```yaml
- uses: {% data reusables.actions.action-checkout %}
```
</td>
<td>
The <code>uses</code> keyword specifies that this step will run <code>v3</code> of the <code>actions/checkout</code> action. This is an action that checks out your repository onto the runner, allowing you to run scripts or other actions against your code (such as build and test tools). You should use the checkout action any time your workflow will run against the repository's code.
</td>
</tr>
<tr>
<td>
```yaml
- uses: {% data reusables.actions.action-setup-node %}
with:
node-version: '14'
```
</td>
<td>
This step uses the <code>{% data reusables.actions.action-setup-node %}</code> action to install the specified version of the Node.js (this example uses v14). This puts both the <code>node</code> and <code>npm</code> commands in your <code>PATH</code>.
</td>
</tr>
<tr>
<td>
```yaml
- run: npm install -g bats
```
</td>
<td>
The <code>run</code> keyword tells the job to execute a command on the runner. In this case, you are using <code>npm</code> to install the <code>bats</code> software testing package.
</td>
</tr>
<tr>
<td>
```yaml
- run: bats -v
```
</td>
<td>
Finally, you'll run the <code>bats</code> command with a parameter that outputs the software version.
</td>
</tr>
</table>
### Visualizing the workflow file
In this diagram, you can see the workflow file you just created and how the {% data variables.product.prodname_actions %} components are organized in a hierarchy. Each step executes a single action or shell script. Steps 1 and 2 run actions, while steps 3 and 4 run shell scripts. To find more prebuilt actions for your workflows, see "[Finding and customizing actions](/actions/learn-github-actions/finding-and-customizing-actions)."
![Workflow overview](/assets/images/help/images/overview-actions-event.png)
## Viewing the workflow's activity
Once your workflow has started running, you can see a visualization graph of the run's progress and view each step's activity on {% data variables.product.prodname_dotcom %}.
{% data reusables.repositories.navigate-to-repo %}
1. Under your repository name, click **Actions**.
![Navigate to repository](/assets/images/help/images/learn-github-actions-repository.png)
1. In the left sidebar, click the workflow you want to see.
![Screenshot of workflow results](/assets/images/help/images/learn-github-actions-workflow.png)
1. Under "Workflow runs", click the name of the run you want to see.
![Screenshot of workflow runs](/assets/images/help/images/learn-github-actions-run.png)
1. Under **Jobs** or in the visualization graph, click the job you want to see.
![Select job](/assets/images/help/images/overview-actions-result-navigate.png)
1. View the results of each step.
![Screenshot of workflow run details](/assets/images/help/images/overview-actions-result-updated-2.png)
{% data reusables.actions.workflow-basic-example-and-explanation %}
## Next steps
@@ -268,7 +100,8 @@ To understand how billing works for {% data variables.product.prodname_actions %
{% data reusables.actions.contacting-support %}
{% ifversion ghec or ghes or ghae %}
## Further reading
{% ifversion ghec or ghes or ghae %}
- "[About {% data variables.product.prodname_actions %} for enterprises](/admin/github-actions/getting-started-with-github-actions-for-your-enterprise/about-github-actions-for-enterprises)"{% endif %}
- "[About {% data variables.product.prodname_actions %} for enterprises](/admin/github-actions/getting-started-with-github-actions-for-your-enterprise/about-github-actions-for-enterprises)"
{% endif %}

View File

@@ -0,0 +1,205 @@
---
title: About workflows
shortTitle: About workflows
intro: 'Get a high level overview {% data variables.product.prodname_actions %} workflows, including triggers, syntax, and advanced features.'
versions:
fpt: '*'
ghes: '*'
ghae: '*'
ghec: '*'
type: overview
redirect_from:
- /actions/learn-github-actions/managing-complex-workflows
- /actions/using-workflows/advanced-workflow-features
topics:
- Workflows
miniTocMaxHeadingLevel: 3
---
## About workflows
{% data reusables.actions.about-workflows-long %}
## Workflow basics
A workflow must contain the following basic components:
1. One or more _events_ that will trigger the workflow.
1. One or more _jobs_, each of which will execute on a _runner_ machine and run a series of one or more _steps_.
1. Each step can either run a script that you define or run an action, which is a reusable extension that can simplify your workflow.
For more information these basic components, see "[Understanding GitHub Actions](/actions/learn-github-actions/understanding-github-actions#the-components-of-github-actions)."
![Workflow overview](/assets/images/help/images/overview-actions-simple.png)
## Triggering a workflow
{% data reusables.actions.about-triggers %}
For more information, see "[Triggering a workflow](/actions/using-workflows/triggering-a-workflow)", and for a full list of events, see "[Events that trigger workflows](/actions/using-workflows/events-that-trigger-workflows)."
## Workflow syntax
Workflow are defined using YAML. For the full reference of the YAML syntax for authoring workflows, see "[Workflow syntax for GitHub Actions](/actions/using-workflows/workflow-syntax-for-github-actions#about-yaml-syntax-for-workflows)."
{% data reusables.actions.workflow-basic-example-and-explanation %}
For more on managing workflow runs, such as re-running, cancelling, or deleting a workflow run, see "[Managing workflow runs](/actions/managing-workflow-runs)."
## Using starter workflows
{% data reusables.actions.workflow-template-overview %}
For more information on using and creating starter workflows, see "[Using starter workflows](/actions/using-workflows/using-starter-workflows)" and "[Creating starter workflows for your organization](/actions/using-workflows/creating-starter-workflows-for-your-organization)."
## Advanced workflow features
This section briefly describes some of the advanced features of {% data variables.product.prodname_actions %} that help you create more complex workflows.
### Storing secrets
If your workflows use sensitive data, such as passwords or certificates, you can save these in {% data variables.product.prodname_dotcom %} as _secrets_ and then use them in your workflows as environment variables. This means that you will be able to create and share workflows without having to embed sensitive values directly in the workflow's YAML source.
This example job demonstrates how to reference an existing secret as an environment variable, and send it as a parameter to an example command.
{% raw %}
```yaml
jobs:
example-job:
runs-on: ubuntu-latest
steps:
- name: Retrieve secret
env:
super_secret: ${{ secrets.SUPERSECRET }}
run: |
example-command "$super_secret"
```
{% endraw %}
For more information, see "[Encrypted secrets](/actions/security-guides/encrypted-secrets)."
### Creating dependent jobs
By default, the jobs in your workflow all run in parallel at the same time. If you have a job that must only run after another job has completed, you can use the `needs` keyword to create this dependency. If one of the jobs fails, all dependent jobs are skipped; however, if you need the jobs to continue, you can define this using the `if` conditional statement.
In this example, the `setup`, `build`, and `test` jobs run in series, with `build` and `test` being dependent on the successful completion of the job that precedes them:
```yaml
jobs:
setup:
runs-on: ubuntu-latest
steps:
- run: ./setup_server.sh
build:
needs: setup
runs-on: ubuntu-latest
steps:
- run: ./build_server.sh
test:
needs: build
runs-on: ubuntu-latest
steps:
- run: ./test_server.sh
```
For more information, see "[Defining prerequisite jobs](/actions/using-jobs/using-jobs-in-a-workflow#defining-prerequisite-jobs)."
### Using a build matrix
You can use a build matrix if you want your workflow to run tests across multiple combinations of parameters, such as operating systems, platforms, and languages. The build matrix is created using the `strategy` keyword, which receives the build options as an array. For example, this build matrix will run the job multiple times, using different versions of Node.js:
```yaml
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node: [6, 8, 10]
steps:
- uses: {% data reusables.actions.action-setup-node %}
with:
node-version: {% raw %}${{ matrix.node }}{% endraw %}
```
For more information, see "[Using a build matrix for your jobs](/actions/using-jobs/using-a-build-matrix-for-your-jobs)."
{% ifversion fpt or ghec %}
### Caching dependencies
{% data variables.product.prodname_dotcom %}-hosted runners are started as fresh environments for each job, so if your jobs regularly reuse dependencies, you can consider caching these files to help improve performance. Once the cache is created, it is available to all workflows in the same repository.
This example demonstrates how to cache the ` ~/.npm` directory:
```yaml
jobs:
example-job:
steps:
- name: Cache node modules
uses: {% data reusables.actions.action-cache %}
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: {% raw %}${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}{% endraw %}
restore-keys: |
{% raw %}${{ runner.os }}-build-${{ env.cache-name }}-{% endraw %}
```
For more information, see "[Caching dependencies to speed up workflows](/actions/using-workflows/caching-dependencies-to-speed-up-workflows)."
{% endif %}
### Using databases and service containers
If your job requires a database or cache service, you can use the [`services`](/actions/using-jobs/running-jobs-in-a-container) keyword to create an ephemeral container to host the service; the resulting container is then available to all steps in that job and is removed when the job has completed. This example demonstrates how a job can use `services` to create a `postgres` container, and then use `node` to connect to the service.
```yaml
jobs:
container-job:
runs-on: ubuntu-latest
container: node:10.18-jessie
services:
postgres:
image: postgres
steps:
- name: Check out repository code
uses: {% data reusables.actions.action-checkout %}
- name: Install dependencies
run: npm ci
- name: Connect to PostgreSQL
run: node client.js
env:
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
```
For more information, see "[Using containerized services](/actions/using-containerized-services)."
### Using labels to route workflows
If you want to be sure that a particular type of runner will process your job, you can use labels to control where jobs are executed. You can assign labels to a self-hosted runner in addition to their default label of `self-hosted`. Then, you can refer to these labels in your YAML workflow, ensuring that the job is routed in a predictable way.{% ifversion not ghae %} {% data variables.product.prodname_dotcom %}-hosted runners have predefined labels assigned.{% endif %}
This example shows how a workflow can use labels to specify the required runner:
```yaml
jobs:
example-job:
runs-on: [self-hosted, linux, x64, gpu]
```
A workflow will only run on a runner that has all the labels in the `runs-on` array. The job will preferentially go to an idle self-hosted runner with the specified labels. {% ifversion fpt or ghec %}If none are available and a {% data variables.product.prodname_dotcom %}-hosted runner with the specified labels exists, the job will go to a {% data variables.product.prodname_dotcom %}-hosted runner.{% endif %}
To learn more about self-hosted runner labels, see "[Using labels with self-hosted runners](/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners)."
{% ifversion fpt or ghec %}
To learn more about {% data variables.product.prodname_dotcom %}-hosted runner labels, see "[Supported runners and hardware resources](/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources)."
{% endif %}
{% ifversion fpt or ghes > 3.3 or ghae-issue-4757 or ghec %}
### Reusing workflows
{% data reusables.actions.reusable-workflows %}
{% endif %}
### Using environments
You can configure environments with protection rules and secrets to control the execution of jobs in a workflow. Each job in a workflow can reference a single environment. Any protection rules configured for the environment must pass before a job referencing the environment is sent to a runner. For more information, see "[Using environments for deployment](/actions/deployment/using-environments-for-deployment)."

View File

@@ -1,185 +0,0 @@
---
title: Advanced workflow features
shortTitle: Advanced workflow features
intro: 'This guide shows you how to use the advanced features of {% data variables.product.prodname_actions %}, with secret management, dependent jobs, caching, build matrices, environments, and labels.'
redirect_from:
- /actions/learn-github-actions/managing-complex-workflows
versions:
fpt: '*'
ghes: '*'
ghae: '*'
ghec: '*'
type: how_to
topics:
- Workflows
miniTocMaxHeadingLevel: 4
---
{% data reusables.actions.enterprise-beta %}
{% data reusables.actions.enterprise-github-hosted-runners %}
## Overview
This article describes some of the advanced features of {% data variables.product.prodname_actions %} that help you create more complex workflows.
## Storing secrets
If your workflows use sensitive data, such as passwords or certificates, you can save these in {% data variables.product.prodname_dotcom %} as _secrets_ and then use them in your workflows as environment variables. This means that you will be able to create and share workflows without having to embed sensitive values directly in the YAML workflow.
This example action demonstrates how to reference an existing secret as an environment variable, and send it as a parameter to an example command.
{% raw %}
```yaml
jobs:
example-job:
runs-on: ubuntu-latest
steps:
- name: Retrieve secret
env:
super_secret: ${{ secrets.SUPERSECRET }}
run: |
example-command "$super_secret"
```
{% endraw %}
For more information, see "[Creating and storing encrypted secrets](/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets)."
## Creating dependent jobs
By default, the jobs in your workflow all run in parallel at the same time. So if you have a job that must only run after another job has completed, you can use the `needs` keyword to create this dependency. If one of the jobs fails, all dependent jobs are skipped; however, if you need the jobs to continue, you can define this using the [`if`](/actions/using-jobs/using-conditions-to-control-job-execution) conditional statement.
In this example, the `setup`, `build`, and `test` jobs run in series, with `build` and `test` being dependent on the successful completion of the job that precedes them:
```yaml
jobs:
setup:
runs-on: ubuntu-latest
steps:
- run: ./setup_server.sh
build:
needs: setup
runs-on: ubuntu-latest
steps:
- run: ./build_server.sh
test:
needs: build
runs-on: ubuntu-latest
steps:
- run: ./test_server.sh
```
For more information, see "[Defining prerequisite jobs](/actions/using-jobs/using-jobs-in-a-workflow#defining-prerequisite-jobs)."
## Using a build matrix
You can use a build matrix if you want your workflow to run tests across multiple combinations of operating systems, platforms, and languages. The build matrix is created using the `strategy` keyword, which receives the build options as an array. For example, this build matrix will run the job multiple times, using different versions of Node.js:
```yaml
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node: [6, 8, 10]
steps:
- uses: {% data reusables.actions.action-setup-node %}
with:
node-version: {% raw %}${{ matrix.node }}{% endraw %}
```
For more information, see "[Using a build matrix for your jobs](/actions/using-jobs/using-a-build-matrix-for-your-jobs)."
{% ifversion fpt or ghec %}
## Caching dependencies
{% data variables.product.prodname_dotcom %}-hosted runners are started as fresh environments for each job, so if your jobs regularly reuse dependencies, you can consider caching these files to help improve performance. Once the cache is created, it is available to all workflows in the same repository.
This example demonstrates how to cache the ` ~/.npm` directory:
```yaml
jobs:
example-job:
steps:
- name: Cache node modules
uses: {% data reusables.actions.action-cache %}
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: {% raw %}${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}{% endraw %}
restore-keys: |
{% raw %}${{ runner.os }}-build-${{ env.cache-name }}-{% endraw %}
```
For more information, see "<a href="/actions/guides/caching-dependencies-to-speed-up-workflows" class="dotcom-only">Caching dependencies to speed up workflows</a>."
{% endif %}
## Using databases and service containers
If your job requires a database or cache service, you can use the [`services`](/actions/using-jobs/running-jobs-in-a-container) keyword to create an ephemeral container to host the service; the resulting container is then available to all steps in that job and is removed when the job has completed. This example demonstrates how a job can use `services` to create a `postgres` container, and then use `node` to connect to the service.
```yaml
jobs:
container-job:
runs-on: ubuntu-latest
container: node:10.18-jessie
services:
postgres:
image: postgres
steps:
- name: Check out repository code
uses: {% data reusables.actions.action-checkout %}
- name: Install dependencies
run: npm ci
- name: Connect to PostgreSQL
run: node client.js
env:
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
```
For more information, see "[Using databases and service containers](/actions/configuring-and-managing-workflows/using-databases-and-service-containers)."
## Using labels to route workflows
This feature helps you assign jobs to a specific hosted runner. If you want to be sure that a particular type of runner will process your job, you can use labels to control where jobs are executed. You can assign labels to a self-hosted runner in addition to their default label of `self-hosted`. Then, you can refer to these labels in your YAML workflow, ensuring that the job is routed in a predictable way.{% ifversion not ghae %} {% data variables.product.prodname_dotcom %}-hosted runners have predefined labels assigned.{% endif %}
This example shows how a workflow can use labels to specify the required runner:
```yaml
jobs:
example-job:
runs-on: [self-hosted, linux, x64, gpu]
```
A workflow will only run on a runner that has all the labels in the `runs-on` array. The job will preferentially go to an idle self-hosted runner with the specified labels. If none are available and a {% data variables.product.prodname_dotcom %}-hosted runner with the specified labels exists, the job will go to a {% data variables.product.prodname_dotcom %}-hosted runner.
To learn more about self-hosted runner labels, see ["Using labels with self-hosted runners](/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners)."
{% ifversion fpt or ghes %}
To learn more about {% data variables.product.prodname_dotcom %}-hosted runner labels, see ["Supported runners and hardware resources"](/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources).
{% endif %}
{% ifversion fpt or ghes > 3.3 or ghae-issue-4757 or ghec %}
## Reusing workflows
{% data reusables.actions.reusable-workflows %}
{% endif %}
## Using environments
You can configure environments with protection rules and secrets. Each job in a workflow can reference a single environment. Any protection rules configured for the environment must pass before a job referencing the environment is sent to a runner. For more information, see "[Using environments for deployment](/actions/deployment/using-environments-for-deployment)."
## Using starter workflows
{% data reusables.actions.workflow-template-overview %}
{% data reusables.repositories.navigate-to-repo %}
{% data reusables.repositories.actions-tab %}
1. If your repository already has existing workflows: In the upper-left corner, click **New workflow**.
![Create a new workflow](/assets/images/help/repository/actions-new-workflow.png)
1. Under the name of the starter workflow you'd like to use, click **Set up this workflow**.
![Set up this workflow](/assets/images/help/settings/actions-create-starter-workflow.png)
## Next steps
To continue learning about {% data variables.product.prodname_actions %}, see "[Sharing workflows, secrets, and runners with your organization](/actions/learn-github-actions/sharing-workflows-secrets-and-runners-with-your-organization)."

View File

@@ -1157,7 +1157,7 @@ You can use these operators in any of the five fields:
You can use [crontab guru](https://crontab.guru/) to help generate your cron syntax and confirm what time it will run. To help you get started, there is also a list of [crontab guru examples](https://crontab.guru/examples.html).
Notifications for scheduled workflows are sent to the user who last modified the cron syntax in the workflow file. For more information, see "[Notifications for workflow runs](/actions/guides/about-continuous-integration#notifications-for-workflow-runs)."
Notifications for scheduled workflows are sent to the user who last modified the cron syntax in the workflow file. For more information, see "[Notifications for workflow runs](/actions/monitoring-and-troubleshooting-workflows/notifications-for-workflow-runs)."
### `status`

View File

@@ -21,12 +21,12 @@ versions:
ghae: '*'
ghec: '*'
children:
- /about-workflows
- /triggering-a-workflow
- /events-that-trigger-workflows
- /workflow-syntax-for-github-actions
- /workflow-commands-for-github-actions
- /reusing-workflows
- /advanced-workflow-features
- /creating-starter-workflows-for-your-organization
- /using-starter-workflows
- /sharing-workflows-secrets-and-runners-with-your-organization

View File

@@ -104,7 +104,7 @@ You can define inputs and secrets, which can be passed from the caller workflow
```
{% endraw %}
For details of the syntax for defining inputs and secrets, see [`on.workflow_call.inputs`](/actions/reference/workflow-syntax-for-github-actions#onworkflow_callinputs) and [`on.workflow_call.secrets`](/actions/reference/workflow-syntax-for-github-actions#onworkflow_callsecrets).
1. Reference the input or secret in the reusable workflow.
1. In the reusable workflow, reference the input or secret that you defined in the `on` key in the previous step.
{% raw %}
```yaml

View File

@@ -20,14 +20,7 @@ miniTocMaxHeadingLevel: 3
## About workflow triggers
Workflow triggers are events that cause a workflow to run. These events can be:
- Events that occur in your workflow's repository
- Events that occur outside of {% data variables.product.product_name %} and trigger a `repository_dispatch` event on {% data variables.product.product_name %}
- Scheduled times
- Manual
For example, you can configure your workflow to run when a push is made to the default branch of your repository, when a release is created, or when an issue is opened.
{% data reusables.actions.about-triggers %}
Workflow triggers are defined with the `on` key. For more information, see "[Workflow syntax for {% data variables.product.prodname_actions %}](/articles/workflow-syntax-for-github-actions#on)."

View File

@@ -39,8 +39,10 @@ Anyone with write permission to a repository can set up {% data variables.produc
{% data reusables.repositories.navigate-to-repo %}
{% data reusables.repositories.actions-tab %}
1. If you already have a workflow in your repository, click **New workflow**.
1. Find the starter workflow that you want to use, then click **Set up this workflow**.{% if actions-starter-template-ui %} To help you find the starter workflow that you want, you can search for keywords or filter by category.{% endif %}
1. If the starter workflow contains comments detailing additional setup steps, follow these steps. Many of the starter workflow have corresponding guides. For more information, see [the {% data variables.product.prodname_actions %} guides](/actions/guides)."
1. The "{% if actions-starter-template-ui %}Choose a workflow{% else %}Choose a workflow template{% endif %}" page shows a selection of recommended starter workflows. Find the starter workflow that you want to use, then click {% if actions-starter-template-ui %}**Configure**{% else %}**Set up this workflow**{% endif %}.{% if actions-starter-template-ui %} To help you find the starter workflow that you want, you can search for keywords or filter by category.{% endif %}
{% if actions-starter-template-ui %}![Configure this workflow](/assets/images/help/settings/actions-create-starter-workflow-updated-ui.png){% else %}![Set up this workflow](/assets/images/help/settings/actions-create-starter-workflow.png){% endif %}
1. If the starter workflow contains comments detailing additional setup steps, follow these steps. Many of the starter workflow have corresponding guides. For more information, see the [{% data variables.product.prodname_actions %} guides](/actions/guides).
1. Some starter workflows use secrets. For example, {% raw %}`${{ secrets.npm_token }}`{% endraw %}. If the starter workflow uses a secret, store the value described in the secret name as a secret in your repository. For more information, see "[Encrypted secrets](/actions/reference/encrypted-secrets)."
1. Optionally, make additional changes. For example, you might want to change the value of `on` to change when the workflow runs.
1. Click **Start commit**.

View File

@@ -1,38 +1,50 @@
---
title: GitHub Enterprise Server releases
intro: 'Documentation for the currently supported and previously deprecated versions of {{ site.data.variables.product.prodname_ghe_server }}.'
intro: "{% data variables.product.company_short %} releases new versions of {% data variables.product.product_name %} regularly. You can review supported versions, see deprecation dates, and browse documentation for the release you've deployed."
allowTitleToDifferFromFilename: true
versions:
ghes: '*'
topics:
- Enterprise
- Upgrades
shortTitle: Releases
---
## Currently supported
## About releases of {% data variables.product.product_name %}
See [{% data variables.product.prodname_enterprise %}](https://github.com/enterprise) for information about the latest release.
{% data reusables.enterprise.constantly-improving %} {% data variables.product.company_short %} supports the four most recent feature releases. For more information, see "[About upgrades to new releases](/admin/overview/about-upgrades-to-new-releases)."
{% for supportedRelease in enterpriseServerReleases.supported %}
- [{% data variables.product.prodname_ghe_server %} {{supportedRelease}}](/enterprise-server@{{supportedRelease}})
{% endfor %}
You can see what's new for each release in the [release notes](/admin/release-notes), and you can view administrator and user documentation for all releases here on {% data variables.product.prodname_docs %}. When you read the documentation, make sure to select the version that reflects your product. For more information, see "[About versions of {% data variables.product.prodname_docs %}](/get-started/learning-about-github/about-versions-of-github-docs)."
## Deprecated
## Currently supported releases
Documentation for deprecated versions remains available but is no longer maintained.
{% data variables.product.company_short %} supports the following releases of {% data variables.product.product_name %}. For more information about the latest release, see the [{% data variables.product.prodname_enterprise %}](https://github.com/enterprise) website.
{% for deprecatedRelease in enterpriseServerReleases.deprecatedReleasesWithNewFormat %}
- [Enterprise Server {{deprecatedRelease}}](/enterprise-server@{{deprecatedRelease}})
{% endfor %}
| Version | Release | Deprecation | Release notes | Documentation |
| :- | :- | :- | :- | :- |
{%- for version in enterpriseServerReleases.supported %}
| {{version}} | {{enterpriseServerReleases.dates[version].releaseDate}} | {{enterpriseServerReleases.dates[version].deprecationDate}} | [{{version}} release notes](/enterprise-server@{{version}}/admin/release-notes) | [{{version}} documentation](/enterprise-server@{{version}}) |
{%- endfor %}
{% for deprecatedReleaseLegacyFormat in enterpriseServerReleases.deprecatedReleasesWithLegacyFormat %}
- [Enterprise Server {{deprecatedReleaseLegacyFormat}}](/enterprise/{{deprecatedReleaseLegacyFormat}})
{% endfor %}
## Deprecated releases
## Deprecated developer documentation
{% data variables.product.company_short %} provides documentation for deprecated versions, but does not maintain or update the documentation.
Developer documentation for deprecated versions remains available but is no longer maintained.
| Version | Release | Deprecation | Release notes | Documentation |
| :- | :- | :- | :- | :- |
{%- for version in enterpriseServerReleases.deprecatedReleasesWithNewFormat %}
| {{version}} | {{enterpriseServerReleases.dates[version].releaseDate}} | {{enterpriseServerReleases.dates[version].deprecationDate}} | [{{version}} release notes](/enterprise-server@{{version}}/admin/release-notes) | [{{version}} documentation](/enterprise-server@{{version}}) |
{%- endfor %}
{%- for version in enterpriseServerReleases.deprecatedReleasesWithLegacyFormat %}
| {{version}} | {{enterpriseServerReleases.dates[version].releaseDate}} | {{enterpriseServerReleases.dates[version].deprecationDate}} | [{{version}} release notes](https://enterprise.github.com/releases/series/{{version}}) | [{{version}} documentation](/enterprise/{{version}}) |
{%- endfor %}
{% for deprecatedDevRelease in enterpriseServerReleases.deprecatedReleasesOnDeveloperSite %}
- [Enterprise Server {{deprecatedDevRelease}}](https://developer.github.com/enterprise/{{deprecatedDevRelease}})
{% endfor %}
### Deprecated developer documentation
{% data variables.product.company_short %} hosted developer documentation for {% data variables.product.product_name %} on a separate site until the 2.17 release. {% data variables.product.company_short %} continues to provide developer documentation for version 2.16 and earlier, but does not maintain or update the documentation.
| Version | Release | Deprecation | Developer documentation |
| :- | :- | :- | :- |
{%- for version in enterpriseServerReleases.deprecatedReleasesOnDeveloperSite %}
| {{version}} | {{enterpriseServerReleases.dates[version].releaseDate}} | {{enterpriseServerReleases.dates[version].deprecationDate}} | [{{version}} developer documentation](https://developer.github.com/enterprise/{{version}}) |
{%- endfor %}

View File

@@ -27,7 +27,7 @@ topics:
As an enterprise owner, you can allow end users to send anonymized contribution counts for their work from {% data variables.product.product_location %} to their {% data variables.product.prodname_dotcom_the_website %} contribution graph.
After you enable {% data variables.product.prodname_unified_contributions %}, before individual users can send contribution counts from {% data variables.product.product_location %} to {% data variables.product.prodname_dotcom_the_website %}, each user must also connect their personal account on {% data variables.product.product_name %} with a personal account on {% data variables.product.prodname_dotcom_the_website %}. For more information, see "[Sending enterprise contributions to your {% data variables.product.prodname_dotcom_the_website %} profile](/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-graphs-on-your-profile/sending-enterprise-contributions-to-your-githubcom-profile)."
After you enable {% data variables.product.prodname_unified_contributions %}, before individual users can send contribution counts from {% data variables.product.product_location %} to {% data variables.product.prodname_dotcom_the_website %}, each user must also connect their user account on {% data variables.product.product_name %} with a personal account on {% data variables.product.prodname_dotcom_the_website %}. For more information, see "[Sending enterprise contributions to your {% data variables.product.prodname_dotcom_the_website %} profile](/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-graphs-on-your-profile/sending-enterprise-contributions-to-your-githubcom-profile)."
{% data reusables.github-connect.sync-frequency %}

View File

@@ -32,7 +32,7 @@ You can choose to allow search results for public repositories on {% data variab
Users will never be able to search {% data variables.product.product_location %} from {% data variables.product.prodname_dotcom_the_website %}, even if they have access to both environments.
After you enable unified search for {% data variables.product.product_location %}, before individual users can see search results from {% data variables.product.prodname_dotcom_the_website %} on {% data variables.product.product_location %}, each user must also connect their personal account on {% data variables.product.product_name %} with a personal account on {% data variables.product.prodname_dotcom_the_website %}. For more information, see "[Enabling {% data variables.product.prodname_dotcom_the_website %} repository search in your private enterprise account](/search-github/getting-started-with-searching-on-github/enabling-githubcom-repository-search-from-your-private-enterprise-environment)."
After you enable unified search for {% data variables.product.product_location %}, before individual users can see search results from private repositories on {% data variables.product.prodname_dotcom_the_website %} in {% data variables.product.product_location %}, each user must also connect their user account on {% data variables.product.product_name %} with a user account on {% data variables.product.prodname_dotcom_the_website %}. For more information, see "[Enabling {% data variables.product.prodname_dotcom_the_website %} repository search in your private enterprise account](/search-github/getting-started-with-searching-on-github/enabling-githubcom-repository-search-from-your-private-enterprise-environment)."
Searching via the REST and GraphQL APIs does not include {% data variables.product.prodname_dotcom_the_website %} search results. Advanced search and searching for wikis in {% data variables.product.prodname_dotcom_the_website %} are not supported.

View File

@@ -50,7 +50,7 @@ Setting secondary rate limits protects the overall level of service on {% data v
3. Type limits for Total Requests, CPU Limit, and CPU Limit for Searching, or accept the pre-filled default limits.
{% data reusables.enterprise_management_console.save-settings %}
## Enabling Git rate limits
## Enabling rate limits for Git
You can apply Git rate limits per repository network or per user ID. Git rate limits are expressed in concurrent operations per minute, and are adaptive based on the current CPU load.
@@ -61,3 +61,44 @@ You can apply Git rate limits per repository network or per user ID. Git rate li
3. Type limits for each repository network or user ID.
![Fields for repository network and user ID limits](/assets/images/enterprise/management-console/example-git-rate-limits.png)
{% data reusables.enterprise_management_console.save-settings %}
{% ifversion ghes > 3.4 %}
## Configuring rate limits for {% data variables.product.prodname_actions %}
You can apply a rate limit to {% data variables.product.prodname_actions %} workflow runs. For more information about {% data variables.product.prodname_actions %}, see "[About {% data variables.product.prodname_actions %} for enterprises](/admin/github-actions/getting-started-with-github-actions-for-your-enterprise/about-github-actions-for-enterprises)."
### About rate limits for {% data variables.product.prodname_actions %}
Your {% data variables.product.product_name %} instance assigns each {% data variables.product.prodname_actions %} workflow job to a runner. If your instance cannot immediately assign a job to an available runner, the job will wait in a queue until a runner is available. If {% data variables.product.prodname_actions %} experiences sustained high load, the queue can back up, and the performance of {% data variables.product.product_location %} may degrade.
To avoid this performance degradation, you can configure a rate limit for {% data variables.product.prodname_actions %}. This rate limit is expressed in job runs per minute. {% data variables.product.product_name %} calculates and applies the rate limit for the sum total of all job runs on the instance. If runs exceed the rate limit, additional runs will fail instead of entering the queue. The following error will appear in the run's annotations.
> You've exceeded the rate limit for workflow run requests. Please wait before retrying the run.
An appropriate rate limit protects {% data variables.product.product_location %} from abnormal usage of {% data variables.product.prodname_actions %} without interfering with day-to-day operations. The exact threshold depends on your instance's available resources and overall load profile. For more information about the hardware requirements for {% data variables.product.prodname_actions %}, see "[Getting started with {% data variables.product.prodname_actions %} for {% data variables.product.product_name %}](/admin/github-actions/getting-started-with-github-actions-for-your-enterprise/getting-started-with-github-actions-for-github-enterprise-server#review-hardware-requirements)."
By default, the rate limit for {% data variables.product.prodname_actions %} is disabled. Because {% data variables.product.product_name %} can handle temporary spikes in usage without performance degradation, this rate limit is intended to protect against sustained high load. We recommend leaving the rate limit disabled unless you are experiencing performance problems. In some cases, {% data variables.contact.github_support %} may recommend that you enable a rate limit for {% data variables.product.prodname_actions %}.
### Enabling or disabling rate limits for {% data variables.product.prodname_actions %}
{% data reusables.enterprise_installation.ssh-into-instance %}
1. To enable and configure the rate limit, run the following two commands, replacing **RUNS-PER-MINUTE** with the value of your choice.
```shell
ghe-config actions-rate-limiting.enabled true
ghe-config actions-rate-limiting.queue-runs-per-minute <em>RUNS-PER-MINUTE</em>
```
1. To disable the rate limit after it's been enabled, run the following command.
```
ghe-config actions-rate-limiting.enabled false
```
1. To apply the configuration, run the following command.
```
ghe-config-apply
```
1. Wait for the configuration run to complete.
{% endif %}

View File

@@ -21,7 +21,7 @@ topics:
- Privacy
- Security
---
You must enable private mode if {% data variables.product.product_location %} is publicly accessible over the Internet. In private mode, users cannot anonymously clone repositories over `git://`. If built-in authentication is also enabled, an administrator must invite new users to create an account on the instance. For more information, see "[Using built-in authentication](/enterprise/{{ currentVersion }}/admin/guides/user-management/using-built-in-authentication)."
You must enable private mode if {% data variables.product.product_location %} is publicly accessible over the Internet. In private mode, users cannot anonymously clone repositories over `git://`. If built-in authentication is also enabled, an administrator must invite new users to create an account on the instance. For more information, see "[Configuring built-in authentication](/admin/identity-and-access-management/using-built-in-authentication/configuring-built-in-authentication)."
{% data reusables.enterprise_installation.image-urls-viewable-warning %}

View File

@@ -186,14 +186,31 @@ For example, the following words are reserved, among others:
For the full list or reserved words, navigate to "Reserved logins" in the site admin dashboard.
{% ifversion ghes or ghae %}
{% if ghas-committers-calculator %}
## {% data variables.product.prodname_advanced_security %} Committers
You can see the number of active committers that are currently using seats for {% data variables.product.prodname_GH_advanced_security %}, and you can calculate how many additional seats would be used if you enabled {% data variables.product.prodname_GH_advanced_security %} for more organizations and repositories.
Under "Current active committer count", you can see the number of active committers for repositories with {% data variables.product.prodname_GH_advanced_security %} enabled. This is the number of licensed seats that are currently being used.
Under "Maximum committers across across entire instance", you can see the number of active committers across all the repositories in your enterprise. This is the number of seats that would be used if you enabled {% data variables.product.prodname_GH_advanced_security %} for every repository in your enterprise.
Under "Calculate Additional Advanced Committers", you can calculate how many more additional seats will be used if you enable {% data variables.product.prodname_GH_advanced_security %} for specific organizations and repositories. Under "Organizations and Repositories", enter or paste a list of organizations and repositories, with one organization or repository per line.
```
example-org
octo-org/octo-repo
```
The result is the number of additional seats that would be used if you enabled {% data variables.product.prodname_GH_advanced_security %} for those organizations and repositories.
For more information about billing for {% data variables.product.prodname_advanced_security %}, see "[About billing for {% data variables.product.prodname_advanced_security %}](/billing/managing-billing-for-github-advanced-security/about-billing-for-github-advanced-security)."
{% endif %}
## Enterprise overview
Refer to this section of the site admin dashboard to manage organizations, people, policies, and settings.
{% endif %}
## Repositories
This is a list of the repositories on {% data variables.product.product_location %}. You can click on a repository name and access functions for administering the repository.

View File

@@ -1,6 +1,6 @@
---
title: Configuring GitHub Enterprise
shortTitle: Configuring GitHub Enterprise
shortTitle: Configure GitHub Enterprise
intro: You can configure your enterprise to suit your organization's needs.
redirect_from:
- /enterprise/admin/configuration

View File

@@ -28,8 +28,9 @@ shortTitle: Upgrading GHES
## Preparing to upgrade
1. Determine an upgrade strategy and choose a version to upgrade to. For more information, see "[Upgrade requirements](/enterprise/{{ currentVersion }}/admin/guides/installation/upgrade-requirements/)" and refer to the [{% data variables.enterprise.upgrade_assistant %}](https://support.github.com/enterprise/server-upgrade) to find the upgrade path from your current release version.
3. Create a fresh backup of your primary instance with the {% data variables.product.prodname_enterprise_backup_utilities %}. For more information, see the [{% data variables.product.prodname_enterprise_backup_utilities %} README.md file](https://github.com/github/backup-utils#readme).
4. If you are upgrading using an upgrade package, schedule a maintenance window for {% data variables.product.prodname_ghe_server %} end users. If you are using a hotpatch, maintenance mode is not required.
1. Create a fresh backup of your primary instance with the {% data variables.product.prodname_enterprise_backup_utilities %}. For more information, see the [{% data variables.product.prodname_enterprise_backup_utilities %} README.md file](https://github.com/github/backup-utils#readme).
1. If {% data variables.product.product_location %} uses ephemeral self-hosted runners for {% data variables.product.prodname_actions %} and you've disabled automatic updates, upgrade your runners to the version of the runner application that your upgraded instance will run.
1. If you are upgrading using an upgrade package, schedule a maintenance window for {% data variables.product.prodname_ghe_server %} end users. If you are using a hotpatch, maintenance mode is not required.
{% note %}

View File

@@ -1,6 +1,6 @@
---
title: Using a staging environment
intro: 'Learn about using {% data variables.product.prodname_actions %} with {% data variables.product.prodname_ghe_server %} staging environments.'
intro: 'Learn about using {% data variables.product.prodname_actions %} with {% data variables.product.prodname_ghe_server %} staging instances.'
versions:
ghes: '*'
type: how_to
@@ -11,17 +11,34 @@ topics:
- Upgrades
redirect_from:
- /admin/github-actions/using-a-staging-environment
shortTitle: Use a staging area
shortTitle: Use staging environment
---
It can be useful to have a staging or testing environment for {% data variables.product.product_location %}, so that you can test updates or new features before implementing them in your production environment.
A common way to create the staging environment is to use a backup of your production instance and restore it to the staging environment.
## About staging environments for {% data variables.product.product_name %}
When setting up a {% data variables.product.prodname_ghe_server %} staging environment that has {% data variables.product.prodname_actions %} enabled, you must use a different external storage configuration for {% data variables.product.prodname_actions %} storage than your production environment uses. Otherwise, your staging environment will write to the same external storage as production.
It can be useful to have a staging or testing environment for {% data variables.product.product_location %}, so that you can test updates or new features before implementing them in your production environment. For more information, see "[Setting up a staging instance](/admin/installation/setting-up-a-github-enterprise-server-instance/setting-up-a-staging-instance)."
Expect to see `404` errors in your staging environment when trying to view logs or artifacts from existing {% data variables.product.prodname_actions %} workflow runs, because that data will be missing from your staging storage location.
## Using a staging environment with {% data variables.product.prodname_actions %}
Although it is not required for {% data variables.product.prodname_actions %} to be functional in your staging environment, you can optionally copy the files from the production storage location to the staging storage location.
A common way to create the staging environment is to restore a backup of your production {% data variables.product.product_name %} instance to a new virtual machine in the staging environment. If you use a staging instance and plan to test {% data variables.product.prodname_actions %} functionality, you should review your storage configuration in the staging environment.
After you restore a {% data variables.product.prodname_ghe_server %} backup to the staging instance, if you try to view logs or artifacts from existing {% data variables.product.prodname_actions %} workflow runs on your staging instance, you will see `404` errors, because this data will be missing from your staging storage location. To work around the `404` errors, you can copy data from production to use in your staging environment.
### Configuring storage
When you set up a staging environment that includes a {% data variables.product.product_name %} instance with {% data variables.product.prodname_actions %} enabled, you must use a different external storage configuration for {% data variables.product.prodname_actions %} storage than your production environment.
{% warning %}
**Warning**: If you don't change the storage configuration, your staging instance may be able to write to the same external storage that you use for production, which could result in loss of data.
{% endwarning %}
For more information about storage configuration for {% data variables.product.prodname_actions %}, see "[Getting started with {% data variables.product.prodname_actions %} for {% data variables.product.prodname_ghe_server %}](/admin/github-actions/getting-started-with-github-actions-for-your-enterprise/getting-started-with-github-actions-for-github-enterprise-server#enabling-github-actions-with-your-storage-provider)."
### Copying files from production to staging
To more accurately mirror your production environment, you can optionally copy files from your production storage location for {% data variables.product.prodname_actions %} to the staging storage location.
* For an Azure storage account, you can use [`azcopy`](https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-blobs#copy-all-containers-directories-and-blobs-to-another-storage-account). For example:

View File

@@ -94,6 +94,12 @@ For more information about minimum hardware requirements for {% data variables.p
{% data reusables.enterprise_installation.about-adjusting-resources %}
{% ifversion ghes > 3.4 %}
Optionally, you can limit resource consumption on {% data variables.product.product_location %} by configuring a rate limit for {% data variables.product.prodname_actions %}. For more information, see "[Configuring rate limits](/admin/configuration/configuring-your-enterprise/configuring-rate-limits#configuring-rate-limits-for-github-actions)."
{% endif %}
## External storage requirements
To enable {% data variables.product.prodname_actions %} on {% data variables.product.prodname_ghe_server %}, you must have access to external blob storage.

View File

@@ -1,60 +0,0 @@
---
title: Allowing built-in authentication for users outside your identity provider
intro: 'You can configure built-in authentication to authenticate users who don''t have access to your identity provider that uses LDAP, SAML, or CAS.'
redirect_from:
- /enterprise/admin/user-management/allowing-built-in-authentication-for-users-outside-your-identity-provider
- /enterprise/admin/authentication/allowing-built-in-authentication-for-users-outside-your-identity-provider
- /admin/authentication/allowing-built-in-authentication-for-users-outside-your-identity-provider
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/allowing-built-in-authentication-for-users-outside-your-identity-provider
versions:
ghes: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
- Identity
shortTitle: Authentication outside IdP
---
## About built-in authentication for users outside your identity provider
You can use built-in authentication for outside users when you are unable to add specific accounts to your identity provider (IdP), such as accounts for contractors or machine users. You can also use built-in authentication to access a fallback account if the identity provider is unavailable.
After built-in authentication is configured and a user successfully authenticates with SAML or CAS, they will no longer have the option to authenticate with a username and password. If a user successfully authenticates with LDAP, the credentials are no longer considered internal.
Built-in authentication for a specific IdP is disabled by default.
{% warning %}
**Warning:** If you disable built-in authentication, you must individually suspend any users that should no longer have access to the instance. For more information, see "[Suspending and unsuspending users](/enterprise/{{ currentVersion }}/admin/guides/user-management/suspending-and-unsuspending-users)."
{% endwarning %}
## Configuring built-in authentication for users outside your identity provider
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.authentication %}
4. Select your identity provider.
![Select identity provider option](/assets/images/enterprise/management-console/identity-provider-select.gif)
5. Select **Allow creation of accounts with built-in authentication**.
![Select built-in authentication option](/assets/images/enterprise/management-console/built-in-auth-identity-provider-select.png)
6. Read the warning, then click **Ok**.
{% data reusables.enterprise_user_management.two_factor_auth_header %}
{% data reusables.enterprise_user_management.2fa_is_available %}
## Inviting users outside your identity provider to authenticate to your instance
When a user accepts the invitation, they can use their username and password to sign in rather than signing in through the IdP.
{% data reusables.enterprise_site_admin_settings.sign-in %}
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.invite-user-sidebar-tab %}
{% data reusables.enterprise_site_admin_settings.invite-user-reset-link %}
## Further reading
- "[Using LDAP](/enterprise/admin/authentication/using-ldap)"
- "[Using SAML](/enterprise/{{ currentVersion }}/admin/guides/user-management/using-saml)"
- "[Using CAS](/enterprise/{{ currentVersion }}/admin/guides/user-management/using-cas)"

View File

@@ -1,41 +0,0 @@
---
title: Changing authentication methods
intro: 'You can change the way {% data variables.product.prodname_ghe_server %} authenticates with your existing accounts at any time.'
redirect_from:
- /enterprise/admin/user-management/changing-authentication-methods
- /enterprise/admin/authentication/changing-authentication-methods
- /admin/authentication/changing-authentication-methods
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/changing-authentication-methods
versions:
ghes: '*'
type: overview
topics:
- Accounts
- Authentication
- Enterprise
- Identity
shortTitle: Change authentication methods
---
User accounts on {% data variables.product.product_location %} are preserved when you change the authentication method and users will continue to log into the same account as long as their username doesn't change.
If the new method of authentication changes usernames, new accounts will be created. As an administrator, you can rename users through the site admin settings or by using [the User Administration API](/rest/reference/enterprise-admin#update-the-username-for-a-user).
Other issues you should take into consideration include:
* **Passwords:** If you switch to using built-in authentication for your instance, users must [set a password](/enterprise/user/articles/how-can-i-reset-my-password/) after the change is completed.
* **Site administrators:** Administrative privileges are [controlled by your identity provider when you use SAML](/enterprise/admin/guides/user-management/using-saml/#saml-attributes) and can be [controlled by group membership when you use LDAP](/enterprise/admin/authentication/using-ldap#configuring-ldap-with-your-github-enterprise-server-instance).
* **Team membership:** Only LDAP lets you [control team membership](/enterprise/admin/authentication/using-ldap#configuring-ldap-with-your-github-enterprise-server-instance) from your directory server.
* **User suspension:** When you use LDAP to authenticate, access to {% data variables.product.prodname_ghe_server %} can be controlled via _restricted groups_. After switching to LDAP, if restricted groups are configured, existing users who are not in one of those groups will be suspended. Suspension will occur either when they log in or during the next LDAP Sync.
* **Group membership:** When you use LDAP to authenticate, users are automatically [suspended and unsuspended](/enterprise/admin/guides/user-management/suspending-and-unsuspending-users) based on restricted group membership and account status with Active Directory.
* **Git authentication:** SAML and CAS only supports Git authentication over HTTP or HTTPS using a [personal access token](/articles/creating-an-access-token-for-command-line-use). Password authentication over HTTP or HTTPS is not supported. LDAP supports password-based Git authentication by default, but we recommend that you [disable that method](/enterprise/admin/authentication/using-ldap#disabling-password-authentication-for-git-operations) and force authentication via a personal access token or SSH key.
* **API authentication:** SAML and CAS only supports API authentication using a [personal access token](/articles/creating-an-access-token-for-command-line-use). Basic authentication is not supported.
* **Two-factor authentication:** {% data reusables.enterprise_user_management.external_auth_disables_2fa %}
* **Built-in authentication for users outside your identity provider:** You can invite users to authenticate to {% data variables.product.product_location %} without adding them to your identity provider. For more information, see "[Allowing built-in authentication for users outside your identity provider](/enterprise/{{ currentVersion }}/admin/guides/user-management/allowing-built-in-authentication-for-users-outside-your-identity-provider)."

View File

@@ -1,24 +0,0 @@
---
title: Disabling unauthenticated sign-ups
redirect_from:
- /enterprise/admin/articles/disabling-sign-ups
- /enterprise/admin/user-management/disabling-unauthenticated-sign-ups
- /enterprise/admin/authentication/disabling-unauthenticated-sign-ups
- /admin/authentication/disabling-unauthenticated-sign-ups
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/disabling-unauthenticated-sign-ups
intro: 'If you''re using built-in authentication, you can block unauthenticated people from being able to create an account.'
versions:
ghes: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
shortTitle: Block account creation
---
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.privacy %}
3. Unselect **Enable sign-up**.
![Enable sign-up checkbox](/assets/images/enterprise/management-console/enable-sign-up.png)
{% data reusables.enterprise_management_console.save-settings %}

View File

@@ -1,25 +0,0 @@
---
title: Authenticating users for your GitHub Enterprise Server instance
intro: 'You can use {% data variables.product.prodname_ghe_server %}''s built-in authentication, or choose between CAS, LDAP, or SAML to integrate your existing accounts and centrally manage user access to {% data variables.product.product_location %}.'
redirect_from:
- /enterprise/admin/categories/authentication
- /enterprise/admin/guides/installation/user-authentication
- /enterprise/admin/articles/inviting-users
- /enterprise/admin/guides/migrations/authenticating-users-for-your-github-enterprise-instance
- /enterprise/admin/user-management/authenticating-users-for-your-github-enterprise-server-instance
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance
versions:
ghes: '*'
topics:
- Enterprise
children:
- /using-built-in-authentication
- /disabling-unauthenticated-sign-ups
- /using-cas
- /using-saml
- /using-ldap
- /allowing-built-in-authentication-for-users-outside-your-identity-provider
- /changing-authentication-methods
shortTitle: Authenticate users
---

View File

@@ -1,54 +0,0 @@
---
title: Using built-in authentication
intro: 'When you use the default authentication method, all authentication details are stored within {% data variables.product.product_location %}. Built-in authentication is the default method if you dont already have an established authentication provider, such as LDAP, SAML, or CAS.'
redirect_from:
- /enterprise/admin/user-management/using-built-in-authentication
- /enterprise/admin/authentication/using-built-in-authentication
- /admin/authentication/using-built-in-authentication
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/using-built-in-authentication
versions:
ghes: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
- Identity
shortTitle: Use built-in authentication
---
You can create custom messages that users will see on the sign in and sign out pages. For more information, see "[Customizing user messages on your instance](/enterprise/admin/user-management/customizing-user-messages-on-your-instance)."
## Configuring built-in authentication
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.authentication %}
4. Select **Built in authentication**.
![Select built-in authentication option](/assets/images/enterprise/management-console/built-in-auth-select.png)
{% data reusables.enterprise_user_management.two_factor_auth_header %}
{% data reusables.enterprise_user_management.2fa_is_available %}
## Creating your account
Once your instance has been created, you'll need to create your own admin account.
1. On the "Create Admin Account" page at `http(s)://[hostname]/join`, choose your username, password, and email address, then click **Create an account**.
![Create Admin Account](/assets/images/enterprise/site-admin-settings/create-first-admin-acct.png)
{% data reusables.enterprise_site_admin_settings.sign-in %}
## Inviting users
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.invite-user-sidebar-tab %}
{% data reusables.enterprise_site_admin_settings.invite-user-reset-link %}
{% tip %}
**Tip:** If email for notifications is configured on the appliance, an invite will also be sent to the provided email address.
{% endtip %}
## Further reading
- "[Configuring email for notifications](/admin/configuration/configuring-your-enterprise/configuring-email-for-notifications)"

View File

@@ -1,53 +0,0 @@
---
title: Using CAS
redirect_from:
- /enterprise/admin/articles/configuring-cas-authentication
- /enterprise/admin/articles/about-cas-authentication
- /enterprise/admin/user-management/using-cas
- /enterprise/admin/authentication/using-cas
- /admin/authentication/using-cas
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/using-cas
intro: 'CAS is a single sign-on (SSO) protocol for multiple web applications. A CAS user account does not take up a {% ifversion ghes %}user license{% else %}seat{% endif %} until the user signs in.'
versions:
ghes: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
- Identity
- SSO
---
{% data reusables.enterprise_user_management.built-in-authentication %}
## Username considerations with CAS
{% data reusables.enterprise_management_console.username_normalization %}
{% data reusables.enterprise_management_console.username_normalization_sample %}
{% data reusables.enterprise_user_management.two_factor_auth_header %}
{% data reusables.enterprise_user_management.external_auth_disables_2fa %}
## CAS attributes
The following attributes are available.
| Attribute name | Type | Description |
|--------------------------|----------|-------------|
| `username` | Required | The {% data variables.product.prodname_ghe_server %} username. |
## Configuring CAS
{% warning %}
**Warning:** Before configuring CAS on {% data variables.product.product_location %}, note that users will not be able to use their CAS usernames and passwords to authenticate API requests or Git operations over HTTP/HTTPS. Instead, they will need to [create an access token](/enterprise/{{ currentVersion }}/user/articles/creating-an-access-token-for-command-line-use).
{% endwarning %}
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.authentication %}
3. Select **CAS**.
![CAS select](/assets/images/enterprise/management-console/cas-select.png)
4. {% data reusables.enterprise_user_management.built-in-authentication-option %} ![Select CAS built-in authentication checkbox](/assets/images/enterprise/management-console/cas-built-in-authentication.png)
5. In the **Server URL** field, type the full URL of your CAS server. If your CAS server uses a certificate that can't be validated by {% data variables.product.prodname_ghe_server %}, you can use the `ghe-ssl-ca-certificate-install` command to install it as a trusted certificate.

View File

@@ -1,210 +0,0 @@
---
title: Using LDAP
redirect_from:
- /enterprise/admin/articles/configuring-ldap-authentication
- /enterprise/admin/articles/about-ldap-authentication
- /enterprise/admin/articles/viewing-ldap-users
- /enterprise/admin/hidden/enabling-ldap-sync
- /enterprise/admin/hidden/ldap-sync
- /enterprise/admin/user-management/using-ldap
- /enterprise/admin/authentication/using-ldap
- /admin/authentication/using-ldap
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/using-ldap
intro: 'LDAP lets you authenticate {% data variables.product.prodname_ghe_server %} against your existing accounts and centrally manage repository access. LDAP is a popular application protocol for accessing and maintaining directory information services, and is one of the most common protocols used to integrate third-party software with large company user directories.'
versions:
ghes: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
- Identity
---
{% data reusables.enterprise_user_management.built-in-authentication %}
## Supported LDAP services
{% data variables.product.prodname_ghe_server %} integrates with these LDAP services:
* Active Directory
* FreeIPA
* Oracle Directory Server Enterprise Edition
* OpenLDAP
* Open Directory
* 389-ds
## Username considerations with LDAP
{% data reusables.enterprise_management_console.username_normalization %}
{% data reusables.enterprise_management_console.username_normalization_sample %}
{% data reusables.enterprise_user_management.two_factor_auth_header %}
{% data reusables.enterprise_user_management.2fa_is_available %}
## Configuring LDAP with {% data variables.product.product_location %}
After you configure LDAP, users will be able to sign into your instance with their LDAP credentials. When users sign in for the first time, their profile names, email addresses, and SSH keys will be set with the LDAP attributes from your directory.
When you configure LDAP access for users via the {% data variables.enterprise.management_console %}, your user licenses aren't used until the first time a user signs in to your instance. However, if you create an account manually using site admin settings, the user license is immediately accounted for.
{% warning %}
**Warning:** Before configuring LDAP on {% data variables.product.product_location %}, make sure that your LDAP service supports paged results.
{% endwarning %}
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.authentication %}
3. Under "Authentication", select **LDAP**.
![LDAP select](/assets/images/enterprise/management-console/ldap-select.png)
4. {% data reusables.enterprise_user_management.built-in-authentication-option %} ![Select LDAP built-in authentication checkbox](/assets/images/enterprise/management-console/ldap-built-in-authentication.png)
5. Add your configuration settings.
## LDAP attributes
Use these attributes to finish configuring LDAP for {% data variables.product.product_location %}.
| Attribute name | Type | Description |
|--------------------------|----------|-------------|
| `Host` | Required | The LDAP host, e.g. `ldap.example.com` or `10.0.0.30`. If the hostname is only available from your internal network, you may need to configure {% data variables.product.product_location %}'s DNS first so it can resolve the hostname using your internal nameservers. |
| `Port` | Required | The port the host's LDAP services are listening on. Examples include: 389 and 636 (for LDAPS). |
| `Encryption` | Required | The encryption method used to secure communications to the LDAP server. Examples include plain (no encryption), SSL/LDAPS (encrypted from the start), and StartTLS (upgrade to encrypted communication once connected). |
| `Domain search user` | Optional | The LDAP user that looks up other users that sign in, to allow authentication. This is typically a service account created specifically for third-party integrations. Use a fully qualified name, such as `cn=Administrator,cn=Users,dc=Example,dc=com`. With Active Directory, you can also use the `[DOMAIN]\[USERNAME]` syntax (e.g. `WINDOWS\Administrator`) for the domain search user with Active Directory. |
| `Domain search password` | Optional | The password for the domain search user. |
| `Administrators group` | Optional | Users in this group are promoted to site administrators when signing into your appliance. If you don't configure an LDAP Administrators group, the first LDAP user account that signs into your appliance will be automatically promoted to a site administrator. |
| `Domain base` | Required | The fully qualified `Distinguished Name` (DN) of an LDAP subtree you want to search for users and groups. You can add as many as you like; however, each group must be defined in the same domain base as the users that belong to it. If you specify restricted user groups, only users that belong to those groups will be in scope. We recommend that you specify the top level of your LDAP directory tree as your domain base and use restricted user groups to control access. |
| `Restricted user groups` | Optional | If specified, only users in these groups will be allowed to log in. You only need to specify the common names (CNs) of the groups, and you can add as many groups as you like. If no groups are specified, *all* users within the scope of the specified domain base will be able to sign in to your {% data variables.product.prodname_ghe_server %} instance. |
| `User ID` | Required | The LDAP attribute that identifies the LDAP user who attempts authentication. Once a mapping is established, users may change their {% data variables.product.prodname_ghe_server %} usernames. This field should be `sAMAccountName` for most Active Directory installations, but it may be `uid` for other LDAP solutions, such as OpenLDAP. The default value is `uid`. |
| `Profile name` | Optional | The name that will appear on the user's {% data variables.product.prodname_ghe_server %} profile page. Unless LDAP Sync is enabled, users may change their profile names. |
| `Emails` | Optional | The email addresses for a user's {% data variables.product.prodname_ghe_server %} account. |
| `SSH keys` | Optional | The public SSH keys attached to a user's {% data variables.product.prodname_ghe_server %} account. The keys must be in OpenSSH format. |
| `GPG keys` | Optional | The GPG keys attached to a user's {% data variables.product.prodname_ghe_server %} account. |
| `Disable LDAP authentication for Git operations` | Optional |If selected, [turns off](#disabling-password-authentication-for-git-operations) users' ability to use LDAP passwords to authenticate Git operations. |
| `Enable LDAP certificate verification` | Optional |If selected, [turns on](#enabling-ldap-certificate-verification) LDAP certificate verification. |
| `Synchronization` | Optional |If selected, [turns on](#enabling-ldap-sync) LDAP Sync. |
### Disabling password authentication for Git operations
Select **Disable username and password authentication for Git operations** in your LDAP settings to enforce use of personal access tokens or SSH keys for Git access, which can help prevent your server from being overloaded by LDAP authentication requests. We recommend this setting because a slow-responding LDAP server, especially combined with a large number of requests due to polling, is a frequent source of performance issues and outages.
![Disable LDAP password auth for Git check box](/assets/images/enterprise/management-console/ldap-disable-password-auth-for-git.png)
When this option is selected, if a user tries to use a password for Git operations via the command line, they will receive an error message that says, `Password authentication is not allowed for Git operations. You must use a personal access token.`
### Enabling LDAP certificate verification
Select **Enable LDAP certificate verification** in your LDAP settings to validate the LDAP server certificate you use with TLS.
![LDAP certificate verification box](/assets/images/enterprise/management-console/ldap-enable-certificate-verification.png)
When this option is selected, the certificate is validated to make sure:
- If the certificate contains at least one Subject Alternative Name (SAN), one of the SANs matches the LDAP hostname. Otherwise, the Common Name (CN) matches the LDAP hostname.
- The certificate is not expired.
- The certificate is signed by a trusted certificate authority (CA).
### Enabling LDAP Sync
{% note %}
**Note:** Teams using LDAP Sync are limited to a maximum 1499 members.
{% endnote %}
LDAP Sync lets you synchronize {% data variables.product.prodname_ghe_server %} users and team membership against your established LDAP groups. This lets you establish role-based access control for users from your LDAP server instead of manually within {% data variables.product.prodname_ghe_server %}. For more information, see "[Creating teams](/enterprise/{{ currentVersion }}/admin/guides/user-management/creating-teams#creating-teams-with-ldap-sync-enabled)."
To enable LDAP Sync, in your LDAP settings, select **Synchronize Emails**, **Synchronize SSH Keys**, or **Synchronize GPG Keys** .
![Synchronization check box](/assets/images/enterprise/management-console/ldap-synchronize.png)
After you enable LDAP sync, a synchronization job will run at the specified time interval to perform the following operations on each user account:
- If you've allowed built-in authentication for users outside your identity provider, and the user is using built-in authentication, move on to the next user.
- If no LDAP mapping exists for the user, try to map the user to an LDAP entry in the directory. If the user cannot be mapped to an LDAP entry, suspend the user and move on to the next user.
- If there is an LDAP mapping and the corresponding LDAP entry in the directory is missing, suspend the user and move on to the next user.
- If the corresponding LDAP entry has been marked as disabled and the user is not already suspended, suspend the user and move on to the next user.
- If the corresponding LDAP entry is not marked as disabled, and the user is suspended, and _Reactivate suspended users_ is enabled in the Admin Center, unsuspend the user.
- If one or more restricted user groups are configured on the instance and the corresponding LDAP entry is not in one of these groups, suspend the user.
- If one or more restricted user groups are configured on the instance, the corresponding LDAP entry is in one of these groups, and _Reactivate suspended users_ is enabled in the Admin Center, unsuspend the user.
- If the corresponding LDAP entry includes a `name` attribute, update the user's profile name.
- If the corresponding LDAP entry is in the Administrators group, promote the user to site administrator.
- If the corresponding LDAP entry is not in the Administrators group, demote the user to a normal account.
- If an LDAP User field is defined for emails, synchronize the user's email settings with the LDAP entry. Set the first LDAP `mail` entry as the primary email.
- If an LDAP User field is defined for SSH public keys, synchronize the user's public SSH keys with the LDAP entry.
- If an LDAP User field is defined for GPG keys, synchronize the user's GPG keys with the LDAP entry.
{% note %}
**Note**: LDAP entries can only be marked as disabled if you use Active Directory and the `userAccountControl` attribute is present and flagged with `ACCOUNTDISABLE`. Some variations of Active Directory, such as AD LDS and ADAM, don't support the `userAccountControl` attribute.
{% endnote %}
A synchronization job will also run at the specified time interval to perform the following operations on each team that has been mapped to an LDAP group:
- If a team's corresponding LDAP group has been removed, remove all members from the team.
- If LDAP member entries have been removed from the LDAP group, remove the corresponding users from the team. If the user is no longer a member of any team in the organization, remove the user from the organization. If the user loses access to any repositories as a result, delete any private forks the user has of those repositories.
- If LDAP member entries have been added to the LDAP group, add the corresponding users to the team. If the user regains access to any repositories as a result, restore any private forks of the repositories that were deleted because the user lost access in the past 90 days.
{% data reusables.enterprise_user_management.ldap-sync-nested-teams %}
{% warning %}
**Security Warning:**
When LDAP Sync is enabled, site admins and organization owners can search the LDAP directory for groups to map the team to.
This has the potential to disclose sensitive organizational information to contractors or other unprivileged users, including:
- The existence of specific LDAP Groups visible to the *Domain search user*.
- Members of the LDAP group who have {% data variables.product.prodname_ghe_server %} user accounts, which is disclosed when creating a team synced with that LDAP group.
If disclosing such information is not desired, your company or organization should restrict the permissions of the configured *Domain search user* in the admin console. If such restriction isn't possible, contact {% data variables.contact.contact_ent_support %}.
{% endwarning %}
### Supported LDAP group object classes
{% data variables.product.prodname_ghe_server %} supports these LDAP group object classes. Groups can be nested.
- `group`
- `groupOfNames`
- `groupOfUniqueNames`
- `posixGroup`
## Viewing and creating LDAP users
You can view the full list of LDAP users who have access to your instance and provision new users.
{% data reusables.enterprise_site_admin_settings.sign-in %}
{% data reusables.enterprise_site_admin_settings.access-settings %}
3. In the left sidebar, click **LDAP users**.
![LDAP users tab](/assets/images/enterprise/site-admin-settings/ldap-users-tab.png)
4. To search for a user, type a full or partial username and click **Search**. Existing users will be displayed in search results. If a user doesnt exist, click **Create** to provision the new user account.
![LDAP search](/assets/images/enterprise/site-admin-settings/ldap-users-search.jpg)
## Updating LDAP accounts
Unless [LDAP Sync is enabled](#enabling-ldap-sync), changes to LDAP accounts are not automatically synchronized with {% data variables.product.prodname_ghe_server %}.
* To use a new LDAP admin group, users must be manually promoted and demoted on {% data variables.product.prodname_ghe_server %} to reflect changes in LDAP.
* To add or remove LDAP accounts in LDAP admin groups, [promote or demote the accounts on {% data variables.product.prodname_ghe_server %}](/enterprise/{{ currentVersion }}/admin/guides/user-management/promoting-or-demoting-a-site-administrator).
* To remove LDAP accounts, [suspend the {% data variables.product.prodname_ghe_server %} accounts](/enterprise/{{ currentVersion }}/admin/guides/user-management/suspending-and-unsuspending-users).
### Manually syncing LDAP accounts
{% data reusables.enterprise_site_admin_settings.sign-in %}
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.search-user %}
{% data reusables.enterprise_site_admin_settings.click-user %}
{% data reusables.enterprise_site_admin_settings.admin-top-tab %}
{% data reusables.enterprise_site_admin_settings.admin-tab %}
5. Under "LDAP," click **Sync now** to manually update the account with data from your LDAP server.
![LDAP sync now button](/assets/images/enterprise/site-admin-settings/ldap-sync-now-button.png)
You can also [use the API to trigger a manual sync](/enterprise/{{ currentVersion }}/user/rest/reference/enterprise-admin#ldap).
## Revoking access to {% data variables.product.product_location %}
If [LDAP Sync is enabled](#enabling-ldap-sync), removing a user's LDAP credentials will suspend their account after the next synchronization run.
If LDAP Sync is **not** enabled, you must manually suspend the {% data variables.product.prodname_ghe_server %} account after you remove the LDAP credentials. For more information, see "[Suspending and unsuspending users](/enterprise/{{ currentVersion }}/admin/guides/user-management/suspending-and-unsuspending-users)".

View File

@@ -1,319 +0,0 @@
---
title: Using SAML
redirect_from:
- /enterprise/admin/articles/configuring-saml-authentication
- /enterprise/admin/articles/about-saml-authentication
- /enterprise/admin/user-management/using-saml
- /enterprise/admin/authentication/using-saml
- /admin/authentication/using-saml
- /enterprise/admin/authentication/authenticating-users-for-your-github-enterprise-server-instance/using-saml
intro: 'You can configure SAML single sign-on (SSO) for {% data variables.product.product_name %}, which allows users to authenticate through a SAML identity provider (IdP) to access your instance.'
versions:
ghes: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
- Identity
- SSO
---
## About SAML for {% data variables.product.product_name %}
SAML SSO allows people to authenticate and access {% data variables.product.product_location %} through an external system for identity management.
SAML is an XML-based standard for authentication and authorization. When you configure SAML for {% data variables.product.product_location %}, the external system for authentication is called an identity provider (IdP). Your instance acts as a SAML service provider (SP). For more information, see [Security Assertion Markup Language](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) on Wikipedia.
{% data reusables.enterprise_user_management.built-in-authentication %}
## Supported SAML services
{% data reusables.saml.saml-supported-idps %}
{% ifversion ghes > 3.3 %}
If your IdP supports encrypted assertions, you can configure encrypted assertions on {% data variables.product.product_name %} for increased security during the authentication process.
{% endif %}
{% data reusables.saml.saml-single-logout-not-supported %}
## Username considerations with SAML
Each {% data variables.product.prodname_ghe_server %} username is determined by one of the following assertions in the SAML response, ordered by priority:
- The custom username attribute, if defined and present
- An `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name` assertion, if present
- An `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress` assertion, if present
- The `NameID` element
The `NameID` element is required even if other attributes are present.
A mapping is created between the `NameID` and the {% data variables.product.prodname_ghe_server %} username, so the `NameID` should be persistent, unique, and not subject to change for the lifecycle of the user.
{% note %}
**Note**: If the `NameID` for a user does change on the IdP, the user will see an error message when they try to sign into {% data variables.product.product_location %}. To restore the user's access, you'll need to update the user account's `NameID` mapping. For more information, see "[Updating a user's SAML `NameID`](#updating-a-users-saml-nameid)."
{% endnote %}
{% data reusables.enterprise_management_console.username_normalization %}
{% data reusables.enterprise_management_console.username_normalization_sample %}
{% data reusables.enterprise_user_management.two_factor_auth_header %}
{% data reusables.enterprise_user_management.external_auth_disables_2fa %}
## SAML metadata
The service provider metadata for {% data variables.product.product_location %} is available at `http(s)://[hostname]/saml/metadata`.
To configure your identity provider manually, the Assertion Consumer Service (ACS) URL is `http(s)://[hostname]/saml/consume`. It uses the `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST` binding.
## SAML attributes
These attributes are available. You can change the attribute names in the [management console](/enterprise/{{ currentVersion }}/admin/guides/installation/accessing-the-management-console/), with the exception of the `administrator` attribute.
| Default attribute name | Type | Description |
|-----------------|----------|-------------|
| `NameID` | Required | A persistent user identifier. Any persistent name identifier format may be used. The `NameID` element will be used for a {% data variables.product.prodname_ghe_server %} username unless one of the alternative assertions is provided. |
| `administrator` | Optional | When the value is 'true', the user will automatically be promoted as an administrator. Any other value or a non-existent value will demote the user to a normal user account. |
| `username` | Optional | The {% data variables.product.prodname_ghe_server %} username. |
| `full_name` | Optional | The name of the user displayed on their profile page. Users may change their names after provisioning. |
| `emails` | Optional | The email addresses for the user. More than one can be specified. |
| `public_keys` | Optional | The public SSH keys for the user. More than one can be specified. |
| `gpg_keys` | Optional | The GPG keys for the user. More than one can be specified. |
To specify more than one value for an attribute, use multiple `<saml2:AttributeValue>` elements.
```
<saml2:Attribute FriendlyName="public_keys" Name="urn:oid:1.2.840.113549.1.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>ssh-rsa LONG KEY</saml2:AttributeValue>
<saml2:AttributeValue>ssh-rsa LONG KEY 2</saml2:AttributeValue>
</saml2:Attribute>
```
## Configuring SAML settings
You can enable or disable SAML authentication for {% data variables.product.product_location %}, or you can edit an existing configuration. You can view and edit authentication settings for {% data variables.product.product_name %} in the {% data variables.enterprise.management_console %}. For more information, see "[Accessing the management console](/admin/configuration/configuring-your-enterprise/accessing-the-management-console)."
{% note %}
**Note**: {% data reusables.enterprise.test-in-staging %}
{% endnote %}
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.authentication %}
1. Select **SAML**.
![Screenshot of option to enable SAML authentication in management console](/assets/images/enterprise/management-console/auth-select-saml.png)
1. {% data reusables.enterprise_user_management.built-in-authentication-option %}
![Screenshot of option to enable built-in authentication outside of SAML IdP](/assets/images/enterprise/management-console/saml-built-in-authentication.png)
1. Optionally, to enable unsolicited response SSO, select **IdP initiated SSO**. By default, {% data variables.product.prodname_ghe_server %} will reply to an unsolicited Identity Provider (IdP) initiated request with an `AuthnRequest` back to the IdP.
![Screenshot of option to enable IdP-initiated unsolicited response](/assets/images/enterprise/management-console/saml-idp-sso.png)
{% tip %}
**Note**: We recommend keeping this value **unselected**. You should enable this feature **only** in the rare instance that your SAML implementation does not support service provider initiated SSO, and when advised by {% data variables.contact.enterprise_support %}.
{% endtip %}
1. Select **Disable administrator demotion/promotion** if you **do not** want your SAML provider to determine administrator rights for users on {% data variables.product.product_location %}.
![Screenshot of option to enable option to respect the "administrator" attribute from the IdP to enable or disable administrative rights](/assets/images/enterprise/management-console/disable-admin-demotion-promotion.png)
{%- ifversion ghes > 3.3 %}
1. Optionally, to allow {% data variables.product.product_location %} to receive encrypted assertions from your SAML IdP, select **Require encrypted assertions**. You must ensure that your IdP supports encrypted assertions and that the encryption and key transport methods in the management console match the values configured on your IdP. You must also provide {% data variables.product.product_location %}'s public certificate to your IdP. For more information, see "[Enabling encrypted assertions](#enabling-encrypted-assertions)."
![Screenshot of "Enable encrypted assertions" checkbox within management console's "Authentication" section](/assets/images/help/saml/management-console-enable-encrypted-assertions.png)
{%- endif %}
1. In the **Single sign-on URL** field, type the HTTP or HTTPS endpoint on your IdP for single sign-on requests. This value is provided by your IdP configuration. If the host is only available from your internal network, you may need to [configure {% data variables.product.product_location %} to use internal nameservers](/enterprise/{{ currentVersion }}/admin/guides/installation/configuring-dns-nameservers/).
![Screenshot of text field for single sign-on URL](/assets/images/enterprise/management-console/saml-single-sign-url.png)
1. Optionally, in the **Issuer** field, type your SAML issuer's name. This verifies the authenticity of messages sent to {% data variables.product.product_location %}.
![Screenshot of text field for SAML issuer URL](/assets/images/enterprise/management-console/saml-issuer.png)
1. In the **Signature Method** and **Digest Method** drop-down menus, choose the hashing algorithm used by your SAML issuer to verify the integrity of the requests from {% data variables.product.product_location %}. Specify the format with the **Name Identifier Format** drop-down menu.
![Screenshot of drop-down menus to select signature and digest method](/assets/images/enterprise/management-console/saml-method.png)
1. Under **Verification certificate**, click **Choose File** and choose a certificate to validate SAML responses from the IdP.
![Screenshot of button for uploading validation certificate from IdP](/assets/images/enterprise/management-console/saml-verification-cert.png)
1. Modify the SAML attribute names to match your IdP if needed, or accept the default names.
![Screenshot of fields for entering additional SAML attributes](/assets/images/enterprise/management-console/saml-attributes.png)
{% ifversion ghes > 3.3 %}
## Enabling encrypted assertions
To enable encrypted assertions, your SAML IdP must also support encrypted assertions. You must provide {% data variables.product.product_location %}'s public certificate to your IdP, and configure encryption settings that match your IdP.
{% note %}
**Note**: {% data reusables.enterprise.test-in-staging %}
{% endnote %}
1. Optionally, enable SAML debugging. SAML debugging records verbose entries in {% data variables.product.product_name %}'s authentication log, and may help you troubleshoot failed authentication attempts. For more information, see "[Configuring SAML debugging](#configuring-saml-debugging)."
{% data reusables.enterprise_site_admin_settings.access-settings %}
{% data reusables.enterprise_site_admin_settings.management-console %}
{% data reusables.enterprise_management_console.authentication %}
1. Select **Require encrypted assertions**.
![Screenshot of "Enable encrypted assertions" checkbox within management console's "Authentication" section](/assets/images/help/saml/management-console-enable-encrypted-assertions.png)
1. To the right of "Encryption Certificate", click **Download** to save a copy of {% data variables.product.product_location %}'s public certificate on your local machine.
![Screenshot of "Download" button for public certificate for encrypted assertions](/assets/images/help/saml/management-console-encrypted-assertions-download-certificate.png)
1. Sign into your SAML IdP as an administrator.
1. In the application for {% data variables.product.product_location %}, enable encrypted assertions.
- Note the encryption method and key transport method.
- Provide the public certificate you downloaded in step 7.
1. Return to the management console on {% data variables.product.product_location %}.
1. To the right of "Encryption Method", select the encryption method for your IdP from step 9.
![Screenshot of "Encryption Method" for encrypted assertions](/assets/images/help/saml/management-console-encrypted-assertions-encryption-method.png)
1. To the right of "Key Transport Method", select the key transport method for your IdP from step 9.
![Screenshot of "Key Transport Method" for encrypted assertions](/assets/images/help/saml/management-console-encrypted-assertions-key-transport-method.png)
1. Click **Save settings**.
{% data reusables.enterprise_site_admin_settings.wait-for-configuration-run %}
If you enabled SAML debugging to test authentication with encrypted assertions, disable SAML debugging when you're done testing. For more information, see "[Configuring SAML debugging](#configuring-saml-debugging)."
{% endif %}
## Updating a user's SAML `NameID`
{% data reusables.enterprise_site_admin_settings.access-settings %}
2. In the left sidebar, click **All users**.
!["All users" sidebar item in site administrator settings](/assets/images/enterprise/site-admin-settings/all-users.png)
3. In the list of users, click the username you'd like to update the `NameID` mapping for.
![Username in list of instance user accounts](/assets/images/enterprise/site-admin-settings/all-users-click-username.png)
{% data reusables.enterprise_site_admin_settings.security-tab %}
5. To the right of "Update SAML NameID", click **Edit** .
!["Edit" button under "SAML authentication" and to the right of "Update SAML NameID"](/assets/images/enterprise/site-admin-settings/update-saml-nameid-edit.png)
6. In the "NameID" field, type the new `NameID` for the user.
!["NameID" field in modal dialog with NameID typed](/assets/images/enterprise/site-admin-settings/update-saml-nameid-field-in-modal.png)
7. Click **Update NameID**.
!["Update NameID" button under updated NameID value within modal](/assets/images/enterprise/site-admin-settings/update-saml-nameid-update.png)
## Revoking access to {% data variables.product.product_location %}
If you remove a user from your identity provider, you must also manually suspend them. Otherwise, they'll continue to be able to authenticate using access tokens or SSH keys. For more information, see "[Suspending and unsuspending users](/enterprise/admin/guides/user-management/suspending-and-unsuspending-users)".
## Response message requirements
The response message must fulfill the following requirements:
- The `<Destination>` element must be provided on the root response document and match the ACS URL only when the root response document is signed. If the assertion is signed, it will be ignored.
- The `<Audience>` element must always be provided as part of the `<AudienceRestriction>` element. It must match the `EntityId` for {% data variables.product.prodname_ghe_server %}. This is the URL to the {% data variables.product.prodname_ghe_server %} instance, such as `https://ghe.corp.example.com`.
- Each assertion in the response **must** be protected by a digital signature. This can be accomplished by signing each individual `<Assertion>` element or by signing the `<Response>` element.
- A `<NameID>` element must be provided as part of the `<Subject>` element. Any persistent name identifier format may be used.
- The `Recipient` attribute must be present and set to the ACS URL. For example:
```xml
<samlp:Response ...>
<saml:Assertion ...>
<saml:Subject>
<saml:NameID ...>...</saml:NameID>
<saml:SubjectConfirmation ...>
<saml:SubjectConfirmationData Recipient="https://ghe.corp.example.com/saml/consume" .../>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:AttributeStatement>
<saml:Attribute FriendlyName="USERNAME-ATTRIBUTE" ...>
<saml:AttributeValue>monalisa</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
```
## Troubleshooting SAML authentication
{% data variables.product.prodname_ghe_server %} logs error messages for failed SAML authentication in the authentication log at _/var/log/github/auth.log_. For more information about SAML response requirements, see "[Response message requirements](#response-message-requirements)."
### Error: "Another user already owns the account"
When a user signs in to {% data variables.product.prodname_ghe_server %} for the first time with SAML authentication, {% data variables.product.prodname_ghe_server %} creates a user account on the instance and maps the SAML `NameID` to the account.
When the user signs in again, {% data variables.product.prodname_ghe_server %} compares the account's `NameID` mapping to the IdP's response. If the `NameID` in the IdP's response no longer matches the `NameID` that {% data variables.product.prodname_ghe_server %} expects for the user, the sign-in will fail. The user will see the following message.
> Another user already owns the account. Please have your administrator check the authentication log.
The message typically indicates that the person's username or email address has changed on the IdP. Ensure that the `NameID` mapping for the user account on {% data variables.product.prodname_ghe_server %} matches the user's `NameID` on your IdP. For more information, see "[Updating a user's SAML `NameID`](#updating-a-users-saml-nameid)."
### Error: Recipient in SAML response was blank or not valid
If the `Recipient` does not match the ACS URL for {% data variables.product.product_location %}, one of the following two error messages will appear in the authentication log when a user attempts to authenticate.
```
Recipient in the SAML response must not be blank.
```
```
Recipient in the SAML response was not valid.
```
Ensure that you set the value for `Recipient` on your IdP to the full ACS URL for {% data variables.product.product_location %}. For example, `https://ghe.corp.example.com/saml/consume`.
### Error: "SAML Response is not signed or has been modified"
If your IdP does not sign the SAML response, or the signature does not match the contents, the following error message will appear in the authentication log.
```
SAML Response is not signed or has been modified.
```
Ensure that you configure signed assertions for the {% data variables.product.prodname_ghe_server %} application on your IdP.
### Error: "Audience is invalid" or "No assertion found"
If the IdP's response has a missing or incorrect value for `Audience`, the following error message will appear in the authentication log.
```shell
Audience is invalid. Audience attribute does not match https://<em>YOUR-INSTANCE-URL</em>
```
Ensure that you set the value for `Audience` on your IdP to the `EntityId` for {% data variables.product.product_location %}, which is the full URL to {% data variables.product.product_location %}. For example, `https://ghe.corp.example.com`.
### Configuring SAML debugging
You can configure {% data variables.product.product_name %} to write verbose debug logs to _/var/log/github/auth.log_ for every SAML authentication attempt. You may be able to troubleshoot failed authentication attempts with this extra output.
{% warning %}
**Warnings**:
- Only enable SAML debugging temporarily, and disable debugging immediately after you finish troubleshooting. If you leave debugging enabled, the size of your log may increase much faster than usual, which can negatively impact the performance of {% data variables.product.product_name %}.
- Test new authentication settings for {% data variables.product.product_location %} in a staging environment before you apply the settings in your production environment. For more information, see "[Setting up a staging instance](/admin/installation/setting-up-a-github-enterprise-server-instance/setting-up-a-staging-instance)."
{% endwarning %}
{% data reusables.enterprise-accounts.access-enterprise %}
{% data reusables.enterprise-accounts.policies-tab %}
{% data reusables.enterprise-accounts.options-tab %}
1. Under "SAML debugging", select the drop-down and click **Enabled**.
![Screenshot of drop-down to enable SAML debugging](/assets/images/enterprise/site-admin-settings/site-admin-saml-debugging-enabled.png)
1. Attempt to sign into {% data variables.product.product_location %} through your SAML IdP.
1. Review the debug output in _/var/log/github/auth.log_ on {% data variables.product.product_location %}.
1. When you're done troubleshooting, select the drop-down and click **Disabled**.
![Screenshot of drop-down to disable SAML debugging](/assets/images/enterprise/site-admin-settings/site-admin-saml-debugging-disabled.png)
### Decoding responses in _auth.log_
Some output in _auth.log_ may be Base64-encoded. You can access the administrative shell and use the `base64` utility on {% data variables.product.product_location %} to decode these responses. For more information, see "[Accessing the administrative shell (SSH)](/admin/configuration/configuring-your-enterprise/accessing-the-administrative-shell-ssh)."
```shell
$ base64 --decode <em>ENCODED OUTPUT</em>
```

View File

@@ -1,56 +0,0 @@
---
title: Configuring authentication and provisioning for your enterprise using Azure AD
shortTitle: Configuring with Azure AD
intro: 'You can use a tenant in Azure Active Directory (Azure AD) as an identity provider (IdP) to centrally manage authentication and user provisioning for {% data variables.product.product_location %}.'
permissions: 'Enterprise owners can configure authentication and provisioning for an enterprise on {% data variables.product.product_name %}.'
versions:
ghae: '*'
type: how_to
topics:
- Accounts
- Authentication
- Enterprise
- Identity
- SSO
redirect_from:
- /admin/authentication/configuring-authentication-and-provisioning-for-your-enterprise-using-azure-ad
- /admin/authentication/configuring-authentication-and-provisioning-with-your-identity-provider/configuring-authentication-and-provisioning-for-your-enterprise-using-azure-ad
---
## About authentication and user provisioning with Azure AD
Azure Active Directory (Azure AD) is a service from Microsoft that allows you to centrally manage user accounts and access to web applications. For more information, see [What is Azure Active Directory?](https://docs.microsoft.com/azure/active-directory/fundamentals/active-directory-whatis) in the Microsoft Docs.
To manage identity and access for {% data variables.product.product_name %}, you can use an Azure AD tenant as a SAML IdP for authentication. You can also configure Azure AD to automatically provision accounts and access membership with SCIM, which allows you to create {% data variables.product.prodname_ghe_managed %} users and manage team and organization membership from your Azure AD tenant.
After you enable SAML SSO and SCIM for {% data variables.product.prodname_ghe_managed %} using Azure AD, you can accomplish the following from your Azure AD tenant.
* Assign the {% data variables.product.prodname_ghe_managed %} application on Azure AD to a user account to automatically create and grant access to a corresponding user account on {% data variables.product.product_name %}.
* Unassign the {% data variables.product.prodname_ghe_managed %} application to a user account on Azure AD to deactivate the corresponding user account on {% data variables.product.product_name %}.
* Assign the {% data variables.product.prodname_ghe_managed %} application to an IdP group on Azure AD to automatically create and grant access to user accounts on {% data variables.product.product_name %} for all members of the IdP group. In addition, the IdP group is available on {% data variables.product.prodname_ghe_managed %} for connection to a team and its parent organization.
* Unassign the {% data variables.product.prodname_ghe_managed %} application from an IdP group to deactivate the {% data variables.product.product_name %} user accounts of all IdP users who had access only through that IdP group and remove the users from the parent organization. The IdP group will be disconnected from any teams on {% data variables.product.product_name %}.
For more information about managing identity and access for your enterprise on {% data variables.product.product_location %}, see "[Managing identity and access for your enterprise](/admin/authentication/managing-identity-and-access-for-your-enterprise)." For more information about synchronizing teams with IdP groups, see "[Synchronizing a team with an identity provider group](/organizations/organizing-members-into-teams/synchronizing-a-team-with-an-identity-provider-group)."
## Prerequisites
To configure authentication and user provisioning for {% data variables.product.product_name %} using Azure AD, you must have an Azure AD account and tenant. For more information, see the [Azure AD website](https://azure.microsoft.com/free/active-directory) and [Quickstart: Create an Azure Active Directory tenant](https://docs.microsoft.com/azure/active-directory/develop/quickstart-create-new-tenant) in the Microsoft Docs.
{% data reusables.saml.assert-the-administrator-attribute %} For more information about including the `administrator` attribute in the SAML claim from Azure AD, see [How to: customize claims issued in the SAML token for enterprise applications](https://docs.microsoft.com/azure/active-directory/develop/active-directory-saml-claims-customization) in the Microsoft Docs.
{% data reusables.saml.create-a-machine-user %}
## Configuring authentication and user provisioning with Azure AD
{% ifversion ghae %}
1. In Azure AD, add {% data variables.product.ae_azure_ad_app_link %} to your tenant and configure single sign-on. For more information, see [Tutorial: Azure Active Directory single sign-on (SSO) integration with {% data variables.product.prodname_ghe_managed %}](https://docs.microsoft.com/azure/active-directory/saas-apps/github-ae-tutorial) in the Microsoft Docs.
1. In {% data variables.product.prodname_ghe_managed %}, enter the details for your Azure AD tenant.
- {% data reusables.saml.ae-enable-saml-sso-during-bootstrapping %}
- If you've already configured SAML SSO for {% data variables.product.product_location %} using another IdP and you want to use Azure AD instead, you can edit your configuration. For more information, see "[Configuring SAML single sign-on for your enterprise](/admin/authentication/configuring-saml-single-sign-on-for-your-enterprise#editing-the-saml-sso-configuration)."
1. Enable user provisioning in {% data variables.product.product_name %} and configure user provisioning in Azure AD. For more information, see "[Configuring user provisioning for your enterprise](/admin/authentication/configuring-user-provisioning-for-your-enterprise#enabling-user-provisioning-for-your-enterprise)."
{% endif %}

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