From f9f69b0527d3e76c1c5ee339db12ce4c50e3bdb2 Mon Sep 17 00:00:00 2001 From: docs-bot <77750099+docs-bot@users.noreply.github.com> Date: Wed, 15 Oct 2025 09:42:02 -0700 Subject: [PATCH 1/4] GraphQL schema update (#57993) Co-authored-by: heiskr <1221423+heiskr@users.noreply.github.com> --- src/graphql/data/fpt/changelog.json | 35 ++ src/graphql/data/fpt/schema.docs.graphql | 203 ++++++++++++ src/graphql/data/fpt/schema.json | 373 ++++++++++++++++++++++ src/graphql/data/ghec/schema.docs.graphql | 203 ++++++++++++ src/graphql/data/ghec/schema.json | 373 ++++++++++++++++++++++ 5 files changed, 1187 insertions(+) diff --git a/src/graphql/data/fpt/changelog.json b/src/graphql/data/fpt/changelog.json index 8dbc38772e7c..ae24cf0eb6d8 100644 --- a/src/graphql/data/fpt/changelog.json +++ b/src/graphql/data/fpt/changelog.json @@ -1,4 +1,39 @@ [ + { + "schemaChanges": [ + { + "title": "The GraphQL schema includes these changes:", + "changes": [ + "

Type 'AddedToProjectV2Event' was added

", + "

Type ConvertedFromDraftEvent was added

", + "

Type 'ProjectV2Event' was added

", + "

Type 'ProjectV2ItemStatusChangedEvent' was added

", + "

Type 'RemovedFromProjectV2Event' was added

", + "

Field totalBlockedBy was added to object type IssueDependenciesSummary

", + "

Field totalBlocking was added to object type IssueDependenciesSummary

", + "

Member 'AddedToProjectV2Eventwas added to Union typeIssueTimelineItems'

", + "

Member ConvertedFromDraftEvent was added to Union type IssueTimelineItems

", + "

Member 'ProjectV2ItemStatusChangedEventwas added to Union typeIssueTimelineItems'

", + "

Member 'RemovedFromProjectV2Eventwas added to Union typeIssueTimelineItems'

", + "

Enum value 'ADDED_TO_PROJECT_V2_EVENTwas added to enumIssueTimelineItemsItemType'

", + "

Enum value 'CONVERTED_FROM_DRAFT_EVENTwas added to enumIssueTimelineItemsItemType'

", + "

Enum value 'PROJECT_V2_ITEM_STATUS_CHANGED_EVENTwas added to enumIssueTimelineItemsItemType'

", + "

Enum value 'REMOVED_FROM_PROJECT_V2_EVENTwas added to enumIssueTimelineItemsItemType'

", + "

Member 'AddedToProjectV2Eventwas added to Union typePullRequestTimelineItems'

", + "

Member ConvertedFromDraftEvent was added to Union type PullRequestTimelineItems

", + "

Member 'ProjectV2ItemStatusChangedEventwas added to Union typePullRequestTimelineItems'

", + "

Member 'RemovedFromProjectV2Eventwas added to Union typePullRequestTimelineItems'

", + "

Enum value 'ADDED_TO_PROJECT_V2_EVENTwas added to enumPullRequestTimelineItemsItemType'

", + "

Enum value 'CONVERTED_FROM_DRAFT_EVENTwas added to enumPullRequestTimelineItemsItemType'

", + "

Enum value 'PROJECT_V2_ITEM_STATUS_CHANGED_EVENTwas added to enumPullRequestTimelineItemsItemType'

", + "

Enum value 'REMOVED_FROM_PROJECT_V2_EVENTwas added to enumPullRequestTimelineItemsItemType'

" + ] + } + ], + "previewChanges": [], + "upcomingChanges": [], + "date": "2025-10-15" + }, { "schemaChanges": [ { diff --git a/src/graphql/data/fpt/schema.docs.graphql b/src/graphql/data/fpt/schema.docs.graphql index a4e3f8872547..abc6e5bd51b9 100644 --- a/src/graphql/data/fpt/schema.docs.graphql +++ b/src/graphql/data/fpt/schema.docs.graphql @@ -1386,6 +1386,36 @@ type AddedToProjectEvent implements Node { ) } +""" +Represents a 'added_to_project_v2' event on a given issue or pull request. +""" +type AddedToProjectV2Event implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the AddedToProjectV2Event object + """ + id: ID! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ An announcement banner for an enterprise or organization. """ @@ -7179,6 +7209,36 @@ type ConvertToDraftEvent implements Node & UniformResourceLocatable { url: URI! } +""" +Represents a 'converted_from_draft' event on a given issue or pull request. +""" +type ConvertedFromDraftEvent implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the ConvertedFromDraftEvent object + """ + id: ID! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ Represents a 'converted_note_to_issue' event on a given issue or pull request. """ @@ -20013,6 +20073,16 @@ type IssueDependenciesSummary { Count of issues this issue is blocking """ blocking: Int! + + """ + Total count of issues this issue is blocked by (open and closed) + """ + totalBlockedBy: Int! + + """ + Total count of issues this issue is blocking (open and closed) + """ + totalBlocking: Int! } """ @@ -20359,6 +20429,7 @@ An item in an issue timeline """ union IssueTimelineItems = | AddedToProjectEvent + | AddedToProjectV2Event | AssignedEvent | BlockedByAddedEvent | BlockedByRemovedEvent @@ -20367,6 +20438,7 @@ union IssueTimelineItems = | ClosedEvent | CommentDeletedEvent | ConnectedEvent + | ConvertedFromDraftEvent | ConvertedNoteToIssueEvent | ConvertedToDiscussionEvent | CrossReferencedEvent @@ -20385,8 +20457,10 @@ union IssueTimelineItems = | ParentIssueAddedEvent | ParentIssueRemovedEvent | PinnedEvent + | ProjectV2ItemStatusChangedEvent | ReferencedEvent | RemovedFromProjectEvent + | RemovedFromProjectV2Event | RenamedTitleEvent | ReopenedEvent | SubIssueAddedEvent @@ -20465,6 +20539,11 @@ enum IssueTimelineItemsItemType { """ ADDED_TO_PROJECT_EVENT + """ + Represents a 'added_to_project_v2' event on a given issue or pull request. + """ + ADDED_TO_PROJECT_V2_EVENT + """ Represents an 'assigned' event on any assignable object. """ @@ -20505,6 +20584,11 @@ enum IssueTimelineItemsItemType { """ CONNECTED_EVENT + """ + Represents a 'converted_from_draft' event on a given issue or pull request. + """ + CONVERTED_FROM_DRAFT_EVENT + """ Represents a 'converted_note_to_issue' event on a given issue or pull request. """ @@ -20595,6 +20679,11 @@ enum IssueTimelineItemsItemType { """ PINNED_EVENT + """ + Represents a 'project_v2_item_status_changed' event on a given issue or pull request. + """ + PROJECT_V2_ITEM_STATUS_CHANGED_EVENT + """ Represents a 'referenced' event on a given `ReferencedSubject`. """ @@ -20605,6 +20694,11 @@ enum IssueTimelineItemsItemType { """ REMOVED_FROM_PROJECT_EVENT + """ + Represents a 'removed_from_project_v2' event on a given issue or pull request. + """ + REMOVED_FROM_PROJECT_V2_EVENT + """ Represents a 'renamed' event on a given issue or pull request """ @@ -37667,6 +37761,21 @@ type ProjectV2Edge { node: ProjectV2 } +""" +Represents an event related to a project on the timeline of an issue or pull request. +""" +interface ProjectV2Event { + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ A field inside a project. """ @@ -38731,6 +38840,46 @@ enum ProjectV2ItemOrderField { POSITION } +""" +Represents a 'project_v2_item_status_changed' event on a given issue or pull request. +""" +type ProjectV2ItemStatusChangedEvent implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the ProjectV2ItemStatusChangedEvent object + """ + id: ID! + + """ + The previous status of the project item. + """ + previousStatus: String! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + The new status of the project item. + """ + status: String! + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ The type of a project item. """ @@ -42966,6 +43115,7 @@ An item in a pull request timeline union PullRequestTimelineItems = | AddedToMergeQueueEvent | AddedToProjectEvent + | AddedToProjectV2Event | AssignedEvent | AutoMergeDisabledEvent | AutoMergeEnabledEvent @@ -42984,6 +43134,7 @@ union PullRequestTimelineItems = | CommentDeletedEvent | ConnectedEvent | ConvertToDraftEvent + | ConvertedFromDraftEvent | ConvertedNoteToIssueEvent | ConvertedToDiscussionEvent | CrossReferencedEvent @@ -43008,6 +43159,7 @@ union PullRequestTimelineItems = | ParentIssueAddedEvent | ParentIssueRemovedEvent | PinnedEvent + | ProjectV2ItemStatusChangedEvent | PullRequestCommit | PullRequestCommitCommentThread | PullRequestReview @@ -43017,6 +43169,7 @@ union PullRequestTimelineItems = | ReferencedEvent | RemovedFromMergeQueueEvent | RemovedFromProjectEvent + | RemovedFromProjectV2Event | RenamedTitleEvent | ReopenedEvent | ReviewDismissedEvent @@ -43103,6 +43256,11 @@ enum PullRequestTimelineItemsItemType { """ ADDED_TO_PROJECT_EVENT + """ + Represents a 'added_to_project_v2' event on a given issue or pull request. + """ + ADDED_TO_PROJECT_V2_EVENT + """ Represents an 'assigned' event on any assignable object. """ @@ -43188,6 +43346,11 @@ enum PullRequestTimelineItemsItemType { """ CONNECTED_EVENT + """ + Represents a 'converted_from_draft' event on a given issue or pull request. + """ + CONVERTED_FROM_DRAFT_EVENT + """ Represents a 'converted_note_to_issue' event on a given issue or pull request. """ @@ -43313,6 +43476,11 @@ enum PullRequestTimelineItemsItemType { """ PINNED_EVENT + """ + Represents a 'project_v2_item_status_changed' event on a given issue or pull request. + """ + PROJECT_V2_ITEM_STATUS_CHANGED_EVENT + """ Represents a Git commit part of a pull request. """ @@ -43358,6 +43526,11 @@ enum PullRequestTimelineItemsItemType { """ REMOVED_FROM_PROJECT_EVENT + """ + Represents a 'removed_from_project_v2' event on a given issue or pull request. + """ + REMOVED_FROM_PROJECT_V2_EVENT + """ Represents a 'renamed' event on a given issue or pull request """ @@ -46028,6 +46201,36 @@ type RemovedFromProjectEvent implements Node { ) } +""" +Represents a 'removed_from_project_v2' event on a given issue or pull request. +""" +type RemovedFromProjectV2Event implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the RemovedFromProjectV2Event object + """ + id: ID! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ Represents a 'renamed' event on a given issue or pull request """ diff --git a/src/graphql/data/fpt/schema.json b/src/graphql/data/fpt/schema.json index d2a5402ed2c7..0b87813706f6 100644 --- a/src/graphql/data/fpt/schema.json +++ b/src/graphql/data/fpt/schema.json @@ -10392,6 +10392,67 @@ } ] }, + { + "name": "AddedToProjectV2Event", + "kind": "objects", + "id": "addedtoprojectv2event", + "href": "/graphql/reference/objects#addedtoprojectv2event", + "description": "

Represents aadded_to_project_v2event on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the AddedToProjectV2Event object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "AnnouncementBanner", "kind": "objects", @@ -17308,6 +17369,67 @@ } ] }, + { + "name": "ConvertedFromDraftEvent", + "kind": "objects", + "id": "convertedfromdraftevent", + "href": "/graphql/reference/objects#convertedfromdraftevent", + "description": "

Represents aconverted_from_draftevent on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the ConvertedFromDraftEvent object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "ConvertedNoteToIssueEvent", "kind": "objects", @@ -31467,6 +31589,22 @@ "id": "int", "kind": "scalars", "href": "/graphql/reference/scalars#int" + }, + { + "name": "totalBlockedBy", + "description": "

Total count of issues this issue is blocked by (open and closed).

", + "type": "Int!", + "id": "int", + "kind": "scalars", + "href": "/graphql/reference/scalars#int" + }, + { + "name": "totalBlocking", + "description": "

Total count of issues this issue is blocking (open and closed).

", + "type": "Int!", + "id": "int", + "kind": "scalars", + "href": "/graphql/reference/scalars#int" } ] }, @@ -51608,6 +51746,83 @@ } ] }, + { + "name": "ProjectV2ItemStatusChangedEvent", + "kind": "objects", + "id": "projectv2itemstatuschangedevent", + "href": "/graphql/reference/objects#projectv2itemstatuschangedevent", + "description": "

Represents aproject_v2_item_status_changedevent on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the ProjectV2ItemStatusChangedEvent object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "previousStatus", + "description": "

The previous status of the project item.

", + "type": "String!", + "id": "string", + "kind": "scalars", + "href": "/graphql/reference/scalars#string" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "status", + "description": "

The new status of the project item.

", + "type": "String!", + "id": "string", + "kind": "scalars", + "href": "/graphql/reference/scalars#string" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "ProjectV2IterationField", "kind": "objects", @@ -59943,6 +60158,67 @@ } ] }, + { + "name": "RemovedFromProjectV2Event", + "kind": "objects", + "id": "removedfromprojectv2event", + "href": "/graphql/reference/objects#removedfromprojectv2event", + "description": "

Represents aremoved_from_project_v2event on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the RemovedFromProjectV2Event object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "RenamedTitleEvent", "kind": "objects", @@ -86123,6 +86399,31 @@ } ] }, + { + "name": "ProjectV2Event", + "kind": "interfaces", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event", + "description": "

Represents an event related to a project on the timeline of an issue or pull request.

", + "fields": [ + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "ProjectV2FieldCommon", "kind": "interfaces", @@ -89916,6 +90217,10 @@ "name": "ADDED_TO_PROJECT_EVENT", "description": "

Represents aadded_to_projectevent on a given issue or pull request.

" }, + { + "name": "ADDED_TO_PROJECT_V2_EVENT", + "description": "

Represents aadded_to_project_v2event on a given issue or pull request.

" + }, { "name": "ASSIGNED_EVENT", "description": "

Represents anassignedevent on any assignable object.

" @@ -89948,6 +90253,10 @@ "name": "CONNECTED_EVENT", "description": "

Represents aconnectedevent on a given issue or pull request.

" }, + { + "name": "CONVERTED_FROM_DRAFT_EVENT", + "description": "

Represents aconverted_from_draftevent on a given issue or pull request.

" + }, { "name": "CONVERTED_NOTE_TO_ISSUE_EVENT", "description": "

Represents aconverted_note_to_issueevent on a given issue or pull request.

" @@ -90020,6 +90329,10 @@ "name": "PINNED_EVENT", "description": "

Represents apinnedevent on a given issue or pull request.

" }, + { + "name": "PROJECT_V2_ITEM_STATUS_CHANGED_EVENT", + "description": "

Represents aproject_v2_item_status_changedevent on a given issue or pull request.

" + }, { "name": "REFERENCED_EVENT", "description": "

Represents areferencedevent on a given ReferencedSubject.

" @@ -90028,6 +90341,10 @@ "name": "REMOVED_FROM_PROJECT_EVENT", "description": "

Represents aremoved_from_projectevent on a given issue or pull request.

" }, + { + "name": "REMOVED_FROM_PROJECT_V2_EVENT", + "description": "

Represents aremoved_from_project_v2event on a given issue or pull request.

" + }, { "name": "RENAMED_TITLE_EVENT", "description": "

Represents arenamedevent on a given issue or pull request.

" @@ -92023,6 +92340,10 @@ "name": "ADDED_TO_PROJECT_EVENT", "description": "

Represents aadded_to_projectevent on a given issue or pull request.

" }, + { + "name": "ADDED_TO_PROJECT_V2_EVENT", + "description": "

Represents aadded_to_project_v2event on a given issue or pull request.

" + }, { "name": "ASSIGNED_EVENT", "description": "

Represents anassignedevent on any assignable object.

" @@ -92091,6 +92412,10 @@ "name": "CONNECTED_EVENT", "description": "

Represents aconnectedevent on a given issue or pull request.

" }, + { + "name": "CONVERTED_FROM_DRAFT_EVENT", + "description": "

Represents aconverted_from_draftevent on a given issue or pull request.

" + }, { "name": "CONVERTED_NOTE_TO_ISSUE_EVENT", "description": "

Represents aconverted_note_to_issueevent on a given issue or pull request.

" @@ -92191,6 +92516,10 @@ "name": "PINNED_EVENT", "description": "

Represents apinnedevent on a given issue or pull request.

" }, + { + "name": "PROJECT_V2_ITEM_STATUS_CHANGED_EVENT", + "description": "

Represents aproject_v2_item_status_changedevent on a given issue or pull request.

" + }, { "name": "PULL_REQUEST_COMMIT", "description": "

Represents a Git commit part of a pull request.

" @@ -92227,6 +92556,10 @@ "name": "REMOVED_FROM_PROJECT_EVENT", "description": "

Represents aremoved_from_projectevent on a given issue or pull request.

" }, + { + "name": "REMOVED_FROM_PROJECT_V2_EVENT", + "description": "

Represents aremoved_from_project_v2event on a given issue or pull request.

" + }, { "name": "RENAMED_TITLE_EVENT", "description": "

Represents arenamedevent on a given issue or pull request.

" @@ -95697,6 +96030,11 @@ "id": "addedtoprojectevent", "href": "/graphql/reference/objects#addedtoprojectevent" }, + { + "name": "AddedToProjectV2Event", + "id": "addedtoprojectv2event", + "href": "/graphql/reference/objects#addedtoprojectv2event" + }, { "name": "AssignedEvent", "id": "assignedevent", @@ -95737,6 +96075,11 @@ "id": "connectedevent", "href": "/graphql/reference/objects#connectedevent" }, + { + "name": "ConvertedFromDraftEvent", + "id": "convertedfromdraftevent", + "href": "/graphql/reference/objects#convertedfromdraftevent" + }, { "name": "ConvertedNoteToIssueEvent", "id": "convertednotetoissueevent", @@ -95827,6 +96170,11 @@ "id": "pinnedevent", "href": "/graphql/reference/objects#pinnedevent" }, + { + "name": "ProjectV2ItemStatusChangedEvent", + "id": "projectv2itemstatuschangedevent", + "href": "/graphql/reference/objects#projectv2itemstatuschangedevent" + }, { "name": "ReferencedEvent", "id": "referencedevent", @@ -95837,6 +96185,11 @@ "id": "removedfromprojectevent", "href": "/graphql/reference/objects#removedfromprojectevent" }, + { + "name": "RemovedFromProjectV2Event", + "id": "removedfromprojectv2event", + "href": "/graphql/reference/objects#removedfromprojectv2event" + }, { "name": "RenamedTitleEvent", "id": "renamedtitleevent", @@ -96659,6 +97012,11 @@ "id": "addedtoprojectevent", "href": "/graphql/reference/objects#addedtoprojectevent" }, + { + "name": "AddedToProjectV2Event", + "id": "addedtoprojectv2event", + "href": "/graphql/reference/objects#addedtoprojectv2event" + }, { "name": "AssignedEvent", "id": "assignedevent", @@ -96749,6 +97107,11 @@ "id": "converttodraftevent", "href": "/graphql/reference/objects#converttodraftevent" }, + { + "name": "ConvertedFromDraftEvent", + "id": "convertedfromdraftevent", + "href": "/graphql/reference/objects#convertedfromdraftevent" + }, { "name": "ConvertedNoteToIssueEvent", "id": "convertednotetoissueevent", @@ -96869,6 +97232,11 @@ "id": "pinnedevent", "href": "/graphql/reference/objects#pinnedevent" }, + { + "name": "ProjectV2ItemStatusChangedEvent", + "id": "projectv2itemstatuschangedevent", + "href": "/graphql/reference/objects#projectv2itemstatuschangedevent" + }, { "name": "PullRequestCommit", "id": "pullrequestcommit", @@ -96914,6 +97282,11 @@ "id": "removedfromprojectevent", "href": "/graphql/reference/objects#removedfromprojectevent" }, + { + "name": "RemovedFromProjectV2Event", + "id": "removedfromprojectv2event", + "href": "/graphql/reference/objects#removedfromprojectv2event" + }, { "name": "RenamedTitleEvent", "id": "renamedtitleevent", diff --git a/src/graphql/data/ghec/schema.docs.graphql b/src/graphql/data/ghec/schema.docs.graphql index a4e3f8872547..abc6e5bd51b9 100644 --- a/src/graphql/data/ghec/schema.docs.graphql +++ b/src/graphql/data/ghec/schema.docs.graphql @@ -1386,6 +1386,36 @@ type AddedToProjectEvent implements Node { ) } +""" +Represents a 'added_to_project_v2' event on a given issue or pull request. +""" +type AddedToProjectV2Event implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the AddedToProjectV2Event object + """ + id: ID! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ An announcement banner for an enterprise or organization. """ @@ -7179,6 +7209,36 @@ type ConvertToDraftEvent implements Node & UniformResourceLocatable { url: URI! } +""" +Represents a 'converted_from_draft' event on a given issue or pull request. +""" +type ConvertedFromDraftEvent implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the ConvertedFromDraftEvent object + """ + id: ID! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ Represents a 'converted_note_to_issue' event on a given issue or pull request. """ @@ -20013,6 +20073,16 @@ type IssueDependenciesSummary { Count of issues this issue is blocking """ blocking: Int! + + """ + Total count of issues this issue is blocked by (open and closed) + """ + totalBlockedBy: Int! + + """ + Total count of issues this issue is blocking (open and closed) + """ + totalBlocking: Int! } """ @@ -20359,6 +20429,7 @@ An item in an issue timeline """ union IssueTimelineItems = | AddedToProjectEvent + | AddedToProjectV2Event | AssignedEvent | BlockedByAddedEvent | BlockedByRemovedEvent @@ -20367,6 +20438,7 @@ union IssueTimelineItems = | ClosedEvent | CommentDeletedEvent | ConnectedEvent + | ConvertedFromDraftEvent | ConvertedNoteToIssueEvent | ConvertedToDiscussionEvent | CrossReferencedEvent @@ -20385,8 +20457,10 @@ union IssueTimelineItems = | ParentIssueAddedEvent | ParentIssueRemovedEvent | PinnedEvent + | ProjectV2ItemStatusChangedEvent | ReferencedEvent | RemovedFromProjectEvent + | RemovedFromProjectV2Event | RenamedTitleEvent | ReopenedEvent | SubIssueAddedEvent @@ -20465,6 +20539,11 @@ enum IssueTimelineItemsItemType { """ ADDED_TO_PROJECT_EVENT + """ + Represents a 'added_to_project_v2' event on a given issue or pull request. + """ + ADDED_TO_PROJECT_V2_EVENT + """ Represents an 'assigned' event on any assignable object. """ @@ -20505,6 +20584,11 @@ enum IssueTimelineItemsItemType { """ CONNECTED_EVENT + """ + Represents a 'converted_from_draft' event on a given issue or pull request. + """ + CONVERTED_FROM_DRAFT_EVENT + """ Represents a 'converted_note_to_issue' event on a given issue or pull request. """ @@ -20595,6 +20679,11 @@ enum IssueTimelineItemsItemType { """ PINNED_EVENT + """ + Represents a 'project_v2_item_status_changed' event on a given issue or pull request. + """ + PROJECT_V2_ITEM_STATUS_CHANGED_EVENT + """ Represents a 'referenced' event on a given `ReferencedSubject`. """ @@ -20605,6 +20694,11 @@ enum IssueTimelineItemsItemType { """ REMOVED_FROM_PROJECT_EVENT + """ + Represents a 'removed_from_project_v2' event on a given issue or pull request. + """ + REMOVED_FROM_PROJECT_V2_EVENT + """ Represents a 'renamed' event on a given issue or pull request """ @@ -37667,6 +37761,21 @@ type ProjectV2Edge { node: ProjectV2 } +""" +Represents an event related to a project on the timeline of an issue or pull request. +""" +interface ProjectV2Event { + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ A field inside a project. """ @@ -38731,6 +38840,46 @@ enum ProjectV2ItemOrderField { POSITION } +""" +Represents a 'project_v2_item_status_changed' event on a given issue or pull request. +""" +type ProjectV2ItemStatusChangedEvent implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the ProjectV2ItemStatusChangedEvent object + """ + id: ID! + + """ + The previous status of the project item. + """ + previousStatus: String! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + The new status of the project item. + """ + status: String! + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ The type of a project item. """ @@ -42966,6 +43115,7 @@ An item in a pull request timeline union PullRequestTimelineItems = | AddedToMergeQueueEvent | AddedToProjectEvent + | AddedToProjectV2Event | AssignedEvent | AutoMergeDisabledEvent | AutoMergeEnabledEvent @@ -42984,6 +43134,7 @@ union PullRequestTimelineItems = | CommentDeletedEvent | ConnectedEvent | ConvertToDraftEvent + | ConvertedFromDraftEvent | ConvertedNoteToIssueEvent | ConvertedToDiscussionEvent | CrossReferencedEvent @@ -43008,6 +43159,7 @@ union PullRequestTimelineItems = | ParentIssueAddedEvent | ParentIssueRemovedEvent | PinnedEvent + | ProjectV2ItemStatusChangedEvent | PullRequestCommit | PullRequestCommitCommentThread | PullRequestReview @@ -43017,6 +43169,7 @@ union PullRequestTimelineItems = | ReferencedEvent | RemovedFromMergeQueueEvent | RemovedFromProjectEvent + | RemovedFromProjectV2Event | RenamedTitleEvent | ReopenedEvent | ReviewDismissedEvent @@ -43103,6 +43256,11 @@ enum PullRequestTimelineItemsItemType { """ ADDED_TO_PROJECT_EVENT + """ + Represents a 'added_to_project_v2' event on a given issue or pull request. + """ + ADDED_TO_PROJECT_V2_EVENT + """ Represents an 'assigned' event on any assignable object. """ @@ -43188,6 +43346,11 @@ enum PullRequestTimelineItemsItemType { """ CONNECTED_EVENT + """ + Represents a 'converted_from_draft' event on a given issue or pull request. + """ + CONVERTED_FROM_DRAFT_EVENT + """ Represents a 'converted_note_to_issue' event on a given issue or pull request. """ @@ -43313,6 +43476,11 @@ enum PullRequestTimelineItemsItemType { """ PINNED_EVENT + """ + Represents a 'project_v2_item_status_changed' event on a given issue or pull request. + """ + PROJECT_V2_ITEM_STATUS_CHANGED_EVENT + """ Represents a Git commit part of a pull request. """ @@ -43358,6 +43526,11 @@ enum PullRequestTimelineItemsItemType { """ REMOVED_FROM_PROJECT_EVENT + """ + Represents a 'removed_from_project_v2' event on a given issue or pull request. + """ + REMOVED_FROM_PROJECT_V2_EVENT + """ Represents a 'renamed' event on a given issue or pull request """ @@ -46028,6 +46201,36 @@ type RemovedFromProjectEvent implements Node { ) } +""" +Represents a 'removed_from_project_v2' event on a given issue or pull request. +""" +type RemovedFromProjectV2Event implements Node & ProjectV2Event { + """ + Identifies the actor who performed the event. + """ + actor: Actor + + """ + Identifies the date and time when the object was created. + """ + createdAt: DateTime! + + """ + The Node ID of the RemovedFromProjectV2Event object + """ + id: ID! + + """ + Project referenced by event. + """ + project: ProjectV2 + + """ + Did this event result from workflow automation? + """ + wasAutomated: Boolean! +} + """ Represents a 'renamed' event on a given issue or pull request """ diff --git a/src/graphql/data/ghec/schema.json b/src/graphql/data/ghec/schema.json index d2a5402ed2c7..0b87813706f6 100644 --- a/src/graphql/data/ghec/schema.json +++ b/src/graphql/data/ghec/schema.json @@ -10392,6 +10392,67 @@ } ] }, + { + "name": "AddedToProjectV2Event", + "kind": "objects", + "id": "addedtoprojectv2event", + "href": "/graphql/reference/objects#addedtoprojectv2event", + "description": "

Represents aadded_to_project_v2event on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the AddedToProjectV2Event object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "AnnouncementBanner", "kind": "objects", @@ -17308,6 +17369,67 @@ } ] }, + { + "name": "ConvertedFromDraftEvent", + "kind": "objects", + "id": "convertedfromdraftevent", + "href": "/graphql/reference/objects#convertedfromdraftevent", + "description": "

Represents aconverted_from_draftevent on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the ConvertedFromDraftEvent object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "ConvertedNoteToIssueEvent", "kind": "objects", @@ -31467,6 +31589,22 @@ "id": "int", "kind": "scalars", "href": "/graphql/reference/scalars#int" + }, + { + "name": "totalBlockedBy", + "description": "

Total count of issues this issue is blocked by (open and closed).

", + "type": "Int!", + "id": "int", + "kind": "scalars", + "href": "/graphql/reference/scalars#int" + }, + { + "name": "totalBlocking", + "description": "

Total count of issues this issue is blocking (open and closed).

", + "type": "Int!", + "id": "int", + "kind": "scalars", + "href": "/graphql/reference/scalars#int" } ] }, @@ -51608,6 +51746,83 @@ } ] }, + { + "name": "ProjectV2ItemStatusChangedEvent", + "kind": "objects", + "id": "projectv2itemstatuschangedevent", + "href": "/graphql/reference/objects#projectv2itemstatuschangedevent", + "description": "

Represents aproject_v2_item_status_changedevent on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the ProjectV2ItemStatusChangedEvent object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "previousStatus", + "description": "

The previous status of the project item.

", + "type": "String!", + "id": "string", + "kind": "scalars", + "href": "/graphql/reference/scalars#string" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "status", + "description": "

The new status of the project item.

", + "type": "String!", + "id": "string", + "kind": "scalars", + "href": "/graphql/reference/scalars#string" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "ProjectV2IterationField", "kind": "objects", @@ -59943,6 +60158,67 @@ } ] }, + { + "name": "RemovedFromProjectV2Event", + "kind": "objects", + "id": "removedfromprojectv2event", + "href": "/graphql/reference/objects#removedfromprojectv2event", + "description": "

Represents aremoved_from_project_v2event on a given issue or pull request.

", + "implements": [ + { + "name": "Node", + "id": "node", + "href": "/graphql/reference/interfaces#node" + }, + { + "name": "ProjectV2Event", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event" + } + ], + "fields": [ + { + "name": "actor", + "description": "

Identifies the actor who performed the event.

", + "type": "Actor", + "id": "actor", + "kind": "interfaces", + "href": "/graphql/reference/interfaces#actor" + }, + { + "name": "createdAt", + "description": "

Identifies the date and time when the object was created.

", + "type": "DateTime!", + "id": "datetime", + "kind": "scalars", + "href": "/graphql/reference/scalars#datetime" + }, + { + "name": "id", + "description": "

The Node ID of the RemovedFromProjectV2Event object.

", + "type": "ID!", + "id": "id", + "kind": "scalars", + "href": "/graphql/reference/scalars#id" + }, + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "RenamedTitleEvent", "kind": "objects", @@ -86123,6 +86399,31 @@ } ] }, + { + "name": "ProjectV2Event", + "kind": "interfaces", + "id": "projectv2event", + "href": "/graphql/reference/interfaces#projectv2event", + "description": "

Represents an event related to a project on the timeline of an issue or pull request.

", + "fields": [ + { + "name": "project", + "description": "

Project referenced by event.

", + "type": "ProjectV2", + "id": "projectv2", + "kind": "objects", + "href": "/graphql/reference/objects#projectv2" + }, + { + "name": "wasAutomated", + "description": "

Did this event result from workflow automation?.

", + "type": "Boolean!", + "id": "boolean", + "kind": "scalars", + "href": "/graphql/reference/scalars#boolean" + } + ] + }, { "name": "ProjectV2FieldCommon", "kind": "interfaces", @@ -89916,6 +90217,10 @@ "name": "ADDED_TO_PROJECT_EVENT", "description": "

Represents aadded_to_projectevent on a given issue or pull request.

" }, + { + "name": "ADDED_TO_PROJECT_V2_EVENT", + "description": "

Represents aadded_to_project_v2event on a given issue or pull request.

" + }, { "name": "ASSIGNED_EVENT", "description": "

Represents anassignedevent on any assignable object.

" @@ -89948,6 +90253,10 @@ "name": "CONNECTED_EVENT", "description": "

Represents aconnectedevent on a given issue or pull request.

" }, + { + "name": "CONVERTED_FROM_DRAFT_EVENT", + "description": "

Represents aconverted_from_draftevent on a given issue or pull request.

" + }, { "name": "CONVERTED_NOTE_TO_ISSUE_EVENT", "description": "

Represents aconverted_note_to_issueevent on a given issue or pull request.

" @@ -90020,6 +90329,10 @@ "name": "PINNED_EVENT", "description": "

Represents apinnedevent on a given issue or pull request.

" }, + { + "name": "PROJECT_V2_ITEM_STATUS_CHANGED_EVENT", + "description": "

Represents aproject_v2_item_status_changedevent on a given issue or pull request.

" + }, { "name": "REFERENCED_EVENT", "description": "

Represents areferencedevent on a given ReferencedSubject.

" @@ -90028,6 +90341,10 @@ "name": "REMOVED_FROM_PROJECT_EVENT", "description": "

Represents aremoved_from_projectevent on a given issue or pull request.

" }, + { + "name": "REMOVED_FROM_PROJECT_V2_EVENT", + "description": "

Represents aremoved_from_project_v2event on a given issue or pull request.

" + }, { "name": "RENAMED_TITLE_EVENT", "description": "

Represents arenamedevent on a given issue or pull request.

" @@ -92023,6 +92340,10 @@ "name": "ADDED_TO_PROJECT_EVENT", "description": "

Represents aadded_to_projectevent on a given issue or pull request.

" }, + { + "name": "ADDED_TO_PROJECT_V2_EVENT", + "description": "

Represents aadded_to_project_v2event on a given issue or pull request.

" + }, { "name": "ASSIGNED_EVENT", "description": "

Represents anassignedevent on any assignable object.

" @@ -92091,6 +92412,10 @@ "name": "CONNECTED_EVENT", "description": "

Represents aconnectedevent on a given issue or pull request.

" }, + { + "name": "CONVERTED_FROM_DRAFT_EVENT", + "description": "

Represents aconverted_from_draftevent on a given issue or pull request.

" + }, { "name": "CONVERTED_NOTE_TO_ISSUE_EVENT", "description": "

Represents aconverted_note_to_issueevent on a given issue or pull request.

" @@ -92191,6 +92516,10 @@ "name": "PINNED_EVENT", "description": "

Represents apinnedevent on a given issue or pull request.

" }, + { + "name": "PROJECT_V2_ITEM_STATUS_CHANGED_EVENT", + "description": "

Represents aproject_v2_item_status_changedevent on a given issue or pull request.

" + }, { "name": "PULL_REQUEST_COMMIT", "description": "

Represents a Git commit part of a pull request.

" @@ -92227,6 +92556,10 @@ "name": "REMOVED_FROM_PROJECT_EVENT", "description": "

Represents aremoved_from_projectevent on a given issue or pull request.

" }, + { + "name": "REMOVED_FROM_PROJECT_V2_EVENT", + "description": "

Represents aremoved_from_project_v2event on a given issue or pull request.

" + }, { "name": "RENAMED_TITLE_EVENT", "description": "

Represents arenamedevent on a given issue or pull request.

" @@ -95697,6 +96030,11 @@ "id": "addedtoprojectevent", "href": "/graphql/reference/objects#addedtoprojectevent" }, + { + "name": "AddedToProjectV2Event", + "id": "addedtoprojectv2event", + "href": "/graphql/reference/objects#addedtoprojectv2event" + }, { "name": "AssignedEvent", "id": "assignedevent", @@ -95737,6 +96075,11 @@ "id": "connectedevent", "href": "/graphql/reference/objects#connectedevent" }, + { + "name": "ConvertedFromDraftEvent", + "id": "convertedfromdraftevent", + "href": "/graphql/reference/objects#convertedfromdraftevent" + }, { "name": "ConvertedNoteToIssueEvent", "id": "convertednotetoissueevent", @@ -95827,6 +96170,11 @@ "id": "pinnedevent", "href": "/graphql/reference/objects#pinnedevent" }, + { + "name": "ProjectV2ItemStatusChangedEvent", + "id": "projectv2itemstatuschangedevent", + "href": "/graphql/reference/objects#projectv2itemstatuschangedevent" + }, { "name": "ReferencedEvent", "id": "referencedevent", @@ -95837,6 +96185,11 @@ "id": "removedfromprojectevent", "href": "/graphql/reference/objects#removedfromprojectevent" }, + { + "name": "RemovedFromProjectV2Event", + "id": "removedfromprojectv2event", + "href": "/graphql/reference/objects#removedfromprojectv2event" + }, { "name": "RenamedTitleEvent", "id": "renamedtitleevent", @@ -96659,6 +97012,11 @@ "id": "addedtoprojectevent", "href": "/graphql/reference/objects#addedtoprojectevent" }, + { + "name": "AddedToProjectV2Event", + "id": "addedtoprojectv2event", + "href": "/graphql/reference/objects#addedtoprojectv2event" + }, { "name": "AssignedEvent", "id": "assignedevent", @@ -96749,6 +97107,11 @@ "id": "converttodraftevent", "href": "/graphql/reference/objects#converttodraftevent" }, + { + "name": "ConvertedFromDraftEvent", + "id": "convertedfromdraftevent", + "href": "/graphql/reference/objects#convertedfromdraftevent" + }, { "name": "ConvertedNoteToIssueEvent", "id": "convertednotetoissueevent", @@ -96869,6 +97232,11 @@ "id": "pinnedevent", "href": "/graphql/reference/objects#pinnedevent" }, + { + "name": "ProjectV2ItemStatusChangedEvent", + "id": "projectv2itemstatuschangedevent", + "href": "/graphql/reference/objects#projectv2itemstatuschangedevent" + }, { "name": "PullRequestCommit", "id": "pullrequestcommit", @@ -96914,6 +97282,11 @@ "id": "removedfromprojectevent", "href": "/graphql/reference/objects#removedfromprojectevent" }, + { + "name": "RemovedFromProjectV2Event", + "id": "removedfromprojectv2event", + "href": "/graphql/reference/objects#removedfromprojectv2event" + }, { "name": "RenamedTitleEvent", "id": "renamedtitleevent", From 5268d1a08434ee096c18833cc3b81a2c40681194 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Wed, 15 Oct 2025 09:43:49 -0700 Subject: [PATCH 2/4] Migrate 8 JavaScript files to TypeScript (#57973) --- ...rmatting.js => note-warning-formatting.ts} | 26 ++++- .../markdownlint-rule-search-replace.d.ts | 1 + ...sh-quotes.js => british-english-quotes.ts} | 30 +++-- .../{search-replace.js => search-replace.ts} | 2 +- .../liquid/{ifversion.js => ifversion.ts} | 82 +++++++++---- ...-code-blocks.js => copilot-code-blocks.ts} | 0 ...abels.js => table-accessibility-labels.ts} | 2 +- .../{schema-helpers.js => schema-helpers.ts} | 110 ++++++++++++++---- .../{openapi-schema.js => openapi-schema.ts} | 37 +++--- src/types/markdownlint-rules.d.ts | 7 -- 10 files changed, 210 insertions(+), 87 deletions(-) rename src/content-linter/lib/linting-rules/{note-warning-formatting.js => note-warning-formatting.ts} (91%) create mode 100644 src/content-linter/markdownlint-rule-search-replace.d.ts rename src/content-linter/tests/unit/{british-english-quotes.js => british-english-quotes.ts} (85%) rename src/content-linter/tests/unit/{search-replace.js => search-replace.ts} (99%) rename src/content-render/liquid/{ifversion.js => ifversion.ts} (77%) rename src/content-render/tests/{copilot-code-blocks.js => copilot-code-blocks.ts} (100%) rename src/content-render/tests/{table-accessibility-labels.js => table-accessibility-labels.ts} (99%) rename src/graphql/scripts/utils/{schema-helpers.js => schema-helpers.ts} (67%) rename src/rest/tests/{openapi-schema.js => openapi-schema.ts} (85%) delete mode 100644 src/types/markdownlint-rules.d.ts diff --git a/src/content-linter/lib/linting-rules/note-warning-formatting.js b/src/content-linter/lib/linting-rules/note-warning-formatting.ts similarity index 91% rename from src/content-linter/lib/linting-rules/note-warning-formatting.js rename to src/content-linter/lib/linting-rules/note-warning-formatting.ts index 3c54f24c62e5..820ac069f8b9 100644 --- a/src/content-linter/lib/linting-rules/note-warning-formatting.js +++ b/src/content-linter/lib/linting-rules/note-warning-formatting.ts @@ -1,13 +1,20 @@ +// @ts-ignore - markdownlint-rule-helpers doesn't provide TypeScript declarations import { addError } from 'markdownlint-rule-helpers' import { getRange } from '../helpers/utils' import frontmatter from '@/frame/lib/read-frontmatter' +import type { RuleParams, RuleErrorCallback } from '@/content-linter/types' + +interface NoteContentItem { + text: string + lineNumber: number +} export const noteWarningFormatting = { names: ['GHD049', 'note-warning-formatting'], description: 'Note and warning tags should be formatted according to style guide', tags: ['formatting', 'callouts', 'notes', 'warnings', 'style'], severity: 'warning', - function: (params, onError) => { + function: (params: RuleParams, onError: RuleErrorCallback) => { // Skip autogenerated files const frontmatterString = params.frontMatterLines.join('\n') const fm = frontmatter(frontmatterString).data @@ -15,8 +22,8 @@ export const noteWarningFormatting = { const lines = params.lines let inLegacyNote = false - let noteStartLine = null - let noteContent = [] + let noteStartLine: number | null = null + let noteContent: NoteContentItem[] = [] for (let i = 0; i < lines.length; i++) { const line = lines[i] @@ -144,7 +151,11 @@ export const noteWarningFormatting = { /** * Validate content inside legacy {% note %} blocks */ -function validateNoteContent(noteContent, noteStartLine, onError) { +function validateNoteContent( + noteContent: NoteContentItem[], + noteStartLine: number | null, + onError: RuleErrorCallback, +) { if (noteContent.length === 0) return const contentLines = noteContent.filter((item) => item.text.trim() !== '') @@ -195,7 +206,12 @@ function validateNoteContent(noteContent, noteStartLine, onError) { /** * Validate content inside new-style callouts */ -function validateCalloutContent(calloutContent, calloutType, calloutStartLine, onError) { +function validateCalloutContent( + calloutContent: NoteContentItem[], + calloutType: string, + calloutStartLine: number, + onError: RuleErrorCallback, +) { if (calloutContent.length === 0) return const contentLines = calloutContent.filter((item) => item.text.trim() !== '>') diff --git a/src/content-linter/markdownlint-rule-search-replace.d.ts b/src/content-linter/markdownlint-rule-search-replace.d.ts new file mode 100644 index 000000000000..10bda4ea8271 --- /dev/null +++ b/src/content-linter/markdownlint-rule-search-replace.d.ts @@ -0,0 +1 @@ +declare module 'markdownlint-rule-search-replace' diff --git a/src/content-linter/tests/unit/british-english-quotes.js b/src/content-linter/tests/unit/british-english-quotes.ts similarity index 85% rename from src/content-linter/tests/unit/british-english-quotes.js rename to src/content-linter/tests/unit/british-english-quotes.ts index 6e338c578b4d..6423d7960eda 100644 --- a/src/content-linter/tests/unit/british-english-quotes.js +++ b/src/content-linter/tests/unit/british-english-quotes.ts @@ -23,7 +23,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'The article "[AUTOTITLE]", covers this topic.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(2) expect(errors[0].lineNumber).toBe(1) if (errors[0].detail) { @@ -43,7 +44,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'See the guide titled "Getting Started", for details.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(4) if (errors[0].detail) { expect(errors[0].detail).toContain('period inside') @@ -65,7 +67,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { "The term 'API endpoint', refers to a specific URL.", ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(2) if (errors[0].detail) { expect(errors[0].detail).toContain('period inside') @@ -86,7 +89,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'The command `git commit -m "Fix bug";` creates a commit.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(0) }) @@ -97,7 +101,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'The webhook URL http://api.service.com"endpoint" should work.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(0) }) @@ -107,7 +112,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'The guide "Setup Instructions", explains everything.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail and fixInfo properties not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(2) // Check that fix info is provided @@ -124,7 +130,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'As Fatima noted, "Testing is crucial"; quality depends on it.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(2) expect(errors[0].lineNumber).toBe(1) expect(errors[1].lineNumber).toBe(2) @@ -136,7 +143,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'The message "Error: \'Invalid input\'" appears sometimes.', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(1) if (errors[0].detail) { expect(errors[0].detail).toContain('period inside') @@ -150,7 +158,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'Reference "[AUTOTITLE]" .', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(3) if (errors[0].detail) { expect(errors[0].detail).toContain('period inside') @@ -194,7 +203,8 @@ describe(britishEnglishQuotes.names.join(' - '), () => { 'Dmitri explained, "The workflow has multiple stages."', ].join('\n') const result = await runRule(britishEnglishQuotes, { strings: { markdown } }) - const errors = result.markdown + // Markdownlint error objects include detail property not in base LintError type + const errors = result.markdown as any[] expect(errors.length).toBe(4) expect(errors[0].lineNumber).toBe(3) // config.yml line expect(errors[1].lineNumber).toBe(4) // Docker Basics line diff --git a/src/content-linter/tests/unit/search-replace.js b/src/content-linter/tests/unit/search-replace.ts similarity index 99% rename from src/content-linter/tests/unit/search-replace.js rename to src/content-linter/tests/unit/search-replace.ts index d7cd43973b64..a498e4b98bbb 100644 --- a/src/content-linter/tests/unit/search-replace.js +++ b/src/content-linter/tests/unit/search-replace.ts @@ -179,7 +179,7 @@ describe(searchReplace.names.join(' - '), () => { const result = await runRule(searchReplace, { strings: { markdown }, - config: searchReplaceConfig, + ruleConfig: searchReplaceConfig['search-replace'], markdownlintOptions: { frontMatter: null }, }) const errors = result.markdown diff --git a/src/content-render/liquid/ifversion.js b/src/content-render/liquid/ifversion.ts similarity index 77% rename from src/content-render/liquid/ifversion.js rename to src/content-render/liquid/ifversion.ts index 7446601d9e28..64059f4bf349 100644 --- a/src/content-render/liquid/ifversion.js +++ b/src/content-render/liquid/ifversion.ts @@ -1,6 +1,30 @@ -import { Tag, isTruthy, Value, TokenizationError } from 'liquidjs' +import { + Tag, + isTruthy, + Value, + TokenizationError, + type TagToken, + type Context, + type Emitter, + type Template, + type TopLevelToken, +} from 'liquidjs' import versionSatisfiesRange from '@/versions/lib/version-satisfies-range' -import supportedOperators from './ifversion-supported-operators' +import supportedOperators, { + type IfversionSupportedOperator, +} from './ifversion-supported-operators' + +interface Branch { + cond: string + templates: Template[] +} + +interface VersionObj { + shortName: string + hasNumberedReleases?: boolean + currentRelease?: string + internalLatestRelease?: string +} const SyntaxHelp = "Syntax Error in 'ifversion' with range - Valid syntax: ifversion [plan] [operator] [releaseNumber]" @@ -14,15 +38,20 @@ const notRegex = /(?:^|\s)not\s/ // using semver to evaluate release numbers instead of doing standard number comparisons, which // don't work the way we want because they evaluate 3.2 > 3.10 = true. export default class extends Tag { + tagToken: TagToken + branches: Branch[] + elseTemplates: Template[] + currentVersionObj: VersionObj | null = null + // The following is verbatim from https://github.com/harttle/liquidjs/blob/v9.22.1/src/builtin/tags/if.ts - constructor(tagToken, remainTokens, liquid) { + constructor(tagToken: TagToken, remainTokens: TopLevelToken[], liquid: any) { super(tagToken, remainTokens, liquid) this.tagToken = tagToken this.branches = [] this.elseTemplates = [] - let p + let p: Template[] const stream = this.liquid.parser .parseStream(remainTokens) .on('start', () => @@ -31,7 +60,7 @@ export default class extends Tag { templates: (p = []), }), ) - .on('tag:elsif', (token) => { + .on('tag:elsif', (token: any) => { this.branches.push({ cond: token.args, templates: (p = []), @@ -39,7 +68,7 @@ export default class extends Tag { }) .on('tag:else', () => (p = this.elseTemplates)) .on('tag:endif', () => stream.stop()) - .on('template', (tpl) => p.push(tpl)) + .on('template', (tpl: Template) => p.push(tpl)) .on('end', () => { throw new Error(`tag ${tagToken.getText()} not closed`) }) @@ -49,10 +78,10 @@ export default class extends Tag { // The following is _mostly_ verbatim from https://github.com/harttle/liquidjs/blob/v9.22.1/src/builtin/tags/if.ts // The additions here are the handleNots(), handleOperators(), and handleVersionNames() calls. - *render(ctx, emitter) { + *render(ctx: Context, emitter: Emitter): Generator { const r = this.liquid.renderer - this.currentVersionObj = ctx.environments.currentVersionObj + this.currentVersionObj = (ctx.environments as any).currentVersionObj for (const branch of this.branches) { let resolvedBranchCond = branch.cond @@ -67,8 +96,8 @@ export default class extends Tag { // Resolve version names to boolean values for Markdown API context. // This will replace syntax like `fpt or ghec` with `true or false` based on current version. // Only apply this transformation in Markdown API context to avoid breaking existing functionality. - if (ctx.environments.markdownRequested) { - resolvedBranchCond = this.handleVersionNames(resolvedBranchCond, ctx) + if ((ctx.environments as any).markdownRequested) { + resolvedBranchCond = this.handleVersionNames(resolvedBranchCond) } // Use Liquid's native function for the final evaluation. @@ -82,13 +111,13 @@ export default class extends Tag { yield r.renderTemplates(this.elseTemplates, ctx, emitter) } - handleNots(resolvedBranchCond) { + handleNots(resolvedBranchCond: string): string { if (!notRegex.test(resolvedBranchCond)) return resolvedBranchCond const condArray = resolvedBranchCond.split(' ') // Find the first index in the array that contains "not". - const notIndex = condArray.findIndex((el) => el === 'not') + const notIndex = condArray.findIndex((el: string) => el === 'not') // E.g., ['not', 'fpt'] const condParts = condArray.slice(notIndex, notIndex + 2) @@ -99,10 +128,10 @@ export default class extends Tag { // If the current version is the version being evaluated in the conditional, // that is negated and resolved to false. If it's NOT the version being // evaluated, that resolves to true. - const resolvedBoolean = !(versionToEvaluate === this.currentVersionObj.shortName) + const resolvedBoolean = !(versionToEvaluate === this.currentVersionObj!.shortName) // Replace syntax like `not fpt` with `true` or `false`. - resolvedBranchCond = resolvedBranchCond.replace(condParts.join(' '), resolvedBoolean) + resolvedBranchCond = resolvedBranchCond.replace(condParts.join(' '), String(resolvedBoolean)) // Run this function recursively until we've resolved all the nots. if (notRegex.test(resolvedBranchCond)) { @@ -112,14 +141,16 @@ export default class extends Tag { return resolvedBranchCond } - handleOperators(resolvedBranchCond) { + handleOperators(resolvedBranchCond: string): string { if (!supportedOperatorsRegex.test(resolvedBranchCond)) return resolvedBranchCond // If this conditional contains multiple parts using `or` or `and`, get only the conditional with operators. const condArray = resolvedBranchCond.split(' ') // Find the first index in the array that contains an operator. - const operatorIndex = condArray.findIndex((el) => supportedOperators.find((op) => el === op)) + const operatorIndex = condArray.findIndex((el: string) => + supportedOperators.find((op: string) => el === op), + ) // E.g., ['ghes', '<', '3.1'] const condParts = condArray.slice(operatorIndex - 1, operatorIndex + 2) @@ -129,7 +160,8 @@ export default class extends Tag { // Make sure the operator is supported and the release number matches `\d\d?\.\d\d?` const syntaxError = - !supportedOperators.includes(operator) || !releaseRegex.test(releaseToEvaluate) + !supportedOperators.includes(operator as IfversionSupportedOperator) || + !releaseRegex.test(releaseToEvaluate) if (syntaxError) { throw new TokenizationError(SyntaxHelp, this.tagToken) @@ -154,25 +186,25 @@ export default class extends Tag { ? this.currentVersionObj.currentRelease : this.currentVersionObj.internalLatestRelease - let resolvedBoolean + let resolvedBoolean: boolean if (operator === '!=') { // If this is the current plan, compare the release numbers. (Our semver package doesn't handle !=.) // If it's not the current version, it's always true. resolvedBoolean = - versionShortName === this.currentVersionObj.shortName + versionShortName === this.currentVersionObj!.shortName ? releaseToEvaluate !== currentRelease : true } else { // If this is the current plan, evaluate the operator using semver. // If it's not the current plan, it's always false. resolvedBoolean = - versionShortName === this.currentVersionObj.shortName - ? versionSatisfiesRange(currentRelease, `${operator}${releaseToEvaluate}`) + versionShortName === this.currentVersionObj!.shortName + ? versionSatisfiesRange(currentRelease!, `${operator}${releaseToEvaluate}`) : false } // Replace syntax like `fpt or ghes < 3.0` with `fpt or true` or `fpt or false`. - resolvedBranchCond = resolvedBranchCond.replace(condParts.join(' '), resolvedBoolean) + resolvedBranchCond = resolvedBranchCond.replace(condParts.join(' '), String(resolvedBoolean)) // Run this function recursively until we've resolved all the special operators. if (supportedOperatorsRegex.test(resolvedBranchCond)) { @@ -182,7 +214,7 @@ export default class extends Tag { return resolvedBranchCond } - handleVersionNames(resolvedBranchCond, ctx) { + handleVersionNames(resolvedBranchCond: string): string { if (!this.currentVersionObj) { console.warn('currentVersionObj not found in ifversion context.') return resolvedBranchCond @@ -190,13 +222,13 @@ export default class extends Tag { // Split the condition into tokens for processing const tokens = resolvedBranchCond.split(/\s+/) - const processedTokens = tokens.map((token) => { + const processedTokens = tokens.map((token: string) => { // Check if the token is a version short name (fpt, ghec, ghes, ghae) const versionShortNames = ['fpt', 'ghec', 'ghes', 'ghae'] if (versionShortNames.includes(token)) { // Transform version names to boolean values for Markdown API // This fixes the original issue where version names were undefined in API context - return token === this.currentVersionObj.shortName ? 'true' : 'false' + return token === this.currentVersionObj!.shortName ? 'true' : 'false' } // Return the token unchanged if it's not a version name return token diff --git a/src/content-render/tests/copilot-code-blocks.js b/src/content-render/tests/copilot-code-blocks.ts similarity index 100% rename from src/content-render/tests/copilot-code-blocks.js rename to src/content-render/tests/copilot-code-blocks.ts diff --git a/src/content-render/tests/table-accessibility-labels.js b/src/content-render/tests/table-accessibility-labels.ts similarity index 99% rename from src/content-render/tests/table-accessibility-labels.js rename to src/content-render/tests/table-accessibility-labels.ts index c65cdfb1a7ae..84dd119f4c8f 100644 --- a/src/content-render/tests/table-accessibility-labels.js +++ b/src/content-render/tests/table-accessibility-labels.ts @@ -6,7 +6,7 @@ import { EOL } from 'os' // Use platform-specific line endings for realistic tests when templates have // been loaded from disk -const nl = (str) => str.replace(/\n/g, EOL) +const nl = (str: string) => str.replace(/\n/g, EOL) describe('table accessibility labels', () => { test('adds aria-labelledby to tables following headings', async () => { diff --git a/src/graphql/scripts/utils/schema-helpers.js b/src/graphql/scripts/utils/schema-helpers.ts similarity index 67% rename from src/graphql/scripts/utils/schema-helpers.js rename to src/graphql/scripts/utils/schema-helpers.ts index cd4bd1e026bd..61cee65e4d92 100644 --- a/src/graphql/scripts/utils/schema-helpers.js +++ b/src/graphql/scripts/utils/schema-helpers.ts @@ -7,42 +7,98 @@ import { isUnionType, isEnumType, isInputObjectType, + GraphQLSchema, } from 'graphql' import path from 'path' -const graphqlTypes = JSON.parse( - await fs.readFile(path.join(process.cwd(), './src/graphql/lib/types.json')), +interface GraphQLTypeInfo { + type: string + kind: string +} + +interface TypeInfo { + name: string + id: string + kind: string + href: string +} + +interface ArgumentInfo { + name: string + defaultValue?: any // GraphQL default values can be of various types + description: string + type: TypeInfo +} + +interface FieldNode { + name: { value: string } + type: any // GraphQL AST type nodes have complex nested structure +} + +interface ArgumentNode { + name: { value: string } + defaultValue?: { value: any } // GraphQL default values can be of various types + description: { value: string } + type: any // GraphQL AST type nodes have complex nested structure +} + +interface DirectiveNode { + name: { value: string } + arguments: Array<{ value: { value: string; kind?: string } }> +} + +interface SchemaMember { + name: string + isDeprecated?: boolean +} + +interface PreviewInfo { + toggled_by: string[] +} + +const graphqlTypes: GraphQLTypeInfo[] = JSON.parse( + await fs.readFile(path.join(process.cwd(), './src/graphql/lib/types.json'), 'utf-8'), ) const singleQuotesInsteadOfBackticks = / '(\S+?)' / -function addPeriod(string) { +function addPeriod(string: string): string { return string.endsWith('.') ? string : string + '.' } -async function getArguments(args, schema) { +async function getArguments( + args: ArgumentNode[], + schema: GraphQLSchema, +): Promise { if (!args.length) return - const newArgs = [] + const newArgs: ArgumentInfo[] = [] for (const arg of args) { - const newArg = {} - const type = {} + const newArg: Partial = {} + const type: Partial = {} newArg.name = arg.name.value newArg.defaultValue = arg.defaultValue ? arg.defaultValue.value : undefined newArg.description = await getDescription(arg.description.value) - type.name = getType(arg) - type.id = getId(type.name) - type.kind = getTypeKind(type.name, schema) - type.href = getFullLink(type.kind, type.id) - newArg.type = type - newArgs.push(newArg) + const typeName = getType(arg) + if (!typeName) continue // Skip if type cannot be determined + type.name = typeName + type.id = getId(typeName) + const typeKind = getTypeKind(typeName, schema) + if (!typeKind) continue // Skip if type kind cannot be determined + type.kind = typeKind + type.href = getFullLink(typeKind, type.id) + newArg.type = type as TypeInfo + newArgs.push(newArg as ArgumentInfo) } return newArgs } -async function getDeprecationReason(directives, schemaMember) { +async function getDeprecationReason( + directives: DirectiveNode[], + schemaMember: SchemaMember, +): Promise { if (!schemaMember.isDeprecated) return // it's possible for a schema member to be deprecated and under preview @@ -55,32 +111,36 @@ async function getDeprecationReason(directives, schemaMember) { return renderContent(deprecationDirective[0].arguments[0].value.value) } -function getDeprecationStatus(directives) { +function getDeprecationStatus(directives: DirectiveNode[]): boolean | undefined { if (!directives.length) return return directives[0].name.value === 'deprecated' } -async function getDescription(rawDescription) { +async function getDescription(rawDescription: string): Promise { rawDescription = rawDescription.replace(singleQuotesInsteadOfBackticks, '`$1`') return renderContent(addPeriod(rawDescription)) } -function getFullLink(baseType, id) { +function getFullLink(baseType: string, id: string): string { return `/graphql/reference/${baseType}#${id}` } -function getId(path) { +function getId(path: string): string { return removeMarkers(path).toLowerCase() } // e.g., given `ObjectTypeDefinition`, get `objects` -function getKind(type) { - return graphqlTypes.find((graphqlType) => graphqlType.type === type).kind +function getKind(type: string): string { + return graphqlTypes.find((graphqlType) => graphqlType.type === type)!.kind } -async function getPreview(directives, schemaMember, previewsPerVersion) { +async function getPreview( + directives: DirectiveNode[], + schemaMember: SchemaMember, + previewsPerVersion: PreviewInfo[], +): Promise { if (!directives.length) return // it's possible for a schema member to be deprecated and under preview @@ -110,7 +170,7 @@ async function getPreview(directives, schemaMember, previewsPerVersion) { // 2. nullable lists: `[foo]`, `[foo!]` // 3. non-null lists: `[foo]!`, `[foo!]!` // see https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/lists.md#lists-nullable-lists-and-lists-of-nulls -function getType(field) { +function getType(field: FieldNode): string | undefined { // 1. single items if (field.type.kind !== 'ListType') { // nullable item, e.g. `license` query has `License` type @@ -153,9 +213,10 @@ function getType(field) { } console.error(`cannot get type of ${field.name.value}`) + return undefined } -function getTypeKind(type, schema) { +function getTypeKind(type: string, schema: GraphQLSchema): string | undefined { type = removeMarkers(type) const typeFromSchema = schema.getType(type) @@ -180,9 +241,10 @@ function getTypeKind(type, schema) { } console.error(`cannot find type kind of ${type}`) + return undefined } -function removeMarkers(str) { +function removeMarkers(str: string): string { return str.replace('[', '').replace(']', '').replace(/!/g, '') } diff --git a/src/rest/tests/openapi-schema.js b/src/rest/tests/openapi-schema.ts similarity index 85% rename from src/rest/tests/openapi-schema.js rename to src/rest/tests/openapi-schema.ts index c0bee320c3b3..810489d5bed0 100644 --- a/src/rest/tests/openapi-schema.js +++ b/src/rest/tests/openapi-schema.ts @@ -15,7 +15,8 @@ import { nonAutomatedRestPaths } from '../lib/config' const schemasPath = 'src/rest/data' -async function getFlatListOfOperations(version) { +// Operations have dynamic structure from OpenAPI schema - using any to avoid complex type definitions +async function getFlatListOfOperations(version: string): Promise { const flatList = [] if (isApiVersioned(version)) { @@ -33,7 +34,8 @@ async function getFlatListOfOperations(version) { return flatList } -function createCategoryList(operations) { +// OpenAPI operations object has dynamic structure based on categories and subcategories +function createCategoryList(operations: any): any[] { const catSubCatList = [] for (const category of Object.keys(operations)) { const subcategories = Object.keys(operations[category]) @@ -47,19 +49,20 @@ function createCategoryList(operations) { describe('markdown for each rest version', () => { // Unique set of all categories across all versions of the OpenAPI schema - const allCategories = new Set() - // Entire schema including categories and subcategories - const openApiSchema = {} + const allCategories = new Set() + // Entire schema including categories and subcategories - using any due to dynamic OpenAPI structure + const openApiSchema: Record = {} // All applicable version of categories based on frontmatter in the categories index.md file - const categoryApplicableVersions = {} + const categoryApplicableVersions: Record = {} - function getApplicableVersionFromFile(file) { + function getApplicableVersionFromFile(file: string) { const currentFile = fs.readFileSync(file, 'utf8') - const { data } = frontmatter(currentFile) + // Frontmatter data structure is dynamic based on file content + const { data } = frontmatter(currentFile) as { data: any } return getApplicableVersions(data.versions, file) } - function getCategorySubcategory(file) { + function getCategorySubcategory(file: string) { const fileSplit = file.split('/') const cat = fileSplit[fileSplit.length - 2] const subCat = fileSplit[fileSplit.length - 1].replace('.md', '') @@ -133,9 +136,14 @@ describe('markdown for each rest version', () => { describe('rest file structure', () => { test('children of content/rest/index.md are in alphabetical order', async () => { const indexContent = fs.readFileSync('content/rest/index.md', 'utf8') - const { data } = readFrontmatter(indexContent) - const nonAutomatedChildren = nonAutomatedRestPaths.map((child) => child.replace('/rest', '')) - const sortableChildren = data.children.filter((child) => !nonAutomatedChildren.includes(child)) + // Frontmatter data structure is dynamic based on file content + const { data } = readFrontmatter(indexContent) as { data: any } + const nonAutomatedChildren = nonAutomatedRestPaths.map((child: string) => + child.replace('/rest', ''), + ) + const sortableChildren = data.children.filter( + (child: string) => !nonAutomatedChildren.includes(child), + ) expect(sortableChildren).toStrictEqual([...sortableChildren].sort()) }) }) @@ -182,7 +190,7 @@ describe('OpenAPI schema validation', () => { }) }) -async function findOperation(version, method, path) { +async function findOperation(version: string, method: string, path: string) { const allOperations = await getFlatListOfOperations(version) return allOperations.find((operation) => { return operation.requestPath === path && operation.verb.toLowerCase() === method.toLowerCase() @@ -203,7 +211,8 @@ describe('code examples are defined', () => { expect(operation.serverUrl).toBe(domain) expect(isPlainObject(operation)).toBe(true) expect(operation.codeExamples).toBeDefined() - operation.codeExamples.forEach((example) => { + // Code examples have dynamic structure from OpenAPI schema + operation.codeExamples.forEach((example: any) => { expect(isPlainObject(example.request)).toBe(true) expect(isPlainObject(example.response)).toBe(true) }) diff --git a/src/types/markdownlint-rules.d.ts b/src/types/markdownlint-rules.d.ts deleted file mode 100644 index 7e7204208e76..000000000000 --- a/src/types/markdownlint-rules.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Simple type declaration for markdownlint external library -// Using any types to avoid complex typing for external dependencies - -declare module '../../../../node_modules/markdownlint/lib/rules' { - const rules: any[] - export = rules -} From a415892096b39184ee4236539ae6166de07877c6 Mon Sep 17 00:00:00 2001 From: Kevin Heis Date: Wed, 15 Oct 2025 09:43:53 -0700 Subject: [PATCH 3/4] Migrate 6 JavaScript files to TypeScript (#57969) --- ...xclusions.js => lint-report-exclusions.ts} | 8 +- ...-aria-labels.js => octicon-aria-labels.ts} | 73 +++++++++---------- ... => outdated-release-phase-terminology.ts} | 0 ...-numbers.js => link-error-line-numbers.ts} | 55 ++++++++------ ...ini-toc-items.js => get-mini-toc-items.ts} | 57 +++++++++++---- src/frame/middleware/render-page.ts | 6 +- src/frame/tests/mini-toc-items.ts | 9 ++- src/graphql/pages/breaking-changes.tsx | 2 +- src/graphql/pages/changelog.tsx | 2 +- src/graphql/pages/schema-previews.tsx | 2 +- ...-api-schema.js => test-open-api-schema.ts} | 41 ++++++----- src/types.ts | 3 +- 12 files changed, 152 insertions(+), 106 deletions(-) rename src/content-linter/tests/unit/{lint-report-exclusions.js => lint-report-exclusions.ts} (97%) rename src/content-linter/tests/unit/{octicon-aria-labels.js => octicon-aria-labels.ts} (65%) rename src/content-linter/tests/unit/{outdated-release-phase-terminology.js => outdated-release-phase-terminology.ts} (100%) rename src/content-render/tests/{link-error-line-numbers.js => link-error-line-numbers.ts} (65%) rename src/frame/lib/{get-mini-toc-items.js => get-mini-toc-items.ts} (77%) rename src/rest/scripts/{test-open-api-schema.js => test-open-api-schema.ts} (79%) diff --git a/src/content-linter/tests/unit/lint-report-exclusions.js b/src/content-linter/tests/unit/lint-report-exclusions.ts similarity index 97% rename from src/content-linter/tests/unit/lint-report-exclusions.js rename to src/content-linter/tests/unit/lint-report-exclusions.ts index 3f614b97ef69..a1b5f084f6dd 100644 --- a/src/content-linter/tests/unit/lint-report-exclusions.js +++ b/src/content-linter/tests/unit/lint-report-exclusions.ts @@ -2,9 +2,15 @@ import { describe, expect, test } from 'vitest' import { shouldIncludeResult } from '../../lib/helpers/should-include-result' import { reportingConfig } from '../../style/github-docs' +interface LintFlaw { + severity: string + ruleNames: string[] + errorDetail?: string +} + describe('lint report exclusions', () => { // Helper function to simulate the reporting logic from lint-report.ts - function shouldIncludeInReport(flaw, filePath) { + function shouldIncludeInReport(flaw: LintFlaw, filePath: string): boolean { if (!flaw.ruleNames || !Array.isArray(flaw.ruleNames)) { return false } diff --git a/src/content-linter/tests/unit/octicon-aria-labels.js b/src/content-linter/tests/unit/octicon-aria-labels.ts similarity index 65% rename from src/content-linter/tests/unit/octicon-aria-labels.js rename to src/content-linter/tests/unit/octicon-aria-labels.ts index 778964313692..aa4f03239a0a 100644 --- a/src/content-linter/tests/unit/octicon-aria-labels.js +++ b/src/content-linter/tests/unit/octicon-aria-labels.ts @@ -1,18 +1,34 @@ import { describe, expect, test } from 'vitest' import { octiconAriaLabels } from '../../lib/linting-rules/octicon-aria-labels' +interface ErrorInfo { + lineNumber: number + detail?: string + context?: string + range?: [number, number] + fixInfo?: any // Matches RuleErrorCallback signature - fixInfo structure varies by rule +} + describe('octicon-aria-labels', () => { const rule = octiconAriaLabels - test('detects octicon without aria-label', () => { - const errors = [] - const onError = (errorInfo) => { + // Helper to create onError callback that captures errors + function createErrorCollector() { + const errors: ErrorInfo[] = [] + // Using any because the actual rule implementation calls onError with an object, + // not individual parameters as defined in RuleErrorCallback + const onError = (errorInfo: any) => { errors.push(errorInfo) } + return { errors, onError } + } + + test('detects octicon without aria-label', () => { + const { errors, onError } = createErrorCollector() const content = ['This is a test with an octicon:', '{% octicon "alert" %}', 'Some more text.'] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(1) expect(errors[0].lineNumber).toBe(2) @@ -21,10 +37,7 @@ describe('octicon-aria-labels', () => { }) test('ignores octicons with aria-label', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with a proper octicon:', @@ -32,16 +45,13 @@ describe('octicon-aria-labels', () => { 'Some more text.', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(0) }) test('detects multiple octicons without aria-label', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with multiple octicons:', @@ -51,7 +61,7 @@ describe('octicon-aria-labels', () => { 'More text.', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(2) expect(errors[0].lineNumber).toBe(2) @@ -61,10 +71,7 @@ describe('octicon-aria-labels', () => { }) test('ignores non-octicon liquid tags', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with non-octicon tags:', @@ -74,16 +81,13 @@ describe('octicon-aria-labels', () => { '{% endif %}', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(0) }) test('suggests correct fix for octicon with other attributes', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with an octicon with other attributes:', @@ -91,7 +95,7 @@ describe('octicon-aria-labels', () => { 'Some more text.', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(1) expect(errors[0].lineNumber).toBe(2) @@ -101,10 +105,7 @@ describe('octicon-aria-labels', () => { }) test('handles octicons with unusual spacing', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with unusual spacing:', @@ -112,7 +113,7 @@ describe('octicon-aria-labels', () => { 'Some more text.', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(1) expect(errors[0].lineNumber).toBe(2) @@ -120,10 +121,7 @@ describe('octicon-aria-labels', () => { }) test('handles octicons split across multiple lines', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with a multi-line octicon:', @@ -133,17 +131,14 @@ describe('octicon-aria-labels', () => { 'Some more text.', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(1) expect(errors[0].detail).toContain('aria-label=chevron-down') }) test('falls back to "icon" when octicon name cannot be determined', () => { - const errors = [] - const onError = (errorInfo) => { - errors.push(errorInfo) - } + const { errors, onError } = createErrorCollector() const content = [ 'This is a test with a malformed octicon:', @@ -151,7 +146,7 @@ describe('octicon-aria-labels', () => { 'Some more text.', ] - rule.function({ lines: content }, onError) + rule.function({ name: 'test.md', lines: content, frontMatterLines: [] }, onError) expect(errors.length).toBe(1) expect(errors[0].detail).toContain('aria-label=icon') diff --git a/src/content-linter/tests/unit/outdated-release-phase-terminology.js b/src/content-linter/tests/unit/outdated-release-phase-terminology.ts similarity index 100% rename from src/content-linter/tests/unit/outdated-release-phase-terminology.js rename to src/content-linter/tests/unit/outdated-release-phase-terminology.ts diff --git a/src/content-render/tests/link-error-line-numbers.js b/src/content-render/tests/link-error-line-numbers.ts similarity index 65% rename from src/content-render/tests/link-error-line-numbers.js rename to src/content-render/tests/link-error-line-numbers.ts index 8c5e78cdcc7b..5ee9a839b842 100644 --- a/src/content-render/tests/link-error-line-numbers.js +++ b/src/content-render/tests/link-error-line-numbers.ts @@ -1,12 +1,13 @@ import { describe, expect, test, beforeEach, afterEach } from 'vitest' import { renderContent } from '@/content-render/index' import { TitleFromAutotitleError } from '@/content-render/unified/rewrite-local-links' +import type { Context } from '@/types' describe('link error line numbers', () => { - let fs - let originalReadFileSync - let originalExistsSync - let mockContext + let fs: any // Dynamic import of fs module for mocking in tests + let originalReadFileSync: any // Storing original fs.readFileSync for restoration after test + let originalExistsSync: any // Storing original fs.existsSync for restoration after test + let mockContext: Context beforeEach(async () => { // Set up file system mocking @@ -20,11 +21,11 @@ describe('link error line numbers', () => { mockContext = { currentLanguage: 'en', currentVersion: 'free-pro-team@latest', - pages: new Map(), - redirects: new Map(), + pages: {} as any, + redirects: {} as any, page: { fullPath: '/fake/test-file.md', - }, + } as any, } }) @@ -60,14 +61,16 @@ More content here.` // The broken link is on line 10 in the original file // (3 lines of frontmatter + 1 blank line + 1 title + 1 blank + 1 content + 1 blank + 1 link line) // The error message should reference the correct line number - expect(error.message).toContain('/nonexistent/page') - expect(error.message).toContain('could not be resolved') - expect(error.message).toContain('(Line: 10)') + expect((error as TitleFromAutotitleError).message).toContain('/nonexistent/page') + expect((error as TitleFromAutotitleError).message).toContain('could not be resolved') + expect((error as TitleFromAutotitleError).message).toContain('(Line: 10)') } }) test('reports correct line numbers with different frontmatter sizes', async () => { - mockContext.page.fullPath = '/fake/test-file-2.md' + mockContext.page = { + fullPath: '/fake/test-file-2.md', + } as any // Test with more extensive frontmatter const template = `--- @@ -96,13 +99,15 @@ Content with a [AUTOTITLE](/another/nonexistent/page) link.` expect.fail('Expected TitleFromAutotitleError to be thrown') } catch (error) { expect(error).toBeInstanceOf(TitleFromAutotitleError) - expect(error.message).toContain('/another/nonexistent/page') - expect(error.message).toContain('could not be resolved') + expect((error as TitleFromAutotitleError).message).toContain('/another/nonexistent/page') + expect((error as TitleFromAutotitleError).message).toContain('could not be resolved') } }) test('handles files without frontmatter correctly', async () => { - mockContext.page.fullPath = '/fake/no-frontmatter.md' + mockContext.page = { + fullPath: '/fake/no-frontmatter.md', + } as any // Test content without frontmatter const template = `# Simple Title @@ -118,13 +123,15 @@ Here is a broken link: [AUTOTITLE](/missing/page).` expect.fail('Expected TitleFromAutotitleError to be thrown') } catch (error) { expect(error).toBeInstanceOf(TitleFromAutotitleError) - expect(error.message).toContain('/missing/page') - expect(error.message).toContain('could not be resolved') + expect((error as TitleFromAutotitleError).message).toContain('/missing/page') + expect((error as TitleFromAutotitleError).message).toContain('could not be resolved') } }) test('error message format is improved', async () => { - mockContext.page.fullPath = '/fake/message-test.md' + mockContext.page = { + fullPath: '/fake/message-test.md', + } as any const template = `--- title: Message Test @@ -142,13 +149,17 @@ title: Message Test expect(error).toBeInstanceOf(TitleFromAutotitleError) // Check that the new error message format is used - expect(error.message).toContain('could not be resolved in one or more versions') - expect(error.message).toContain('Make sure that this link can be reached from all versions') - expect(error.message).toContain('/test/broken/link') + expect((error as TitleFromAutotitleError).message).toContain( + 'could not be resolved in one or more versions', + ) + expect((error as TitleFromAutotitleError).message).toContain( + 'Make sure that this link can be reached from all versions', + ) + expect((error as TitleFromAutotitleError).message).toContain('/test/broken/link') // Check that the old error message format is NOT used - expect(error.message).not.toContain('Unable to find Page by') - expect(error.message).not.toContain('To fix it, look at') + expect((error as TitleFromAutotitleError).message).not.toContain('Unable to find Page by') + expect((error as TitleFromAutotitleError).message).not.toContain('To fix it, look at') } }) }) diff --git a/src/frame/lib/get-mini-toc-items.js b/src/frame/lib/get-mini-toc-items.ts similarity index 77% rename from src/frame/lib/get-mini-toc-items.js rename to src/frame/lib/get-mini-toc-items.ts index a247a22bef05..e2d0c8cf8fd9 100644 --- a/src/frame/lib/get-mini-toc-items.js +++ b/src/frame/lib/get-mini-toc-items.ts @@ -2,9 +2,33 @@ import cheerio from 'cheerio' import { range } from 'lodash-es' import { renderContent } from '@/content-render/index' +import type { Context } from '@/types' + +interface MiniTocContents { + href: string + title: string +} + +export interface MiniTocItem { + contents: MiniTocContents + items?: MiniTocItem[] + platform?: string +} + +interface FlatTocItem { + contents: MiniTocContents + headingLevel: number + platform: string + indentationLevel: number + items?: FlatTocItem[] +} // Keep maxHeadingLevel=2 for accessibility reasons, see docs-engineering#2701 for more info -export default function getMiniTocItems(html, maxHeadingLevel = 2, headingScope = '') { +export default function getMiniTocItems( + html: string, + maxHeadingLevel = 2, + headingScope = '', +): MiniTocItem[] { const $ = cheerio.load(html, { xmlMode: true }) // eg `h2, h3` or `h2, h3, h4` depending on maxHeadingLevel @@ -20,7 +44,7 @@ export default function getMiniTocItems(html, maxHeadingLevel = 2, headingScope // - `platform` to show or hide platform-specific headings via client JS // H1 = highest importance, H6 = lowest importance - let mostImportantHeadingLevel + let mostImportantHeadingLevel: number | undefined const flatToc = headings .get() .filter((item) => { @@ -48,13 +72,14 @@ export default function getMiniTocItems(html, maxHeadingLevel = 2, headingScope // remove any tags but leave content $('strong', item).map((i, el) => $(el).replaceWith($(el).contents())) - const contents = { href, title: $(item).text().trim() } - const headingLevel = parseInt($(item)[0].name.match(/\d+/)[0], 10) || 0 // the `2` from `h2` + const contents: MiniTocContents = { href, title: $(item).text().trim() } + const element = $(item)[0] as cheerio.TagElement + const headingLevel = parseInt(element.name.match(/\d+/)![0], 10) || 0 // the `2` from `h2` const platform = $(item).parent('.ghd-tool').attr('class') || '' // track the most important heading level while we're looping through the items - if (headingLevel < mostImportantHeadingLevel || mostImportantHeadingLevel === undefined) { + if (headingLevel < mostImportantHeadingLevel! || mostImportantHeadingLevel === undefined) { mostImportantHeadingLevel = headingLevel } @@ -65,8 +90,8 @@ export default function getMiniTocItems(html, maxHeadingLevel = 2, headingScope // set the indentation level for each item based on the most important // heading level in the current article return { - ...item, - indentationLevel: item.headingLevel - mostImportantHeadingLevel, + ...item!, + indentationLevel: item!.headingLevel - mostImportantHeadingLevel!, } }) @@ -77,18 +102,18 @@ export default function getMiniTocItems(html, maxHeadingLevel = 2, headingScope } // Recursively build a tree from the list of allItems -function buildNestedToc(allItems, startIndex = 0) { +function buildNestedToc(allItems: FlatTocItem[], startIndex = 0): FlatTocItem[] { const startItem = allItems[startIndex] if (!startItem) { return [] } let curLevelIndentation = startItem.indentationLevel - const currentLevel = [] + const currentLevel: FlatTocItem[] = [] for (let cursor = startIndex; cursor < allItems.length; cursor++) { const cursorItem = allItems[cursor] const nextItem = allItems[cursor + 1] - const nextItemIsNested = nextItem && nextItem.indentationLevel > cursorItem.indentationLevel + const nextItemIsNested = nextItem && nextItem.indentationLevel! > cursorItem.indentationLevel! // if it's the current indentation level, push it on and keep going if (curLevelIndentation === cursorItem.indentationLevel) { @@ -125,10 +150,10 @@ function buildNestedToc(allItems, startIndex = 0) { // Strip the bits and pieces from each object in the array that are // not needed in the React component rendering. -function minimalMiniToc(toc) { +function minimalMiniToc(toc: FlatTocItem[]): MiniTocItem[] { return toc.map(({ platform, contents, items }) => { - const minimal = { contents } - const subItems = minimalMiniToc(items) + const minimal: MiniTocItem = { contents } + const subItems = minimalMiniToc(items || []) if (subItems.length) minimal.items = subItems if (platform) minimal.platform = platform return minimal @@ -136,11 +161,11 @@ function minimalMiniToc(toc) { } export async function getAutomatedPageMiniTocItems( - items, - context, + items: string[], + context: Context, depth = 2, markdownHeading = '', -) { +): Promise { const titles = markdownHeading + items diff --git a/src/frame/middleware/render-page.ts b/src/frame/middleware/render-page.ts index 95866cc6ec90..f647718ef790 100644 --- a/src/frame/middleware/render-page.ts +++ b/src/frame/middleware/render-page.ts @@ -28,7 +28,7 @@ async function buildRenderedPage(req: ExtendedRequest): Promise { return (await pageRenderTimed(context)) as string } -async function buildMiniTocItems(req: ExtendedRequest): Promise { +function buildMiniTocItems(req: ExtendedRequest) { const { context } = req if (!context) throw new Error('request not contextualized') const { page } = context @@ -38,7 +38,7 @@ async function buildMiniTocItems(req: ExtendedRequest): Promise { ].join('\n') const tocItems = getMiniTocItems(html, 3) expect(tocItems.length).toBe(2) - expect(tocItems[0].items.length).toBe(3) + expect(tocItems[0].items?.length).toBe(3) }) /** @@ -56,10 +56,11 @@ describe('mini toc items', () => { ].join('\n') const tocItems = getMiniTocItems(html, 3) expect(tocItems.length).toBe(4) - expect(tocItems[3].items.length).toBe(1) + expect(tocItems[3].items?.length).toBe(1) }) - // Mock scenario from: /en/organizations/managing-membership-in-your-organization/inviting-users-to-join-your-organization + // Mock scenario from: + // /en/organizations/managing-membership-in-your-organization/inviting-users-to-join-your-organization test('creates empty toc', async () => { const html = h1('test') const tocItems = getMiniTocItems(html, 3) @@ -86,6 +87,6 @@ describe('mini toc items', () => { ].join('\n') const tocItems = getMiniTocItems(html, 5) expect(tocItems.length).toBe(3) - expect(tocItems[1].items[0].items[0].items.length).toBe(1) + expect(tocItems[1].items?.[0].items?.[0].items?.length).toBe(1) }) }) diff --git a/src/graphql/pages/breaking-changes.tsx b/src/graphql/pages/breaking-changes.tsx index c638c493de0f..7e8734616df2 100644 --- a/src/graphql/pages/breaking-changes.tsx +++ b/src/graphql/pages/breaking-changes.tsx @@ -38,7 +38,7 @@ export default function GraphqlBreakingChanges({ export const getServerSideProps: GetServerSideProps = async (context) => { const { getGraphqlBreakingChanges } = await import('@/graphql/lib/index') - const { getAutomatedPageMiniTocItems } = await import('@/frame/lib/get-mini-toc-items.js') + const { getAutomatedPageMiniTocItems } = await import('@/frame/lib/get-mini-toc-items') const req = context.req as any const res = context.res as any diff --git a/src/graphql/pages/changelog.tsx b/src/graphql/pages/changelog.tsx index 9142a753ae57..5966d7f872e2 100644 --- a/src/graphql/pages/changelog.tsx +++ b/src/graphql/pages/changelog.tsx @@ -29,7 +29,7 @@ export default function GraphqlChangelog({ mainContext, schema, automatedPageCon export const getServerSideProps: GetServerSideProps = async (context) => { const { getGraphqlChangelog } = await import('@/graphql/lib/index') - const { getAutomatedPageMiniTocItems } = await import('@/frame/lib/get-mini-toc-items.js') + const { getAutomatedPageMiniTocItems } = await import('@/frame/lib/get-mini-toc-items') const req = context.req as any const res = context.res as any diff --git a/src/graphql/pages/schema-previews.tsx b/src/graphql/pages/schema-previews.tsx index 97848971c893..e9799f58908d 100644 --- a/src/graphql/pages/schema-previews.tsx +++ b/src/graphql/pages/schema-previews.tsx @@ -34,7 +34,7 @@ export default function GraphqlPreviews({ mainContext, schema, automatedPageCont export const getServerSideProps: GetServerSideProps = async (context) => { const { getPreviews } = await import('@/graphql/lib/index') - const { getAutomatedPageMiniTocItems } = await import('@/frame/lib/get-mini-toc-items.js') + const { getAutomatedPageMiniTocItems } = await import('@/frame/lib/get-mini-toc-items') const req = context.req as any const res = context.res as any diff --git a/src/rest/scripts/test-open-api-schema.js b/src/rest/scripts/test-open-api-schema.ts similarity index 79% rename from src/rest/scripts/test-open-api-schema.js rename to src/rest/scripts/test-open-api-schema.ts index 5a3e05d13279..77e90dd85264 100755 --- a/src/rest/scripts/test-open-api-schema.js +++ b/src/rest/scripts/test-open-api-schema.ts @@ -15,7 +15,13 @@ import { nonAutomatedRestPaths } from '../lib/config' import { deprecated } from '@/versions/lib/enterprise-server-releases' import walkFiles from '@/workflows/walk-files' -export async function getDiffOpenAPIContentRest() { +type CheckObject = Record> + +type DifferenceResult = Record + +type ErrorMessages = Record> + +export async function getDiffOpenAPIContentRest(): Promise { const contentFiles = getAutomatedMarkdownFiles('content/rest') // Creating the categories/subcategories based on the current content directory const checkContentDir = await createCheckContentDirectory(contentFiles) @@ -25,15 +31,13 @@ export async function getDiffOpenAPIContentRest() { // Get Differences between categories/subcategories from dereferenced schemas and the content/rest directory frontmatter versions const differences = getDifferences(openAPISchemaCheck, checkContentDir) - const errorMessages = {} + const errorMessages: ErrorMessages = {} if (Object.keys(differences).length > 0) { for (const schemaName in differences) { errorMessages[schemaName] = {} differences[schemaName].forEach((category) => { - if (!errorMessages[schemaName]) errorMessages[schemaName] = category - errorMessages[schemaName][category] = { contentDir: checkContentDir[schemaName][category], openAPI: openAPISchemaCheck[schemaName][category], @@ -45,7 +49,7 @@ export async function getDiffOpenAPIContentRest() { return errorMessages } -async function createOpenAPISchemasCheck() { +async function createOpenAPISchemasCheck(): Promise { const openAPICheck = createCheckObj() const restDirectory = fs .readdirSync(REST_DATA_DIR) @@ -55,12 +59,12 @@ async function createOpenAPISchemasCheck() { restDirectory.forEach((dir) => { const filename = path.join(REST_DATA_DIR, dir, REST_SCHEMA_FILENAME) - const fileSchema = JSON.parse(fs.readFileSync(filename)) + const fileSchema = JSON.parse(fs.readFileSync(filename, 'utf8')) const categories = Object.keys(fileSchema).sort() const version = getDocsVersion(dir) categories.forEach((category) => { - const subcategories = Object.keys(fileSchema[category]) + const subcategories = Object.keys(fileSchema[category]) as string[] if (isApiVersioned(version)) { getOnlyApiVersions(version).forEach( (apiVersion) => (openAPICheck[apiVersion][category] = subcategories.sort()), @@ -74,12 +78,12 @@ async function createOpenAPISchemasCheck() { return openAPICheck } -async function createCheckContentDirectory(contentFiles) { +async function createCheckContentDirectory(contentFiles: string[]): Promise { const checkContent = createCheckObj() for (const filename of contentFiles) { const { data } = frontmatter(await fs.promises.readFile(filename, 'utf8')) - const applicableVersions = getApplicableVersions(data.versions, filename) + const applicableVersions = getApplicableVersions(data?.versions, filename) const splitPath = filename.split('/') const subCategory = splitPath[splitPath.length - 1].replace('.md', '') const category = @@ -104,18 +108,18 @@ async function createCheckContentDirectory(contentFiles) { return checkContent } -function isApiVersioned(version) { +function isApiVersioned(version: string): boolean { return allVersions[version] && allVersions[version].apiVersions.length > 0 } -function getOnlyApiVersions(version) { +function getOnlyApiVersions(version: string): string[] { return allVersions[version].apiVersions.map( (apiVersion) => `${allVersions[version].version}.${apiVersion}`, ) } -function createCheckObj() { - const versions = {} +function createCheckObj(): CheckObject { + const versions: CheckObject = {} Object.keys(allVersions).forEach((version) => { isApiVersioned(version) ? getOnlyApiVersions(version).forEach((apiVersion) => (versions[apiVersion] = {})) @@ -125,8 +129,11 @@ function createCheckObj() { return versions } -function getDifferences(openAPISchemaCheck, contentCheck) { - const differences = {} +function getDifferences( + openAPISchemaCheck: CheckObject, + contentCheck: CheckObject, +): DifferenceResult { + const differences: DifferenceResult = {} for (const version in openAPISchemaCheck) { const diffOpenApiContent = difference(openAPISchemaCheck[version], contentCheck[version]) if (Object.keys(diffOpenApiContent).length > 0) differences[version] = diffOpenApiContent @@ -135,7 +142,7 @@ function getDifferences(openAPISchemaCheck, contentCheck) { return differences } -function difference(obj1, obj2) { +function difference(obj1: Record, obj2: Record): string[] { const diff = Object.keys(obj1).reduce((result, key) => { if (!Object.prototype.hasOwnProperty.call(obj2, key)) { result.push(key) @@ -149,7 +156,7 @@ function difference(obj1, obj2) { return diff } -export function getAutomatedMarkdownFiles(rootDir) { +export function getAutomatedMarkdownFiles(rootDir: string): string[] { return walkFiles(rootDir, '.md') .filter((file) => !file.includes('index.md')) .filter((file) => !nonAutomatedRestPaths.some((path) => file.includes(path))) diff --git a/src/types.ts b/src/types.ts index 53d39f91b62a..a21087550a34 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,6 +3,7 @@ import type { Failbot } from '@github/failbot' import type enterpriseServerReleases from '@/versions/lib/enterprise-server-releases.d' import type { ValidOcticon } from '@/landings/types' +import type { MiniTocItem } from '@/frame/lib/get-mini-toc-items' // Shared type for resolved article information used across landing pages and carousels export interface ResolvedArticle { @@ -180,7 +181,7 @@ export type Context = { featuredLinks?: FeaturedLinksExpanded currentLearningTrack?: LearningTrack | null renderedPage?: string - miniTocItems?: string | undefined + miniTocItems?: MiniTocItem[] markdownRequested?: boolean } export type LearningTracks = { From 46543158abe69a5a95dc2025d4d8f77528f9a370 Mon Sep 17 00:00:00 2001 From: Sunbrye Ly <56200261+sunbrye@users.noreply.github.com> Date: Wed, 15 Oct 2025 10:02:10 -0700 Subject: [PATCH 4/4] Tented model 005 (#57974) --- .../reference/ai-models/model-comparison.md | 48 ++++++++++--------- .../reference/ai-models/model-hosting.md | 3 +- .../reference/ai-models/supported-models.md | 26 +++++----- .../copilot/available-models-per-plan.md | 1 + data/reusables/copilot/model-multipliers.md | 1 + data/variables/copilot.yml | 9 ++-- 6 files changed, 48 insertions(+), 40 deletions(-) diff --git a/content/copilot/reference/ai-models/model-comparison.md b/content/copilot/reference/ai-models/model-comparison.md index 3aead50a30fb..8d38b2a40017 100644 --- a/content/copilot/reference/ai-models/model-comparison.md +++ b/content/copilot/reference/ai-models/model-comparison.md @@ -27,24 +27,25 @@ contentType: reference Use this table to find a suitable model quickly, see more detail in the sections below. -| Model | Task area | Excels at (primary use case) | Additional capabilities | Further reading | -|--------------------------------------------------------|----------------------------------------------|-------------------------------------------------------------------------|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| {% data variables.copilot.copilot_gpt_41 %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode, vision | [{% data variables.copilot.copilot_gpt_41 %} model card](https://openai.com/index/gpt-4-1/) | -| {% data variables.copilot.copilot_gpt_5_codex %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode | [{% data variables.copilot.copilot_gpt_5_codex %} model card](https://cdn.openai.com/pdf/97cc5669-7a25-4e63-b15f-5fd5bdc4d149/gpt-5-codex-system-card.pdf) | -| {% data variables.copilot.copilot_gpt_5_mini %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode, reasoning, vision | [{% data variables.copilot.copilot_gpt_5_mini %} model card](https://cdn.openai.com/gpt-5-system-card.pdf) | -| {% data variables.copilot.copilot_gpt_5 %} | Deep reasoning and debugging | Multi-step problem solving and architecture-level code analysis | Reasoning | [{% data variables.copilot.copilot_gpt_5 %} model card](https://cdn.openai.com/gpt-5-system-card.pdf) | -| {% data variables.copilot.copilot_o3 %} | Deep reasoning and debugging | Multi-step problem solving and architecture-level code analysis | Reasoning | [{% data variables.copilot.copilot_o3 %} model card](https://openai.com/index/o3-o4-mini-system-card/) | -| {% data variables.copilot.copilot_o4_mini %} | Fast help with simple or repetitive tasks | Fast, reliable answers to lightweight coding questions | Lower latency | [{% data variables.copilot.copilot_o4_mini %} model card](https://openai.com/index/o3-o4-mini-system-card/) | -| {% data variables.copilot.copilot_claude_sonnet_45 %} | General-purpose coding and agent tasks | Complex problem-solving challenges, sophisticated reasoning | Agent mode | [{% data variables.copilot.copilot_claude_sonnet_45 %} model card](https://assets.anthropic.com/m/12f214efcc2f457a/original/Claude-Sonnet-4-5-System-Card.pdf) | -| {% data variables.copilot.copilot_claude_opus_41 %} | Deep reasoning and debugging | Complex problem-solving challenges, sophisticated reasoning | Reasoning, vision | [{% data variables.copilot.copilot_claude_opus_41 %} model card](https://assets.anthropic.com/m/4c024b86c698d3d4/original/Claude-4-1-System-Card.pdf) | -| {% data variables.copilot.copilot_claude_opus %} | Deep reasoning and debugging | Complex problem-solving challenges, sophisticated reasoning | Reasoning, vision | [{% data variables.copilot.copilot_claude_opus %} model card](https://www-cdn.anthropic.com/6be99a52cb68eb70eb9572b4cafad13df32ed995.pdf) | -| {% data variables.copilot.copilot_claude_sonnet_35 %} | Fast help with simple or repetitive tasks | Quick responses for code, syntax, and documentation | Agent mode, vision | [{% data variables.copilot.copilot_claude_sonnet_35 %} model card](https://www-cdn.anthropic.com/fed9cc193a14b84131812372d8d5857f8f304c52/Model_Card_Claude_3_Addendum.pdf) | -| {% data variables.copilot.copilot_claude_sonnet_37 %} | Deep reasoning and debugging | Structured reasoning across large, complex codebases | Agent mode, vision | [{% data variables.copilot.copilot_claude_sonnet_37 %} model card](https://assets.anthropic.com/m/785e231869ea8b3b/original/claude-3-7-sonnet-system-card.pdf) | -| {% data variables.copilot.copilot_claude_sonnet_40 %} | Deep reasoning and debugging | Performance and practicality, perfectly balanced for coding workflows | Agent mode, vision | [{% data variables.copilot.copilot_claude_sonnet_40 %} model card](https://www-cdn.anthropic.com/6be99a52cb68eb70eb9572b4cafad13df32ed995.pdf) | -| {% data variables.copilot.copilot_gemini_25_pro %} | Deep reasoning and debugging | Complex code generation, debugging, and research workflows | Reasoning, vision | [{% data variables.copilot.copilot_gemini_25_pro %} model card](https://storage.googleapis.com/model-cards/documents/gemini-2.5-pro.pdf) | -| {% data variables.copilot.copilot_gemini_flash %} | Working with visuals (diagrams, screenshots) | Real-time responses and visual reasoning for UI and diagram-based tasks | Vision | [{% data variables.copilot.copilot_gemini_flash %} model card](https://storage.googleapis.com/model-cards/documents/gemini-2-flash.pdf) | -| {% data variables.copilot.copilot_grok_code %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode | [{% data variables.copilot.copilot_grok_code %} model card](https://data.x.ai/2025-08-20-grok-4-model-card.pdf) | -| {% data variables.copilot.copilot_qwen_25 %} | General-purpose coding and writing | Code generation, reasoning, and code repair / debugging | Reasoning | [{% data variables.copilot.copilot_qwen_25 %} model card](https://arxiv.org/pdf/2409.12186) +| Model | Task area | Excels at (primary use case) | Additional capabilities | Further reading | +|-------------------------------------------------------|--------------------------------------------------|-------------------------------------------------------------------------|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| {% data variables.copilot.copilot_gpt_41 %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode, vision | [{% data variables.copilot.copilot_gpt_41 %} model card](https://openai.com/index/gpt-4-1/) | +| {% data variables.copilot.copilot_gpt_5_codex %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode | [{% data variables.copilot.copilot_gpt_5_codex %} model card](https://cdn.openai.com/pdf/97cc5669-7a25-4e63-b15f-5fd5bdc4d149/gpt-5-codex-system-card.pdf) | +| {% data variables.copilot.copilot_gpt_5_mini %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode, reasoning, vision | [{% data variables.copilot.copilot_gpt_5_mini %} model card](https://cdn.openai.com/gpt-5-system-card.pdf) | +| {% data variables.copilot.copilot_gpt_5 %} | Deep reasoning and debugging | Multi-step problem solving and architecture-level code analysis | Reasoning | [{% data variables.copilot.copilot_gpt_5 %} model card](https://cdn.openai.com/gpt-5-system-card.pdf) | +| {% data variables.copilot.copilot_o3 %} | Deep reasoning and debugging | Multi-step problem solving and architecture-level code analysis | Reasoning | [{% data variables.copilot.copilot_o3 %} model card](https://openai.com/index/o3-o4-mini-system-card/) | +| {% data variables.copilot.copilot_o4_mini %} | Fast help with simple or repetitive tasks | Fast, reliable answers to lightweight coding questions | Lower latency | [{% data variables.copilot.copilot_o4_mini %} model card](https://openai.com/index/o3-o4-mini-system-card/) | +| {% data variables.copilot.copilot_claude_haiku_45 %} | Fast help with simple or repetitive tasks | Fast, reliable answers to lightweight coding questions | Agent mode | Not available | +| {% data variables.copilot.copilot_claude_sonnet_45 %} | General-purpose coding and agent tasks | Complex problem-solving challenges, sophisticated reasoning | Agent mode | [{% data variables.copilot.copilot_claude_sonnet_45 %} model card](https://assets.anthropic.com/m/12f214efcc2f457a/original/Claude-Sonnet-4-5-System-Card.pdf) | +| {% data variables.copilot.copilot_claude_opus_41 %} | Deep reasoning and debugging | Complex problem-solving challenges, sophisticated reasoning | Reasoning, vision | [{% data variables.copilot.copilot_claude_opus_41 %} model card](https://assets.anthropic.com/m/4c024b86c698d3d4/original/Claude-4-1-System-Card.pdf) | +| {% data variables.copilot.copilot_claude_opus %} | Deep reasoning and debugging | Complex problem-solving challenges, sophisticated reasoning | Reasoning, vision | [{% data variables.copilot.copilot_claude_opus %} model card](https://www-cdn.anthropic.com/6be99a52cb68eb70eb9572b4cafad13df32ed995.pdf) | +| {% data variables.copilot.copilot_claude_sonnet_35 %} | Fast help with simple or repetitive tasks | Quick responses for code, syntax, and documentation | Agent mode, vision | [{% data variables.copilot.copilot_claude_sonnet_35 %} model card](https://www-cdn.anthropic.com/fed9cc193a14b84131812372d8d5857f8f304c52/Model_Card_Claude_3_Addendum.pdf) | +| {% data variables.copilot.copilot_claude_sonnet_37 %} | Deep reasoning and debugging | Structured reasoning across large, complex codebases | Agent mode, vision | [{% data variables.copilot.copilot_claude_sonnet_37 %} model card](https://assets.anthropic.com/m/785e231869ea8b3b/original/claude-3-7-sonnet-system-card.pdf) | +| {% data variables.copilot.copilot_claude_sonnet_40 %} | Deep reasoning and debugging | Performance and practicality, perfectly balanced for coding workflows | Agent mode, vision | [{% data variables.copilot.copilot_claude_sonnet_40 %} model card](https://www-cdn.anthropic.com/6be99a52cb68eb70eb9572b4cafad13df32ed995.pdf) | +| {% data variables.copilot.copilot_gemini_25_pro %} | Deep reasoning and debugging | Complex code generation, debugging, and research workflows | Reasoning, vision | [{% data variables.copilot.copilot_gemini_25_pro %} model card](https://storage.googleapis.com/model-cards/documents/gemini-2.5-pro.pdf) | +| {% data variables.copilot.copilot_gemini_flash %} | Working with visuals (diagrams, screenshots) | Real-time responses and visual reasoning for UI and diagram-based tasks | Vision | [{% data variables.copilot.copilot_gemini_flash %} model card](https://storage.googleapis.com/model-cards/documents/gemini-2-flash.pdf) | +| {% data variables.copilot.copilot_grok_code %} | General-purpose coding and writing | Fast, accurate code completions and explanations | Agent mode | [{% data variables.copilot.copilot_grok_code %} model card](https://data.x.ai/2025-08-20-grok-4-model-card.pdf) | +| {% data variables.copilot.copilot_qwen_25 %} | General-purpose coding and writing | Code generation, reasoning, and code repair / debugging | Reasoning | [{% data variables.copilot.copilot_qwen_25 %} model card](https://arxiv.org/pdf/2409.12186) | ## Task: General-purpose coding and writing @@ -78,11 +79,12 @@ These models are optimized for speed and responsiveness. They’re ideal for qui ### Recommended models -| Model | Why it's a good fit | -|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------------| -| {% data variables.copilot.copilot_o4_mini %} | A quick and cost-effective model for repetitive or simple coding tasks. Offers clear, concise suggestions. | -| {% data variables.copilot.copilot_claude_sonnet_35 %} | Balances fast responses with quality output. Ideal for small tasks and lightweight code explanations. | -| {% data variables.copilot.copilot_gemini_flash %} | Extremely low latency and multimodal support (where available). Great for fast, interactive feedback. | +| Model | Why it's a good fit | +|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------| +| {% data variables.copilot.copilot_o4_mini %} | A quick and cost-effective model for repetitive or simple coding tasks. Offers clear, concise suggestions. | +| {% data variables.copilot.copilot_claude_haiku_45 %} | Balances fast responses with quality output. Ideal for small tasks and lightweight code explanations. | +| {% data variables.copilot.copilot_claude_sonnet_35 %} | Balances fast responses with quality output. Ideal for small tasks and lightweight code explanations. | +| {% data variables.copilot.copilot_gemini_flash %} | Extremely low latency and multimodal support (where available). Great for fast, interactive feedback. | ### When to use these models diff --git a/content/copilot/reference/ai-models/model-hosting.md b/content/copilot/reference/ai-models/model-hosting.md index b354bb6bf569..822d57575240 100644 --- a/content/copilot/reference/ai-models/model-hosting.md +++ b/content/copilot/reference/ai-models/model-hosting.md @@ -35,6 +35,7 @@ When using OpenAI's models, input requests and output responses continue to run Used for: +* {% data variables.copilot.copilot_claude_haiku_45 %} * {% data variables.copilot.copilot_claude_sonnet_45 %} * {% data variables.copilot.copilot_claude_opus_41 %} * {% data variables.copilot.copilot_claude_opus %} @@ -43,7 +44,7 @@ Used for: * {% data variables.copilot.copilot_claude_sonnet_37 %} Thinking * {% data variables.copilot.copilot_claude_sonnet_40 %} -{% data variables.copilot.copilot_claude_opus_41 %} is hosted by Anthropic PBC. {% data variables.copilot.copilot_claude_opus %} and {% data variables.copilot.copilot_claude_sonnet_40 %} are hosted by Anthropic PBC and Google Cloud Platform. {% data variables.copilot.copilot_claude_sonnet_45 %} and {% data variables.copilot.copilot_claude_sonnet_37 %} are hosted by Amazon Web Services, Anthropic PBC, and Google Cloud Platform. {% data variables.copilot.copilot_claude_sonnet_35 %} is hosted exclusively by Amazon Web Services. {% data variables.product.github %} has provider agreements in place to ensure data is not used for training. Additional details for each provider are included below: +{% data variables.copilot.copilot_claude_haiku_45 %} and {% data variables.copilot.copilot_claude_opus_41 %} are hosted by Anthropic PBC. {% data variables.copilot.copilot_claude_opus %} and {% data variables.copilot.copilot_claude_sonnet_40 %} are hosted by Anthropic PBC and Google Cloud Platform. {% data variables.copilot.copilot_claude_sonnet_45 %} and {% data variables.copilot.copilot_claude_sonnet_37 %} are hosted by Amazon Web Services, Anthropic PBC, and Google Cloud Platform. {% data variables.copilot.copilot_claude_sonnet_35 %} is hosted exclusively by Amazon Web Services. {% data variables.product.github %} has provider agreements in place to ensure data is not used for training. Additional details for each provider are included below: * Amazon Bedrock: Amazon makes the [following data commitments](https://docs.aws.amazon.com/bedrock/latest/userguide/data-protection.html): _Amazon Bedrock doesn't store or log your prompts and completions. Amazon Bedrock doesn't use your prompts and completions to train any AWS models and doesn't distribute them to third parties_. * Anthropic PBC: {% data variables.product.github %} maintains a [zero data retention agreement](https://privacy.anthropic.com/en/articles/8956058-i-have-a-zero-retention-agreement-with-anthropic-what-products-does-it-apply-to) with Anthropic. diff --git a/content/copilot/reference/ai-models/supported-models.md b/content/copilot/reference/ai-models/supported-models.md index e2f0ca607387..f868621daaa6 100644 --- a/content/copilot/reference/ai-models/supported-models.md +++ b/content/copilot/reference/ai-models/supported-models.md @@ -39,24 +39,25 @@ This table lists the AI models available in {% data variables.product.prodname_c {% rowheaders %} -| Model name | Provider | Release status | Agent mode | Ask mode | Edit mode | -|----------------------------------------------------------------|-----------|-------------------------------------------------------------------|---------------------------------------------|----------------------|---------------| -| {% data variables.copilot.copilot_gpt_41 %} | OpenAI | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_gpt_5_codex %} | OpenAI | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_gpt_5_mini %} | OpenAI | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_gpt_5 %} | OpenAI | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| Model name | Provider | Release status | Agent mode | Ask mode | Edit mode | +|----------------------------------------------------------------|-----------|-----------------------------------------------------------------|---------------------------------------------|----------------------|---------------| +| {% data variables.copilot.copilot_gpt_41 %} | OpenAI | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_gpt_5_codex %} | OpenAI | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_gpt_5_mini %} | OpenAI | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_gpt_5 %} | OpenAI | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o3 %} | OpenAI | {% data variables.release-phases.closing_down_caps %}: 2025-10-23 | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o4_mini %} | OpenAI | {% data variables.release-phases.closing_down_caps %}: 2025-10-23 | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_sonnet_45 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_opus_41 %} | Anthropic | GA | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_haiku_45 %} | Anthropic | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_sonnet_45 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_opus_41 %} | Anthropic | GA | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_opus %} | Anthropic | {% data variables.release-phases.closing_down_caps %}: 2025-10-23 | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_35 %} | Anthropic | {% data variables.release-phases.closing_down_caps %}: 2025-11-06 | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_37 %} | Anthropic | {% data variables.release-phases.closing_down_caps %}: 2025-10-23 | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_37 %} Thinking | Anthropic | {% data variables.release-phases.closing_down_caps %}: 2025-10-23 | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_sonnet_40 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_gemini_25_pro %} | Google | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_sonnet_40 %} | Anthropic | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_gemini_25_pro %} | Google | GA | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_gemini_flash %} | Google | {% data variables.release-phases.closing_down_caps %}: 2025-10-23 | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_grok_code %} | xAI | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_grok_code %} | xAI | {% data variables.release-phases.public_preview_caps %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% endrowheaders %} @@ -78,7 +79,8 @@ The following table shows which models are available in each client. | {% data variables.copilot.copilot_gpt_5 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o3 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o4_mini %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | -| {% data variables.copilot.copilot_claude_sonnet_45 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_haiku_45 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | +| {% data variables.copilot.copilot_claude_sonnet_45 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_opus_41 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_opus %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_35 %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | diff --git a/data/reusables/copilot/available-models-per-plan.md b/data/reusables/copilot/available-models-per-plan.md index 7d6269da36bb..4f5c6050e0b2 100644 --- a/data/reusables/copilot/available-models-per-plan.md +++ b/data/reusables/copilot/available-models-per-plan.md @@ -8,6 +8,7 @@ | {% data variables.copilot.copilot_gpt_5 %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o3 %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_o4_mini %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_claude_haiku_45 %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_sonnet_45 %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_opus_41 %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_claude_opus %} | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | diff --git a/data/reusables/copilot/model-multipliers.md b/data/reusables/copilot/model-multipliers.md index 1fc3da00e748..31ade8310abb 100644 --- a/data/reusables/copilot/model-multipliers.md +++ b/data/reusables/copilot/model-multipliers.md @@ -9,6 +9,7 @@ | {% data variables.copilot.copilot_gpt_4o %} | 0 | 1 | | {% data variables.copilot.copilot_o3 %} | 1 | Not applicable | | {% data variables.copilot.copilot_o4_mini %} | 0.33 | Not applicable | +| {% data variables.copilot.copilot_claude_haiku_45 %} | 0.33 | Not applicable | | {% data variables.copilot.copilot_claude_sonnet_45 %} | 1 | Not applicable | | {% data variables.copilot.copilot_claude_sonnet_35 %} | 1 | 1 | | {% data variables.copilot.copilot_claude_sonnet_37 %} | 1 | Not applicable | diff --git a/data/variables/copilot.yml b/data/variables/copilot.yml index b665de08b155..0a7e2907a91d 100644 --- a/data/variables/copilot.yml +++ b/data/variables/copilot.yml @@ -112,23 +112,24 @@ max-chat-indexed-repos: '50' ## LLM models for Copilot # Claude: copilot_claude: 'Claude' +copilot_claude_haiku_45: 'Claude Haiku 4.5' +copilot_claude_opus: 'Claude Opus 4' +copilot_claude_opus_41: 'Claude Opus 4.1' copilot_claude_sonnet: 'Claude Sonnet' copilot_claude_sonnet_35: 'Claude Sonnet 3.5' copilot_claude_sonnet_37: 'Claude Sonnet 3.7' copilot_claude_sonnet_40: 'Claude Sonnet 4' copilot_claude_sonnet_45: 'Claude Sonnet 4.5' -copilot_claude_opus_41: 'Claude Opus 4.1' -copilot_claude_opus: 'Claude Opus 4' # Gemini: copilot_gemini: 'Gemini' copilot_gemini_flash: 'Gemini 2.0 Flash' copilot_gemini_25_pro: 'Gemini 2.5 Pro' # OpenAI GPT series: -copilot_gpt_41: 'GPT-4.1' copilot_gpt_4o: 'GPT-4o' +copilot_gpt_41: 'GPT-4.1' copilot_gpt_5: 'GPT-5' -copilot_gpt_5_mini: 'GPT-5 mini' copilot_gpt_5_codex: 'GPT-5-Codex' +copilot_gpt_5_mini: 'GPT-5 mini' # OpenAI 'o' series: copilot_o3: 'o3' copilot_o4_mini: 'o4-mini'