Merge branch 'main' into sophietheking-6776
@@ -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: '.' }],
|
||||
},
|
||||
|
||||
2
.github/workflows/autoupdate-branch.yml
vendored
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
4
.github/workflows/browser-test.yml
vendored
@@ -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') }}
|
||||
|
||||
@@ -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') }}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
2
.github/workflows/code-lint.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/codeql.yml
vendored
@@ -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!)
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
|
||||
|
||||
2
.github/workflows/crowdin-cleanup.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/docs-review-collect.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/enterprise-dates.yml
vendored
@@ -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
|
||||
|
||||
@@ -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') }}
|
||||
|
||||
2
.github/workflows/link-check-all.yml
vendored
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
2
.github/workflows/manually-purge-fastly.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
|
||||
uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
2
.github/workflows/open-enterprise-issue.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/openapi-decorate.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/openapi-schema-check.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/optimize-images.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/orphaned-assets-check.yml
vendored
@@ -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.)
|
||||
|
||||
2
.github/workflows/os-ready-for-review.yml
vendored
@@ -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
|
||||
|
||||
4
.github/workflows/pa11y.yml
vendored
@@ -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') }}
|
||||
|
||||
2
.github/workflows/package-lock-lint.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/ready-for-doc-review.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/remove-unused-assets.yml
vendored
@@ -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:
|
||||
|
||||
4
.github/workflows/repo-sync.yml
vendored
@@ -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:
|
||||
|
||||
4
.github/workflows/site-policy-sync.yml
vendored
@@ -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 }}
|
||||
|
||||
4
.github/workflows/sync-search-indices.yml
vendored
@@ -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') }}
|
||||
|
||||
4
.github/workflows/sync-search-pr.yml
vendored
@@ -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') }}
|
||||
|
||||
6
.github/workflows/test.yml
vendored
@@ -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') }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
2
.github/workflows/update-graphql-files.yml
vendored
@@ -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:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
translations/
|
||||
includes/
|
||||
data/release-notes/
|
||||
script/bookmarklets/
|
||||
|
||||
BIN
assets/images/help/organizations/customize_pins_link.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
assets/images/help/organizations/new_organization_page.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
assets/images/help/organizations/org_member_readme.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
assets/images/help/organizations/org_profile_view.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
assets/images/help/organizations/org_public_readme.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
assets/images/help/organizations/pin_repositories_link.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
assets/images/help/organizations/pinned_repo_dialog.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 57 KiB |
BIN
assets/images/help/sponsors/your-sponsors-tab.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
@@ -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>
|
||||
|
||||
@@ -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()
|
||||
|
||||
37
components/context/RestContext.tsx
Normal 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 || [],
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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) => (
|
||||
<MarkdownContent>{renderedPage}</MarkdownContent>
|
||||
{restOperations &&
|
||||
restOperations.length > 0 &&
|
||||
restOperations.map((operation, index) => (
|
||||
<RestOperation
|
||||
key={`${subcategory}-${operation.title}-${index}`}
|
||||
key={`restOperation-${operation.title}-${index}`}
|
||||
operation={operation}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,3 @@ export interface ChildParameter {
|
||||
description: string
|
||||
type: string
|
||||
}
|
||||
|
||||
export interface RestCategoryOperationsT {
|
||||
[subcategory: string]: Operation[]
|
||||
}
|
||||
|
||||
124
components/sidebar/ProductCollapsibleSection.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
206
components/sidebar/RestCollapsibleSection.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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,31 +29,20 @@ 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)
|
||||
)
|
||||
return (
|
||||
<ul data-testid="sidebar" className={styles.container}>
|
||||
<AllProductsLink />
|
||||
|
||||
{!currentProductTree.page.hidden && (
|
||||
<>
|
||||
<li data-testid="sidebar-product" title={productTitle} className="my-2">
|
||||
<Link
|
||||
href={currentProductTree.href}
|
||||
className="pl-4 pr-5 pb-1 f4 color-fg-default no-underline"
|
||||
>
|
||||
{productTitle}
|
||||
</Link>
|
||||
</li>
|
||||
const productTitle = currentProductTree.renderedShortTitle || currentProductTree.renderedFullTitle
|
||||
|
||||
<li className="my-3">
|
||||
const productSection = () => (
|
||||
<li className="my-3" data-testid="product-sidebar-items">
|
||||
<ul className="list-style-none">
|
||||
{currentProductTree.childPages.map((childPage, i) => {
|
||||
{currentProductTree &&
|
||||
currentProductTree.childPages.map((childPage, i) => {
|
||||
const isStandaloneCategory = childPage.page.documentType === 'article'
|
||||
|
||||
const childTitle = childPage.renderedShortTitle || childPage.renderedFullTitle
|
||||
@@ -74,7 +64,7 @@ export const SidebarProduct = () => {
|
||||
{childTitle}
|
||||
</Link>
|
||||
) : (
|
||||
<CollapsibleSection
|
||||
<ProductCollapsibleSection
|
||||
defaultOpen={defaultOpen}
|
||||
routePath={routePath}
|
||||
title={childTitle}
|
||||
@@ -86,123 +76,104 @@ export const SidebarProduct = () => {
|
||||
})}
|
||||
</ul>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</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>
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
<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) => {
|
||||
<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)
|
||||
const isCurrent = routePath === childPage.href
|
||||
|
||||
const isActive =
|
||||
routePath.includes(childPage.href + '/') || routePath === childPage.href
|
||||
const defaultOpen = hasExactCategory ? isActive : false
|
||||
return (
|
||||
<li key={childPage.href + i} data-is-current-page={isCurrent}>
|
||||
<details
|
||||
open={isActive}
|
||||
onToggle={(e) => e.stopPropagation()}
|
||||
className="details-reset"
|
||||
<li
|
||||
key={childPage.href + i}
|
||||
data-is-active-category={isActive}
|
||||
data-is-current-page={isActive && isStandaloneCategory}
|
||||
className={cx('py-1', isActive && 'color-bg-inset')}
|
||||
>
|
||||
<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>
|
||||
<ProductCollapsibleSection
|
||||
defaultOpen={defaultOpen}
|
||||
routePath={routePath}
|
||||
title={childTitle}
|
||||
page={childPage}
|
||||
/>
|
||||
</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)} />
|
||||
</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>
|
||||
) : null}
|
||||
<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>
|
||||
</>
|
||||
}
|
||||
</details>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ul data-testid="sidebar" className={styles.container}>
|
||||
<AllProductsLink />
|
||||
|
||||
{!currentProductTree.page.hidden && (
|
||||
<>
|
||||
<li data-testid="sidebar-product" title={productTitle} className="my-2">
|
||||
<Link
|
||||
href={currentProductTree.href}
|
||||
className="pl-4 pr-5 pb-1 f4 color-fg-default no-underline"
|
||||
>
|
||||
{productTitle}
|
||||
</Link>
|
||||
</li>
|
||||
{currentProduct && currentProduct.id === 'rest' ? restSection() : productSection()}
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -17,5 +17,6 @@ children:
|
||||
- /personalizing-your-profile
|
||||
- /managing-your-profile-readme
|
||||
- /pinning-items-to-your-profile
|
||||
- /setting-your-profile-to-private
|
||||
---
|
||||
|
||||
|
||||
@@ -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.
|
||||

|
||||
3. Click **Update preferences**.
|
||||
{% data reusables.user-settings.update-preferences %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -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 %}
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 %}
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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)."
|
||||
|
||||

|
||||
|
||||
## 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**.
|
||||

|
||||
1. In the left sidebar, click the workflow you want to see.
|
||||

|
||||
1. Under "Workflow runs", click the name of the run you want to see.
|
||||

|
||||
1. Under **Jobs** or in the visualization graph, click the job you want to see.
|
||||

|
||||
1. View the results of each step.
|
||||

|
||||
{% 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 %}
|
||||
|
||||
205
content/actions/using-workflows/about-workflows.md
Normal 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)."
|
||||
|
||||

|
||||
|
||||
## 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)."
|
||||
@@ -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**.
|
||||

|
||||
1. Under the name of the starter workflow you'd like to use, click **Set up this workflow**.
|
||||

|
||||
|
||||
## 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)."
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)."
|
||||
|
||||
|
||||
@@ -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 %}{% else %}{% 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**.
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||

|
||||
{% 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 %}
|
||||
@@ -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 %}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||

|
||||
5. Select **Allow creation of accounts with built-in authentication**.
|
||||

|
||||
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)"
|
||||
@@ -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)."
|
||||
@@ -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**.
|
||||

|
||||
{% data reusables.enterprise_management_console.save-settings %}
|
||||
@@ -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
|
||||
---
|
||||
|
||||
@@ -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 don’t 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**.
|
||||

|
||||
|
||||
{% 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**.
|
||||

|
||||
{% 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)"
|
||||
@@ -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**.
|
||||

|
||||
4. {% data reusables.enterprise_user_management.built-in-authentication-option %} 
|
||||
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.
|
||||
@@ -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**.
|
||||

|
||||
4. {% data reusables.enterprise_user_management.built-in-authentication-option %} 
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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** .
|
||||
|
||||

|
||||
|
||||
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**.
|
||||

|
||||
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 doesn’t exist, click **Create** to provision the new user account.
|
||||

|
||||
|
||||
## 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.
|
||||

|
||||
|
||||
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)".
|
||||
@@ -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**.
|
||||
|
||||

|
||||
1. {% data reusables.enterprise_user_management.built-in-authentication-option %}
|
||||
|
||||

|
||||
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.
|
||||
|
||||

|
||||
|
||||
{% 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 %}.
|
||||
|
||||

|
||||
{%- 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)."
|
||||
|
||||

|
||||
{%- 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/).
|
||||
|
||||

|
||||
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 %}.
|
||||
|
||||

|
||||
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.
|
||||
|
||||

|
||||
1. Under **Verification certificate**, click **Choose File** and choose a certificate to validate SAML responses from the IdP.
|
||||
|
||||

|
||||
1. Modify the SAML attribute names to match your IdP if needed, or accept the default names.
|
||||
|
||||

|
||||
|
||||
{% 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**.
|
||||
|
||||

|
||||
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.
|
||||
|
||||

|
||||
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.
|
||||
|
||||

|
||||
1. To the right of "Key Transport Method", select the key transport method for your IdP from step 9.
|
||||
|
||||

|
||||
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**.
|
||||

|
||||
3. In the list of users, click the username you'd like to update the `NameID` mapping for.
|
||||

|
||||
{% data reusables.enterprise_site_admin_settings.security-tab %}
|
||||
5. To the right of "Update SAML NameID", click **Edit** .
|
||||

|
||||
6. In the "NameID" field, type the new `NameID` for the user.
|
||||

|
||||
7. Click **Update NameID**.
|
||||

|
||||
|
||||
## 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**.
|
||||
|
||||

|
||||
|
||||
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**.
|
||||
|
||||

|
||||
|
||||
### 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>
|
||||
```
|
||||
@@ -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 %}
|
||||