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'