From 50a53149814fe63a3d96c03d50857b770390ded7 Mon Sep 17 00:00:00 2001 From: Cory Calahan Date: Tue, 22 Jul 2025 08:20:09 -0700 Subject: [PATCH 01/10] Include a caveat regarding select hardware migration topics (#56730) --- data/reusables/support/scope-of-support.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/reusables/support/scope-of-support.md b/data/reusables/support/scope-of-support.md index 81030198e86c..bb8a0bd2b080 100644 --- a/data/reusables/support/scope-of-support.md +++ b/data/reusables/support/scope-of-support.md @@ -2,7 +2,8 @@ If your support request is outside of the scope of what our team can help you wi * Third party integrations, such as Jira{% ifversion ghes %} * Hardware setup -* Hypervisor-related issues, such as OS disk detection, network setup, boot failure, VM console access, etc{% endif %} +* Hypervisor-related issues, such as OS disk detection, network setup, boot failure, VM console access, etc. +* Migration assistance between specific hardware platforms or storage providers{% endif %} * CI/CD, such as Jenkins * Azure DevOps (please contact Azure Support) * Writing scripts From e47f382f3c004eb4f053534a3a07f6e0d2221796 Mon Sep 17 00:00:00 2001 From: bss-mc <117171930+bss-mc@users.noreply.github.com> Date: Tue, 22 Jul 2025 08:24:17 -0700 Subject: [PATCH 02/10] Add enterprise allow list considerations for SSH / PAT authorization (#56709) Co-authored-by: Justin Alex <1155821+jusuchin85@users.noreply.github.com> --- ...zing-a-personal-access-token-for-use-with-single-sign-on.md | 3 +++ .../authorizing-an-ssh-key-for-use-with-single-sign-on.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/content/authentication/authenticating-with-single-sign-on/authorizing-a-personal-access-token-for-use-with-single-sign-on.md b/content/authentication/authenticating-with-single-sign-on/authorizing-a-personal-access-token-for-use-with-single-sign-on.md index e01e0d22d1b1..ce0adc29f95c 100644 --- a/content/authentication/authenticating-with-single-sign-on/authorizing-a-personal-access-token-for-use-with-single-sign-on.md +++ b/content/authentication/authenticating-with-single-sign-on/authorizing-a-personal-access-token-for-use-with-single-sign-on.md @@ -29,6 +29,9 @@ You must authorize your {% data variables.product.pat_v1 %} after creation befor 1. In the dropdown menu, to the right of the organization you'd like to authorize the token for, click **Authorize**. +> [!NOTE] +> When authorizing a {% data variables.product.pat_v1 %} for use within an organization that belongs to an enterprise which has both an IP allow list and single sign-on enabled at the enterprise level, your IP must also be allowed at the enterprise level. See [AUTOTITLE](/admin/configuring-settings/hardening-security-for-your-enterprise/restricting-network-traffic-to-your-enterprise-with-an-ip-allow-list). + ## Further reading * [AUTOTITLE](/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) diff --git a/content/authentication/authenticating-with-single-sign-on/authorizing-an-ssh-key-for-use-with-single-sign-on.md b/content/authentication/authenticating-with-single-sign-on/authorizing-an-ssh-key-for-use-with-single-sign-on.md index 930b915fb221..cdcfe5a47cb6 100644 --- a/content/authentication/authenticating-with-single-sign-on/authorizing-an-ssh-key-for-use-with-single-sign-on.md +++ b/content/authentication/authenticating-with-single-sign-on/authorizing-an-ssh-key-for-use-with-single-sign-on.md @@ -37,6 +37,9 @@ You do not need to authorize SSH certificates signed by your organization's SSH ![Screenshot of the "Authentication Keys" section. Next to a key, a dropdown menu, labeled "Configure SSO," is outlined in orange.](/assets/images/help/settings/ssh-sso-button.png) 1. In the dropdown menu, to the right of the organization you'd like to authorize the SSH key for, click **Authorize**. +> [!NOTE] +> When authorizing an SSH key for use within an organization that belongs to an enterprise which has both an IP allow list and single sign-on enabled at the enterprise level, your IP must also be allowed at the enterprise level. See [AUTOTITLE](/admin/configuring-settings/hardening-security-for-your-enterprise/restricting-network-traffic-to-your-enterprise-with-an-ip-allow-list). + ## Further reading * [AUTOTITLE](/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys) From 4e9dc8b4562453e99fb8dce71e5fba8d924b466e Mon Sep 17 00:00:00 2001 From: Ben Ahmady <32935794+subatoi@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:34:27 +0100 Subject: [PATCH 03/10] [EDI] Creating and publishing actions content (#56770) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../administering-github-actions/index.md | 1 - .../creating-a-third-party-cli-action.md} | 8 ++++---- .../index.md | 16 ++++++++-------- .../managing-custom-actions.md | 3 +++ .../publishing-actions-in-github-marketplace.md | 7 ++++--- .../releasing-and-maintaining-actions.md | 2 +- .../setting-exit-codes-for-actions.md | 2 +- content/actions/how-tos/index.md | 1 + .../actions/how-tos/sharing-automations/index.md | 1 - 9 files changed, 22 insertions(+), 19 deletions(-) rename content/actions/how-tos/{sharing-automations/creating-actions/developing-a-third-party-cli-action.md => creating-and-publishing-actions/creating-a-third-party-cli-action.md} (90%) rename content/actions/how-tos/{sharing-automations/creating-actions => creating-and-publishing-actions}/index.md (67%) rename content/actions/how-tos/{administering-github-actions => creating-and-publishing-actions}/managing-custom-actions.md (97%) rename content/actions/how-tos/{sharing-automations/creating-actions => creating-and-publishing-actions}/publishing-actions-in-github-marketplace.md (96%) rename content/actions/how-tos/{sharing-automations/creating-actions => creating-and-publishing-actions}/releasing-and-maintaining-actions.md (98%) rename content/actions/how-tos/{sharing-automations/creating-actions => creating-and-publishing-actions}/setting-exit-codes-for-actions.md (95%) diff --git a/content/actions/how-tos/administering-github-actions/index.md b/content/actions/how-tos/administering-github-actions/index.md index b875ec6bb71d..e164afec891e 100644 --- a/content/actions/how-tos/administering-github-actions/index.md +++ b/content/actions/how-tos/administering-github-actions/index.md @@ -9,7 +9,6 @@ versions: children: - /viewing-github-actions-metrics - /making-retired-namespaces-available-on-ghecom - - /managing-custom-actions redirect_from: - /actions/administering-github-actions --- diff --git a/content/actions/how-tos/sharing-automations/creating-actions/developing-a-third-party-cli-action.md b/content/actions/how-tos/creating-and-publishing-actions/creating-a-third-party-cli-action.md similarity index 90% rename from content/actions/how-tos/sharing-automations/creating-actions/developing-a-third-party-cli-action.md rename to content/actions/how-tos/creating-and-publishing-actions/creating-a-third-party-cli-action.md index ea726570b810..e1aacbbabba8 100644 --- a/content/actions/how-tos/sharing-automations/creating-actions/developing-a-third-party-cli-action.md +++ b/content/actions/how-tos/creating-and-publishing-actions/creating-a-third-party-cli-action.md @@ -1,14 +1,14 @@ --- -title: Developing a third party CLI action -shortTitle: CLI setup action +title: Creating a third party CLI action +shortTitle: Create a CLI action intro: 'Learn how to develop an action to set up a CLI on {% data variables.product.prodname_actions %} runners.' redirect_from: - /actions/creating-actions/developing-a-third-party-cli-action - /actions/sharing-automations/creating-actions/developing-a-third-party-cli-action + - /actions/how-tos/sharing-automations/creating-actions/developing-a-third-party-cli-action versions: fpt: '*' ghec: '*' -type: tutorial topics: - Actions --- @@ -29,7 +29,7 @@ This article will demonstrate how to write an action that retrieves a specific v ## Prerequisites -You should have an understanding of how to write a custom action. For more information, see [AUTOTITLE](/actions/creating-actions/about-custom-actions). For a more detailed guide on how to write a custom action, see [AUTOTITLE](/actions/creating-actions/creating-a-javascript-action). +You should have an understanding of how to write a custom action. For more information, see [AUTOTITLE](/actions/how-tos/creating-and-publishing-actions/managing-custom-actions). ## Example diff --git a/content/actions/how-tos/sharing-automations/creating-actions/index.md b/content/actions/how-tos/creating-and-publishing-actions/index.md similarity index 67% rename from content/actions/how-tos/sharing-automations/creating-actions/index.md rename to content/actions/how-tos/creating-and-publishing-actions/index.md index f1959b86be84..6672b6860dd1 100644 --- a/content/actions/how-tos/sharing-automations/creating-actions/index.md +++ b/content/actions/how-tos/creating-and-publishing-actions/index.md @@ -1,18 +1,18 @@ --- -title: Creating actions -shortTitle: Create actions +title: Creating and publishing actions +shortTitle: Create and publish actions intro: 'You can create your own actions, use and customize actions shared by the {% data variables.product.prodname_dotcom %} community, or write and share the actions you build.' versions: fpt: '*' ghes: '*' ghec: '*' +redirect_from: + - /actions/sharing-automations/creating-actions + - /actions/how-tos/sharing-automations/creating-actions children: + - /managing-custom-actions + - /creating-a-third-party-cli-action - /setting-exit-codes-for-actions - - /releasing-and-maintaining-actions - /publishing-actions-in-github-marketplace - - /developing-a-third-party-cli-action -redirect_from: - - /actions/sharing-automations/creating-actions + - /releasing-and-maintaining-actions --- - -{% data reusables.actions.enterprise-github-hosted-runners %} diff --git a/content/actions/how-tos/administering-github-actions/managing-custom-actions.md b/content/actions/how-tos/creating-and-publishing-actions/managing-custom-actions.md similarity index 97% rename from content/actions/how-tos/administering-github-actions/managing-custom-actions.md rename to content/actions/how-tos/creating-and-publishing-actions/managing-custom-actions.md index 54b321120a95..431f2124634d 100644 --- a/content/actions/how-tos/administering-github-actions/managing-custom-actions.md +++ b/content/actions/how-tos/creating-and-publishing-actions/managing-custom-actions.md @@ -1,5 +1,6 @@ --- title: Managing custom actions +shortTitle: Manage custom actions intro: 'Learn how to create and manage your own actions, and customize actions shared by the {% data variables.product.prodname_dotcom %} community.' versions: fpt: '*' @@ -9,6 +10,8 @@ type: overview topics: - Action development - Fundamentals +redirect_from: + - /actions/how-tos/administering-github-actions/managing-custom-actions --- ## Choosing a location for your action diff --git a/content/actions/how-tos/sharing-automations/creating-actions/publishing-actions-in-github-marketplace.md b/content/actions/how-tos/creating-and-publishing-actions/publishing-actions-in-github-marketplace.md similarity index 96% rename from content/actions/how-tos/sharing-automations/creating-actions/publishing-actions-in-github-marketplace.md rename to content/actions/how-tos/creating-and-publishing-actions/publishing-actions-in-github-marketplace.md index d8eacbe9489e..058c3e1abfb5 100644 --- a/content/actions/how-tos/sharing-automations/creating-actions/publishing-actions-in-github-marketplace.md +++ b/content/actions/how-tos/creating-and-publishing-actions/publishing-actions-in-github-marketplace.md @@ -7,16 +7,17 @@ redirect_from: - /actions/building-actions/publishing-actions-in-github-marketplace - /actions/creating-actions/publishing-actions-in-github-marketplace - /actions/sharing-automations/creating-actions/publishing-actions-in-github-marketplace + - /actions/how-tos/sharing-automations/creating-actions/publishing-actions-in-github-marketplace versions: fpt: '*' ghec: '*' -type: how_to shortTitle: Publish in GitHub Marketplace --- -You must accept the terms of service to publish actions in {% data variables.product.prodname_marketplace %}. +## Prerequisites -## About publishing actions +>[!NOTE] +> You must accept the terms of service to publish actions in {% data variables.product.prodname_marketplace %}. Before you can publish an action, you'll need to create an action in your repository. For more information, see [AUTOTITLE](/actions/creating-actions). diff --git a/content/actions/how-tos/sharing-automations/creating-actions/releasing-and-maintaining-actions.md b/content/actions/how-tos/creating-and-publishing-actions/releasing-and-maintaining-actions.md similarity index 98% rename from content/actions/how-tos/sharing-automations/creating-actions/releasing-and-maintaining-actions.md rename to content/actions/how-tos/creating-and-publishing-actions/releasing-and-maintaining-actions.md index d8f346afd6c4..02912f6e43f0 100644 --- a/content/actions/how-tos/sharing-automations/creating-actions/releasing-and-maintaining-actions.md +++ b/content/actions/how-tos/creating-and-publishing-actions/releasing-and-maintaining-actions.md @@ -2,7 +2,6 @@ title: Releasing and maintaining actions shortTitle: Release and maintain actions intro: You can leverage automation and open source best practices to release and maintain actions. -type: tutorial topics: - Action development - Actions @@ -14,6 +13,7 @@ versions: redirect_from: - /actions/creating-actions/releasing-and-maintaining-actions - /actions/sharing-automations/creating-actions/releasing-and-maintaining-actions + - /actions/how-tos/sharing-automations/creating-actions/releasing-and-maintaining-actions --- {% data reusables.actions.enterprise-github-hosted-runners %} diff --git a/content/actions/how-tos/sharing-automations/creating-actions/setting-exit-codes-for-actions.md b/content/actions/how-tos/creating-and-publishing-actions/setting-exit-codes-for-actions.md similarity index 95% rename from content/actions/how-tos/sharing-automations/creating-actions/setting-exit-codes-for-actions.md rename to content/actions/how-tos/creating-and-publishing-actions/setting-exit-codes-for-actions.md index 88bb706d2a6d..85878a71f3cc 100644 --- a/content/actions/how-tos/sharing-automations/creating-actions/setting-exit-codes-for-actions.md +++ b/content/actions/how-tos/creating-and-publishing-actions/setting-exit-codes-for-actions.md @@ -6,11 +6,11 @@ redirect_from: - /actions/building-actions/setting-exit-codes-for-actions - /actions/creating-actions/setting-exit-codes-for-actions - /actions/sharing-automations/creating-actions/setting-exit-codes-for-actions + - /actions/how-tos/sharing-automations/creating-actions/setting-exit-codes-for-actions versions: fpt: '*' ghes: '*' ghec: '*' -type: how_to --- {% data reusables.actions.enterprise-github-hosted-runners %} diff --git a/content/actions/how-tos/index.md b/content/actions/how-tos/index.md index 59e687f7e0a2..f514786a7381 100644 --- a/content/actions/how-tos/index.md +++ b/content/actions/how-tos/index.md @@ -9,6 +9,7 @@ versions: children: - /writing-workflows - /managing-workflow-runs-and-deployments + - /creating-and-publishing-actions - /sharing-automations - /using-github-hosted-runners - /managing-self-hosted-runners diff --git a/content/actions/how-tos/sharing-automations/index.md b/content/actions/how-tos/sharing-automations/index.md index 6a7b71ff3fd5..9f5d4ce4cbe8 100644 --- a/content/actions/how-tos/sharing-automations/index.md +++ b/content/actions/how-tos/sharing-automations/index.md @@ -14,7 +14,6 @@ redirect_from: - /articles/creating-a-github-action - /actions/sharing-automations children: - - /creating-actions - /reuse-workflows - /creating-workflow-templates-for-your-organization - /sharing-actions-and-workflows-from-your-private-repository From ca46b664a6235efde4e228c780593a7c1ad16a34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:11:36 -0700 Subject: [PATCH 04/10] Bump the npm_and_yarn group with 1 update (#56757) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index e18def1cced0..6737dcdf26ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4783,19 +4783,44 @@ } }, "node_modules/@types/request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" }, "engines": { "node": ">= 0.12" } }, + "node_modules/@types/request/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -8957,14 +8982,15 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { From d7d8465e1cd1cd83a2ff34854f847c0b7d3b4f17 Mon Sep 17 00:00:00 2001 From: Bob <144845785+justb0b@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:25:43 -0700 Subject: [PATCH 05/10] Added information about prompt caching for Gemini models (#56754) --- .../copilot/reference/ai-models/how-copilot-serves-ai-models.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content/copilot/reference/ai-models/how-copilot-serves-ai-models.md b/content/copilot/reference/ai-models/how-copilot-serves-ai-models.md index b473c5c0dcf5..00db143b3013 100644 --- a/content/copilot/reference/ai-models/how-copilot-serves-ai-models.md +++ b/content/copilot/reference/ai-models/how-copilot-serves-ai-models.md @@ -49,4 +49,6 @@ Used for: {% data variables.product.prodname_copilot %} uses {% data variables.copilot.copilot_gemini_flash %} and {% data variables.copilot.copilot_gemini_25_pro %} hosted on Google Cloud Platform (GCP). When using {% data variables.copilot.copilot_gemini %} models, prompts and metadata are sent to GCP, which makes the [following data commitment](https://cloud.google.com/vertex-ai/generative-ai/docs/data-governance): _{% data variables.copilot.copilot_gemini %} doesn't use your prompts, or its responses, as data to train its models._ +To provide better service quality and reduce latency, {% data variables.product.github %} uses [prompt caching](https://cloud.google.com/vertex-ai/generative-ai/docs/data-governance#customer_data_retention_and_achieving_zero_data_retention). + When using {% data variables.copilot.copilot_gemini %} models, input prompts and output completions continue to run through {% data variables.product.prodname_copilot %}'s content filters for public code matching, when applied, along with those for harmful or offensive content. From d76db0abc68fb1090de642a978947279fc8a714f Mon Sep 17 00:00:00 2001 From: JakeKimShiba <109673568+JakeKimShiba@users.noreply.github.com> Date: Wed, 23 Jul 2025 01:25:49 +0900 Subject: [PATCH 06/10] Update content exclusion limitations for GitHub Copilot (#56738) Co-authored-by: John Clement <70238417+jclement136@users.noreply.github.com> --- .../copilot/concepts/content-exclusion-for-github-copilot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/copilot/concepts/content-exclusion-for-github-copilot.md b/content/copilot/concepts/content-exclusion-for-github-copilot.md index 9cd1c27921ed..98a82c64004e 100644 --- a/content/copilot/concepts/content-exclusion-for-github-copilot.md +++ b/content/copilot/concepts/content-exclusion-for-github-copilot.md @@ -50,7 +50,7 @@ Content exclusions also apply to {% data variables.copilot.copilot_code-review_s {% data reusables.copilot.content-exclusion-limitations %} -Currently, content exclusions do not apply to symbolic links (symlinks). +Currently, content exclusions do not apply to symbolic links (symlinks) and repositories located on remote filesystems. ### Data sent to {% data variables.product.prodname_dotcom %} From f68c6e87c84f9bf5675465605fb2ab5bfeaed4a9 Mon Sep 17 00:00:00 2001 From: Patrick Knight Date: Tue, 22 Jul 2025 11:26:38 -0500 Subject: [PATCH 07/10] Update repository policy rules preview with limits (#56733) Co-authored-by: John Clement <70238417+jclement136@users.noreply.github.com> --- data/reusables/enterprise/repo-policy-rules-preview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/data/reusables/enterprise/repo-policy-rules-preview.md b/data/reusables/enterprise/repo-policy-rules-preview.md index fda811b12120..4abe49a37d01 100644 --- a/data/reusables/enterprise/repo-policy-rules-preview.md +++ b/data/reusables/enterprise/repo-policy-rules-preview.md @@ -1 +1,2 @@ >[!NOTE] Repository policies are currently in {% data variables.release-phases.public_preview %} and subject to change. +>You can have up to 75 total policies and rulesets per organization, and up to 75 total policies and rulesets per enterprise. From f694d3619ac1c0f64e01f12a41ac23b9e6c4c344 Mon Sep 17 00:00:00 2001 From: Patrick Knight Date: Tue, 22 Jul 2025 11:34:01 -0500 Subject: [PATCH 08/10] Fix markdown syntax for ruleset note (#56774) --- data/reusables/repositories/ruleset-beta-note.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/reusables/repositories/ruleset-beta-note.md b/data/reusables/repositories/ruleset-beta-note.md index cec89fb6175d..0b127d3ba7d8 100644 --- a/data/reusables/repositories/ruleset-beta-note.md +++ b/data/reusables/repositories/ruleset-beta-note.md @@ -1,2 +1,2 @@ -> [!NOTE] -> {% ifversion ghes > 3.16 %}Only changes made to a ruleset after you have upgraded to {% data variables.product.prodname_ghe_server %} 3.17.0, or a later version, are included in the ruleset history.{% endif %} +> {% ifversion ghes > 3.16 %}[!NOTE] +> Only changes made to a ruleset after you have upgraded to {% data variables.product.prodname_ghe_server %} 3.17.0, or a later version, are included in the ruleset history.{% endif %} From 77744a9703fe2211bc2294a2114f6e2eba92bbe5 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Tue, 22 Jul 2025 10:12:33 -0700 Subject: [PATCH 09/10] Filter metadata permissions when combined with additional permissions (#56263) --- src/github-apps/scripts/sync.js | 45 ++- src/github-apps/tests/metadata-permissions.js | 308 ++++++++++++++++++ 2 files changed, 348 insertions(+), 5 deletions(-) create mode 100644 src/github-apps/tests/metadata-permissions.js diff --git a/src/github-apps/scripts/sync.js b/src/github-apps/scripts/sync.js index eab79943a1cd..088a11d11a56 100755 --- a/src/github-apps/scripts/sync.js +++ b/src/github-apps/scripts/sync.js @@ -103,11 +103,25 @@ export async function syncGitHubAppsData(openApiSource, sourceSchemas, progAcces const excludedActors = progActorResources[permissionName]['excluded_actors'] - const additionalPermissions = - progAccessData[operation.operationId].permissions.length > 1 || - progAccessData[operation.operationId].permissions.some( - (permissionSet) => Object.keys(permissionSet).length > 1, + const additionalPermissions = calculateAdditionalPermissions( + progAccessData[operation.operationId].permissions, + ) + + // Filter out metadata permissions when combined with other permissions + // The metadata permission is automatically granted with any other repository permission, + // so documenting it for operations that require additional permissions is misleading. + // This fixes the issue where mutating operations (PUT, DELETE) incorrectly appeared + // to only need metadata access when they actually require write permissions. + // See: https://github.com/github/docs-engineering/issues/5212 + if ( + shouldFilterMetadataPermission( + permissionName, + progAccessData[operation.operationId].permissions, ) + ) { + continue + } + // github app permissions if (!isActorExcluded(excludedActors, 'server_to_server', actorTypeMap)) { const serverToServerPermissions = githubAppsData['server-to-server-permissions'] @@ -332,6 +346,28 @@ function sentenceCase(str) { return str.charAt(0).toUpperCase() + str.slice(1) } +/** + * Calculates whether an operation has additional permissions beyond a single permission. + */ +export function calculateAdditionalPermissions(permissionSets) { + return ( + permissionSets.length > 1 || + permissionSets.some((permissionSet) => Object.keys(permissionSet).length > 1) + ) +} + +/** + * Determines whether a metadata permission should be filtered out when it has additional permissions. + * Prevents misleading documentation where mutating operations appear to only need metadata access. + */ +export function shouldFilterMetadataPermission(permissionName, permissionSets) { + if (permissionName !== 'metadata') { + return false + } + + return calculateAdditionalPermissions(permissionSets) +} + export function isActorExcluded(excludedActors, actorType, actorTypeMap = {}) { if (!excludedActors || !Array.isArray(excludedActors)) { return false @@ -358,7 +394,6 @@ export function isActorExcluded(excludedActors, actorType, actorTypeMap = {}) { return false } - function addAppData(storage, category, data) { if (!storage[category]) { storage[category] = [] diff --git a/src/github-apps/tests/metadata-permissions.js b/src/github-apps/tests/metadata-permissions.js new file mode 100644 index 000000000000..08084fa9e043 --- /dev/null +++ b/src/github-apps/tests/metadata-permissions.js @@ -0,0 +1,308 @@ +import { describe, expect, test } from 'vitest' +import { shouldFilterMetadataPermission, calculateAdditionalPermissions } from '../scripts/sync.js' + +describe('metadata permissions filtering', () => { + // Mock data structure representing operations with metadata permissions + const mockOperationsWithMetadata = [ + { + operationId: 'repos/enable-automated-security-fixes', + permissionSets: [{ metadata: 'read', administration: 'write' }], + }, + { + operationId: 'repos/get-readme', + permissionSets: [{ metadata: 'read' }], + }, + { + operationId: 'orgs/update-webhook', + permissionSets: [{ metadata: 'read', organization_administration: 'write' }], + }, + { + operationId: 'repos/get-content', + permissionSets: [{ contents: 'read' }], + }, + ] + + // Mock programmatic access data + const mockProgAccessData = { + 'repos/enable-automated-security-fixes': { + userToServerRest: true, + serverToServer: true, + permissions: [{ metadata: 'read', administration: 'write' }], + }, + 'repos/get-readme': { + userToServerRest: true, + serverToServer: true, + permissions: [{ metadata: 'read' }], + }, + 'orgs/update-webhook': { + userToServerRest: true, + serverToServer: true, + permissions: [{ metadata: 'read', organization_administration: 'write' }], + }, + 'repos/get-content': { + userToServerRest: true, + serverToServer: true, + permissions: [{ contents: 'read' }], + }, + } + + // Mock actor resources + const mockProgActorResources = { + metadata: { + title: 'Metadata', + visibility: 'public', + }, + administration: { + title: 'Administration', + visibility: 'public', + }, + organization_administration: { + title: 'Organization administration', + visibility: 'public', + }, + contents: { + title: 'Contents', + visibility: 'public', + }, + } + + test('calculateAdditionalPermissions works correctly', () => { + // Single permission set with multiple permissions + expect(calculateAdditionalPermissions([{ metadata: 'read', admin: 'write' }])).toBe(true) + + // Single permission set with single permission + expect(calculateAdditionalPermissions([{ metadata: 'read' }])).toBe(false) + + // Multiple permission sets + expect(calculateAdditionalPermissions([{ metadata: 'read' }, { admin: 'write' }])).toBe(true) + + // Empty permission sets + expect(calculateAdditionalPermissions([])).toBe(false) + }) + + test('identifies metadata with additional permissions correctly', () => { + // Case 1: metadata + administration (should be filtered) + const metadataWithAdmin = [{ metadata: 'read', administration: 'write' }] + expect(shouldFilterMetadataPermission('metadata', metadataWithAdmin)).toBe(true) + + // Case 2: metadata only (should NOT be filtered) + const metadataOnly = [{ metadata: 'read' }] + expect(shouldFilterMetadataPermission('metadata', metadataOnly)).toBe(false) + + // Case 3: non-metadata permission (should NOT be filtered) + const nonMetadata = [{ contents: 'read' }] + expect(shouldFilterMetadataPermission('contents', nonMetadata)).toBe(false) + }) + + test('filters metadata operations with additional permissions', () => { + const filteredOperations = [] + const metadataPermissions = [] + + for (const operation of mockOperationsWithMetadata) { + const progData = mockProgAccessData[operation.operationId] + + for (const permissionSet of progData.permissions) { + for (const [permissionName] of Object.entries(permissionSet)) { + if (mockProgActorResources[permissionName]?.visibility === 'private') continue + + const additionalPermissions = calculateAdditionalPermissions(progData.permissions) + + // Apply metadata filtering logic + if (shouldFilterMetadataPermission(permissionName, progData.permissions)) { + // Skip this metadata permission as it has additional permissions + continue + } + + if (permissionName === 'metadata') { + metadataPermissions.push({ + operationId: operation.operationId, + additionalPermissions, + }) + } else { + filteredOperations.push({ + operationId: operation.operationId, + permission: permissionName, + additionalPermissions, + }) + } + } + } + } + + // Should only have metadata permission from the metadata-only operation + expect(metadataPermissions).toHaveLength(1) + expect(metadataPermissions[0].operationId).toBe('repos/get-readme') + expect(metadataPermissions[0].additionalPermissions).toBe(false) + + // Should have other permissions from operations with additional permissions + const adminPermission = filteredOperations.find((op) => op.permission === 'administration') + expect(adminPermission).toBeDefined() + expect(adminPermission.operationId).toBe('repos/enable-automated-security-fixes') + expect(adminPermission.additionalPermissions).toBe(true) + + const orgAdminPermission = filteredOperations.find( + (op) => op.permission === 'organization_administration', + ) + expect(orgAdminPermission).toBeDefined() + expect(orgAdminPermission.operationId).toBe('orgs/update-webhook') + expect(orgAdminPermission.additionalPermissions).toBe(true) + }) + + test('preserves non-metadata permissions regardless of additional permissions', () => { + const nonMetadataOperations = mockOperationsWithMetadata.filter( + (op) => + !mockProgAccessData[op.operationId].permissions.some((permSet) => 'metadata' in permSet), + ) + + expect(nonMetadataOperations).toHaveLength(1) + expect(nonMetadataOperations[0].operationId).toBe('repos/get-content') + + // Verify contents permission would be preserved + const contentsPermissionSet = mockProgAccessData['repos/get-content'].permissions[0] + expect('contents' in contentsPermissionSet).toBe(true) + expect('metadata' in contentsPermissionSet).toBe(false) + }) + + test('handles edge cases in permission sets', () => { + // Empty permission set + expect(shouldFilterMetadataPermission('metadata', [])).toBe(false) + + // Permission set with empty object (edge case) + const edgeCase1 = [{ metadata: 'read' }, {}] + expect(shouldFilterMetadataPermission('metadata', edgeCase1)).toBe(true) + + // Multiple permission sets with metadata in different sets + const edgeCase2 = [{ metadata: 'read' }, { admin: 'write' }] + expect(shouldFilterMetadataPermission('metadata', edgeCase2)).toBe(true) + }) + + test('filters metadata permissions that match the GitHub issue examples', () => { + // These are examples from the GitHub issue that should be filtered out + // PUT /orgs/{org}/actions/permissions/repositories/{repository_id} + const putActionsPermissions = [{ metadata: 'read', organization_administration: 'write' }] + + // DELETE /orgs/{org}/actions/permissions/repositories/{repository_id} + const deleteActionsPermissions = [{ metadata: 'read', organization_administration: 'write' }] + + // These should be filtered out because they have metadata + additional permissions + expect(shouldFilterMetadataPermission('metadata', putActionsPermissions)).toBe(true) + expect(shouldFilterMetadataPermission('metadata', deleteActionsPermissions)).toBe(true) + + // But the organization_administration permissions should NOT be filtered + expect( + shouldFilterMetadataPermission('organization_administration', putActionsPermissions), + ).toBe(false) + expect( + shouldFilterMetadataPermission('organization_administration', deleteActionsPermissions), + ).toBe(false) + }) + + test('preserves metadata permissions that are standalone', () => { + // Example of a metadata-only permission that should be preserved + const metadataOnlyPermissions = [{ metadata: 'read' }] + + // This should NOT be filtered out + expect(shouldFilterMetadataPermission('metadata', metadataOnlyPermissions)).toBe(false) + }) + + test('handles complex permission structures from real data', () => { + // Multiple permission sets (should filter metadata) + const multiplePermissionSets = [{ metadata: 'read' }, { administration: 'write' }] + expect(shouldFilterMetadataPermission('metadata', multiplePermissionSets)).toBe(true) + + // Single permission set with multiple permissions (should filter metadata) + const multiplePermissionsInSet = [ + { metadata: 'read', contents: 'write', pull_requests: 'write' }, + ] + expect(shouldFilterMetadataPermission('metadata', multiplePermissionsInSet)).toBe(true) + + // Multiple permission sets where metadata is not in the first set + const metadataInSecondSet = [{ administration: 'write' }, { metadata: 'read' }] + expect(shouldFilterMetadataPermission('metadata', metadataInSecondSet)).toBe(true) + }) + + test('validates filtering logic against known problematic endpoints', () => { + // Based on the issue description, these types of operations should have + // their metadata permissions filtered out: + + // Runner group operations + const runnerGroupPermissions = [{ metadata: 'read', organization_administration: 'write' }] + + // Organization secrets operations + const orgSecretsPermissions = [{ metadata: 'read', organization_secrets: 'write' }] + + // Repository operations with admin permissions + const repoAdminPermissions = [{ metadata: 'read', administration: 'write' }] + + // All of these should filter out metadata + expect(shouldFilterMetadataPermission('metadata', runnerGroupPermissions)).toBe(true) + expect(shouldFilterMetadataPermission('metadata', orgSecretsPermissions)).toBe(true) + expect(shouldFilterMetadataPermission('metadata', repoAdminPermissions)).toBe(true) + + // But should preserve the actual required permissions + expect( + shouldFilterMetadataPermission('organization_administration', runnerGroupPermissions), + ).toBe(false) + expect(shouldFilterMetadataPermission('organization_secrets', orgSecretsPermissions)).toBe( + false, + ) + expect(shouldFilterMetadataPermission('administration', repoAdminPermissions)).toBe(false) + }) + + test('verifies consistency with additional-permissions flag calculation', () => { + const testCases = [ + // Single permission, single set - no additional permissions + { permissionSets: [{ metadata: 'read' }], expected: false }, + + // Multiple permissions, single set - has additional permissions + { permissionSets: [{ metadata: 'read', admin: 'write' }], expected: true }, + + // Single permission, multiple sets - has additional permissions + { permissionSets: [{ metadata: 'read' }, { admin: 'write' }], expected: true }, + + // Multiple permissions, multiple sets - has additional permissions + { + permissionSets: [{ metadata: 'read', contents: 'read' }, { admin: 'write' }], + expected: true, + }, + ] + + for (const testCase of testCases) { + const additionalPermissions = calculateAdditionalPermissions(testCase.permissionSets) + const shouldFilter = shouldFilterMetadataPermission('metadata', testCase.permissionSets) + + // The filtering logic should match the additional permissions calculation + expect(shouldFilter).toBe(additionalPermissions) + expect(additionalPermissions).toBe(testCase.expected) + } + }) + + test('validates filtering logic matches expected behavior from issue', () => { + // Based on the GitHub issue, these operations should be filtered out from metadata: + // - PUT /orgs/{org}/actions/permissions/repositories/{repository_id} + // - DELETE /orgs/{org}/actions/permissions/repositories/{repository_id} + // Because they have metadata + organization_administration permissions + + const mockMutatingOperation = { + operationId: 'actions/set-selected-repositories-enabled-github-actions-organization', + permissionSets: [{ metadata: 'read', organization_administration: 'write' }], + } + + const progData = { + userToServerRest: true, + serverToServer: true, + permissions: [{ metadata: 'read', organization_administration: 'write' }], + } + + // This should be filtered out from metadata permissions + expect(shouldFilterMetadataPermission('metadata', progData.permissions)).toBe(true) + + // But organization_administration permission should still be included + expect( + shouldFilterMetadataPermission('organization_administration', progData.permissions), + ).toBe(false) + + // Verify additional permissions flag is set correctly + expect(calculateAdditionalPermissions(progData.permissions)).toBe(true) + }) +}) From 596e626d666b1ea5ecf33c7c2012aff8b81b5ac6 Mon Sep 17 00:00:00 2001 From: Jake Coffman Date: Tue, 22 Jul 2025 12:29:27 -0500 Subject: [PATCH 10/10] Dependabot org-level private registries (#56714) Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- ...iguring-access-to-private-registries-for-dependabot.md | 8 +++++++- .../giving-org-access-private-registries.md | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/content/code-security/dependabot/working-with-dependabot/configuring-access-to-private-registries-for-dependabot.md b/content/code-security/dependabot/working-with-dependabot/configuring-access-to-private-registries-for-dependabot.md index ddce43061e35..21d10bb56507 100644 --- a/content/code-security/dependabot/working-with-dependabot/configuring-access-to-private-registries-for-dependabot.md +++ b/content/code-security/dependabot/working-with-dependabot/configuring-access-to-private-registries-for-dependabot.md @@ -33,7 +33,13 @@ For specific ecosystems, you can configure {% data variables.product.prodname_de ## Configuring private registries -You configure {% data variables.product.prodname_dependabot %}'s access to private registries in the `dependabot.yml` file. +{% ifversion org-private-registry %} + +You can configure {% data variables.product.prodname_dependabot %}'s access to private registries at the org-level. For more information on how to configure that, see [AUTOTITLE](/code-security/securing-your-organization/enabling-security-features-in-your-organization/giving-org-access-private-registries). + +{% endif %} + +You can also configure {% data variables.product.prodname_dependabot %}'s access to private registries in the `dependabot.yml` file. The top-level `registries` key is optional and specifies authentication details. {% data reusables.dependabot.dependabot-updates-registries %} diff --git a/content/code-security/securing-your-organization/enabling-security-features-in-your-organization/giving-org-access-private-registries.md b/content/code-security/securing-your-organization/enabling-security-features-in-your-organization/giving-org-access-private-registries.md index 08442226faf6..c7725bb806ee 100644 --- a/content/code-security/securing-your-organization/enabling-security-features-in-your-organization/giving-org-access-private-registries.md +++ b/content/code-security/securing-your-organization/enabling-security-features-in-your-organization/giving-org-access-private-registries.md @@ -59,7 +59,7 @@ Any private registries used by the build must also be accessible to the workflow ## {% data variables.product.prodname_dependabot %} updates access to private registries -{% data variables.product.prodname_dependabot %} uses any private registries defined in the `dependabot.yml` file. It does not have access to the organization-level private registries used by {% data variables.product.prodname_code_scanning %} default setup. +{% data variables.product.prodname_dependabot %} can use any of the org-level private registries, as well as uses any private registries defined in the `dependabot.yml` file in the repo. {% data variables.product.prodname_dependabot %} cannot check for security or version updates for code stored in a private registry unless it can access the registry. If you do not configure access to the private registry, then {% data variables.product.prodname_dependabot %} cannot raise pull requests to update any of the dependencies stored in the registry.