From 8fa8c00196916eaf3147744c93774d6212aaaf48 Mon Sep 17 00:00:00 2001 From: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:39:11 +0000 Subject: [PATCH 01/10] [EDI] Evaluating the security settings of a repository (#60059) --- .../report-and-fix-vulnerabilities/index.md | 3 +- ...tely-reporting-a-security-vulnerability.md | 7 ++- ...g-the-security-settings-of-a-repository.md | 54 ------------------- .../report-a-vulnerability/index.md | 16 ------ data/learning-tracks/code-security.yml | 2 +- 5 files changed, 9 insertions(+), 73 deletions(-) rename content/code-security/how-tos/report-and-fix-vulnerabilities/{report-a-vulnerability => }/privately-reporting-a-security-vulnerability.md (79%) delete mode 100644 content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/evaluating-the-security-settings-of-a-repository.md delete mode 100644 content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/index.md diff --git a/content/code-security/how-tos/report-and-fix-vulnerabilities/index.md b/content/code-security/how-tos/report-and-fix-vulnerabilities/index.md index 38a120bdc97d..032b268b284d 100644 --- a/content/code-security/how-tos/report-and-fix-vulnerabilities/index.md +++ b/content/code-security/how-tos/report-and-fix-vulnerabilities/index.md @@ -17,6 +17,7 @@ topics: contentType: how-tos children: - configure-vulnerability-reporting - - report-a-vulnerability + - privately-reporting-a-security-vulnerability - fix-reported-vulnerabilities --- + diff --git a/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/privately-reporting-a-security-vulnerability.md b/content/code-security/how-tos/report-and-fix-vulnerabilities/privately-reporting-a-security-vulnerability.md similarity index 79% rename from content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/privately-reporting-a-security-vulnerability.md rename to content/code-security/how-tos/report-and-fix-vulnerabilities/privately-reporting-a-security-vulnerability.md index 6f7a17d77546..fed5cbccab06 100644 --- a/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/privately-reporting-a-security-vulnerability.md +++ b/content/code-security/how-tos/report-and-fix-vulnerabilities/privately-reporting-a-security-vulnerability.md @@ -13,6 +13,11 @@ shortTitle: Report privately redirect_from: - /code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability - /code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability + - /code-security/security-advisories/repository-security-advisories/evaluating-the-security-settings-of-a-repository + - /code-security/security-advisories/working-with-repository-security-advisories/evaluating-the-security-settings-of-a-repository + - /code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/evaluating-the-security-settings-of-a-repository + - /code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability + - /code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/privately-reporting-a-security-vulnerability --- {% data reusables.security-advisory.private-vulnerability-reporting-enable %} @@ -21,7 +26,7 @@ redirect_from: > * If you have admin or security permissions for a public repository, you don’t need to submit a vulnerability report. Instead, create a draft security advisory directly. See [AUTOTITLE](/code-security/security-advisories/working-with-repository-security-advisories/creating-a-repository-security-advisory). > * Private vulnerability reporting is separate from a repository’s `SECURITY.md` file. You can only report vulnerabilities privately for repositories where this feature is enabled, and you don’t need to follow the instructions in `SECURITY.md`. -If a public repository has private vulnerability reporting enabled, anyone can submit a private vulnerability report to the repository maintainers. Users can also evaluate the general security of a public repository and suggest a security policy. See [AUTOTITLE](/code-security/security-advisories/working-with-repository-security-advisories/evaluating-the-security-settings-of-a-repository). +If a public repository has private vulnerability reporting enabled, anyone can submit a private vulnerability report to the repository maintainers. If the repository doesn't have private vulnerability reporting enabled, you need to initiate the reporting process by following the instructions in the security policy for the repository, or by creating an issue asking the maintainers for a preferred security contact. See [AUTOTITLE](/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/about-coordinated-disclosure-of-security-vulnerabilities#about-reporting-and-disclosing-vulnerabilities-in-projects-on-github). diff --git a/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/evaluating-the-security-settings-of-a-repository.md b/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/evaluating-the-security-settings-of-a-repository.md deleted file mode 100644 index cbc6f5353e32..000000000000 --- a/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/evaluating-the-security-settings-of-a-repository.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Evaluating the security settings of a repository -intro: Security researchers can assess the security settings of a public repository, suggest a security policy and report a vulnerability. -permissions: '{% data reusables.permissions.repository-security-advisory-evaluate %}' -versions: - fpt: '*' - ghec: '*' -contentType: how-tos -topics: - - Security advisories - - Vulnerabilities -shortTitle: Evaluate repository security -redirect_from: - - /code-security/security-advisories/repository-security-advisories/evaluating-the-security-settings-of-a-repository - - /code-security/security-advisories/working-with-repository-security-advisories/evaluating-the-security-settings-of-a-repository ---- - -## About evaluating a repository's security settings - -Evaluating a public repository's security settings can help security researchers understand the repository's security posture. This information can help you decide whether to engage with the repository maintainers, for example, by reporting a vulnerability in the repository. - -If a repository is public, high level information about the repository's security settings is available to anyone. For example, you can see whether the repository has a security policy, and whether private vulnerability reporting is enabled. You can also view published and closed security advisories for the repository. If no security policy is associated with a repository, you can suggest one. If the repository has private vulnerability reporting enabled, you can privately report security vulnerabilities directly to repository maintainers. - -If you have admin permissions to the repository, and the repository is owned by an organization, you can see more detailed information about the repository's security settings through the security overview. For more information on the security overview, see [AUTOTITLE](/code-security/security-overview/about-security-overview). - - If a repository is private, you can only see the security settings if you have admin permissions to the repository or have been granted special security permissions covering the repository, for example, as an organization-wide security manager. - -If you would like to evaluate the security posture of repositories at scale, you can use the API to check whether or not some security settings are enabled for repositories, such as private vulnerability reporting. For more information, see [AUTOTITLE](/rest/repos/repos#check-if-private-vulnerability-reporting-is-enabled-for-a-repository). - -## Suggesting a security policy for a repository - - If you do not have admin or security permissions for a public repository, you can still suggest a security policy to the repository maintainers if one doesn't already exist. The repository maintainers can then choose to accept or reject your suggestion. If the repository maintainers accept your suggestion, the security policy will be associated with the repository. - -{% data reusables.repositories.navigate-to-repo %} -{% data reusables.repositories.sidebar-security %} -1. If the repository has a security policy, it will be displayed. If no security policy is associated with the repository, click **Suggest a policy**. -1. A SECURITY.md file will be created in the repository's default branch. The file will contain a template for a security policy. You can edit the file to add your suggested security policy. -1. When you are done, click **Commit changes**. -1. Fill out the **Commit changes** dialog. - * Under "Commit message", enter a commit message. - * Optionally, under "Extended description", describe the changes being made. - * Select "Create a new branch for this commit and start a pull request" - * Click **Commit changes**. -1. Click **Create pull request**. -1. Optionally, leave a comment. -1. Click **Create pull request**. - -## Reporting a vulnerability in a repository - -If you do not have admin or security permissions for a public repository, you can still privately report a security vulnerability to repository maintainers if private vulnerability reporting is enabled. The repository maintainers can then choose to accept or reject your report. If the repository maintainers accept your report, a security advisory will be created for the repository. - -{% data reusables.security-advisory.private-vulnerability-reporting-disabled %} - -{% data reusables.security-advisory.reporting-a-vulnerability-non-admin %} diff --git a/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/index.md b/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/index.md deleted file mode 100644 index 8e5bcde3a2d7..000000000000 --- a/content/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: How-tos for reporting vulnerabilities -shortTitle: Report and evaluate -intro: Learn how to report vulnerabilities and evaluate the security settings of a repository on {% data variables.product.github %}. -versions: - fpt: '*' - ghes: '*' -topics: - - Vulnerabilities - - Repositories - - Health -contentType: how-tos -children: - - privately-reporting-a-security-vulnerability - - evaluating-the-security-settings-of-a-repository ---- diff --git a/data/learning-tracks/code-security.yml b/data/learning-tracks/code-security.yml index 7364e1f2100d..a28897ba7886 100644 --- a/data/learning-tracks/code-security.yml +++ b/data/learning-tracks/code-security.yml @@ -15,7 +15,7 @@ security_advisories: - >- /code-security/tutorials/fix-reported-vulnerabilities/write-security-advisories - >- - /code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/privately-reporting-a-security-vulnerability + /code-security/how-tos/report-and-fix-vulnerabilities/privately-reporting-a-security-vulnerability - >- /code-security/how-tos/report-and-fix-vulnerabilities/fix-reported-vulnerabilities/managing-privately-reported-security-vulnerabilities - >- From f5e7d9bfee5b16f904c7cb97c2d54b4ee5fcc81f Mon Sep 17 00:00:00 2001 From: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:41:31 +0000 Subject: [PATCH 02/10] [EDI] Calculating the cost savings of push protection (#59985) --- .../configure-specific-tools/index.md | 2 +- .../calculating-the-cost-savings-of-push-protection.md | 7 ++++--- .../tutorials/remediate-leaked-secrets/index.md | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) rename content/code-security/{how-tos/secure-at-scale/configure-organization-security/configure-specific-tools => tutorials/remediate-leaked-secrets}/calculating-the-cost-savings-of-push-protection.md (95%) diff --git a/content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/index.md b/content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/index.md index 99f5258c512d..bb80b1929d26 100644 --- a/content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/index.md +++ b/content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/index.md @@ -10,9 +10,9 @@ children: - /assess-your-secret-risk - /viewing-the-secret-risk-assessment-report-for-your-organization - /estimating-the-price-of-secret-protection - - /calculating-the-cost-savings-of-push-protection - /protect-your-secrets - /configuring-default-setup-for-code-scanning-at-scale - /configuring-advanced-setup-for-code-scanning-with-codeql-at-scale - /enforcing-dependency-review-across-an-organization --- + diff --git a/content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/calculating-the-cost-savings-of-push-protection.md b/content/code-security/tutorials/remediate-leaked-secrets/calculating-the-cost-savings-of-push-protection.md similarity index 95% rename from content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/calculating-the-cost-savings-of-push-protection.md rename to content/code-security/tutorials/remediate-leaked-secrets/calculating-the-cost-savings-of-push-protection.md index d60f21e6af83..9b9270737341 100644 --- a/content/code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/calculating-the-cost-savings-of-push-protection.md +++ b/content/code-security/tutorials/remediate-leaked-secrets/calculating-the-cost-savings-of-push-protection.md @@ -1,7 +1,7 @@ --- title: Calculating the cost savings of push protection -shortTitle: Push protection cost savings -intro: Learn how to use the {% data variables.secret-scanning.roi-calculator %} to estimate the remediation time and labor costs you'll avoid by preventing leaked secrets. +shortTitle: Calculate cost savings +intro: Estimate the remediation time and labor costs you'll avoid by preventing leaked secrets. product: '{% data reusables.gated-features.secret-risk-assessment-calculators %}' versions: feature: secret-risk-assessment @@ -9,9 +9,10 @@ permissions: '{% data reusables.permissions.push-protection-roi-calculator %}' topics: - Secret scanning - Secret Protection -contentType: how-tos +contentType: tutorials redirect_from: - /code-security/securing-your-organization/understanding-your-organizations-exposure-to-leaked-secrets/calculating-the-cost-savings-of-push-protection + - /code-security/how-tos/secure-at-scale/configure-organization-security/configure-specific-tools/calculating-the-cost-savings-of-push-protection --- ## What is the cost savings calculator? diff --git a/content/code-security/tutorials/remediate-leaked-secrets/index.md b/content/code-security/tutorials/remediate-leaked-secrets/index.md index 39f59c330cc0..65913202c2e4 100644 --- a/content/code-security/tutorials/remediate-leaked-secrets/index.md +++ b/content/code-security/tutorials/remediate-leaked-secrets/index.md @@ -7,6 +7,8 @@ versions: ghec: '*' contentType: tutorials children: + - /calculating-the-cost-savings-of-push-protection - /evaluating-alerts - /remediating-a-leaked-secret --- + From 34bf111574cbe0aaa2c35c190adaffe948b69637 Mon Sep 17 00:00:00 2001 From: Kathleen <36471738+kathleenqin@users.noreply.github.com> Date: Thu, 5 Mar 2026 06:45:15 -0800 Subject: [PATCH 03/10] Update copilot metrics data freshness sla (#60045) --- .../copilot/concepts/copilot-usage-metrics/copilot-metrics.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/content/copilot/concepts/copilot-usage-metrics/copilot-metrics.md b/content/copilot/concepts/copilot-usage-metrics/copilot-metrics.md index a5bc24c84b0f..4155c7f05993 100644 --- a/content/copilot/concepts/copilot-usage-metrics/copilot-metrics.md +++ b/content/copilot/concepts/copilot-usage-metrics/copilot-metrics.md @@ -93,9 +93,7 @@ To be included in the {% data variables.product.prodname_copilot_short %} usage The data in the {% data variables.product.prodname_copilot_short %} usage metrics dashboard and API reports is updated on a regular schedule. -During the preview, you can expect data to be available within **three full days**. This means that data for a given day is processed and made available within three full UTC days after that day closes. - -For example, all usage data for a Monday (which closes at midnight UTC) will be visible in the dashboard and API by the end of Thursday UTC. In some cases, such as processing delays over weekends, data may appear up to four calendar days behind the current date. +You can expect data to be available within **two full days**. This means that data for a given day is processed and made available within two full UTC days after that day closes. ## What does the data measure? From 715bff5910fbf7fba3a57dc130aae4d0607ca17a Mon Sep 17 00:00:00 2001 From: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:49:42 +0000 Subject: [PATCH 04/10] [EDI] Assessing adoption of security features (#59990) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Sophie <29382425+sophietheking@users.noreply.github.com> --- .../assessing-adoption-code-security.md | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/assessing-adoption-code-security.md b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/assessing-adoption-code-security.md index fc4863cbf81f..1d47b369b587 100644 --- a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/assessing-adoption-code-security.md +++ b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/assessing-adoption-code-security.md @@ -2,7 +2,7 @@ title: Assessing adoption of security features shortTitle: Assess adoption of features allowTitleToDifferFromFilename: true -intro: You can use security overview to see which teams and repositories have already enabled features for secure coding, and identify any that are not yet protected. +intro: See which teams and repositories have already enabled features for secure coding, and identify any that are not yet protected. permissions: '{% data reusables.permissions.security-overview %}' product: '{% data reusables.gated-features.security-overview-fpt-both %}' contentType: how-tos @@ -21,9 +21,7 @@ redirect_from: - /code-security/security-overview/assessing-adoption-code-security --- -## About adoption of features for secure coding - -You can use security overview to see which repositories and teams have already enabled each security feature, and where people need more encouragement to adopt these features. The "Security coverage" view shows a summary and detailed information on feature enablement for an organization. You can filter the view to show a subset of repositories using the "enabled" and "not enabled" links, the "Teams" dropdown menu, and a search field in the page header. +You can use security overview to see which repositories and teams have already enabled each security feature, and where people need more encouragement to adopt these features. {% ifversion security-configurations %} ![Screenshot of the header section of the "Security coverage" view on the "Security" tab for an organization.](/assets/images/help/security-overview/security-coverage-view-summary.png) @@ -34,12 +32,6 @@ You can use security overview to see which repositories and teams have already e >[!NOTE] "Pull request alerts" are reported as enabled only when {% data variables.product.prodname_code_scanning %} has analyzed at least one pull request since alerts were enabled for the repository. -{% ifversion security-overview-export-data %} -You can download a CSV file of the data displayed on the "Security coverage" page. This data file can be used for efforts like security research and in-depth data analysis, and can integrate easily with external datasets. For more information, see [AUTOTITLE](/code-security/security-overview/exporting-data-from-security-overview). -{% endif %} - -You can use the "Enablement trends" view to see enablement status and enablement status trends over time for {% data variables.product.prodname_dependabot %}, {% data variables.product.prodname_code_scanning %}, or {% data variables.product.prodname_secret_scanning %} for repositories in an organization, or across organizations in an enterprise. For each of these features, you can view a graph visualizing the percentage of repositories that have the feature enabled, as well as a detailed table with enablement percentages for different points in time. For more information, see [Viewing enablement trends for an organization](#viewing-enablement-trends-for-an-organization) and [Viewing enablement trends for an enterprise](#viewing-enablement-trends-for-an-enterprise). - ## Viewing the enablement of security features for an organization You can view data to assess the enablement of features for secure coding across repositories in an organization. @@ -116,10 +108,21 @@ You can view data to assess the enablement status and enablement status trends o >[!TIP] You can use the `owner:` filter in the search field to filter the data by organization. For more information, see [AUTOTITLE](/code-security/security-overview/filtering-alerts-in-security-overview). -## Interpreting and acting on the enablement data +## Acting on enablement data + +After you have reviewed enablement coverage, consider the following actions. -Some security features can and should be enabled on all repositories. For example, {% data variables.secret-scanning.alerts %} and push protection reduce the risk of a security leak no matter what information is stored in the repository. If you see repositories that don't already use these features, you should either enable them or discuss an enablement plan with the team who owns the repository. For information on enabling features for a whole organization, see {% ifversion security-configurations %}[AUTOTITLE](/code-security/securing-your-organization/enabling-security-features-in-your-organization){% else %}[AUTOTITLE](/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-security-and-analysis-settings-for-your-organization){% endif %}. +1. Check if your enterprise has configured overly restrictive policies that limit the use of security features. See [AUTOTITLE](/admin/policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-code-security-and-analysis-for-your-enterprise). +1. Enable features that should be enabled on all repositories. For information on enabling features for a whole organization, see {% ifversion security-configurations %}[AUTOTITLE](/code-security/securing-your-organization/enabling-security-features-in-your-organization){% else %}[AUTOTITLE](/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-security-and-analysis-settings-for-your-organization){% endif %}. -Other features are not suitable for use in all repositories. For example, there would be no point in enabling {% data variables.product.prodname_dependabot %} for repositories that only use ecosystems or languages that are unsupported. As such, it's normal to have some repositories where these features are not enabled. + For example, {% data variables.secret-scanning.alerts %} and push protection reduce the risk of a security leak no matter what information is stored in the repository. If you see repositories that don't already use these features, you should either enable them or discuss an enablement plan with the team who owns the repository. + +1. For other features, consider whether the feature should be enabled in more repositories. For example, there would be no point in enabling {% data variables.product.prodname_dependabot %} for repositories that only use ecosystems or languages that are unsupported. As such, it's normal to have some repositories where these features are not enabled. + +## Next steps + +{% ifversion security-overview-export-data %} +You can download a CSV file of the data displayed on the "Security coverage" page. This data file can be used for efforts like security research and in-depth data analysis, and can integrate easily with external datasets. See [AUTOTITLE](/code-security/security-overview/exporting-data-from-security-overview). +{% endif %} -Your enterprise may also have configured policies to limit the use of some security features. For more information, see [AUTOTITLE](/admin/policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-code-security-and-analysis-for-your-enterprise). +You can use the "Enablement trends" view to see enablement status and enablement status trends over time for {% data variables.product.prodname_dependabot %}, {% data variables.product.prodname_code_scanning %}, or {% data variables.product.prodname_secret_scanning %} across repositories or organizations. See [Viewing enablement trends for an organization](#viewing-enablement-trends-for-an-organization) or [Viewing enablement trends for an enterprise](#viewing-enablement-trends-for-an-enterprise). From 70a2adbb4b87df2a2c213e2f1a92ef7f78134c14 Mon Sep 17 00:00:00 2001 From: Sam Browning <106113886+sabrowning1@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:53:23 -0500 Subject: [PATCH 05/10] [EDI] Testing query help files (#60008) --- .../testing-query-help-files.md | 55 +++++-------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/content/code-security/how-tos/scan-code-for-vulnerabilities/scan-from-the-command-line/testing-query-help-files.md b/content/code-security/how-tos/scan-code-for-vulnerabilities/scan-from-the-command-line/testing-query-help-files.md index 272b09a716b7..d4ee44abaf82 100644 --- a/content/code-security/how-tos/scan-code-for-vulnerabilities/scan-from-the-command-line/testing-query-help-files.md +++ b/content/code-security/how-tos/scan-code-for-vulnerabilities/scan-from-the-command-line/testing-query-help-files.md @@ -1,7 +1,7 @@ --- title: Testing query help files shortTitle: Test query help files -intro: You can use the {% data variables.product.prodname_codeql_cli %} to preview your query help files as Markdown and ensure they are valid. +intro: Ensure your {% data variables.product.prodname_codeql %} query help files are valid by previewing them as Markdown. product: '{% data reusables.gated-features.codeql %}' versions: fpt: '*' @@ -18,53 +18,28 @@ redirect_from: contentType: how-tos --- -## About testing query help files - -Test query help files by rendering them as Markdown to ensure they are valid before uploading them to the {% data variables.product.prodname_codeql %} repository or using them in code scanning. - - - -Query help is documentation that accompanies a query to explain how the query works, as well as providing information about the potential problem that the query identifies. It is good practice to write query help for all new queries. For more information, see [Contributing to {% data variables.product.prodname_codeql %}](https://github.com/github/codeql/blob/main/CONTRIBUTING.md) in the {% data variables.product.prodname_codeql %} repository. - -The {% data variables.product.prodname_codeql_cli %} includes a command to test query help and render the content as markdown, so that you can easily preview the content in your IDE. Use the command to validate query help files before uploading them to the {% data variables.product.prodname_codeql %} repository or sharing them with other users. From {% data variables.product.prodname_codeql_cli %} 2.7.1 onwards, you can also include the markdown-rendered query help in SARIF files -generated during {% data variables.product.prodname_codeql %} analyses so that the query help can be displayed in the code scanning UI. For more information, see [AUTOTITLE](/code-security/codeql-cli/getting-started-with-the-codeql-cli/analyzing-your-code-with-codeql-queries). - ## Prerequisites -* The query help (`.qhelp`) file must have an accompanying query (`.ql`) file with an identical base name. -* The query help file should follow the standard structure and style for query help documentation. For more information, see the [Query help style guide](https://github.com/github/codeql/blob/main/docs/query-help-style-guide.md) in the {% data variables.product.prodname_codeql %} repository. - -## Running `codeql generate query-help` - -You can test query help files by running the following command: - -```shell -codeql generate query-help --format= [--output=] -``` - -For this command `` must be the path to a `.qhelp` file, the path to a `.ql` file, the path to a directory containing queries and query help files, or the path to a query suite. - -You must specify a `--format` option, which defines how the query help is rendered. Currently, you must specify `markdown` to render the query help as markdown. - -The `--output` option defines a file path where the rendered query help will be saved. - -* For directories containing `.qhelp` files or a query suites defining one or more `.qhelp` files, you must specify an `--output` directory. Filenames within the output directory will be derived from the `.qhelp` file names. -* For single `.qhelp` or `.ql` files, you may specify an `--output` option. If you don’t specify an output path, the rendered query help is written to `stdout`. - -For full details of all the options you can use when testing query help files, see [AUTOTITLE](/code-security/codeql-cli/codeql-cli-manual/generate-query-help). +* The query help (`.qhelp`) files must have accompanying query (`.ql`) files with identical base names. +* The query help files should follow the standard structure and style for query help documentation. For more information, see the [Query help style guide](https://github.com/github/codeql/blob/main/docs/query-help-style-guide.md) in the {% data variables.product.prodname_codeql %} repository. -## Results +## Previewing your query help files -When you run the command, {% data variables.product.prodname_codeql %} attempts to render each `.qhelp` file that has an accompanying `.ql` file. For single files, the rendered content will be printed to `stdout` if you don’t specify an `--output` option. For all other use cases, the rendered content is saved to the specified output path. +1. To render your query help files as Markdown, run the following command: -By default, the {% data variables.product.prodname_codeql_cli %} will print a warning message if: + ```shell copy + codeql generate query-help --format=markdown [--output=] + ``` -* Any of the query help is invalid, along with a description of the invalid query help elements -* Any `.qhelp` files specified in the command don’t have the same base name as an accompanying `.ql` file -* Any `.ql` files specified in the command don’t have the same base name as an accompanying `.qhelp` file + For information on the options available for this command, see [AUTOTITLE](/code-security/reference/code-scanning/codeql/codeql-cli-manual/generate-query-help). -You can tell the {% data variables.product.prodname_codeql_cli %} how to handle these warnings by including a `--warnings` option in your command. For more information, see [AUTOTITLE](/code-security/codeql-cli/codeql-cli-manual/generate-query-help#--warningsmode). +1. If you receive any warning messages, review and fix them, then rerun the command. By default, the {% data variables.product.prodname_codeql_cli %} will print a warning message if: + * Any of the query help is invalid + * Any `.qhelp` files specified in the command don’t have the same base name as an accompanying `.ql` file + * Any `.ql` files specified in the command don’t have the same base name as an accompanying `.qhelp` file +1. Review the rendered Markdown in your output directory, file, or terminal to check that your files appear as expected. ## Further reading * [Query help files](https://codeql.github.com/docs/writing-codeql-queries/query-help-files/#query-help-files) +* [AUTOTITLE](/code-security/codeql-cli/codeql-cli-manual/generate-query-help) From f7df0cd0db87c1d9f42f9ca87b2cd68770ecfe56 Mon Sep 17 00:00:00 2001 From: Sam Browning <106113886+sabrowning1@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:53:29 -0500 Subject: [PATCH 06/10] [EDI] Interpreting security findings (#60044) --- ...pplying-a-custom-security-configuration.md | 2 +- .../find-insecure-repositories.md | 31 +++++++ .../analyze-organization-data/index.md | 2 +- .../interpreting-security-findings.md | 89 ------------------- ...security-overview-feature-specific-page.md | 2 +- 5 files changed, 34 insertions(+), 92 deletions(-) create mode 100644 content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/find-insecure-repositories.md delete mode 100644 content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/interpreting-security-findings.md diff --git a/content/code-security/how-tos/secure-at-scale/configure-organization-security/establish-complete-coverage/applying-a-custom-security-configuration.md b/content/code-security/how-tos/secure-at-scale/configure-organization-security/establish-complete-coverage/applying-a-custom-security-configuration.md index c20779d4fe1a..1e3c44c871c3 100644 --- a/content/code-security/how-tos/secure-at-scale/configure-organization-security/establish-complete-coverage/applying-a-custom-security-configuration.md +++ b/content/code-security/how-tos/secure-at-scale/configure-organization-security/establish-complete-coverage/applying-a-custom-security-configuration.md @@ -38,7 +38,7 @@ After you create a {% data variables.product.prodname_custom_security_configurat ## Next steps -To learn how to interpret security findings from your {% data variables.product.prodname_custom_security_configuration %} on a repository, see [AUTOTITLE](/code-security/securing-your-organization/managing-the-security-of-your-organization/interpreting-security-findings). +To learn how to monitor security alerts in your organization, see [AUTOTITLE](/code-security/how-tos/view-and-interpret-data/analyze-organization-data/find-insecure-repositories). {% data reusables.security-configurations.edit-configuration-next-step %} diff --git a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/find-insecure-repositories.md b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/find-insecure-repositories.md new file mode 100644 index 000000000000..3ba5d6860d4e --- /dev/null +++ b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/find-insecure-repositories.md @@ -0,0 +1,31 @@ +--- +title: Finding repositories with security alerts using security overview +shortTitle: Find insecure repositories +intro: Monitor and prioritize security alerts with security overview. +permissions: '{% data reusables.permissions.security-org-enable %}' +versions: + feature: security-configurations +topics: + - Code Security + - Secret Protection + - Organizations + - Security +contentType: how-tos +redirect_from: + - /code-security/securing-your-organization/managing-the-security-of-your-organization/interpreting-security-findings-on-a-repository + - /code-security/securing-your-organization/managing-the-security-of-your-organization/interpreting-security-findings + - /code-security/securing-your-organization/managing-the-security-of-your-organization + - /code-security/how-tos/view-and-interpret-data/analyze-organization-data/interpreting-security-findings +--- + +> [!NOTE] +> {% data reusables.security-overview.information-varies-GHAS %} + +{% data reusables.organizations.navigate-to-org %} +{% data reusables.organizations.security-overview %} +1. By default, security overview shows alerts for all native {% data variables.product.github %} tools. To display alerts for a specific tool, replace `tool:github` in the filter text box: + * `tool:dependabot` shows only alerts for dependencies identified by {% data variables.product.prodname_dependabot %} + * `tool:secret-scanning` shows only alerts for secrets identified by {% data variables.product.prodname_secret_scanning %} + * `tool:codeql` shows only alerts for potential security vulnerabilities identified by {% data variables.product.prodname_codeql %} {% data variables.product.prodname_code_scanning %} +1. You can add further filters to show only the repositories you want to assess. The list of repositories and metrics displayed on the page automatically update to match your current selection. For more information on filtering, see [AUTOTITLE](/code-security/security-overview/filtering-alerts-in-security-overview). +{% data reusables.organizations.security-overview-feature-specific-page %} diff --git a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/index.md b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/index.md index 8a87fcfb7265..83c5b040396c 100644 --- a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/index.md +++ b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/index.md @@ -19,9 +19,9 @@ children: - /assessing-code-security-risk - /assessing-adoption-code-security - /explore-code-quality + - /find-insecure-repositories - /exporting-data-from-security-overview - /viewing-security-insights - - /interpreting-security-findings - /viewing-metrics-for-pull-request-alerts - /viewing-metrics-for-secret-scanning-push-protection - /viewing-metrics-for-dependabot-alerts diff --git a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/interpreting-security-findings.md b/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/interpreting-security-findings.md deleted file mode 100644 index a40840b536b2..000000000000 --- a/content/code-security/how-tos/view-and-interpret-data/analyze-organization-data/interpreting-security-findings.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Interpreting security findings -shortTitle: Interpret security data -intro: You can analyze security data on repositories in your organization to determine if you need to make changes to your security setup. -permissions: '{% data reusables.permissions.security-org-enable %}' -versions: - feature: security-configurations -topics: - - Code Security - - Secret Protection - - Organizations - - Security -contentType: how-tos -redirect_from: - - /code-security/securing-your-organization/managing-the-security-of-your-organization/interpreting-security-findings-on-a-repository - - /code-security/securing-your-organization/managing-the-security-of-your-organization/interpreting-security-findings - - /code-security/securing-your-organization/managing-the-security-of-your-organization ---- - -## About security findings - -After you apply a {% data variables.product.prodname_security_configuration %} to a repository, the enabled security features will likely raise security findings on that repository. These findings may show up as feature-specific alerts, or as automatically generated pull requests designed to keep your repositories secure. You can analyze the findings across the organization and make any necessary adjustments to your {% data variables.product.prodname_security_configuration %}. - -To best secure your organization, you should encourage contributors to review and resolve security alerts and pull requests. {% ifversion security-campaigns %}In addition, you can collaborate with contributors to fix historical security alerts, see [AUTOTITLE](/code-security/securing-your-organization/fixing-security-alerts-at-scale/best-practice-fix-alerts-at-scale).{% endif %} - -## Finding repositories with security alerts using security overview - -{% data reusables.security-overview.information-varies-GHAS %} -{% data reusables.organizations.navigate-to-org %} -{% data reusables.organizations.security-overview %} -1. By default, the overview shows alerts for all native {% data variables.product.github %} tools (filter: `tool:github`). To display alerts for a specific tool, replace `tool:github` in the filter text box. For example: - * `tool:dependabot` to show only alerts for dependencies identified by {% data variables.product.prodname_dependabot %}. - * `tool:secret-scanning` to only show alerts for secrets identified by {% data variables.product.prodname_secret_scanning %}. - * `tool:codeql` to show only alerts for potential security vulnerabilities identified by {% data variables.product.prodname_codeql %} {% data variables.product.prodname_code_scanning %}. -1. You can add further filters to show only the repositories you want to assess. The list of repositories and metrics displayed on the page automatically update to match your current selection. For more information on filtering, see [AUTOTITLE](/code-security/security-overview/filtering-alerts-in-security-overview). -{% data reusables.organizations.security-overview-feature-specific-page %} - -## Interpreting {% data variables.product.prodname_secret_scanning %} alerts - -{% data reusables.security-configurations.secret-scanning-security-configs-summary %} {% ifversion fpt or ghec %}There are two types of {% data variables.product.prodname_secret_scanning %} alerts: - -* {% data variables.secret-scanning.partner_alerts_caps %}, which are sent to the provider who issued the secret -* {% data variables.secret-scanning.user_alerts_caps %}, which appear on {% data variables.product.github %} and can be resolved - -{% endif %} -You can view {% data variables.product.prodname_secret_scanning %} alerts for an organization by navigating to the main page of that organization, clicking the **{% octicon "shield" aria-hidden="true" aria-label="shield" %} Security** tab, then clicking **{% octicon "key" aria-hidden="true" aria-label="key" %} {% data variables.product.prodname_secret_scanning_caps %}** in the "Metrics" or "Alerts" section. - -* **Metrics**. To see detailed information on push protection events, see [AUTOTITLE](/code-security/security-overview/viewing-metrics-for-secret-scanning-push-protection). -* **Alerts**. To see detailed information on **Default** and **Generic** alerts for exposed secrets in the organization. - -For an introduction to {% data variables.product.prodname_secret_scanning %} alerts, see [AUTOTITLE](/code-security/secret-scanning/managing-alerts-from-secret-scanning/about-alerts). - -To learn how to evaluate {% data variables.product.prodname_secret_scanning %} alerts, see [AUTOTITLE](/code-security/secret-scanning/managing-alerts-from-secret-scanning/evaluating-alerts). - -## Interpreting {% data variables.product.prodname_code_scanning %} alerts - -{% data reusables.code-scanning.about-code-scanning %} These problems are raised as {% data variables.product.prodname_code_scanning %} alerts, which contain detailed information on the vulnerability or error detected. - -You can view the {% data variables.product.prodname_code_scanning %} alerts for an organization by navigating to the main page of that organization, clicking the **{% octicon "shield" aria-hidden="true" aria-label="shield" %} Security** tab, then clicking: - -* **{% data variables.product.prodname_codeql %} pull request alerts**. To see information on {% data variables.product.prodname_code_scanning %} alerts found and remediated in pull requests. -* **{% data variables.product.prodname_code_scanning_caps %}**. To see detailed information on alerts for potentially vulnerable code in the organization, see [AUTOTITLE](/code-security/security-overview/viewing-metrics-for-pull-request-alerts). - -For an introduction to {% data variables.product.prodname_code_scanning %} alerts, see [AUTOTITLE](/code-security/code-scanning/managing-code-scanning-alerts/about-code-scanning-alerts). - -To learn how to interpret and resolve {% data variables.product.prodname_code_scanning %} alerts, see [AUTOTITLE](/code-security/code-scanning/managing-code-scanning-alerts/assessing-code-scanning-alerts-for-your-repository) and [AUTOTITLE](/code-security/code-scanning/managing-code-scanning-alerts/resolving-code-scanning-alerts). - -## Interpreting {% data variables.product.prodname_dependabot_alerts %} - -{% data variables.product.prodname_dependabot_alerts %} inform you about vulnerabilities in the dependencies that you use in repositories in your organization. You can view {% data variables.product.prodname_dependabot_alerts %} for an organization by navigating to the main page of that organization, clicking the **{% octicon "shield" aria-hidden="true" aria-label="shield" %} Security** tab, then clicking **{% octicon "dependabot" aria-hidden="true" aria-label="dependabot" %} {% data variables.product.prodname_dependabot %}**. - -For an introduction to {% data variables.product.prodname_dependabot_alerts %}, see [AUTOTITLE](/code-security/dependabot/dependabot-alerts/about-dependabot-alerts). - -To learn how to interpret and resolve {% data variables.product.prodname_dependabot_alerts %}, see [AUTOTITLE](/code-security/dependabot/dependabot-alerts/viewing-and-updating-dependabot-alerts). - -> [!NOTE] -> If you enabled {% data variables.product.prodname_dependabot_security_updates %}, {% data variables.product.prodname_dependabot %} can also automatically raise pull requests to update the dependencies used in the repositories of the organization. For more information, see [AUTOTITLE](/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates). - -## Next steps - -{% ifversion security-configurations-cloud %} - -If you are using the {% data variables.product.prodname_github_security_configuration %}, and your findings indicate the security enablement settings are not meeting your needs, you should create a {% data variables.product.prodname_custom_security_configuration %}. To get started, see [AUTOTITLE](/code-security/securing-your-organization/enabling-security-features-in-your-organization/creating-a-custom-security-configuration). - -{% endif %} - -If {% ifversion security-configurations-cloud %}you are using a {% data variables.product.prodname_custom_security_configuration %}, and {% endif %}your findings indicate the security enablement settings are not meeting your needs, you can edit your existing configuration. For more information, see [AUTOTITLE](/code-security/securing-your-organization/managing-the-security-of-your-organization/editing-a-custom-security-configuration). - -Lastly, you can also edit your organization-level security settings with {% data variables.product.prodname_global_settings %}. To learn more, see [AUTOTITLE](/code-security/securing-your-organization/enabling-security-features-in-your-organization/configuring-global-security-settings-for-your-organization). diff --git a/data/reusables/organizations/security-overview-feature-specific-page.md b/data/reusables/organizations/security-overview-feature-specific-page.md index 9eefe104f540..c61f4d1c45c5 100644 --- a/data/reusables/organizations/security-overview-feature-specific-page.md +++ b/data/reusables/organizations/security-overview-feature-specific-page.md @@ -1 +1 @@ -1. Optionally, use the sidebar on the left to explore alerts for a specific security feature in greater detail. On each page, you can use filters that are specific to that feature to refine your search. For more information about the available qualifiers, see [AUTOTITLE](/code-security/security-overview/filtering-alerts-in-security-overview). +1. Optionally, use the sidebar on the left to explore alerts for a specific security feature in greater detail. On each page, you can use filters that are specific to that feature to refine your search. From 4c16416e47b0029863791a8806a799af97d6fe30 Mon Sep 17 00:00:00 2001 From: Kathleen <36471738+kathleenqin@users.noreply.github.com> Date: Thu, 5 Mar 2026 07:24:54 -0800 Subject: [PATCH 07/10] Update copilot-usage-metrics.md with further IDE and CLI definitions (#60042) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Sophie <29382425+sophietheking@users.noreply.github.com> --- .../copilot-usage-metrics/copilot-usage-metrics.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md b/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md index 5c245f4c0d17..fce6ecf89672 100644 --- a/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md +++ b/content/copilot/reference/copilot-usage-metrics/copilot-usage-metrics.md @@ -91,6 +91,10 @@ These fields appear in the exported NDJSON reports and in the {% data variables. | `last_known_ide_version` / `last_known_plugin_version` | The most recent IDE and {% data variables.copilot.copilot_chat_short %} extension version detected for each user. | | `daily_active_cli_users` | Number of unique users in the enterprise who used {% data variables.product.prodname_copilot_short %} via the CLI on a given day. This field is **independent** of IDE active user counts and is **not** included in IDE-based active user definitions. Omitted for enterprises with no CLI usage on that day. | | `totals_by_cli` | Breakdown of CLI-specific metrics for the enterprise on a given day. Independent of IDE metrics—CLI usage is **not** reflected in other fields such as `totals_by_ide` or `totals_by_feature`. Omitted for enterprises with no CLI usage on that day. See [{% data variables.copilot.copilot_cli_short %} metrics fields](#copilot-cli-metrics-fields-api-only) below. | +| `used_cli` | Captures whether the user has used {% data variables.copilot.copilot_cli_short %} that day. | +| `used_agent` | Captures whether the user has used IDE agent mode that day. | +| `used_chat` | Captures whether the user has used IDE chat that day. | + ### {% data variables.copilot.copilot_cli_short %} metrics fields (API only) @@ -103,6 +107,8 @@ The `totals_by_cli` object contains the following nested fields when CLI usage i | `totals_by_cli.token_usage.output_tokens_sum` | Total number of output tokens generated across all CLI requests on this day. | | `totals_by_cli.token_usage.prompt_tokens_sum` | Total number of prompt tokens sent across all CLI requests on this day. | | `totals_by_cli.token_usage.avg_tokens_per_request` | Average number of **output** and **prompt** tokens per CLI request, computed as `(output_tokens_sum + prompt_tokens_sum) ÷ request_count`.| +| `totals_by_cli.prompt_count` | Total number of user prompts, commands, or queries executed within a session. | +| `totals_by_cli.last_known_cli_version` | Most recent Copilot CLI version detected for the user that day. | ### Pull request activity fields (API only) From a8bcc51947464bc3b017ce0734c6e85261b4dc83 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Thu, 5 Mar 2026 07:31:42 -0800 Subject: [PATCH 08/10] Clarify backtick escaping instruction for gh cli (#59846) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: heiskr <1221423+heiskr@users.noreply.github.com> --- .github/instructions/all.instructions.md | 1 - .github/instructions/code.instructions.md | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/instructions/all.instructions.md b/.github/instructions/all.instructions.md index b370dc3dbb98..a32182f60098 100644 --- a/.github/instructions/all.instructions.md +++ b/.github/instructions/all.instructions.md @@ -29,4 +29,3 @@ When you create a pull request: 3. Label with "llm-generated". 4. If an issue exists, include "fixes owner/repo#issue" or "towards owner/repo#issue" as appropriate. 5. Always create PRs in **draft mode** using `--draft` flag. -6. When you are using gh cli, always _escape backticks_. diff --git a/.github/instructions/code.instructions.md b/.github/instructions/code.instructions.md index f2ba0e5bba17..17d3679bd61d 100644 --- a/.github/instructions/code.instructions.md +++ b/.github/instructions/code.instructions.md @@ -9,7 +9,7 @@ For code reviews, follow guidelines, tests, and validate instructions. For creat ## Guidelines - If available, use ripgrep (`rg`) instead of `grep`. -- When using gh cli, always _escape backticks_. +- When using gh cli in double-quoted strings, escape backticks to prevent bash command substitution. In single-quoted strings, backticks do not need escaping. - All scripts should be listed in `package.json` and use `tsx`. - Whenever you create or comment on an issue or pull request, indicate you are GitHub Copilot. - Be careful fetching full HTML pages off the internet. Prefer to use MCP or gh cli whenever possible for github.com. Limit the number of tokens when grabbing HTML. @@ -17,6 +17,8 @@ For code reviews, follow guidelines, tests, and validate instructions. For creat - All new code should be written in TypeScript and not JavaScript. - We use absolute imports, relative to the `src` directory, using the `@` symbol. For example, `getRedirect` which lives in `src/redirects/lib/get-redirect.ts` can be imported with `import getRedirect from '@/redirects/lib/get-redirect'`. The same rule applies for TypeScript (`.ts`) imports, e.g. `import type { GeneralSearchHit } from '@/search/types'` - For updates to the content linter, read important information in `src/content-linter/README.md`. +- Do not commit to `main` branch. +- Do not use git force push, and avoid git rebase. ## Tests From 6f3cb206888404f5b22d978a34b31b9a2b5215b9 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Thu, 5 Mar 2026 07:32:12 -0800 Subject: [PATCH 09/10] Fix search indexing Slack alert failing on empty message (#59848) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/index-general-search.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/index-general-search.yml b/.github/workflows/index-general-search.yml index f23ccf201398..47db5026c871 100644 --- a/.github/workflows/index-general-search.yml +++ b/.github/workflows/index-general-search.yml @@ -285,7 +285,7 @@ jobs: } >> "$GITHUB_OUTPUT" - name: Send consolidated Slack notification - if: ${{ steps.check-artifacts.outputs.has_artifacts == 'true' }} + if: ${{ steps.check-artifacts.outputs.has_artifacts == 'true' && fromJSON(steps.aggregate.outputs.result).hasFailures }} uses: ./.github/actions/slack-alert with: slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }} From 189007e8655a30fbeaf1ffa2f9f240e6590b3cc1 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Thu, 5 Mar 2026 07:34:59 -0800 Subject: [PATCH 10/10] Render REST response schemas as markdown to fix activity/events 503 (#59845) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/article-api/lib/summarize-schema.ts | 194 ++++++++++++++++++ .../templates/rest-page.template.md | 21 +- src/article-api/tests/rest-transformer.ts | 35 +--- src/article-api/tests/summarize-schema.ts | 174 ++++++++++++++++ .../transformers/rest-transformer.ts | 3 +- 5 files changed, 391 insertions(+), 36 deletions(-) create mode 100644 src/article-api/lib/summarize-schema.ts create mode 100644 src/article-api/tests/summarize-schema.ts diff --git a/src/article-api/lib/summarize-schema.ts b/src/article-api/lib/summarize-schema.ts new file mode 100644 index 000000000000..8d467d3b5b4e --- /dev/null +++ b/src/article-api/lib/summarize-schema.ts @@ -0,0 +1,194 @@ +type JsonSchema = { + type?: string | string[] + format?: string + enum?: (string | number | boolean)[] + default?: unknown + deprecated?: boolean + readOnly?: boolean + minimum?: number + maximum?: number + minLength?: number + maxLength?: number + pattern?: string + minItems?: number + maxItems?: number + uniqueItems?: boolean + additionalProperties?: boolean | JsonSchema + properties?: Record + required?: string[] + items?: JsonSchema + oneOf?: JsonSchema[] + anyOf?: JsonSchema[] + allOf?: JsonSchema[] + title?: string + description?: string + examples?: unknown[] + example?: unknown +} + +const MAX_DEPTH = 4 + +function renderTypeConstraints(schema: JsonSchema): string { + const parts: string[] = [] + + const t = schema.type + if (t) { + parts.push(Array.isArray(t) ? t.join(' or ') : t) + } + if (schema.format) parts.push(`format: ${schema.format}`) + if (schema.enum) { + const vals = schema.enum.map((v) => `\`${v}\``).join(', ') + parts.push(`enum: ${vals}`) + } + if (schema.default !== undefined) parts.push(`default: \`${JSON.stringify(schema.default)}\``) + if (schema.deprecated) parts.push('deprecated') + if (schema.readOnly) parts.push('read-only') + if (schema.minimum !== undefined) parts.push(`minimum: ${schema.minimum}`) + if (schema.maximum !== undefined) parts.push(`maximum: ${schema.maximum}`) + if (schema.minLength !== undefined) parts.push(`minLength: ${schema.minLength}`) + if (schema.maxLength !== undefined) parts.push(`maxLength: ${schema.maxLength}`) + if (schema.pattern) parts.push(`pattern: \`${schema.pattern}\``) + if (schema.minItems !== undefined) parts.push(`minItems: ${schema.minItems}`) + if (schema.maxItems !== undefined) parts.push(`maxItems: ${schema.maxItems}`) + if (schema.uniqueItems) parts.push('unique items') + if (schema.additionalProperties === true) { + parts.push('additional properties allowed') + } else if (typeof schema.additionalProperties === 'object') { + parts.push(`additional properties: ${renderTypeConstraints(schema.additionalProperties)}`) + } + + return parts.join(', ') || 'object' +} + +function renderCompositionVariants( + keyword: string, + variants: JsonSchema[], + indent: number, + depth: number, +): string { + const prefix = ' '.repeat(indent) + const label = keyword.replace('Of', ' of') + const lines: string[] = [`${prefix}* ${label}:`] + + for (const variant of variants) { + const name = variant.title || renderTypeConstraints(variant) + lines.push(`${prefix} * **${name}**`) + if (depth < MAX_DEPTH && variant.properties) { + const nested = renderProperties(variant, indent + 2, depth + 1) + if (nested) lines.push(nested) + } + } + + return lines.join('\n') +} + +function renderProperties( + schema: JsonSchema, + indent: number, + depth: number, + requiredFields?: string[], +): string { + const props = schema.properties || {} + const req = new Set(requiredFields || schema.required || []) + const prefix = ' '.repeat(indent) + const lines: string[] = [] + + for (const [name, prop] of Object.entries(props)) { + const reqStr = req.has(name) ? 'required, ' : '' + + // Check for composition keywords at property level + const compositionKey = (['oneOf', 'anyOf', 'allOf'] as const).find((k) => prop[k]) + if (compositionKey) { + const label = compositionKey.replace('Of', ' of') + lines.push(`${prefix}* \`${name}\`: ${reqStr}${label}:`) + for (const variant of prop[compositionKey]!) { + const vName = variant.title || renderTypeConstraints(variant) + lines.push(`${prefix} * **${vName}**`) + if (depth < MAX_DEPTH && variant.properties) { + const nested = renderProperties(variant, indent + 2, depth + 1) + if (nested) lines.push(nested) + } + } + continue + } + + const propType = Array.isArray(prop.type) ? prop.type[0] : prop.type + + if (propType === 'array' && prop.items) { + const itemTitle = prop.items.title + if (prop.items.properties && depth < MAX_DEPTH) { + const label = itemTitle ? `array of \`${itemTitle}\`` : 'array of objects' + lines.push(`${prefix}* \`${name}\`: ${reqStr}${label}:`) + lines.push(renderProperties(prop.items, indent + 1, depth + 1)) + } else { + lines.push(`${prefix}* \`${name}\`: ${reqStr}array of ${renderTypeConstraints(prop.items)}`) + } + } else if (prop.properties && depth < MAX_DEPTH) { + const label = prop.title ? `\`${prop.title}\`` : renderTypeConstraints(prop) + lines.push(`${prefix}* \`${name}\`: ${reqStr}${label}:`) + lines.push(renderProperties(prop, indent + 1, depth + 1)) + } else { + lines.push(`${prefix}* \`${name}\`: ${reqStr}${renderTypeConstraints(prop)}`) + } + } + + return lines.filter(Boolean).join('\n') +} + +/** + * Converts a JSON Schema response object into a readable markdown bullet list. + * Includes type, required, format, enum, default, constraints — but omits + * examples and descriptions to keep the output compact. + */ +export function summarizeSchema(schema: JsonSchema): string { + if (!schema || typeof schema !== 'object') return '' + + // Handle top-level composition + for (const keyword of ['oneOf', 'anyOf', 'allOf'] as const) { + if (schema[keyword]) { + return renderCompositionVariants(keyword, schema[keyword]!, 0, 0) + } + } + + // Handle top-level array + if (schema.type === 'array' && schema.items) { + const items = schema.items + const constraints: string[] = [] + if (schema.minItems !== undefined) constraints.push(`minItems: ${schema.minItems}`) + if (schema.maxItems !== undefined) constraints.push(`maxItems: ${schema.maxItems}`) + if (schema.uniqueItems) constraints.push('unique items') + const constraintStr = constraints.length ? ` (${constraints.join(', ')})` : '' + const itemTitle = items.title + + // Composition inside items + const compositionKey = (['oneOf', 'anyOf', 'allOf'] as const).find((k) => items[k]) + if (compositionKey) { + const label = compositionKey.replace('Of', ' of') + const titlePart = itemTitle ? `\`${itemTitle}\` ` : '' + const lines = [`Array${constraintStr} of ${titlePart}objects: ${label}:`] + for (const variant of items[compositionKey]!) { + const name = variant.title || renderTypeConstraints(variant) + lines.push(` * **${name}**`) + if (variant.properties) { + const nested = renderProperties(variant, 2, 1) + if (nested) lines.push(nested) + } + } + return lines.join('\n') + } + + if (items.properties) { + const label = itemTitle ? `\`${itemTitle}\`` : 'objects' + return `Array${constraintStr} of ${label}:\n${renderProperties(items, 1, 1)}` + } + + return `Array${constraintStr} of ${renderTypeConstraints(items)}` + } + + // Handle top-level object + if (schema.properties) { + return renderProperties(schema, 0, 0) + } + + return renderTypeConstraints(schema) +} diff --git a/src/article-api/templates/rest-page.template.md b/src/article-api/templates/rest-page.template.md index 50a9a25f02f1..73e7e4311149 100644 --- a/src/article-api/templates/rest-page.template.md +++ b/src/article-api/templates/rest-page.template.md @@ -5,6 +5,7 @@ {{ manualContent }} {% for operation in restOperations %} + ## {{ operation.title }} ``` @@ -14,22 +15,27 @@ {{ operation.description }} {% if operation.hasParameters %} + ### Parameters {% if operation.showHeaders %} + #### Headers {% if operation.needsContentTypeHeader %} + - **`content-type`** (string, required) Setting to `application/json` is required. {% endif %} + - **`accept`** (string) Setting to `application/vnd.github+json` is recommended. {% endif %} {% if operation.parameters.size > 0 %} + #### Path and query parameters {% for param in operation.parameters %} @@ -39,6 +45,7 @@ {% endif %} {% if operation.bodyParameters.size > 0 %} + #### Body parameters {% for param in operation.bodyParameters %} @@ -49,19 +56,23 @@ {% endif %} {% if operation.statusCodes.size > 0 %} + ### HTTP response status codes {% for statusCode in operation.statusCodes %} + - **{{ statusCode.httpStatusCode }}**{% if statusCode.description %} - {{ statusCode.description }}{% elsif statusCode.httpStatusMessage %} - {{ statusCode.httpStatusMessage }}{% endif %} {% endfor %} {% endif %} {% if operation.codeExamples.size > 0 %} + ### Code examples {% for example in operation.codeExamples %} {% if example.request.description %} + #### {{ example.request.description }} {% endif %} @@ -80,18 +91,10 @@ curl -L \ -d '{{ example.request.bodyParameters }}'{% endif %} ``` -**Response schema:** +**Response schema (Status: {{ example.response.statusCode }}):** {% if example.response.schema %} -```json -Status: {{ example.response.statusCode }} - {{ example.response.schema }} -``` -{% else %} -``` -Status: {{ example.response.statusCode }} -``` {% endif %} {% endfor %} diff --git a/src/article-api/tests/rest-transformer.ts b/src/article-api/tests/rest-transformer.ts index 3cd8e6d5ad85..ee5d0d5794ad 100644 --- a/src/article-api/tests/rest-transformer.ts +++ b/src/article-api/tests/rest-transformer.ts @@ -107,7 +107,7 @@ describe('REST transformer', () => { // Check for request/response labels expect(res.body).toContain('**Request:**') - expect(res.body).toContain('**Response schema:**') + expect(res.body).toContain('**Response schema (Status: 200):**') // Check for curl code block expect(res.body).toContain('```curl') @@ -173,36 +173,19 @@ describe('REST transformer', () => { expect(res.body).toMatch(/\[.*?\]\(\/en\/.*?\)/) }) - test('Response schema is formatted correctly', async () => { + test('Response schema is formatted as markdown', async () => { const res = await get(makeURL('/en/rest/actions/artifacts')) expect(res.statusCode).toBe(200) - // Check for JSON code block with schema label - expect(res.body).toContain('**Response schema:**') - expect(res.body).toContain('```json') - expect(res.body).toContain('Status: 200') + // Check for markdown-formatted schema + expect(res.body).toContain('**Response schema (Status: 200):**') - // Verify schema structure is present (not an example) - expect(res.body).toContain('"type":') - expect(res.body).toContain('"properties":') + // Schema should be rendered as a markdown bullet list, not JSON + expect(res.body).toContain('* `total_count`:') + expect(res.body).toContain('* `artifacts`:') - // Check for common schema keywords - const schemaMatch = res.body.match(/```json\s+Status: 200\s+([\s\S]*?)```/) - expect(schemaMatch).toBeTruthy() - - if (schemaMatch) { - const schemaContent = schemaMatch[1] - const schema = JSON.parse(schemaContent) - - // Verify it's a valid OpenAPI/JSON schema structure - expect(schema).toHaveProperty('type') - expect(schema.type).toBe('object') - expect(schema).toHaveProperty('properties') - - // Verify it has expected properties for artifacts response - expect(schema.properties).toHaveProperty('total_count') - expect(schema.properties).toHaveProperty('artifacts') - } + // Should not contain raw JSON Schema keywords + expect(res.body).not.toContain('"properties":') }) test('Non-REST pages return appropriate error', async () => { diff --git a/src/article-api/tests/summarize-schema.ts b/src/article-api/tests/summarize-schema.ts new file mode 100644 index 000000000000..221cef0fccab --- /dev/null +++ b/src/article-api/tests/summarize-schema.ts @@ -0,0 +1,174 @@ +import { describe, expect, test } from 'vitest' + +import { summarizeSchema } from '@/article-api/lib/summarize-schema' + +describe('summarizeSchema', () => { + test('simple object with properties', () => { + const result = summarizeSchema({ + type: 'object', + required: ['id', 'name'], + properties: { + id: { type: 'integer' }, + name: { type: 'string' }, + email: { type: 'string', format: 'email' }, + }, + }) + expect(result).toContain('* `id`: required, integer') + expect(result).toContain('* `name`: required, string') + expect(result).toContain('* `email`: string, format: email') + }) + + test('array of objects', () => { + const result = summarizeSchema({ + type: 'array', + items: { + title: 'User', + type: 'object', + required: ['id'], + properties: { + id: { type: 'integer' }, + login: { type: 'string' }, + }, + }, + }) + expect(result).toContain('Array of `User`:') + expect(result).toContain('* `id`: required, integer') + expect(result).toContain('* `login`: string') + }) + + test('enum values are listed', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + state: { type: 'string', enum: ['open', 'closed'] }, + }, + }) + expect(result).toContain('enum: `open`, `closed`') + }) + + test('default values are shown', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + per_page: { type: 'integer', default: 30 }, + }, + }) + expect(result).toContain('default: `30`') + }) + + test('deprecated fields are marked', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + old_field: { type: 'string', deprecated: true }, + }, + }) + expect(result).toContain('deprecated') + }) + + test('oneOf variants list titles', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + payload: { + oneOf: [ + { title: 'PushEvent', type: 'object', properties: { ref: { type: 'string' } } }, + { title: 'ForkEvent', type: 'object', properties: { forkee: { type: 'object' } } }, + ], + }, + }, + }) + expect(result).toContain('one of:') + expect(result).toContain('**PushEvent**') + expect(result).toContain('**ForkEvent**') + }) + + test('nested objects recurse with title', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + owner: { + title: 'User', + type: 'object', + required: ['id'], + properties: { + id: { type: 'integer' }, + login: { type: 'string' }, + }, + }, + }, + }) + expect(result).toContain('* `owner`: `User`:') + expect(result).toContain(' * `id`: required, integer') + }) + + test('constraints are included', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + count: { type: 'integer', minimum: 0, maximum: 100 }, + name: { type: 'string', minLength: 1, maxLength: 255, pattern: '^[a-z]+$' }, + }, + }) + expect(result).toContain('minimum: 0') + expect(result).toContain('maximum: 100') + expect(result).toContain('minLength: 1') + expect(result).toContain('maxLength: 255') + expect(result).toContain('pattern: `^[a-z]+$`') + }) + + test('readOnly fields are marked', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + id: { type: 'integer', readOnly: true }, + }, + }) + expect(result).toContain('read-only') + }) + + test('array items with constraints', () => { + const result = summarizeSchema({ + type: 'array', + minItems: 1, + maxItems: 50, + items: { type: 'string' }, + }) + expect(result).toContain('minItems: 1') + expect(result).toContain('maxItems: 50') + }) + + test('returns empty string for null/undefined input', () => { + // @ts-expect-error testing invalid input + expect(summarizeSchema(null)).toBe('') + // @ts-expect-error testing invalid input + expect(summarizeSchema(undefined)).toBe('') + }) + + test('does not include examples or descriptions', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + id: { + type: 'integer', + description: 'The unique identifier', + examples: [42], + }, + }, + }) + expect(result).not.toContain('unique identifier') + expect(result).not.toContain('42') + expect(result).toContain('* `id`: integer') + }) + + test('uses colon separator not em dash', () => { + const result = summarizeSchema({ + type: 'object', + properties: { + id: { type: 'integer' }, + }, + }) + expect(result).not.toContain('—') + expect(result).toContain(':') + }) +}) diff --git a/src/article-api/transformers/rest-transformer.ts b/src/article-api/transformers/rest-transformer.ts index 2ef6f845d8c9..ee279da11bb9 100644 --- a/src/article-api/transformers/rest-transformer.ts +++ b/src/article-api/transformers/rest-transformer.ts @@ -3,6 +3,7 @@ import type { PageTransformer } from './types' import type { Operation } from '@/rest/components/types' import { renderContent } from '@/content-render/index' import { loadTemplate } from '@/article-api/lib/load-template' +import { summarizeSchema } from '@/article-api/lib/summarize-schema' import matter from '@gr2m/gray-matter' import { fastTextOnly } from '@/content-render/unified/text-only' @@ -193,7 +194,7 @@ export class RestTransformer implements PageTransformer { response: { statusCode: example.response?.statusCode, schema: (example.response as any)?.schema - ? JSON.stringify((example.response as any).schema, null, 2) + ? summarizeSchema((example.response as any).schema) : null, }, }