From 929818065a8545476e4cf8e2cab6517f40345ef0 Mon Sep 17 00:00:00 2001 From: dndirangu Date: Mon, 14 Nov 2022 04:59:47 +0100 Subject: [PATCH 01/11] Update using-labels-with-self-hosted-runners.md (#32503) Co-authored-by: Lucas Costi --- .../using-labels-with-self-hosted-runners.md | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/content/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners.md b/content/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners.md index c984702305..d1bfec7c63 100644 --- a/content/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners.md +++ b/content/actions/hosting-your-own-runners/using-labels-with-self-hosted-runners.md @@ -66,24 +66,35 @@ The custom label is created and assigned to the self-hosted runner. Custom label 1. Click on the assigned label to remove it from your self-hosted runner. {% data reusables.actions.actions-unused-labels %} {% endif %} -## Using the configuration script to create and assign labels +## Programmatically assign labels -You can use the configuration script on the self-hosted runner to create and assign custom labels. For example, this command assigns a label named `gpu` to the self-hosted runner. +You can programmatically assign labels to a self-hosted runner after the runner is created, or during its initial configuration. -```shell -./config.sh --labels gpu -``` +* To programmatically assign labels to an existing self-hosted runner, you must use the REST API. For more information, see the "[Self-hosted runners](/rest/actions/self-hosted-runners)" REST API. +* To programmatically assign labels to a self-hosted runner during the initial runner configuration, you can pass label names to the `config` script using the `labels` parameter. -The label is created if it does not already exist. You can also use this approach to assign the default labels to runners, such as `x64` or `linux`. When default labels are assigned using the configuration script, {% data variables.product.prodname_actions %} accepts them as given and does not validate that the runner is actually using that operating system or architecture. + {% note %} + + **Note:** You cannot use the `config` script to assign labels to an existing self-hosted runner. + + {% endnote %} -You can use comma separation to assign multiple labels. For example: + For example, this command assigns a label named `gpu` when configuring a new self-hosted runner: -```shell -./config.sh --labels gpu,x64,linux -``` + ``` + ./config.sh --url --token --labels gpu + ``` -{% note %} + The label is created if it does not already exist. You can also use this approach to assign the default labels to runners, such as `x64` or `linux`. When default labels are assigned using the configuration script, {% data variables.product.prodname_actions %} accepts them as given and does not validate that the runner is actually using that operating system or architecture. -** Note:** If you replace an existing runner, then you must reassign any custom labels. + You can use comma separation to assign multiple labels. For example: -{% endnote %} + ``` + ./config.sh --url --token --labels gpu,x64,linux + ``` + + {% note %} + + ** Note:** If you replace an existing runner, then you must reassign any custom labels. + + {% endnote %} From 4822d41e01a2c28f4627529237257130272ef7c1 Mon Sep 17 00:00:00 2001 From: Evan Bonsignori Date: Sun, 13 Nov 2022 23:35:07 -0800 Subject: [PATCH 02/11] check version for release notes (#32461) --- middleware/contextualizers/ghae-release-notes.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/middleware/contextualizers/ghae-release-notes.js b/middleware/contextualizers/ghae-release-notes.js index 091e4a4d80..25ea905070 100644 --- a/middleware/contextualizers/ghae-release-notes.js +++ b/middleware/contextualizers/ghae-release-notes.js @@ -1,9 +1,13 @@ import { formatReleases, renderPatchNotes } from '../../lib/release-notes-utils.js' +import { allVersions } from '../../lib/all-versions.js' export default async function ghaeReleaseNotesContext(req, res, next) { if (!(req.pagePath.endsWith('/release-notes') || req.pagePath.endsWith('/admin'))) return next() - const requestedPlan = req.context.currentVersion.split('@')[0] - if (requestedPlan !== 'github-ae') return next() + if ( + !allVersions[req.context.currentVersion] || + req.context.currentVersion.split('@')[0] !== 'github-ae' + ) + return next() const ghaeReleaseNotes = req.context.site.data['release-notes']['github-ae'] // internalLatestRelease is set in lib/all-versions, e.g., '3.5' but UI still displays '@latest'. From 401d9696a6007f6842c1542c5490b7415cd33d87 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Mon, 14 Nov 2022 13:34:21 +0100 Subject: [PATCH 03/11] use /api/search/v1 in Search.tsx (#31952) --- components/Search.tsx | 106 +++++++++++++++++++++++------------- data/ui.yml | 1 + middleware/api/search.js | 12 +++- tests/browser/browser.js | 4 +- tests/content/api-search.js | 30 ++++++++++ 5 files changed, 109 insertions(+), 44 deletions(-) diff --git a/components/Search.tsx b/components/Search.tsx index 13bd9e5aad..a314389df4 100644 --- a/components/Search.tsx +++ b/components/Search.tsx @@ -16,24 +16,33 @@ import { Link } from 'components/Link' import styles from './Search.module.scss' -// The search endpoint used prior to using /api/search/legacy was -// just /search, which used middleware/search.js. We are leaving that -// middleware in tact to allow folks that previously used the /search -// endpoint to continue doing so. But, we changed the endpoint used by -// the search input on docs.github.com to use the new /api/search/legacy -// endpoint. -// Eventually, we will deprecate the /search and /api/search/legacy -// endpoints and use the /api/search/v1 endpoint, which has -// a different response JSON format. -const SEARCH_API_ENDPOINT = '/api/search/legacy' +const SEARCH_API_ENDPOINT = '/api/search/v1' -type SearchResult = { +type Hit = { + id: string url: string - breadcrumbs: string title: string - content: string - score: number - popularity: number + breadcrumbs: string + highlights: { + title: Array + content: Array + } + score?: number + popularity?: number + es_url?: string +} + +// Note, the JSON will contain other keys too, but since we don't use +// them in this component, we don't need to specify them. +type Meta = { + found: { + value: number + } +} + +type Data = { + hits: Hit[] + meta: Meta } type Props = { @@ -73,10 +82,14 @@ export function Search({ language, version, query, + // In its current state, can't with confidence know if the user + // initiated a search because of the input debounce or if the + // user has finished typing. + autocomplete: 'true', })}` : null - const { data: results, error: searchError } = useSWR( + const { data, error: searchError } = useSWR( fetchURL, async (url: string) => { const response = await fetch(url) @@ -102,14 +115,14 @@ export function Search({ } ) - const [previousResults, setPreviousResults] = useState() + const [previousData, setPreviousData] = useState() useEffect(() => { - if (results) { - setPreviousResults(results) + if (data) { + setPreviousData(data) } else if (!query) { - setPreviousResults(undefined) + setPreviousData(undefined) } - }, [results, query]) + }, [data, query]) // The `isLoading` boolean will become false every time the useSWR hook // fires off a new XHR. So it toggles from false/true often. @@ -124,7 +137,7 @@ export function Search({ // mean saying "Loading..." is a lie! // That's why we combine them into a final one. We're basically doing // this to favor *NOT* saying "Loading...". - const isLoadingRaw = Boolean(query && !results && !searchError) + const isLoadingRaw = Boolean(query && !data && !searchError) const [isLoadingDebounced] = useDebounce(isLoadingRaw, 500) const isLoading = isLoadingRaw && isLoadingDebounced @@ -216,7 +229,7 @@ export function Search({ isHeaderSearch={isHeaderSearch} isMobileSearch={isMobileSearch} isLoading={isLoading} - results={previousResults} + results={previousData} closeSearch={closeSearch} debug={debug} query={query} @@ -342,7 +355,7 @@ function ShowSearchResults({ isHeaderSearch: boolean isMobileSearch: boolean isLoading: boolean - results: SearchResult[] | undefined + results: Data | undefined closeSearch: () => void debug: boolean query: string @@ -461,11 +474,33 @@ function ShowSearchResults({ {t('search_results_for')}: {query}

- {t('matches_displayed')}: {results.length === 0 ? t('no_results') : results.length} + {results.meta.found.value === 0 ? ( + t('no_results') + ) : ( + + {t('matches_found')}: {results.meta.found.value.toLocaleString()} + + )} + .{' '} + {results.meta.found.value > results.hits.length && ( + + {t('matches_displayed')}:{' '} + {results.meta.found.value === 0 ? t('no_results') : results.hits.length} + + )}

- {results.map(({ url, breadcrumbs, title, content, score, popularity }, index) => { + {results.hits.map((hit, index) => { + const { url, breadcrumbs, title, highlights, score, popularity } = hit + + const contentHTML = + highlights.content && highlights.content.length > 0 + ? highlights.content.join('
') + : '' + const titleHTML = + highlights.title && highlights.title.length > 0 ? highlights.title[0] : title + return (
- {/* Breadcrumbs in search records don't include the page title. These fields may contain elements that we need to render */} - {debug && ( + {debug && score !== undefined && popularity !== undefined && ( score: {score.toFixed(4)} popularity: {popularity.toFixed(4)} @@ -505,13 +533,13 @@ function ShowSearchResults({

{ validate: (v) => v >= 1 && v <= 10, }, { key: 'sort', default_: DEFAULT_SORT, validate: (v) => POSSIBLE_SORTS.includes(v) }, - { key: 'debug', default_: Boolean(process.env.NODE_ENV === 'development' || req.query.debug) }, + { key: 'autocomplete', default_: false, cast: toBoolean }, + { key: 'debug', default_: process.env.NODE_ENV === 'development', cast: toBoolean }, ] const search = {} @@ -221,11 +222,16 @@ const validationMiddleware = (req, res, next) => { return next() } +function toBoolean(value) { + if (value === 'true' || value === '1') return true + return false +} + router.get( '/v1', validationMiddleware, catchMiddlewareError(async function search(req, res) { - const { indexName, query, page, size, debug, sort } = req.search + const { indexName, query, autocomplete, page, size, debug, sort } = req.search // The getSearchResults() function is a mix of preparing the search, // sending & receiving it, and post-processing the response from the @@ -236,7 +242,7 @@ router.get( const tags = ['version:v1', `indexName:${indexName}`] const timed = statsd.asyncTimer(getSearchResults, 'api.search', tags) - const options = { indexName, query, page, size, debug, sort } + const options = { indexName, query, page, size, debug, sort, usePrefixSearch: autocomplete } try { const { meta, hits } = await timed(options) diff --git a/tests/browser/browser.js b/tests/browser/browser.js index 1e04bfd9ae..4fd81dfbe3 100644 --- a/tests/browser/browser.js +++ b/tests/browser/browser.js @@ -91,7 +91,7 @@ describe('browser search', () => { newPage.on('request', (interceptedRequest) => { if ( interceptedRequest.method() === 'GET' && - /api\/search\/legacy\?/i.test(interceptedRequest.url()) + /api\/search\/v1\?/i.test(interceptedRequest.url()) ) { const { searchParams } = new URL(interceptedRequest.url()) expect(searchParams.get('version')).toBe('dotcom') @@ -119,7 +119,7 @@ describe('browser search', () => { newPage.on('request', (interceptedRequest) => { if ( interceptedRequest.method() === 'GET' && - /api\/search\/legacy\?/i.test(interceptedRequest.url()) + /api\/search\/v1\?/i.test(interceptedRequest.url()) ) { const { searchParams } = new URL(interceptedRequest.url()) expect(searchParams.get('version')).toBe('ghae') diff --git a/tests/content/api-search.js b/tests/content/api-search.js index 73c60783a7..cfe8870016 100644 --- a/tests/content/api-search.js +++ b/tests/content/api-search.js @@ -83,6 +83,36 @@ describeIfElasticsearchURL('search v1 middleware', () => { expect(hit.es_url).toBeTruthy() }) + test('search with and without autocomplete on', async () => { + // *Without* autocomplete=true + { + const sp = new URLSearchParams() + sp.set('query', 'sill') + const res = await get('/api/search/v1?' + sp) + expect(res.statusCode).toBe(200) + const results = JSON.parse(res.text) + // Fixtures contains no word called 'sill'. It does contain the term + // 'silly' which, in English, becomes 'silli` when stemmed. + // Because we don't use `&autocomplete=true` this time, we expect + // to find nothing. + expect(results.meta.found.value).toBe(0) + } + + // *With* autocomplete=true + { + const sp = new URLSearchParams() + sp.set('query', 'sill') + sp.set('autocomplete', 'true') + const res = await get('/api/search/v1?' + sp) + expect(res.statusCode).toBe(200) + const results = JSON.parse(res.text) + expect(results.meta.found.value).toBeGreaterThanOrEqual(1) + const hit = results.hits[0] + const contentHighlights = hit.highlights.content + expect(contentHighlights[0]).toMatch('silly') + } + }) + test('find nothing', async () => { const sp = new URLSearchParams() sp.set('query', 'xojixjoiwejhfoiuwehjfioweufhj') From 2f665145716dbbb6174b5ef8fa72513ac38de99d Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Mon, 14 Nov 2022 13:46:36 +0100 Subject: [PATCH 04/11] make highlighting fields configurable (#32328) --- middleware/api/es-search.js | 76 ++++++++++++------- middleware/api/search.js | 32 +++++++- tests/content/api-search.js | 44 +++++++++++ .../github-docs-dotcom-en-records.json | 6 +- 4 files changed, 126 insertions(+), 32 deletions(-) diff --git a/middleware/api/es-search.js b/middleware/api/es-search.js index c6129a97ce..928b9ac7cb 100644 --- a/middleware/api/es-search.js +++ b/middleware/api/es-search.js @@ -1,5 +1,8 @@ import { Client } from '@elastic/elasticsearch' +export const POSSIBLE_HIGHLIGHT_FIELDS = ['title', 'content', 'headings'] +export const DEFAULT_HIGHLIGHT_FIELDS = ['title', 'content'] + const ELASTICSEARCH_URL = process.env.ELASTICSEARCH_URL const isDevMode = process.env.NODE_ENV !== 'production' @@ -37,6 +40,7 @@ export async function getSearchResults({ topics, includeTopics, usePrefixSearch, + highlights, }) { if (topics && !Array.isArray(topics)) { throw new Error("'topics' has to be an array") @@ -72,7 +76,8 @@ export async function getSearchResults({ matchQuery.bool.filter = topicsFilter } - const highlight = getHighlightConfiguration(query) + const highlightFields = highlights || DEFAULT_HIGHLIGHT_FIELDS + const highlight = getHighlightConfiguration(query, highlightFields) const searchQuery = { highlight, @@ -141,7 +146,7 @@ export async function getSearchResults({ // const hitsAll = result.hits // ES >7.11 const hitsAll = result.body // ES <=7.11 - const hits = getHits(hitsAll.hits.hits, { indexName, debug, includeTopics }) + const hits = getHits(hitsAll.hits.hits, { indexName, debug, includeTopics, highlightFields }) const t1 = new Date() const meta = { @@ -345,14 +350,26 @@ function getMatchQueries(query, { usePrefixSearch, fuzzy }) { return matchQueries } -function getHits(hits, { indexName, debug, includeTopics }) { +function getHits(hits, { indexName, debug, includeTopics, highlightFields }) { return hits.map((hit) => { + // Return `hit.highlights[...]` based on the highlight fields requested. + // So if you searched with `&highlights=headings&highlights=content` + // this will become: + // { + // content: [...], + // headings: [...] + // } + // even if there was a match on 'title'. + const hitHighlights = Object.fromEntries( + highlightFields.map((key) => [key, (hit.highlight && hit.highlight[key]) || []]) + ) + const result = { id: hit._id, url: hit._source.url, title: hit._source.title, breadcrumbs: hit._source.breadcrumbs, - highlights: hit.highlight || {}, + highlights: hitHighlights, } if (includeTopics) { result.topics = hit._source.topics || [] @@ -374,31 +391,38 @@ function getHits(hits, { indexName, debug, includeTopics }) { // of highlights of content under each title. If we feel it shows too // many highlights in the search result UI, we can come back here // and change it to something more appropriate. -function getHighlightConfiguration(query) { - return { - pre_tags: [''], - post_tags: [''], - fields: { - title: { - fragment_size: 200, - number_of_fragments: 1, - }, - headings: { fragment_size: 150, number_of_fragments: 2 }, - // The 'no_match_size' is so we can display *something* for the - // preview if there was no highlight match at all within the content. - content: { - fragment_size: 150, - number_of_fragments: 3, - no_match_size: 150, +function getHighlightConfiguration(query, highlights) { + const fields = {} + if (highlights.includes('title')) { + fields.title = { + fragment_size: 200, + number_of_fragments: 1, + } + } + if (highlights.includes('headings')) { + fields.headings = { fragment_size: 150, number_of_fragments: 2 } + } + if (highlights.includes('content')) { + // The 'no_match_size' is so we can display *something* for the + // preview if there was no highlight match at all within the content. + fields.content = { + fragment_size: 150, + number_of_fragments: 3, + no_match_size: 150, - highlight_query: { - match_phrase_prefix: { - content: { - query, - }, + highlight_query: { + match_phrase_prefix: { + content: { + query, }, }, }, - }, + } + } + + return { + pre_tags: [''], + post_tags: [''], + fields, } } diff --git a/middleware/api/search.js b/middleware/api/search.js index 716dee9e06..c0cfdb2c21 100644 --- a/middleware/api/search.js +++ b/middleware/api/search.js @@ -7,7 +7,11 @@ import { allVersions } from '../../lib/all-versions.js' import statsd from '../../lib/statsd.js' import { defaultCacheControl } from '../cache-control.js' import catchMiddlewareError from '../catch-middleware-error.js' -import { getSearchResults } from './es-search.js' +import { + getSearchResults, + POSSIBLE_HIGHLIGHT_FIELDS, + DEFAULT_HIGHLIGHT_FIELDS, +} from './es-search.js' // Used by the legacy search const versions = new Set(Object.values(searchVersions)) @@ -182,6 +186,19 @@ const validationMiddleware = (req, res, next) => { validate: (v) => v >= 1 && v <= 10, }, { key: 'sort', default_: DEFAULT_SORT, validate: (v) => POSSIBLE_SORTS.includes(v) }, + { + key: 'highlights', + default_: DEFAULT_HIGHLIGHT_FIELDS, + cast: (v) => (Array.isArray(v) ? v : [v]), + validate: (v) => { + for (const highlight of v) { + if (!POSSIBLE_HIGHLIGHT_FIELDS.includes(highlight)) { + throw new ValidationError(`highlight value '${highlight}' is not valid`) + } + } + return true + }, + }, { key: 'autocomplete', default_: false, cast: toBoolean }, { key: 'debug', default_: process.env.NODE_ENV === 'development', cast: toBoolean }, ] @@ -231,7 +248,7 @@ router.get( '/v1', validationMiddleware, catchMiddlewareError(async function search(req, res) { - const { indexName, query, autocomplete, page, size, debug, sort } = req.search + const { indexName, query, autocomplete, page, size, debug, sort, highlights } = req.search // The getSearchResults() function is a mix of preparing the search, // sending & receiving it, and post-processing the response from the @@ -242,7 +259,16 @@ router.get( const tags = ['version:v1', `indexName:${indexName}`] const timed = statsd.asyncTimer(getSearchResults, 'api.search', tags) - const options = { indexName, query, page, size, debug, sort, usePrefixSearch: autocomplete } + const options = { + indexName, + query, + page, + size, + debug, + sort, + highlights, + usePrefixSearch: autocomplete, + } try { const { meta, hits } = await timed(options) diff --git a/tests/content/api-search.js b/tests/content/api-search.js index cfe8870016..1b12e40a70 100644 --- a/tests/content/api-search.js +++ b/tests/content/api-search.js @@ -57,8 +57,11 @@ describeIfElasticsearchURL('search v1 middleware', () => { expect(hit.url).toBe('/en/foo') expect(hit.title).toBe('Foo') expect(hit.breadcrumbs).toBe('fooing') + // By default, 'title' and 'content' is included in highlights, + // but not 'headings' expect(hit.highlights.title[0]).toBe('Foo') expect(hit.highlights.content[0]).toMatch('foo') + expect(hit.highlights.headings).toBeUndefined() // Check that it can be cached at the CDN expect(res.headers['set-cookie']).toBeUndefined() @@ -123,6 +126,38 @@ describeIfElasticsearchURL('search v1 middleware', () => { expect(results.meta.found.value).toBe(0) }) + test('configurable highlights', async () => { + const sp = new URLSearchParams() + sp.set('query', 'introduction heading') + sp.append('highlights', 'headings') + sp.append('highlights', 'content') + const res = await get('/api/search/v1?' + sp) + expect(res.statusCode).toBe(200) + const results = JSON.parse(res.text) + expect(results.meta.found.value).toBeGreaterThanOrEqual(1) + for (const hit of results.hits) { + expect(hit.highlights.title).toBeFalsy() + expect(hit.highlights.headings).toBeTruthy() + expect(hit.highlights.content).toBeTruthy() + } + }) + + test('highlights keys matches highlights configuration', async () => { + const sp = new URLSearchParams() + // This will match because it's in the 'content' but not in 'headings' + sp.set('query', 'Fact of life') + sp.set('highlights', 'headings') + const res = await get('/api/search/v1?' + sp) + expect(res.statusCode).toBe(200) + const results = JSON.parse(res.text) + expect(results.meta.found.value).toBeGreaterThanOrEqual(1) + for (const hit of results.hits) { + expect(hit.highlights.headings).toBeTruthy() + expect(hit.highlights.title).toBeFalsy() + expect(hit.highlights.content).toBeFalsy() + } + }) + test('version can be aliased', async () => { const sp = new URLSearchParams() sp.set('query', 'foo') @@ -199,6 +234,15 @@ describeIfElasticsearchURL('search v1 middleware', () => { expect(res.statusCode).toBe(400) expect(JSON.parse(res.text).error).toMatch('sort') } + // unrecognized highlights + { + const sp = new URLSearchParams() + sp.set('query', 'test') + sp.set('highlights', 'neverheardof') + const res = await get('/api/search/v1?' + sp) + expect(res.statusCode).toBe(400) + expect(JSON.parse(res.text).error).toMatch('neverheardof') + } }) test('breadcrumbless records should always return a string', async () => { diff --git a/tests/content/fixtures/search-indexes/github-docs-dotcom-en-records.json b/tests/content/fixtures/search-indexes/github-docs-dotcom-en-records.json index 95aee65198..b7e4f4d245 100644 --- a/tests/content/fixtures/search-indexes/github-docs-dotcom-en-records.json +++ b/tests/content/fixtures/search-indexes/github-docs-dotcom-en-records.json @@ -3,7 +3,7 @@ "objectID": "/en/foo", "breadcrumbs": "fooing", "title": "Foo", - "headings": "", + "headings": "Heading 1", "content": "This is a fixture with the silly foo word.", "topics": ["Test", "Fixture"], "popularity": 0.5 @@ -12,7 +12,7 @@ "objectID": "/en/bar", "breadcrumbs": "baring", "title": "Bar", - "headings": "", + "headings": "Sub-heading This Sub-heading That", "content": "Can't have foo if you don't also have bar.", "topics": ["Test", "Fixture", "Get started"], "popularity": 0.6 @@ -21,7 +21,7 @@ "objectID": "/en/bar", "breadcrumbs": "", "title": "Breadcrumbless", - "headings": "", + "headings": "Introduction", "content": "Not all pages have a breadcrumb. Fact of life.", "topics": [], "popularity": 0.1 From 1f72b9239fa81e722c7eabb873701e91ef6cb336 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Mon, 14 Nov 2022 15:15:44 +0100 Subject: [PATCH 05/11] unbreak sync-search-pr.yml Action (#32573) --- .github/workflows/sync-search-pr.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/sync-search-pr.yml b/.github/workflows/sync-search-pr.yml index 4a02acb756..0e5d3c6111 100644 --- a/.github/workflows/sync-search-pr.yml +++ b/.github/workflows/sync-search-pr.yml @@ -95,10 +95,9 @@ jobs: run: | mkdir /tmp/records - npm run sync-search-indices -- \ + npm run sync-search-indices -- /tmp/records \ --language en \ - --version dotcom \ - /tmp/records + --version dotcom ls -lh /tmp/records @@ -108,10 +107,9 @@ jobs: - name: Index into Elasticsearch run: | - ./script/search/index-elasticsearch.js \ + ./script/search/index-elasticsearch.js /tmp/records \ --language en \ - --version dotcom \ - /tmp/records + --version dotcom - name: Check created indexes and aliases run: | From f7ee79727dee0991653e9b889d33ebd7d831e40d Mon Sep 17 00:00:00 2001 From: Anne-Marie <102995847+am-stead@users.noreply.github.com> Date: Mon, 14 Nov 2022 15:46:01 +0100 Subject: [PATCH 06/11] [2022-11-14]: Dependency Review Action #7739 (#32208) Co-authored-by: Courtney Claessens --- .../about-dependency-review.md | 2 - .../configuring-dependency-review.md | 166 ++++++++++++++---- ...ependency-review-action-fail-on-scopes.yml | 7 + 3 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 data/features/dependency-review-action-fail-on-scopes.yml diff --git a/content/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review.md b/content/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review.md index 3e83d7902b..914c982ece 100644 --- a/content/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review.md +++ b/content/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review.md @@ -46,8 +46,6 @@ The dependency review feature becomes available when you enable the dependency g {% ifversion fpt or ghec or ghes > 3.5 or ghae > 3.5 %} ## Dependency review enforcement -{% data reusables.dependency-review.dependency-review-action-beta-note %} - The action is available for all {% ifversion fpt or ghec %}public repositories, as well as private {% endif %}repositories that have {% data variables.product.prodname_GH_advanced_security %} enabled. {% data reusables.dependency-review.action-enterprise %} diff --git a/content/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-dependency-review.md b/content/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-dependency-review.md index 460c0bb236..0f6307553b 100644 --- a/content/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-dependency-review.md +++ b/content/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-dependency-review.md @@ -1,6 +1,7 @@ --- title: Configuring dependency review intro: You can use dependency review to catch vulnerabilities before they are added to your project. +miniTocMaxHeadingLevel: 3 shortTitle: Configure dependency review versions: fpt: '*' @@ -50,9 +51,8 @@ Dependency review is available when dependency graph is enabled for {% data vari {% endif %} {% ifversion dependency-review-action-configuration %} -## Configuring the {% data variables.product.prodname_dependency_review_action %} +## About configuring the {% data variables.product.prodname_dependency_review_action %} -{% data reusables.dependency-review.dependency-review-action-beta-note %} {% data reusables.dependency-review.dependency-review-action-overview %} The following configuration options are available. @@ -63,7 +63,11 @@ The following configuration options are available. {%- ifversion dependency-review-action-licenses %} | `allow-licenses` | Optional | Contains a list of allowed licenses. You can find the possible values for this parameter in the [Licenses](/rest/licenses) page of the API documentation.
The action will fail on pull requests that introduce dependencies with licenses that do not match the list.|{% endif %} {%- ifversion dependency-review-action-licenses %} -| `deny-licenses` | Optional | Contains a list of prohibited licenses. You can find the possible values for this parameter in the [Licenses](/rest/licenses) page of the API documentation.
The action will fail on pull requests that introduce dependencies with licenses that match the list.|{% endif %} +| `deny-licenses` | Optional | Contains a list of prohibited licenses. You can find the possible values for this parameter in the [Licenses](/rest/licenses) page of the API documentation.
The action will fail on pull requests that introduce dependencies with licenses that match the list.|{% endif %}{% ifversion dependency-review-action-fail-on-scopes %} +| `fail-on-scopes` | Optional | Contains a list of strings representing the build environments you want to support (`development`, `runtime`, `unknown`).
The action will fail on pull requests that introduce vulnerabilites in the scopes that match the list.|{% endif %} +| `allow-ghsas` | Optional | Contains a list of {% data variables.product.prodname_advisory_database %} IDs that can be skipped during detection. You can find the possible values for this parameter in the [{% data variables.product.prodname_advisory_database %}](https://github.com/advisories). | +| `config-file` | Optional | Specifies a path to a configuration file. The configuration file can be local to the repository or a file located in an external repository.| +| `external-repo-token` | Optional | Specifies a token for fetching the configuration file, if the file resides in a private external repository. The token must have read access to the repository.| {% ifversion dependency-review-action-licenses %} {% tip %} @@ -73,37 +77,139 @@ The following configuration options are available. {% endtip %} {% endif %} -This {% data variables.product.prodname_dependency_review_action %} example file illustrates how you can use these configuration options. Notice that the example uses short version number for the action (`v2`) instead of a semver release number (for example, `v2.0.8`). This ensures that you use the most recent minor version of the action. +## Configuring the {% data variables.product.prodname_dependency_review_action %} -```yaml{:copy} -name: 'Dependency Review' -on: [pull_request] +There are two methods of configuring the {% data variables.product.prodname_dependency_review_action %}: +- Inlining the configuration options in your workflow file. +- Referencing a configuration file in your workflow file. -permissions: - contents: read +Notice that all of the examples use a short version number for the action (`v3`) instead of a semver release number (for example, `v3.0.8`). This ensures that you use the most recent minor version of the action. +### Using inline configuration to set up the {% data variables.product.prodname_dependency_review_action %} -jobs: - dependency-review: - runs-on: ubuntu-latest - steps: - - name: 'Checkout Repository' - uses: {% data reusables.actions.action-checkout %} - - name: Dependency Review - uses: actions/dependency-review-action@v2 - with: - # Possible values: "critical", "high", "moderate", "low" - fail-on-severity: critical -{% ifversion dependency-review-action-licenses %} - # You can only can only include one of these two options: `allow-licenses` and `deny-licences` - # ([String]). Only allow these licenses (optional) - # Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses - # allow-licenses: GPL-3.0, BSD-3-Clause, MIT +1. Add a new YAML workflow to your `.github/workflows` folder. + + {% ifversion ghes %}For `runs-on`, the default label is `self-hosted`. You can replace the default label with the label of any of your runners.{% endif %} + ```yaml{:copy} + name: 'Dependency Review' + on: [pull_request] - # ([String]). Block the pull request on these licenses (optional) - # Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses - # deny-licenses: LGPL-2.0, BSD-2-Clause -{% endif %} -``` + permissions: + contents: read + jobs: + dependency-review: + {% ifversion ghes %}runs-on: self-hosted + {% else %}runs-on: ubuntu-latest + {% endif %}steps: + - name: 'Checkout Repository' + uses: {% data reusables.actions.action-checkout %} + - name: Dependency Review + uses: actions/dependency-review-action@v3 + ``` +1. Specify your settings. + + This {% data variables.product.prodname_dependency_review_action %} example file illustrates how you can use the available configuration options. + ```yaml{:copy} + name: 'Dependency Review' + on: [pull_request] + + permissions: + contents: read + + jobs: + dependency-review: + {% ifversion ghes %}runs-on: self-hosted + {% else %}runs-on: ubuntu-latest + {% endif %}steps: + - name: 'Checkout Repository' + uses: {% data reusables.actions.action-checkout %} + - name: Dependency Review + uses: actions/dependency-review-action@v3 + with: + # Possible values: "critical", "high", "moderate", "low" + fail-on-severity: critical + {% ifversion dependency-review-action-licenses %} + # You can only include one of these two options: `allow-licenses` and `deny-licences` + # ([String]). Only allow these licenses (optional) + # Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses + allow-licenses: GPL-3.0, BSD-3-Clause, MIT + # ([String]). Block the pull request on these licenses (optional) + # Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses + deny-licenses: LGPL-2.0, BSD-2-Clause + {% endif %} + # ([String]). Skip these {% data variables.product.prodname_advisory_database %} IDs during detection (optional) + # Possible values: Any valid {% data variables.product.prodname_advisory_database %} ID from https://github.com/advisories + allow-ghsas: GHSA-abcd-1234-5679, GHSA-efgh-1234-5679 + {% ifversion dependency-review-action-fail-on-scopes %} + # ([String]). Block pull requests that introduce vulnerabilities in the scopes that match this list (optional) + # Possible values: "development", "runtime", "unknown" + fail-on-scopes: development, runtime + {% endif %} + ``` +### Using a configuration file to set up {% data variables.product.prodname_dependency_review_action %} + +1. Add a new YAML workflow to your `.github/workflows` folder and use `config-file` to specify that you are using a configuration file. + + {% ifversion ghes %}For `runs-on`, the default label is `self-hosted`. You can replace the default label with the label of any of your runners.{% endif %} + ```yaml{:copy} + name: 'Dependency Review' + on: [pull_request] + + permissions: + contents: read + + jobs: + dependency-review: + {% ifversion ghes %}runs-on: self-hosted + {% else %}runs-on: ubuntu-latest + {% endif %}steps: + - name: 'Checkout Repository' + uses: {% data reusables.actions.action-checkout %} + - name: Dependency Review + uses: actions/dependency-review-action@v3 + with: + # ([String]). Representing a path to a configuration file local to the repository or in an external repository. + # Possible values: An absolute path to a local file or an external file. + config-file: './.github/dependency-review-config.yml' + # Syntax for an external file: OWNER/REPOSITORY/FILENAME@BRANCH + config-file: 'github/octorepo/dependency-review-config.yml@main' + + # ([Token]) Use if your configuration file resides in a private external repository. + # Possible values: Any GitHub token with read access to the private external repository. + external-repo-token: 'ghp_123456789abcde' + ``` +1. Create the configuration file in the path you have specified. + + This YAML example file illustrates how you can use the available configuration options. + ```yaml{:copy} + # Possible values: "critical", "high", "moderate", "low" + fail-on-severity: critical + {% ifversion dependency-review-action-licenses %} + # You can only include one of these two options: `allow-licenses` and `deny-licences` + # ([String]). Only allow these licenses (optional) + # Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses + allow-licenses: + - GPL-3.0 + - BSD-3-Clause + - MIT + # ([String]). Block the pull request on these licenses (optional) + # Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses + deny-licenses: + - LGPL-2.0 + - BSD-2-Clause + {% endif %} + # ([String]). Skip these {% data variables.product.prodname_advisory_database %} IDs during detection (optional) + # Possible values: Any valid {% data variables.product.prodname_advisory_database %} ID from https://github.com/advisories + allow-ghsas: + - GHSA-abcd-1234-5679 + - GHSA-efgh-1234-5679 + {% ifversion dependency-review-action-fail-on-scopes %} + # ([String]). Block pull requests that introduce vulnerabilities in the scopes that match this list (optional) + # Possible values: "development", "runtime", "unknown" + fail-on-scopes: + - development + - runtime + {% endif %} + ``` For further details about the configuration options, see [`dependency-review-action`](https://github.com/actions/dependency-review-action#readme). {% endif %} diff --git a/data/features/dependency-review-action-fail-on-scopes.yml b/data/features/dependency-review-action-fail-on-scopes.yml new file mode 100644 index 0000000000..032f7da8ab --- /dev/null +++ b/data/features/dependency-review-action-fail-on-scopes.yml @@ -0,0 +1,7 @@ +# Reference: Issue #7739 - Dependency review action, new config option "fail-on-scopes" added. + +versions: + fpt: '*' + ghec: '*' + ghes: '> 3.8' + ghae: '> 3.8' From d497bd6f9c921059e67dde2fa465b4f00df1fcb9 Mon Sep 17 00:00:00 2001 From: Courtney Claessens Date: Mon, 14 Nov 2022 09:54:58 -0500 Subject: [PATCH 07/11] [2022-11-10]: Remove beta label for dependency review API (#32477) Co-authored-by: Anne-Marie <102995847+am-stead@users.noreply.github.com> --- content/rest/dependency-graph/dependency-review.md | 2 -- .../dependency-review/dependency-review-api-beta-note.md | 5 ----- 2 files changed, 7 deletions(-) delete mode 100644 data/reusables/dependency-review/dependency-review-api-beta-note.md diff --git a/content/rest/dependency-graph/dependency-review.md b/content/rest/dependency-graph/dependency-review.md index d81b7f4242..1adb43e127 100644 --- a/content/rest/dependency-graph/dependency-review.md +++ b/content/rest/dependency-graph/dependency-review.md @@ -14,6 +14,4 @@ allowTitleToDifferFromFilename: true ## About the Dependency review API -{% data reusables.dependency-review.dependency-review-api-beta-note %} - The Dependency Review API allows you to understand dependency changes, and the security impact of these changes, before you add them to your environment. You can view the diff of dependencies between two commits of a repository, including vulnerability data for any version updates with known vulnerabilities. For more information about dependency review, see "[About dependency review](/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review)." diff --git a/data/reusables/dependency-review/dependency-review-api-beta-note.md b/data/reusables/dependency-review/dependency-review-api-beta-note.md deleted file mode 100644 index 73ee2bb66a..0000000000 --- a/data/reusables/dependency-review/dependency-review-api-beta-note.md +++ /dev/null @@ -1,5 +0,0 @@ -{% note %} - -**Note**: The Dependency Review API is currently in public beta and subject to change. - -{% endnote %} From 12c3b3be7a84ac64ef6d74fdf78e262d0d953514 Mon Sep 17 00:00:00 2001 From: literarytea Date: Mon, 14 Nov 2022 08:55:13 -0600 Subject: [PATCH 08/11] Update github-acceptable-use-policies.md (#31053) Co-authored-by: Matt Pollard --- .../acceptable-use-policies/github-acceptable-use-policies.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/site-policy/acceptable-use-policies/github-acceptable-use-policies.md b/content/site-policy/acceptable-use-policies/github-acceptable-use-policies.md index 6df64f63d2..324e167dbe 100644 --- a/content/site-policy/acceptable-use-policies/github-acceptable-use-policies.md +++ b/content/site-policy/acceptable-use-policies/github-acceptable-use-policies.md @@ -61,7 +61,8 @@ We do not allow content or activity on GitHub that is: * creation of or participation in secondary markets for the purpose of the proliferation of inauthentic activity; * using GitHub as a platform for propagating abuse on other platforms; * phishing or attempted phishing; or -* using our servers for any form of excessive automated bulk activity, to place undue burden on our servers through automated means, or to relay any form of unsolicited advertising or solicitation through our servers, such as get-rich-quick schemes. +* using our servers for any form of excessive automated bulk activity, to place undue burden on our servers through automated means, or to relay any form of unsolicited advertising or solicitation through our servers, such as get-rich-quick schemes; +* incentivized by (or incentivizes inauthentic engagement with) rewards such as cryptocurrency airdrops, tokens, credits, gifts or other give-aways. ## 5. Site Access and Safety We do not allow content or activity on GitHub that: From 0caa424a16bb586c39c8cea5f40ccbae2dc4ac45 Mon Sep 17 00:00:00 2001 From: Tugdual Grall Date: Mon, 14 Nov 2022 15:58:59 +0100 Subject: [PATCH 09/11] Documenting "Downgrading your organization's subscription" for ghec org (#32522) Co-authored-by: Lucas Costi Co-authored-by: Laura Coursen --- .../downgrading-your-github-subscription.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/content/billing/managing-billing-for-your-github-account/downgrading-your-github-subscription.md b/content/billing/managing-billing-for-your-github-account/downgrading-your-github-subscription.md index a78c974347..28bbd81e9b 100644 --- a/content/billing/managing-billing-for-your-github-account/downgrading-your-github-subscription.md +++ b/content/billing/managing-billing-for-your-github-account/downgrading-your-github-subscription.md @@ -54,9 +54,12 @@ If you downgrade your organization from {% data variables.product.prodname_team If you downgrade your organization from {% data variables.product.prodname_ghe_cloud %} to {% data variables.product.prodname_team %} or {% data variables.product.prodname_free_team %}, the account will lose access to advanced security, compliance, and deployment controls. {% data reusables.gated-features.more-info %} + {% note %} -**Note:** If you're currently trialing {% data variables.product.prodname_ghe_cloud %}, and you don't purchase {% data variables.product.prodname_enterprise %} before the trial ends, your organization will be automatically downgraded to {% data variables.product.prodname_free_team %} or {% data variables.product.prodname_team %}. For more information, see "[Setting up a trial of {% data variables.product.prodname_ghe_cloud %}](/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud#finishing-your-trial)." +**Notes:** + - If your organization is owned by an enterprise account, billing cannot be managed at the organization level. To downgrade, you must remove the organization from the enterprise account first. For more information, see "[Removing organizations from your enterprise](/enterprise-cloud@latest/admin/user-management/managing-organizations-in-your-enterprise/removing-organizations-from-your-enterprise)." + - If you're currently trialing {% data variables.product.prodname_ghe_cloud %}, and you don't purchase {% data variables.product.prodname_enterprise %} before the trial ends, your organization will be automatically downgraded to {% data variables.product.prodname_free_team %} or {% data variables.product.prodname_team %}. For more information, see "[Setting up a trial of {% data variables.product.prodname_ghe_cloud %}](/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud#finishing-your-trial)." {% endnote %} From 38a4ffb373f95f79543f1d34ec4bcd3debbf5bb1 Mon Sep 17 00:00:00 2001 From: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com> Date: Mon, 14 Nov 2022 15:33:06 +0000 Subject: [PATCH 10/11] Make placeholders more consistent in "Using GitHub Codespaces with GitHub CLI" (#32508) --- .../using-github-codespaces-with-github-cli.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/codespaces/developing-in-codespaces/using-github-codespaces-with-github-cli.md b/content/codespaces/developing-in-codespaces/using-github-codespaces-with-github-cli.md index 85469065f5..78bca1ff88 100644 --- a/content/codespaces/developing-in-codespaces/using-github-codespaces-with-github-cli.md +++ b/content/codespaces/developing-in-codespaces/using-github-codespaces-with-github-cli.md @@ -42,7 +42,7 @@ You can work with {% data variables.product.prodname_github_codespaces %} in the If you have not already done so, run `gh auth login` to authenticate with your {% data variables.product.prodname_dotcom %} account. -To use `gh` to work with {% data variables.product.prodname_github_codespaces %}, type `gh codespace ` or its alias `gh cs `. +To use `gh` to work with {% data variables.product.prodname_github_codespaces %}, type `gh codespace SUBCOMMAND` or its alias `gh cs SUBCOMMAND`. As an example of a series of commands you might use to work with {% data variables.product.prodname_github_codespaces %}, you could: @@ -51,15 +51,15 @@ As an example of a series of commands you might use to work with {% data variabl * Create a new codespace for the required repository branch:
`gh codespace create -r github/docs -b main` * SSH into the new codespace:
- `gh codespace ssh -c mona-github-docs-v4qxrv7rfwv9w` + `gh codespace ssh -c octocat-literate-space-parakeet-7gwrqp9q9jcx4vq` * Forward a port to your local machine:
- `gh codespace ports forward 8000:8000 -c mona-github-docs-v4qxrv7rfwv9w` + `gh codespace ports forward 8000:8000 -c octocat-literate-space-parakeet-7gwrqp9q9jcx4vq` ## `gh` commands for {% data variables.product.prodname_github_codespaces %} The sections below give example commands for each of the available operations. -For a complete reference of `gh` commands for {% data variables.product.prodname_github_codespaces %}, including details of all available options for each command, see the {% data variables.product.prodname_cli %} online help for "[gh codespace](https://cli.github.com/manual/gh_codespace)." Alternatively, use `gh codespace [...] --help` on the command line. +For a complete reference of `gh` commands for {% data variables.product.prodname_github_codespaces %}, including details of all available options for each command, see the {% data variables.product.prodname_cli %} online help for "[gh codespace](https://cli.github.com/manual/gh_codespace)." Alternatively, on the command line, use `gh codespace --help` for general help or `gh codespace SUBCOMMAND --help` for help with a specific subcommand. {% note %} @@ -163,7 +163,7 @@ The location of files and directories on the codespace is relative to the home d * Copy a file to the directory in which a repository is checked out in a codespace: - `gh codespace cp myfile.txt remote:/workspaces/` + `gh codespace cp myfile.txt remote:/workspaces/REPOSITORY-NAME` * Copy a file from a codespace to the current directory on the local machine: @@ -233,7 +233,7 @@ You can use the {% data variables.product.prodname_cli %} extension to create a ### Change the machine type of a codespace ```shell -gh codespace edit -m machine-type-name +gh codespace edit -m MACHINE-TYPE-NAME ``` For more information, see the "{% data variables.product.prodname_cli %}" tab of "[Changing the machine type for your codespace](/codespaces/customizing-your-codespace/changing-the-machine-type-for-your-codespace)." From c2aa10a61db44ee111c09565b6114dd5c97b6e2e Mon Sep 17 00:00:00 2001 From: Laura Coursen Date: Mon, 14 Nov 2022 09:50:34 -0600 Subject: [PATCH 11/11] Best practices for repositories, organizations, and enterprises (#32102) Co-authored-by: Matt Pollard --- ...bout-authentication-for-your-enterprise.md | 2 +- .../best-practices-for-enterprises.md | 49 +++++++++++++++++++ content/admin/overview/index.md | 1 + .../about-the-security-overview.md | 2 +- ...ng-started-with-github-enterprise-cloud.md | 2 + ...g-started-with-github-enterprise-server.md | 2 + ...g-up-a-trial-of-github-enterprise-cloud.md | 2 + ...-up-a-trial-of-github-enterprise-server.md | 2 + .../about-organizations.md | 2 +- .../best-practices-for-organizations.md | 35 +++++++++++++ .../index.md | 1 + .../about-repositories.md | 3 +- .../best-practices-for-repositories.md | 30 ++++++++++++ .../index.md | 1 + .../about-readmes.md | 2 +- data/reusables/enterprise/best-practices.md | 1 + .../enterprise/ghec-authentication-options.md | 1 + .../org-ownership-recommendation.md | 2 +- data/reusables/repositories/about-READMEs.md | 1 + .../about-the-security-overview.md | 1 + 20 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 content/admin/overview/best-practices-for-enterprises.md create mode 100644 content/organizations/collaborating-with-groups-in-organizations/best-practices-for-organizations.md create mode 100644 content/repositories/creating-and-managing-repositories/best-practices-for-repositories.md create mode 100644 data/reusables/enterprise/best-practices.md create mode 100644 data/reusables/enterprise/ghec-authentication-options.md create mode 100644 data/reusables/repositories/about-READMEs.md create mode 100644 data/reusables/security-overview/about-the-security-overview.md diff --git a/content/admin/identity-and-access-management/managing-iam-for-your-enterprise/about-authentication-for-your-enterprise.md b/content/admin/identity-and-access-management/managing-iam-for-your-enterprise/about-authentication-for-your-enterprise.md index 7ebd13139b..c060a0b236 100644 --- a/content/admin/identity-and-access-management/managing-iam-for-your-enterprise/about-authentication-for-your-enterprise.md +++ b/content/admin/identity-and-access-management/managing-iam-for-your-enterprise/about-authentication-for-your-enterprise.md @@ -21,7 +21,7 @@ topics: Enterprise owners on {% data variables.product.product_name %} can control the requirements for authentication and access to the enterprise's resources. -You can choose to allow members to create and manage user accounts, or your enterprise can create and manage accounts for members with {% data variables.product.prodname_emus %}. If you allow members to manage their own accounts, you can also configure SAML authentication to both increase security and centralize identity and access for the web applications that your team uses. +{% data reusables.enterprise.ghec-authentication-options %} After learning more about these options, to determine which method is best for your enterprise, see "[Identifying the best authentication method for your enterprise](#identifying-the-best-authentication-method-for-your-enterprise)." diff --git a/content/admin/overview/best-practices-for-enterprises.md b/content/admin/overview/best-practices-for-enterprises.md new file mode 100644 index 0000000000..fd1a6f19ce --- /dev/null +++ b/content/admin/overview/best-practices-for-enterprises.md @@ -0,0 +1,49 @@ +--- +title: Best practices for enterprises +shortTitle: Best practices +intro: Learn {% data variables.product.company_short %}-recommended practices for your enterprise. +versions: + ghec: '*' + ghes: '*' + ghae: '*' +type: overview +topics: + - Accounts + - Enterprise + - Fundamentals +--- + +{% ifversion ghec %} +## Identify the best authentication method for your enterprise + +{% data reusables.enterprise.ghec-authentication-options %} + +For help identifying the authentication method that will best meet your needs, see "[About authentication for your enterprise](/admin/identity-and-access-management/managing-iam-for-your-enterprise/about-authentication-for-your-enterprise)." +{% endif %} + +## Use policies + +We recommend using policies to enforce business rules and regulatory compliance. + +{% data reusables.enterprise.about-policies %} For more information, see "[About enterprise policies](/admin/policies/enforcing-policies-for-your-enterprise/about-enterprise-policies)." + +## Minimize the number of organizations + +Large enterprises often need multiple organizations, but try to create as few as possible to reflect top-level corporate divisions. A smaller number of organizations encourages innersource practices and allows discussions to involve a wider audience. + +Instead, you can manage repository access and security requirements at a more granular level within each organization by using teams. For more information, see "[About teams](/organizations/organizing-members-into-teams/about-teams)." + +## Avoid extensive collaboration in user-owned repositories + +We recommend collaborating in organization-owned repositories whenever possible and minimizing collaboration in user-owned repositories. Organization-owned repositories have more sophisticated security and administrative features, and they remain accessible even as enterprise membership changes. + +## Use human-readable usernames + +{% ifversion ghec %}If you control the usernames for enterprise members, use{% else %}Use{% endif %} human-readable usernames, and avoid machine-generated IDs that are difficult for humans to read. + +You can manage the display of usernames within your enterprise's private repositories. For more information, see "[Managing the display of member names in your organization](/organizations/managing-organization-settings/managing-the-display-of-member-names-in-your-organization)." + +## Further reading + +- "[Best practices for repositories](/repositories/creating-and-managing-repositories/best-practices-for-repositories)" +- "[Best practices for organizations](/organizations/collaborating-with-groups-in-organizations/best-practices-for-organizations)" \ No newline at end of file diff --git a/content/admin/overview/index.md b/content/admin/overview/index.md index f5c37790f4..2865ffd5e6 100644 --- a/content/admin/overview/index.md +++ b/content/admin/overview/index.md @@ -16,6 +16,7 @@ children: - /about-enterprise-accounts - /system-overview - /about-the-github-enterprise-api + - /best-practices-for-enterprises - /creating-an-enterprise-account - /accessing-compliance-reports-for-your-enterprise --- diff --git a/content/code-security/security-overview/about-the-security-overview.md b/content/code-security/security-overview/about-the-security-overview.md index 51ceb3b60c..29b36286e4 100644 --- a/content/code-security/security-overview/about-the-security-overview.md +++ b/content/code-security/security-overview/about-the-security-overview.md @@ -28,7 +28,7 @@ shortTitle: About the security overview ## About the security overview -The security overview provides high-level summaries of the security status of an organization or enterprise and make it easy to identify problematic repositories that require intervention. You can also use the security overview to see which repositories have enabled specific security features and to configure any available security features that are not currently in use. {% ifversion fpt %}For more information, see [the {% data variables.product.prodname_ghe_cloud %} documentation](/enterprise-cloud@latest/code-security/security-overview/about-the-security-overview).{% endif %} +{% data reusables.security-overview.about-the-security-overview %} {% ifversion fpt %}For more information, see [the {% data variables.product.prodname_ghe_cloud %} documentation](/enterprise-cloud@latest/code-security/security-overview/about-the-security-overview).{% endif %} {% ifversion ghec or ghes or ghae %} The security overview shows which security features are enabled for repositories and consolidate alerts for each feature. diff --git a/content/get-started/onboarding/getting-started-with-github-enterprise-cloud.md b/content/get-started/onboarding/getting-started-with-github-enterprise-cloud.md index 8d918c17ca..ad6be77621 100644 --- a/content/get-started/onboarding/getting-started-with-github-enterprise-cloud.md +++ b/content/get-started/onboarding/getting-started-with-github-enterprise-cloud.md @@ -205,6 +205,8 @@ Members of your organization or enterprise can use GitHub's learning and support ### 1. Reading about {% data variables.product.prodname_ghe_cloud %} on {% data variables.product.prodname_docs %} You can read documentation that reflects the features available with {% data variables.product.prodname_ghe_cloud %}. For more information, see "[About versions of {% data variables.product.prodname_docs %}](/get-started/learning-about-github/about-versions-of-github-docs)." +{% data reusables.enterprise.best-practices %} + ### 2. Learning with {% data variables.product.prodname_learning %} Members of your organization or enterprise can learn new skills by completing fun, realistic projects in your very own GitHub repository with [{% data variables.product.prodname_learning %}](https://skills.github.com/). Each course is a hands-on lesson created by the GitHub community and taught by a friendly bot. diff --git a/content/get-started/onboarding/getting-started-with-github-enterprise-server.md b/content/get-started/onboarding/getting-started-with-github-enterprise-server.md index 5f749b66af..f3368b385c 100644 --- a/content/get-started/onboarding/getting-started-with-github-enterprise-server.md +++ b/content/get-started/onboarding/getting-started-with-github-enterprise-server.md @@ -119,6 +119,8 @@ Your enterprise members can learn more about Git and {% data variables.product.p You can read documentation that reflects the features available with {% data variables.product.prodname_ghe_server %}. For more information, see "[About versions of {% data variables.product.prodname_docs %}](/get-started/learning-about-github/about-versions-of-github-docs)." +{% data reusables.enterprise.best-practices %} + ### 2. Learning with {% data variables.product.prodname_learning %} {% data reusables.getting-started.learning-enterprise %} diff --git a/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud.md b/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud.md index 9ae2cfe6fd..5d39981bfd 100644 --- a/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud.md +++ b/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-cloud.md @@ -62,6 +62,8 @@ After you set up your trial, you can explore {% data variables.product.prodname_ {% data reusables.docs.you-can-read-docs-for-your-product %} +{% data reusables.enterprise.best-practices %} + {% data reusables.products.product-roadmap %} ## Finishing your trial diff --git a/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-server.md b/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-server.md index 9b44fab841..56ce427eb4 100644 --- a/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-server.md +++ b/content/get-started/signing-up-for-github/setting-up-a-trial-of-github-enterprise-server.md @@ -55,6 +55,8 @@ To get the most out of your trial, follow these steps: {% endnote %} +{% data reusables.enterprise.best-practices %} + {% data reusables.products.product-roadmap %} ## Finishing your trial diff --git a/content/organizations/collaborating-with-groups-in-organizations/about-organizations.md b/content/organizations/collaborating-with-groups-in-organizations/about-organizations.md index 3efe549712..52fc0b96ca 100644 --- a/content/organizations/collaborating-with-groups-in-organizations/about-organizations.md +++ b/content/organizations/collaborating-with-groups-in-organizations/about-organizations.md @@ -28,7 +28,7 @@ You can configure the organization to meet the unique needs of your group by man To harden your organization's security, you can enforce security requirements and review the organization's audit log. For more information, see "[Keeping your organization secure](/organizations/keeping-your-organization-secure)." -{% data reusables.organizations.org-ownership-recommendation %} For more information, see "[Maintaining ownership continuity for your organization](/organizations/managing-peoples-access-to-your-organization-with-roles/maintaining-ownership-continuity-for-your-organization)." +To learn how to use organizations most effectively, see "[Best practices for organizations](/organizations/collaborating-with-groups-in-organizations/best-practices-for-organizations)." {% ifversion fpt or ghec %} ## About feature availability diff --git a/content/organizations/collaborating-with-groups-in-organizations/best-practices-for-organizations.md b/content/organizations/collaborating-with-groups-in-organizations/best-practices-for-organizations.md new file mode 100644 index 0000000000..808c1c17ae --- /dev/null +++ b/content/organizations/collaborating-with-groups-in-organizations/best-practices-for-organizations.md @@ -0,0 +1,35 @@ +--- +title: Best practices for organizations +shortTitle: Best practices +intro: Learn {% data variables.product.prodname_dotcom %}-recommended practices for your organization. +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +topics: + - Organizations + - Teams +--- + +## Assign multiple owners + +{% data reusables.organizations.org-ownership-recommendation %} For more information, see "[Maintaining ownership continuity for your organization](/organizations/managing-peoples-access-to-your-organization-with-roles/maintaining-ownership-continuity-for-your-organization)." + +## Use teams + +We recommend using teams to facilitate collaboration in your organization. For more information, see "[About teams](/organizations/organizing-members-into-teams/about-teams)." + +{% ifversion ghec %} +We highly recommend managing team membership through your identity provider (IdP). For more information, see "[Managing team synchronization for your organization](/organizations/managing-saml-single-sign-on-for-your-organization/managing-team-synchronization-for-your-organization)." + +{% data reusables.enterprise-accounts.emu-scim-note %} +{% endif %} + +We recommend keeping teams visible whenever possible and reserving secret teams for sensitive situations. For more information, see "[Changing team visibility](/organizations/organizing-members-into-teams/changing-team-visibility)." + +{% ifversion ghec or ghes or ghae %} +## Use the security overview + +{% data reusables.security-overview.about-the-security-overview %} For more information, see "[About the security overview](/code-security/security-overview/about-the-security-overview)." +{% endif %} \ No newline at end of file diff --git a/content/organizations/collaborating-with-groups-in-organizations/index.md b/content/organizations/collaborating-with-groups-in-organizations/index.md index bd2e17c6b1..2a4d880e6b 100644 --- a/content/organizations/collaborating-with-groups-in-organizations/index.md +++ b/content/organizations/collaborating-with-groups-in-organizations/index.md @@ -16,6 +16,7 @@ topics: children: - /about-organizations - /about-your-organization-dashboard + - /best-practices-for-organizations - /creating-a-new-organization-from-scratch - /accessing-your-organizations-settings - /customizing-your-organizations-profile diff --git a/content/repositories/creating-and-managing-repositories/about-repositories.md b/content/repositories/creating-and-managing-repositories/about-repositories.md index 04007167b4..aad88ee02a 100644 --- a/content/repositories/creating-and-managing-repositories/about-repositories.md +++ b/content/repositories/creating-and-managing-repositories/about-repositories.md @@ -42,6 +42,8 @@ You can use repositories to manage your work and collaborate with others. {% data reusables.repositories.repo-size-limit %} +To learn how to use repositories most effectively, see "[Best practices for repositories](/repositories/creating-and-managing-repositories/best-practices-for-repositories)." + ## About repository visibility You can restrict who has access to a repository by choosing a repository's visibility: {% ifversion ghes or ghec %}public, internal, or private{% elsif ghae %}private or internal{% else %} public or private{% endif %}. @@ -138,7 +140,6 @@ The compare view and pull requests pages display a list of commits between the ` ## Further reading -- "[Creating a new repository](/articles/creating-a-new-repository)" - "[About forks](/github/collaborating-with-pull-requests/working-with-forks/about-forks)" - "[Collaborating with issues and pull requests](/categories/collaborating-with-issues-and-pull-requests)" - "[Managing your work on {% data variables.product.prodname_dotcom %}](/categories/managing-your-work-on-github/)" diff --git a/content/repositories/creating-and-managing-repositories/best-practices-for-repositories.md b/content/repositories/creating-and-managing-repositories/best-practices-for-repositories.md new file mode 100644 index 0000000000..fc706fcb0c --- /dev/null +++ b/content/repositories/creating-and-managing-repositories/best-practices-for-repositories.md @@ -0,0 +1,30 @@ +--- +title: Best practices for repositories +shortTitle: Best practices +intro: Learn how to use repositories most effectively. +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +topics: + - Repositories +--- + +## Create a README file + +To make it easier for people to understand and navigate your work, we recommend that you create a README file for every repository. + +{% data reusables.repositories.about-READMEs %} For more information, see "[About READMEs](/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes)." + +## Favor branching over forking + +To streamline collaboration, we recommend that regular collaborators work from a single repository, creating pull requests between branches instead of between repositories. Forking is best suited for accepting contributions from people that are unaffiliated with a project, such as open-source contributors. + +To maintain quality of important branches, such as `main`, while using a branching workflow, you can use protected branches with required status checks and pull request reviews. For more information, see "[About protected branches](/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches)." + +## Use {% data variables.large_files.product_name_long %} + +To optimize performance, {% data variables.location.product_location %} limits the sizes of files allowed in repositories. For more information, see "[About large files on {% data variables.product.prodname_dotcom %}](/repositories/working-with-files/managing-large-files/about-large-files-on-github)." + +To track large files in a Git repository, we recommend using {% data variables.large_files.product_name_long %} ({% data variables.large_files.product_name_short %}). For more information, see "[About {% data variables.large_files.product_name_long %}](/repositories/working-with-files/managing-large-files/about-git-large-file-storage)." diff --git a/content/repositories/creating-and-managing-repositories/index.md b/content/repositories/creating-and-managing-repositories/index.md index b695df6407..8e9a83834f 100644 --- a/content/repositories/creating-and-managing-repositories/index.md +++ b/content/repositories/creating-and-managing-repositories/index.md @@ -13,6 +13,7 @@ topics: - Repositories children: - /about-repositories + - /best-practices-for-repositories - /creating-a-new-repository - /creating-a-repository-from-a-template - /creating-a-template-repository diff --git a/content/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes.md b/content/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes.md index 7de402dfc0..5450d81b0a 100644 --- a/content/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes.md +++ b/content/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes.md @@ -17,7 +17,7 @@ topics: --- ## About READMEs -You can add a README file to a repository to communicate important information about your project. A README, along with a repository license, citation file{% ifversion fpt or ghec %}, contribution guidelines, and a code of conduct{% elsif ghes %} and contribution guidelines{% endif %}, communicates expectations for your project and helps you manage contributions. +{% data reusables.repositories.about-READMEs %} For more information about providing guidelines for your project, see {% ifversion fpt or ghec %}"[Adding a code of conduct to your project](/communities/setting-up-your-project-for-healthy-contributions/adding-a-code-of-conduct-to-your-project)" and {% endif %}"[Setting up your project for healthy contributions](/communities/setting-up-your-project-for-healthy-contributions)." diff --git a/data/reusables/enterprise/best-practices.md b/data/reusables/enterprise/best-practices.md new file mode 100644 index 0000000000..a9b7ed42e9 --- /dev/null +++ b/data/reusables/enterprise/best-practices.md @@ -0,0 +1 @@ +To learn how your enterprise can use {% data variables.product.product_name %} most effectively, see "[Best practices for enterprises](/admin/overview/best-practices-for-enterprises)." \ No newline at end of file diff --git a/data/reusables/enterprise/ghec-authentication-options.md b/data/reusables/enterprise/ghec-authentication-options.md new file mode 100644 index 0000000000..9f886ec1d3 --- /dev/null +++ b/data/reusables/enterprise/ghec-authentication-options.md @@ -0,0 +1 @@ +You can choose to allow members to create and manage user accounts, or your enterprise can create and manage accounts for members with {% data variables.product.prodname_emus %}. If you allow members to manage their own accounts, you can also configure SAML authentication to both increase security and centralize identity and access for the web applications that your team uses. diff --git a/data/reusables/organizations/org-ownership-recommendation.md b/data/reusables/organizations/org-ownership-recommendation.md index 54745704c2..ec3e3c1596 100644 --- a/data/reusables/organizations/org-ownership-recommendation.md +++ b/data/reusables/organizations/org-ownership-recommendation.md @@ -1 +1 @@ -Projects maintained and managed by one sole organization owner can easily become inaccessible if the organization owner is unreachable. We recommend an organization have at least two people with *owner* permissions to ensure no one will lose access to a project. +If an organization only has one owner, the organization's projects can become inaccessible if the owner is unreachable. To ensure that no one will lose access to a project, we recommend that at least two people within each organization have the owner role. diff --git a/data/reusables/repositories/about-READMEs.md b/data/reusables/repositories/about-READMEs.md new file mode 100644 index 0000000000..be0bb6d2a6 --- /dev/null +++ b/data/reusables/repositories/about-READMEs.md @@ -0,0 +1 @@ +You can add a README file to a repository to communicate important information about your project. A README, along with a repository license, citation file{% ifversion fpt or ghec %}, contribution guidelines, and a code of conduct{% elsif ghes %} and contribution guidelines{% endif %}, communicates expectations for your project and helps you manage contributions. \ No newline at end of file diff --git a/data/reusables/security-overview/about-the-security-overview.md b/data/reusables/security-overview/about-the-security-overview.md new file mode 100644 index 0000000000..2e1978ee6b --- /dev/null +++ b/data/reusables/security-overview/about-the-security-overview.md @@ -0,0 +1 @@ +The security overview provides high-level summaries of the security status of an organization or enterprise and make it easy to identify problematic repositories that require intervention. You can also use the security overview to see which repositories have enabled specific security features and to configure any available security features that are not currently in use. \ No newline at end of file