Skip to content

Commit

Permalink
Merge pull request #36621 from github/repo-sync
Browse files Browse the repository at this point in the history
Repo sync
  • Loading branch information
docs-bot authored Mar 5, 2025
2 parents 0acb4ca + 38f3f4b commit 0a5d1c6
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 25 deletions.
83 changes: 83 additions & 0 deletions config/moda/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ environments:
profile: general
region: iad

# 12 staging environments, evergreens only
# they should all contain the same configs
- name: staging-boxwood
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-cedar
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
Expand All @@ -16,6 +27,60 @@ environments:
profile: general
region: iad

- name: staging-cypress
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-fir
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-hemlock
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-holly
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-juniper
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-laurel
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-pine
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
Expand All @@ -25,6 +90,24 @@ environments:
profile: general
region: iad

- name: staging-redwood
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-sequoia
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
secret_environment: production
required_review_tasks: []
cluster_selector:
profile: general
region: iad

- name: staging-spruce
require_pipeline: false
notify_still_locked: true # Notify last person to lock this after an hour
Expand Down
34 changes: 32 additions & 2 deletions content/rest/scim/scim.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,39 @@ These endpoints are used by SCIM-enabled Identity Providers (IdPs) to automate p

You must authenticate as an owner of a {% data variables.product.github %} organization to use these endpoints. The REST API expects an OAuth 2.0 Bearer token (for example, a {% data variables.product.prodname_github_app %} user access token) to be included in the `Authorization` header. If you use a {% data variables.product.pat_v1 %} for authentication, it must have the `admin:org` scope and you must also [authorize it for use with your SAML SSO organization](/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on).

### Mapping of SAML and SCIM data
### Matching SAML and SCIM attributes

{% data reusables.scim.nameid-and-username-must-match %}
To successfully link a {% data variables.product.github %} user account to a SCIM identity in an organization, specific attributes from your Identity Provider's SAML response and SCIM API provisioning call must match for a user.

#### Microsoft Entra ID for SAML

When using Entra ID (previously known as Azure AD) for SAML, the following SAML attribute and SCIM attribute must match.

| SAML attribute | Matching SCIM attribute |
| :- | :- |
| `http://schemas.microsoft.com/identity/claims/objectidentifier` | `externalId` |

#### Other IdPs for SAML

When using other IdPs for SAML, the following SAML claims and SCIM attribute must match.

| SAML attribute | Matching SCIM attribute |
| :- | :- |
| `NameID` | `userName` |

There are two different ways a {% data variables.product.github %} user account can get linked to a SCIM identity in an organization when these SAML/SCIM attributes match:

1. For users who are not yet members of the organization:
* The IdP sends a SCIM provisioning call to {% data variables.product.github %} for a user who is not a member of an organization. This generates an organization invitation and an unlinked SCIM identity in the organization.
* User authenticates via SAML in the organization.
* {% data variables.product.github %} automatically links the SAML and SCIM identity to the new user account in the organization.

1. For existing organization members:
* The IdP sends a SCIM provisioning call to {% data variables.product.github %} for a user who is already a member of the organization.
* If the organization member does not have a linked SAML identity in the organization, this generates an organization invitation and an unlinked SCIM identity in the organization. User authenticates via SAML in the organization to link their SAML and SCIM identity.
* If the organization member has a linked SAML identity in the organization, {% data variables.product.github %} automatically links the SCIM identity to the existing user account in the organization. No organization invite is created.

Ensuring that a user gets properly linked to their SCIM identity in the organization can help prevent unexpected issues with SCIM deprovisioning when the user's access to the app is removed on the IdP side. For more information on auditing the linked SCIM identities in an organization, see [AUTOTITLE](/enterprise-cloud@latest/organizations/managing-saml-single-sign-on-for-your-organization/troubleshooting-identity-and-access-management-for-your-organization#auditing-organization-members-on-github)

### Supported SCIM User attributes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ If you have questions about this list, please contact us at <[email protected]>
| Name of Subprocessor | Description of Processing | Location of Processing | Corporate Location |
| --------------------------- | ------------------------------------------------------------------------------ | ----------------------- | ------------------ |
| Amazon Web Services (AWS) | Cloud Hosted Infrastructure and Data Hosting | United States | United States |
| Anthropic PBC | AI Inference and AI Services | United States | United States |
| Azure (Microsoft) | Cloud Hosted Infrastructure and Data Hosting | United States, France,</br>Switzerland, and Japan | United States |
| Azure Cognitive Services | Customer support ticketing analysis | United States | United States |
| Cloudflare | Content delivery service | United States | United States |
Expand Down
6 changes: 4 additions & 2 deletions data/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ release_notes:
search:
input:
aria_label: Open search overlay
placeholder: Search or ask Copilot
placeholder: Search or ask {{icon}} Copilot
placeholder_no_icon: Search or ask Copilot
shortcut: Type {{icon}} to search
overlay:
input_aria_label: Search or ask Copilot
suggestions_list_aria_label: Search suggestions
Expand All @@ -38,7 +40,7 @@ search:
beta_tag: Beta
return_to_search: Return to search
clear_search_query: Clear
view_all_search_results: View all {{length}} results
view_all_search_results: View more results
no_results_found: No results found
ai:
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
Expand Down
6 changes: 4 additions & 2 deletions src/fixtures/fixtures/data/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ release_notes:
search:
input:
aria_label: Open search overlay
placeholder: Search or ask Copilot
placeholder: Search or ask {{icon}} Copilot
placeholder_no_icon: Search or ask Copilot
shortcut: Type {{icon}} to search
overlay:
input_aria_label: Search or ask Copilot
suggestions_list_aria_label: Search suggestions
Expand All @@ -38,7 +40,7 @@ search:
beta_tag: Beta
return_to_search: Return to search
clear_search_query: Clear
view_all_search_results: View all {{length}} results
view_all_search_results: View more results
no_results_found: No results found
ai:
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type MarkdownContentPropsT = {
children: string
className?: string
openLinksInNewTab?: boolean
includeQueryParams?: boolean
eventGroupKey?: string
eventGroupId?: string
as?: keyof JSX.IntrinsicElements
Expand All @@ -20,16 +21,48 @@ export const UnrenderedMarkdownContent = ({
children,
className,
openLinksInNewTab = true,
includeQueryParams = true,
eventGroupKey = '',
eventGroupId = '',
...restProps
}: MarkdownContentPropsT) => {
// Overrides for ReactMarkdown components
const components = {} as Components
if (openLinksInNewTab) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
components.a = ({ node, ...props }) => (
<a {...props} target="_blank" data-group-key={eventGroupKey} data-group-id={eventGroupId}>
// eslint-disable-next-line @typescript-eslint/no-unused-vars
components.a = ({ node, ...props }) => {
let href = props.href || ''
let existingAnchorParams = ''
// When we want to include specific query parameters in the URL
if (includeQueryParams) {
if (href.includes('?')) {
href = href.split('?')[0]
existingAnchorParams = href.split('?')[1]
}
// Include feature, search-overlay-ask-ai, and search-overlay-input query parameters if they exist in the current URL
const existingURLParams = new URLSearchParams(window.location.search)
const newParams = new URLSearchParams()
if (existingURLParams.get('feature')) {
newParams.set('feature', existingURLParams.get('feature') || '')
}
if (existingURLParams.get('search-overlay-ask-ai')) {
newParams.set('search-overlay-ask-ai', existingURLParams.get('search-overlay-ask-ai') || '')
}
if (existingURLParams.get('search-overlay-input')) {
newParams.set('search-overlay-input', existingURLParams.get('search-overlay-input') || '')
}
// Combine new and existing query parameters
if (newParams.toString()) {
href = `${href}?${existingAnchorParams}&${newParams.toString()}`
}
}
return (
<a
{...props}
href={href}
target={openLinksInNewTab ? '_blank' : undefined}
data-group-key={eventGroupKey}
data-group-id={eventGroupId}
>
{props.children}
</a>
)
Expand Down
4 changes: 2 additions & 2 deletions src/search/components/hooks/useAISearchAutocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type UseCombinedSearchReturn = {
clearAutocompleteResults: () => void
}

const DEBOUNCE_TIME = 300 // In milliseconds
const DEBOUNCE_TIME = 1 // In milliseconds

// Results are only cached for the current session
// We cache results so if a user presses backspace, we can show the results immediately without burdening the API
Expand Down Expand Up @@ -65,7 +65,7 @@ export function useCombinedSearchResults({
useEffect(() => {
debouncedFetchRef.current = debounce((value: string) => {
fetchAutocompleteResults(value)
}, DEBOUNCE_TIME) // 300ms debounce
}, DEBOUNCE_TIME) // 1ms debounce

return () => {
debouncedFetchRef.current?.cancel()
Expand Down
2 changes: 1 addition & 1 deletion src/search/components/input/AskAIResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export function AskAIResults({
</div>
) : (
<article aria-busy={responseLoading} aria-live="polite">
{!aiCouldNotAnswer && message === '' ? (
{!aiCouldNotAnswer && message !== '' ? (
<span ref={disclaimerRef} className={styles.disclaimerText}>
{t('search.ai.disclaimer')}
</span>
Expand Down
28 changes: 28 additions & 0 deletions src/search/components/input/SearchBarButton.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,34 @@
font-weight: var(--base-text-weight-normal, 400) !important;
}

.placeholderShortcutContainer {
float: right;
color: var(--fgColor-disabled);
margin-right: 8px;
}

.forwardSlashIcon {
display: inline-grid;
width: var(--base-size-16, 16px);
height: var(--base-size-16, 16px);
color: var(--color-fg-default);

margin-right: 4px;
margin-left: 4px;
padding-left: 6px;
padding-right: 6px;
padding-top: 2px;
padding-bottom: 2px;

border-radius: var(--borderRadius-small);

border: 0.0625rem solid var(--color-fg-muted);
border-radius: 0.1875rem;
box-shadow: none;
align-items: center;
justify-content: center;
}

.searchIconContainer {
display: flex;
align-items: center;
Expand Down
16 changes: 14 additions & 2 deletions src/search/components/input/SearchBarButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ export function SearchBarButton({ isSearchOpen, setIsSearchOpen }: Props) {
}
}

const shortcutElements = t('search.input.shortcut')
.split(/({{[^}]+}})/)
.filter((item) => item.trim() !== '')
.map((item) => <>{item.trim()}</>)
shortcutElements[1] = <kbd className={styles.forwardSlashIcon}>/</kbd>

const placeHolderElements = t('search.input.placeholder')
.split(/({{[^}]+}})/)
.filter((item) => item.trim() !== '')
.map((item) => <>{item.trim()}</>)
placeHolderElements[1] = <CopilotIcon aria-hidden className="mr-1 ml-1" />

return (
<>
{/* We don't want to show the input when overlay is open */}
Expand Down Expand Up @@ -78,8 +90,8 @@ export function SearchBarButton({ isSearchOpen, setIsSearchOpen }: Props) {
urlSearchInputQuery
) : (
<>
{t('search.input.placeholder')}
<CopilotIcon aria-hidden className="mr-1 ml-1" />
<span className={styles.placeholderText}>{placeHolderElements}</span>
<span className={styles.placeholderShortcutContainer}>{shortcutElements}</span>
</>
)}
</span>
Expand Down
Loading

0 comments on commit 0a5d1c6

Please sign in to comment.