@@ -40,10 +40,8 @@ const (
4040 HeaderRequestID = "X-Github-Request-Id"
4141
4242 // https://docs.github.com/en/rest/about-the-rest-api/api-versions#about-api-versioning
43- defaultAPIVersion = api20221128
44- latestAPIVersion = api20260310
45- api20221128 = "2022-11-28"
46- api20260310 = "2026-03-10"
43+ api20221128 = "2022-11-28"
44+ api20260310 = "2026-03-10"
4745
4846 defaultBaseURL = "https://api.github.com/"
4947 defaultUserAgent = "go-github" + "/" + Version
@@ -178,6 +176,13 @@ type Client struct {
178176 // Base URL for uploading files.
179177 uploadURL * url.URL
180178
179+ // Default API version to set in the X-Github-Api-Version header.
180+ apiVersionDefault string
181+ // Minimum API version that the client can use.
182+ apiVersionMin string
183+ // Maximum API version that the client can use.
184+ apiVersionMax string
185+
181186 // User agent used when communicating with the GitHub API.
182187 userAgent string
183188
@@ -347,6 +352,8 @@ type clientOptions struct {
347352 httpClient * http.Client
348353 transport http.RoundTripper
349354 timeout * time.Duration
355+ apiVersionMin * string
356+ apiVersionMax * string
350357 userAgent * string
351358 envProxy bool
352359 token * string
@@ -558,7 +565,11 @@ func NewClient(opts ...ClientOptionsFunc) (*Client, error) {
558565// newClient creates a new Client with the provided options. This is an internal
559566// helper function that is called by [NewClient] and [Client.Clone].
560567func newClient (opts clientOptions ) (* Client , error ) {
561- c := & Client {}
568+ c := & Client {
569+ apiVersionDefault : api20221128 ,
570+ apiVersionMin : api20221128 ,
571+ apiVersionMax : api20260310 ,
572+ }
562573
563574 if opts .httpClient != nil {
564575 c .client = opts .httpClient
@@ -609,6 +620,14 @@ func newClient(opts clientOptions) (*Client, error) {
609620 CheckRedirect : func (* http.Request , []* http.Request ) error { return http .ErrUseLastResponse },
610621 }
611622
623+ if opts .apiVersionMin != nil {
624+ c .apiVersionMin = * opts .apiVersionMin
625+ }
626+
627+ if opts .apiVersionMax != nil {
628+ c .apiVersionMax = * opts .apiVersionMax
629+ }
630+
612631 if opts .userAgent != nil {
613632 c .userAgent = * opts .userAgent
614633 } else {
@@ -718,6 +737,8 @@ func (c *Client) Clone(opts ...ClientOptionsFunc) (*Client, error) {
718737 }
719738
720739 o := clientOptions {
740+ apiVersionMin : & c .apiVersionMin ,
741+ apiVersionMax : & c .apiVersionMax ,
721742 userAgent : & c .userAgent ,
722743 baseURL : Ptr (* c .baseURL ),
723744 uploadURL : Ptr (* c .uploadURL ),
@@ -814,7 +835,7 @@ func (c *Client) NewRequest(ctx context.Context, method, urlStr string, body any
814835 if c .userAgent != "" {
815836 req .Header .Set ("User-Agent" , c .userAgent )
816837 }
817- req .Header .Set (headerAPIVersion , defaultAPIVersion )
838+ req .Header .Set (headerAPIVersion , c . apiVersionDefault )
818839
819840 for _ , opt := range opts {
820841 opt (req )
@@ -851,7 +872,7 @@ func (c *Client) NewFormRequest(ctx context.Context, urlStr string, body io.Read
851872 if c .userAgent != "" {
852873 req .Header .Set ("User-Agent" , c .userAgent )
853874 }
854- req .Header .Set (headerAPIVersion , defaultAPIVersion )
875+ req .Header .Set (headerAPIVersion , c . apiVersionDefault )
855876
856877 for _ , opt := range opts {
857878 opt (req )
@@ -922,7 +943,7 @@ func (c *Client) NewUploadRequest(ctx context.Context, urlStr string, reader io.
922943 req .Header .Set ("Content-Type" , mediaType )
923944 req .Header .Set ("Accept" , mediaTypeV3 )
924945 req .Header .Set ("User-Agent" , c .userAgent )
925- req .Header .Set (headerAPIVersion , defaultAPIVersion )
946+ req .Header .Set (headerAPIVersion , c . apiVersionDefault )
926947
927948 for _ , opt := range opts {
928949 opt (req )
@@ -1143,6 +1164,28 @@ const (
11431164// unexpectedly large error body.
11441165const maxErrorBodySize = 1 * 1024 * 1024 // 1 MiB
11451166
1167+ // ErrUnsupportedAPIVersion is returned when the API version specified in the
1168+ // request is not supported by the client.
1169+ var ErrUnsupportedAPIVersion = errors .New ("unsupported api version" )
1170+
1171+ // checkRequestAPIVersionBeforeDo checks if the API version specified in the
1172+ // request is supported by the client before making the API call. If the
1173+ // version is not supported, it returns [ErrUnsupportedAPIVersion]. If the
1174+ // version is empty it returns nil.
1175+ func (c * Client ) checkRequestAPIVersionBeforeDo (req * http.Request ) error {
1176+ reqAPIVersion := req .Header .Get (headerAPIVersion )
1177+
1178+ if reqAPIVersion == "" {
1179+ return nil
1180+ }
1181+
1182+ if reqAPIVersion < c .apiVersionMin || reqAPIVersion > c .apiVersionMax {
1183+ return ErrUnsupportedAPIVersion
1184+ }
1185+
1186+ return nil
1187+ }
1188+
11461189// bareDo sends an API request using `caller` http.Client passed in the parameters
11471190// and lets you handle the api response. If an error or API Error occurs, the error
11481191// will contain more information. Otherwise, you are supposed to read and close the
@@ -1151,6 +1194,10 @@ const maxErrorBodySize = 1 * 1024 * 1024 // 1 MiB
11511194func (c * Client ) bareDo (caller * http.Client , req * http.Request ) (* Response , error ) {
11521195 ctx := req .Context ()
11531196
1197+ if err := c .checkRequestAPIVersionBeforeDo (req ); err != nil {
1198+ return nil , err
1199+ }
1200+
11541201 rateLimitCategory := CoreCategory
11551202
11561203 if ! c .disableRateLimitCheck {
0 commit comments