diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 73ce92bf2d..10410cf645 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -17,7 +17,8 @@ // Install features. Type 'feature' in the VS Code command palette for a full list. "features": { - "git-lfs": "latest" + "git-lfs": "latest", + "sshd": "latest" }, // Visual Studio Code extensions which help authoring for docs.github.com. diff --git a/.github/actions-scripts/content-changes-table-comment.js b/.github/actions-scripts/content-changes-table-comment.js index 32400b46c8..4aecea4709 100755 --- a/.github/actions-scripts/content-changes-table-comment.js +++ b/.github/actions-scripts/content-changes-table-comment.js @@ -2,7 +2,6 @@ import * as github from '@actions/github' import { setOutput } from '@actions/core' -import got from 'got' import { getContents } from '../../script/helpers/git-utils.js' import parse from '../../lib/read-frontmatter.js' @@ -48,13 +47,6 @@ const articleFiles = files.filter( const lines = await Promise.all( articleFiles.map(async (file) => { - // Action triggered on PR and after preview env is deployed. Check health to determine if preview env is ready (healthy) - let appUrlIsHealthy = false - try { - const res = await got.head(`${APP_URL}/healthz`, { retry: { limit: 0 } }) - appUrlIsHealthy = res.statusCode === 200 - } catch (err) {} - const sourceUrl = file.blob_url const fileName = file.filename.slice(pathPrefix.length) const fileUrl = fileName.slice(0, fileName.lastIndexOf('.')) @@ -78,8 +70,7 @@ const lines = await Promise.all( const { data } = parse(fileContents) let contentCell = '' - let previewCell = appUrlIsHealthy ? '' : '_Deployment pending..._' - + let previewCell = '' let prodCell = '' if (file.status === 'added') contentCell = 'New file: ' @@ -107,16 +98,12 @@ const lines = await Promise.all( if (versions.toString() === nonEnterpriseDefaultVersion) { // omit version from fpt url - previewCell += appUrlIsHealthy ? `[${plan}](${APP_URL}/${fileUrl})
` : '' + previewCell += `[${plan}](${APP_URL}/${fileUrl})
` prodCell += `[${plan}](${PROD_URL}/${fileUrl})
` } else { // for non-versioned releases (ghae, ghec) use full url - if (appUrlIsHealthy) { - previewCell += appUrlIsHealthy - ? `[${plan}](${APP_URL}/${versions}/${fileUrl})
` - : '' - } + previewCell += `[${plan}](${APP_URL}/${versions}/${fileUrl})
` prodCell += `[${plan}](${PROD_URL}/${versions}/${fileUrl})
` } } else if (versions.length) { @@ -126,9 +113,7 @@ const lines = await Promise.all( prodCell += `${plan}@ ` versions.forEach((version) => { - previewCell += appUrlIsHealthy - ? `[${version.split('@')[1]}](${APP_URL}/${version}/${fileUrl}) ` - : '' + previewCell += `[${version.split('@')[1]}](${APP_URL}/${version}/${fileUrl}) ` prodCell += `[${version.split('@')[1]}](${PROD_URL}/${version}/${fileUrl}) ` }) previewCell += '
' diff --git a/.github/workflows/content-changes-table-comment.yml b/.github/workflows/content-changes-table-comment.yml index 355af58d08..51fa2ce095 100644 --- a/.github/workflows/content-changes-table-comment.yml +++ b/.github/workflows/content-changes-table-comment.yml @@ -5,10 +5,6 @@ name: Content Changes Table Comment # **Who does it impact**: docs-internal/docs maintainers and contributors on: - # Trigger this workflow after preview deployment runs - workflow_run: - workflows: - - Azure - Deploy Preview Environment workflow_dispatch: pull_request_target: @@ -44,6 +40,7 @@ jobs: filters: | filterContentDir: - 'content/**/*' + filterContentDir: needs: PR-Preview-Links if: ${{ needs.PR-Preview-Links.outputs.filterContentDir == 'true' }} diff --git a/.gitignore b/.gitignore index 8b780e4e2e..7a5746c1df 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ coverage/ /assets/images/early-access /content/early-access /data/early-access +/script/dev-toc/static .next .eslintcache *.tsbuildinfo diff --git a/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-all-repos.png b/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-all-repos.png new file mode 100644 index 0000000000..94b6c547aa Binary files /dev/null and b/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-all-repos.png differ diff --git a/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-select-repo-only.png b/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-select-repo-only.png new file mode 100644 index 0000000000..bac45fbd59 Binary files /dev/null and b/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-select-repo-only.png differ diff --git a/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-select-repos-option.png b/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-select-repos-option.png new file mode 100644 index 0000000000..697abe1e6e Binary files /dev/null and b/assets/images/help/repository/secret-scanning-dry-run-custom-pattern-select-repos-option.png differ diff --git a/components/context/PlaygroundContext.tsx b/components/context/PlaygroundContext.tsx index f2753d8555..b7f5245cfd 100644 --- a/components/context/PlaygroundContext.tsx +++ b/components/context/PlaygroundContext.tsx @@ -59,7 +59,8 @@ export const PlaygroundContextProvider = (props: { children: React.ReactNode }) const router = useRouter() const [activeSectionIndex, setActiveSectionIndex] = useState(0) const [scrollToSection, setScrollToSection] = useState() - const path = router.asPath.split('?')[0] + const path = router.asPath.split('?')[0].split('#')[0] + const relevantArticles = articles.filter(({ slug }) => slug === path) const { langId } = router.query diff --git a/components/graphql/GraphqlItem.tsx b/components/graphql/GraphqlItem.tsx index eae46a7d41..49a8b0417c 100644 --- a/components/graphql/GraphqlItem.tsx +++ b/components/graphql/GraphqlItem.tsx @@ -12,7 +12,7 @@ type Props = { export function GraphqlItem({ item, heading, children, headingLevel = 2 }: Props) { const lowerCaseName = item.name.toLowerCase() return ( - <> +
{headingLevel === 2 && (

@@ -38,6 +38,6 @@ export function GraphqlItem({ item, heading, children, headingLevel = 2 }: Props {heading &&

{heading}

} {children}

- + ) } diff --git a/components/hooks/useUserLanguage.ts b/components/hooks/useUserLanguage.ts index 82a6a88af3..63d225c87c 100644 --- a/components/hooks/useUserLanguage.ts +++ b/components/hooks/useUserLanguage.ts @@ -1,10 +1,12 @@ import { useState, useEffect } from 'react' import Cookies from 'js-cookie' +import { useRouter } from 'next/router' import { languageKeys } from '../../lib/languages.js' import { PREFERRED_LOCALE_COOKIE_NAME } from '../../lib/constants.js' export function useUserLanguage() { + const { locale } = useRouter() const [userLanguage, setUserLanguage] = useState('en') useEffect(() => { @@ -22,7 +24,7 @@ export function useUserLanguage() { if (languagePreferred) { setUserLanguage(languagePreferred) } - }, []) + }, [locale]) return { userLanguage } } diff --git a/components/lib/get-rest-code-samples.ts b/components/lib/get-rest-code-samples.ts index 119967c0fc..982c6945cb 100644 --- a/components/lib/get-rest-code-samples.ts +++ b/components/lib/get-rest-code-samples.ts @@ -25,7 +25,10 @@ export function getShellExample(operation: Operation, codeSample: CodeSample) { let requestBodyParams = '' if (codeSample?.request?.bodyParameters) { - requestBodyParams = `-d '${JSON.stringify(codeSample.request.bodyParameters)}'` + requestBodyParams = `-d '${JSON.stringify(codeSample.request.bodyParameters).replace( + /'/g, + "'\\''" + )}'` // If the content type is application/x-www-form-urlencoded the format of // the shell example is --data-urlencode param1=value1 --data-urlencode param2=value2 diff --git a/components/playground/CodeLanguagePicker.tsx b/components/playground/CodeLanguagePicker.tsx index 6cef145135..f7df48ed4c 100644 --- a/components/playground/CodeLanguagePicker.tsx +++ b/components/playground/CodeLanguagePicker.tsx @@ -13,6 +13,7 @@ export const CodeLanguagePicker = () => { {codeLanguages.map((language) => ( = ({ article }) => { {editorFiles.map((file, i) => { return ( +
+ +{% for productPage in currentEnglishTree.childPages %} +{% assign productId = productPage.page.relativePath | replace: "/index.md", "" %} +{% if defaultOpenSections contains productId %} +
{{productPage.renderedFullTitle}} +{% else %} +
{{productPage.renderedFullTitle}} +{% endif %} + +
+{% endfor %} +{% endif %} + + + + + diff --git a/script/rest/utils/operation.js b/script/rest/utils/operation.js index c994c28a56..0b47929dfe 100644 --- a/script/rest/utils/operation.js +++ b/script/rest/utils/operation.js @@ -165,6 +165,9 @@ export default class Operation { async renderBodyParameterDescriptions() { if (!this.#operation.requestBody) return [] + // There is currently only one operation with more than one content type + // and the request body parameter types are the same for both. + // Operation Id: markdown/render-raw const contentType = Object.keys(this.#operation.requestBody.content)[0] let bodyParamsObject = get( this.#operation, @@ -378,13 +381,17 @@ async function getBodyParams(paramsObject, requiredParams) { param.childParamsGroups.push( ...flatten( childParamsGroup.params - .filter((param) => param.childParamsGroups.length) + .filter((param) => param.childParamsGroups?.length) .map((param) => param.childParamsGroups) ) ) } - - return param + const paramDecorated = { ...param } + delete paramDecorated.items + delete paramDecorated.rawDescription + delete paramDecorated.rawType + if (paramDecorated.childParamsGroups.length === 0) delete paramDecorated.childParamsGroups + return paramDecorated }) ) } diff --git a/tests/meta/repository-references.js b/tests/meta/repository-references.js index e2112204cb..35bdfbb030 100644 --- a/tests/meta/repository-references.js +++ b/tests/meta/repository-references.js @@ -17,67 +17,68 @@ If this test is failing... // These are a list of known public repositories in the GitHub organization const PUBLIC_REPOS = new Set([ - 'site-policy', - 'roadmap', - 'linguist', - 'super-linter', + 'actions-oidc-gateway-example', + 'advisory-database', 'backup-utils', + 'browser-support', + 'choosealicense.com', 'codeql-action-sync-tool', 'codeql-action', 'codeql-cli-binaries', - 'codeql', 'codeql-go', - 'platform-samples', - 'github-services', - 'explore', - 'enterprise-releases', - 'markup', - 'hubot', - 'VisualStudio', 'codeql', - 'gitignore', - 'feedback', - 'semantic', - 'git-lfs', - 'git-sizer', - 'dmca', - 'gov-takedowns', - 'janky', - 'rest-api-description', - 'smimesign', - 'tweetsodium', - 'choosealicense.com', - 'renaming', - 'localization-support', - 'docs', - 'securitylab', - 'hello-world', - 'hello-world.git', - 'insights-releases', - 'help-docs-archived-enterprise-versions', - 'stack-graphs', + 'codeql', 'codespaces-precache', - 'advisory-database', - 'browser-support', - 'haikus-for-codespaces', - 'actions-oidc-gateway-example', 'copilot.vim', 'dependency-submission-toolkit', + 'dmca', + 'docs', + 'enterprise-releases', + 'explore', + 'feedback', + 'gh-net', + 'git-lfs', + 'git-sizer', + 'github-services', + 'gitignore', + 'gov-takedowns', + 'haikus-for-codespaces', + 'hello-world.git', + 'hello-world', + 'help-docs-archived-enterprise-versions', + 'hubot', + 'insights-releases', + 'janky', + 'linguist', + 'localization-support', + 'markup', + 'platform-samples', + 'renaming', + 'rest-api-description', + 'roadmap', + 'securitylab', + 'semantic', + 'site-policy', + 'smimesign', + 'stack-graphs', + 'super-linter', + 'tweetsodium', + 'VisualStudio', ]) const ALLOW_DOCS_PATHS = [ '.github/actions-scripts/enterprise-server-issue-templates/*.md', '.github/review-template.md', + '.github/workflows/hubber-contribution-help.yml', '.github/workflows/sync-search-indices.yml', 'contributing/search.md', + 'docs/index.yaml', + 'lib/excluded-links.js', 'lib/rest/**/*.json', 'lib/webhooks/**/*.json', 'ownership.yaml', - 'docs/index.yaml', - 'lib/excluded-links.js', 'script/README.md', 'script/toggle-ghae-feature-flags.js', - '.github/workflows/hubber-contribution-help.yml', ] const REPO_REGEXP = /\/\/github\.com\/github\/(?!docs[/'"\n])([\w-.]+)/gi diff --git a/tests/rendering/server.js b/tests/rendering/server.js index 8c0b70f6f5..04206efb86 100644 --- a/tests/rendering/server.js +++ b/tests/rendering/server.js @@ -326,7 +326,7 @@ describe('server', () => { test('renders mini TOC in articles with more than one heading', async () => { const $ = await getDOM('/en/github/getting-started-with-github/githubs-products') expect($('h2#in-this-article').length).toBe(1) - expect($('h2#in-this-article + div div ul').length).toBeGreaterThan(1) + expect($('h2#in-this-article + nav ul').length).toBeGreaterThan(1) }) test('renders mini TOC in articles that includes h3s when specified by frontmatter', async () => { @@ -334,8 +334,8 @@ describe('server', () => { '/en/admin/policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-security-settings-in-your-enterprise' ) expect($('h2#in-this-article').length).toBe(1) - expect($('h2#in-this-article + div div ul').length).toBeGreaterThan(0) // non-indented items - expect($('h2#in-this-article + div div ul li div div ul.ml-3').length).toBeGreaterThan(0) // indented items + expect($('h2#in-this-article + nav div ul').length).toBeGreaterThan(0) // non-indented items + expect($('h2#in-this-article + nav div ul li div div ul.ml-3').length).toBeGreaterThan(0) // indented items }) test('does not render mini TOC in articles with only one heading', async () => { @@ -358,13 +358,13 @@ describe('server', () => { // TODO test('renders mini TOC with correct links when headings contain markup', async () => { const $ = await getDOM('/en/actions/using-workflows/workflow-syntax-for-github-actions') - expect($('h2#in-this-article + div div ul a[href="#on"]').length).toBe(1) + expect($('h2#in-this-article + nav div ul a[href="#on"]').length).toBe(1) }) // TODO test('renders mini TOC with correct links when headings contain markup in localized content', async () => { const $ = await getDOM('/ja/actions/using-workflows/workflow-syntax-for-github-actions') - expect($('h2#in-this-article + div div ul a[href="#on"]').length).toBe(1) + expect($('h2#in-this-article + nav div ul a[href="#on"]').length).toBe(1) }) }) @@ -916,11 +916,11 @@ describe('extended Markdown', () => { test('renders expected mini TOC headings in platform-specific content', async () => { const $ = await getDOM('/en/github/using-git/associating-text-editors-with-git') expect($('h2#in-this-article').length).toBe(1) - expect($('h2#in-this-article + div div ul li.extended-markdown.mac').length).toBeGreaterThan(1) + expect($('h2#in-this-article + nav div ul li.extended-markdown.mac').length).toBeGreaterThan(1) expect( - $('h2#in-this-article + div div ul li.extended-markdown.windows').length + $('h2#in-this-article + nav div ul li.extended-markdown.windows').length ).toBeGreaterThan(1) - expect($('h2#in-this-article + div div ul li.extended-markdown.linux').length).toBeGreaterThan( + expect($('h2#in-this-article + nav div ul li.extended-markdown.linux').length).toBeGreaterThan( 1 ) })