Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions .github/workflows/link-check-internal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
required: true
default: 'en'
create_copilot_issue:
description: 'Create a Copilot-assigned issue with the top 5 redirects to fix'
description: 'Create a Copilot-assigned issue with the top 10 redirects to fix'
type: boolean
required: false
default: false
Expand Down Expand Up @@ -127,7 +127,7 @@ jobs:

const report = JSON.parse(fs.readFileSync(reportFile, 'utf8'))
const allRedirectGroups = report.groups.filter(g => g.isWarning)
const redirectGroups = allRedirectGroups.slice(0, 5)
const redirectGroups = allRedirectGroups.slice(0, 10)

if (redirectGroups.length === 0) {
core.info('No redirect groups found, skipping Copilot issue.')
Expand All @@ -142,24 +142,30 @@ jobs:
return `| \`${g.target}\` | \`${redirectTarget}\` | \`${file}\` | ${lines} |`
}).join('\n')

const actionRunUrl = '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
const hasMore = allRedirectGroups.length > redirectGroups.length
const countLine = hasMore
? `These are the first ${redirectGroups.length} of ${allRedirectGroups.length} redirects found. The full list is available in the [workflow run artifacts](${actionRunUrl}).`
: `These are the first ${redirectGroups.length} of ${allRedirectGroups.length} redirects found.`
const artifactsUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}/artifacts`

const body = [
const bodyLines = [
'Copilot please fix the redirected internal links listed in the table below. All changes should be made within the `github/docs-internal` repository. For each entry, open the source file and replace the **Current Link** with the **Update To** path.',
'When all changes are made, open a pull request in `github/docs-internal` with the fixes. The pull request description should reference this issue to create a link between them. When the pull request is open, leave a comment on this issue with a link to it.',
'',
countLine,
`These are the first ${redirectGroups.length} of ${allRedirectGroups.length} redirects found.`,
'',
'## Redirects to fix',
'',
'| Current Link | Update To | File | Line(s) |',
'|---|---|---|---|',
tableRows,
].join('\n')
]

const MAX_ISSUE_BODY_LENGTH = 65536
const artifactNote = `\n\n> [!NOTE]\n> The report was truncated because it exceeded the issue body length limit. [View the complete redirect report in the workflow artifacts](${artifactsUrl}).`

let body = bodyLines.join('\n')
if (body.length > MAX_ISSUE_BODY_LENGTH) {
const truncatedLength = MAX_ISSUE_BODY_LENGTH - artifactNote.length
const lastNewline = body.lastIndexOf('\n', truncatedLength)
body = body.slice(0, lastNewline > 0 ? lastNewline : truncatedLength) + artifactNote
}

// Use the REST API with agent_assignment to properly trigger Copilot cloud agent.
// See: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/start-copilot-sessions#using-the-rest-api
Expand All @@ -173,7 +179,7 @@ jobs:
agent_assignment: {
target_repo: 'github/docs-internal',
base_branch: 'main',
custom_instructions: 'For each entry in the table, open the source file in the github/docs-internal repository and replace the Current Link with the Update To path. When all changes are made, open a pull request in github/docs-internal with the fixes. The pull request description should reference this issue to create a link between them. When the pull request is open, leave a comment on this issue with a link to it.',
custom_instructions: 'For each entry in the table, open the source file in the github/docs-internal repository and replace the Current Link with the Update To path. When all changes are made, open a pull request in github/docs-internal with the fixes. When the pull request is open, leave a comment on this issue with a link to it.',
},
})

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/sync-llms-txt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ jobs:
REPO="github/docs-internal"
if gh api "repos/$REPO/git/ref/heads/$BRANCH" --jq '.object.sha' > /dev/null 2>&1; then
echo "Branch $BRANCH exists, fetching"
git fetch origin "$BRANCH"
git -c url."https://x-access-token:${GH_TOKEN}@github.com/".insteadOf="https://github.com/" \
fetch origin "$BRANCH"
git checkout "$BRANCH"
else
echo "Branch $BRANCH does not exist, creating from main"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# ---------------------------------------------------------------
# To update the sha:
# https://github.com/github/gh-base-image/pkgs/container/gh-base-image%2Fgh-base-noble
FROM ghcr.io/github/gh-base-image/gh-base-noble:20260501-222137-g8063ecb13@sha256:9c650d5e53cbf6c95951373d197ede7955329ef695f5fc6fb8a1c56a8e3b817f AS base
FROM ghcr.io/github/gh-base-image/gh-base-noble:20260505-222701-gb8f4d82d0@sha256:e5ee5190511450a452713144fb1dcd957535ec7c68705efa48b3d2cbb9871b0d AS base

# Install curl for Node install and determining the early access branch
# Install git for cloning docs-early-access & translations repos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ You may be able to view the email addresses for members of your enterprise on ei

* If you verify a domain for your enterprise, you can view members' email addresses for the verified domain. For more information, see [AUTOTITLE](/admin/configuration/configuring-your-enterprise/verifying-or-approving-a-domain-for-your-enterprise).

> [!NOTE]
> Email addresses for verified domains are not returned in a guaranteed order. If a member has email addresses for multiple verified domains, old or stale email addresses may remain after an IdP change. The list of verified domain email addresses cannot reliably identify the member's canonical or current corporate email address.

* If you don't use {% data variables.product.prodname_emus %}, and you also don't configure SAML single sign-on (SSO), members access your enterprise's resources on {% data variables.product.github %} solely using a personal account. {% data reusables.saml.personal-accounts-determine-email-visibility %}

If you use {% data variables.product.prodname_emus %}, verify a domain, or configure SAML SSO for your enterprise, you may be able to view the email addresses in one or more of the following ways.
Expand All @@ -119,6 +122,8 @@ If you use {% data variables.product.prodname_emus %}, verify a domain, or confi
* `GitHub com saml name`: The `NameID` from the user's linked SAML identity, which is typically the user's email address (for more information, see [AUTOTITLE](/admin/identity-and-access-management/using-saml-for-enterprise-iam/saml-configuration-reference))
* `GitHub com verified domain emails`: Email addresses for any verified domains (for more information, see [AUTOTITLE](/admin/configuration/configuring-your-enterprise/verifying-or-approving-a-domain-for-your-enterprise))

The `GitHub com verified domain emails` value is unordered. Emails may be returned in a non-deterministic order, and you cannot request priority, sorting, or filtering for the user's current email address.

For more information, see [AUTOTITLE](/admin/user-management/managing-users-in-your-enterprise/exporting-membership-information-for-your-enterprise).
{% data reusables.saml.use-api-to-get-externalidentity %}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ If you don't already have single sign-on recovery codes for your enterprise, dow

1. Use a recovery code to sign into {% data variables.product.prodname_dotcom %} as the setup user, whose username is your enterprise's shortcode suffixed with `_admin`. For more information about the setup user, see [AUTOTITLE](/admin/identity-and-access-management/understanding-iam-for-enterprises/getting-started-with-enterprise-managed-users).
1. Disable authentication for your enterprise. For more information, see [AUTOTITLE](/admin/identity-and-access-management/configuring-authentication-for-enterprise-managed-users/disabling-authentication-for-enterprise-managed-users#disabling-authentication).
1. Wait up to an hour for {% data variables.product.github %} to suspend your enterprise's members, delete the linked SCIM identities, and delete the SCIM-provisioned IdP groups.
1. Wait for {% data variables.product.github %} to suspend your enterprise's members, delete the linked SCIM identities, and delete the SCIM-provisioned IdP groups.

> [!NOTE]
> * After you disable authentication, GitHub runs multiple background tasks which must complete before you continue with the remaining steps in this article. For large enterprises, this can take several hours or even days.
> * To confirm completion, go to the authentication settings page for your enterprise (Enterprise settings → Authentication security). While the tasks are still running, the "Enable OIDC configuration" or "Add SAML configuration" button will be disabled, and you’ll see a warning like “Previous SAML provider is being removed.”

### 5. Validate suspension of your enterprise's members

Expand Down
3 changes: 3 additions & 0 deletions data/reusables/saml/use-api-to-get-externalidentity.md
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
1. Use the GraphQL API to retrieve the `ExternalIdentity` for each member. For more information, see [AUTOTITLE](/graphql/overview/about-the-graphql-api) and [AUTOTITLE](/graphql/reference/objects#externalidentity) in the GraphQL API documentation.

> [!NOTE]
> Access to external identities depends on whether SAML is configured at the organization or enterprise level. Organization-level external identities are available to organization owners, organization owner {% data variables.product.pat_generic_plural %} with the `read:org` or `admin:org` scope, and {% data variables.product.prodname_github_app %} installation tokens with read or write access to members when the app is installed on the organization. Enterprise-level external identities require an enterprise owner {% data variables.product.pat_generic %} with the `read:enterprise` or `admin:enterprise` scope. {% data variables.product.prodname_github_apps %} cannot access enterprise-level external identities, including enterprise-level SAML identities for {% data variables.product.prodname_ghe_cloud %} with personal user accounts.
11 changes: 11 additions & 0 deletions src/audit-logs/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'path'

import { readCompressedJsonFileFallback } from '@/frame/lib/read-json-file'
import { getOpenApiVersion } from '@/versions/lib/all-versions'
import { supported as supportedGhesReleases } from '@/versions/lib/enterprise-server-releases'
import findPage from '@/frame/lib/find-page'
import type { Context, Page } from '@/types'
import type {
Expand Down Expand Up @@ -300,6 +301,7 @@ export async function filterAndUpdateGhesDataByAllowlistValues({
auditLogPage,
titleContext,
globalFields = [],
supportedGhesVersions = supportedGhesReleases,
}: {
eventsToCheck: RawAuditLogEventT[]
allowListValue: string
Expand All @@ -308,9 +310,17 @@ export async function filterAndUpdateGhesDataByAllowlistValues({
auditLogPage: string
titleContext?: TitleResolutionContext
globalFields?: string[]
supportedGhesVersions?: string[]
}) {
if (!currentGhesEvents) currentGhesEvents = {}

// Upstream `audit-log-allowlists/data/schema.json` lags docs's deprecation
// schedule, so events still list `ghes` keys for versions we've already
// dropped from `supported` in `enterprise-server-releases.ts`. Without this
// filter, the nightly sync would re-add `src/audit-logs/data/ghes-X.Y/`
// dirs for those deprecated versions. See docs-engineering#6562.
const supportedGhesVersionSet = new Set(supportedGhesVersions)

const seenByGhesVersion = new Map()
for (const [ghesVersion, events] of Object.entries(currentGhesEvents)) {
if (!events[auditLogPage]) continue
Expand All @@ -320,6 +330,7 @@ export async function filterAndUpdateGhesDataByAllowlistValues({

for (const event of eventsToCheck) {
for (const ghesVersion of Object.keys(event.ghes)) {
if (!supportedGhesVersionSet.has(ghesVersion)) continue
const ghesVersionAllowlists = event.ghes[ghesVersion]._allowlists
const fullGhesVersion = `ghes-${ghesVersion}`

Expand Down
39 changes: 39 additions & 0 deletions src/audit-logs/tests/unit/filter-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,50 @@ describe('audit log event filtering', () => {
appendedDescriptions: {},
},
auditLogPage,
supportedGhesVersions: ['3.10', '3.11', '3.12'],
})
const getActions = (version: string) =>
currentEvents[version][auditLogPage].map((event) => event.action)
expect(getActions('ghes-3.10').includes('repo.create')).toBe(true)
expect(getActions('ghes-3.11').includes('repo.create')).toBe(true)
expect(auditLogPage in currentEvents['ghes-3.12']).toBeFalsy()
})

test('ghes skips versions not in the supported list', async () => {
const eventsToProcess: RawAuditLogEventT[] = [
{
action: 'repo.create',
description: 'repo was created',
docs_reference_links: '',
_allowlists: [],
ghes: {
'3.14': {
_allowlists: ['user'],
},
'3.15': {
_allowlists: ['user'],
},
},
},
]

const currentEvents: VersionedAuditLogData = {}
const auditLogPage = 'user'

await filterAndUpdateGhesDataByAllowlistValues({
eventsToCheck: eventsToProcess,
allowListValue: 'user',
currentGhesEvents: currentEvents,
pipelineConfig: {
sha: '',
appendedDescriptions: {},
},
auditLogPage,
supportedGhesVersions: ['3.15'],
})
expect(currentEvents['ghes-3.14']).toBeUndefined()
expect(currentEvents['ghes-3.15'][auditLogPage].map((event) => event.action)).toContain(
'repo.create',
)
})
})
2 changes: 1 addition & 1 deletion src/graphql/data/ghec/schema.docs.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -69460,7 +69460,7 @@ type User implements Actor & Agentic & Node & PackageOwner & ProfileOwner & Proj
): Organization

"""
Verified email addresses that match verified domains for a specified organization the user is a member of.
Verified email addresses that match verified domains for a specified organization the user is a member of. Results are unordered. There is no way to specify ordering, priority, or filtering, and this field should not be used to determine a user's canonical or current corporate email in multi-domain contexts.
"""
organizationVerifiedDomainEmails(
"""
Expand Down
Loading
Loading