Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
744 changes: 428 additions & 316 deletions schema/dereferenced/repos.json

Large diffs are not rendered by default.

832 changes: 480 additions & 352 deletions schema/dereferenced/settings.json

Large diffs are not rendered by default.

744 changes: 428 additions & 316 deletions schema/dereferenced/suborgs.json

Large diffs are not rendered by default.

20 changes: 14 additions & 6 deletions schema/repos.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"description": "Repository settings",
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}/patch/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}/patch/requestBody/content/application~1json/schema"
},
{
"type": "object",
Expand Down Expand Up @@ -162,7 +162,7 @@
"description": "A collaborator entry giving a specific user access to a repository.",
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1collaborators~1{username}/put/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1collaborators~1{username}/put/requestBody/content/application~1json/schema"
},
{
"type": "object",
Expand Down Expand Up @@ -190,7 +190,7 @@
},
"TeamSettings": {
"description": "A team entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1teams/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1teams/post/requestBody/content/application~1json/schema"
},
"MilestoneSettings": {
"description": "A milestone entry",
Expand All @@ -217,13 +217,21 @@
"type": "string"
},
"protection": {
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1branches~1{branch}~1protection/put/requestBody/content/application~1json/schema"
"anyOf": [
{
"type": "null",
"description": "Set to `null` to delete the existing branch protection"
},
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1branches~1{branch}~1protection/put/requestBody/content/application~1json/schema"
}
]
}
Comment thread
tdabasinskas marked this conversation as resolved.
}
},
"AutolinkSettings": {
"description": "An autolink reference entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1autolinks/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1autolinks/post/requestBody/content/application~1json/schema"
},
"ValidatorSettings": {
"description": "Repository name validation",
Expand All @@ -236,7 +244,7 @@
},
"RulesetSettings": {
"description": "A ruleset entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1rulesets/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1rulesets/post/requestBody/content/application~1json/schema"
},
"EnvironmentsSettings": {
"description": "A deployment environment configuration entry",
Expand Down
20 changes: 14 additions & 6 deletions schema/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"description": "Repository settings",
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}/patch/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}/patch/requestBody/content/application~1json/schema"
},
{
"type": "object",
Expand Down Expand Up @@ -169,7 +169,7 @@
"description": "A collaborator entry giving a specific user access to a repository.",
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1collaborators~1{username}/put/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1collaborators~1{username}/put/requestBody/content/application~1json/schema"
},
{
"type": "object",
Expand Down Expand Up @@ -197,7 +197,7 @@
},
"TeamSettings": {
"description": "A team entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1teams/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1teams/post/requestBody/content/application~1json/schema"
},
"MilestoneSettings": {
"description": "A milestone entry",
Expand All @@ -224,13 +224,21 @@
"type": "string"
},
"protection": {
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1branches~1{branch}~1protection/put/requestBody/content/application~1json/schema"
"anyOf": [
{
"type": "null",
"description": "Set to `null` to delete the existing branch protection"
},
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1branches~1{branch}~1protection/put/requestBody/content/application~1json/schema"
}
]
}
Comment thread
tdabasinskas marked this conversation as resolved.
}
},
"AutolinkSettings": {
"description": "An autolink reference entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1autolinks/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1autolinks/post/requestBody/content/application~1json/schema"
},
"ValidatorSettings": {
"description": "Repository name validation",
Expand All @@ -243,7 +251,7 @@
},
"RulesetSettings": {
"description": "A ruleset entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1rulesets/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1rulesets/post/requestBody/content/application~1json/schema"
},
"EnvironmentsSettings": {
"description": "A deployment environment configuration entry",
Expand Down
20 changes: 14 additions & 6 deletions schema/suborgs.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"description": "Repository settings. Use force_create to create the repository if it does not exist, and template to specify a template repository to use when creating it.",
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}/patch/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}/patch/requestBody/content/application~1json/schema"
},
{
"type": "object",
Expand Down Expand Up @@ -196,7 +196,7 @@
"description": "A collaborator entry giving a specific user access to a repository.",
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1collaborators~1{username}/put/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1collaborators~1{username}/put/requestBody/content/application~1json/schema"
},
{
"type": "object",
Expand Down Expand Up @@ -224,7 +224,7 @@
},
"TeamSettings": {
"description": "A team entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1teams/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1teams/post/requestBody/content/application~1json/schema"
},
"MilestoneSettings": {
"description": "A milestone entry",
Expand All @@ -251,13 +251,21 @@
"type": "string"
},
"protection": {
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1branches~1{branch}~1protection/put/requestBody/content/application~1json/schema"
"anyOf": [
{
"type": "null",
"description": "Set to `null` to delete the existing branch protection"
},
{
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1branches~1{branch}~1protection/put/requestBody/content/application~1json/schema"
}
]
}
Comment thread
tdabasinskas marked this conversation as resolved.
}
},
"AutolinkSettings": {
"description": "An autolink reference entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1autolinks/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1repos~1{owner}~1{repo}~1autolinks/post/requestBody/content/application~1json/schema"
},
"ValidatorSettings": {
"description": "Repository name validation",
Expand All @@ -270,7 +278,7 @@
},
"RulesetSettings": {
"description": "A ruleset entry",
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1rulesets/post/requestBody/content/application~1json/schema"
"$ref": "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions-next/api.github.com/api.github.com.2026-03-10.json#/paths/~1orgs~1{org}~1rulesets/post/requestBody/content/application~1json/schema"
},
"EnvironmentsSettings": {
"description": "A deployment environment configuration entry",
Expand Down
8 changes: 5 additions & 3 deletions script/build-schema
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const path = require('node:path')

const schemas = [
{ src: 'schema/settings.json', dest: 'schema/dereferenced/settings.json' },
{ src: 'schema/suborgs.json', dest: 'schema/dereferenced/suborgs.json' },
{ src: 'schema/repos.json', dest: 'schema/dereferenced/repos.json' }
{ src: 'schema/suborgs.json', dest: 'schema/dereferenced/suborgs.json' },
{ src: 'schema/repos.json', dest: 'schema/dereferenced/repos.json' }
]

;(async () => {
Expand All @@ -32,9 +32,11 @@ const schemas = [
console.log(`Fetching ${specUrl} ...`)
const resolvedSpec = await $RefParser.dereference(specUrl)

// Serve the pre-dereferenced spec for the exact URL the schema files pin,
// so the resolver can never match a different document.
const githubApiResolver = {
order: 1,
canRead: /\/descriptions\/api\.github\.com\/api\.github\.com/,
canRead: file => file.url === specUrl,
read: () => resolvedSpec
}
Comment thread
tdabasinskas marked this conversation as resolved.
Comment thread
tdabasinskas marked this conversation as resolved.

Expand Down
54 changes: 54 additions & 0 deletions test/unit/schema.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* eslint-disable no-undef */

const fs = require('fs')
const path = require('path')

// The generated schemas declare JSON Schema draft 2020-12, where OpenAPI 3.0's
// `nullable` keyword does not exist. The build consumes GitHub's OpenAPI 3.1
// description, which models null-ability as `type: [X, 'null']` unions instead,
// so no `nullable` keyword may survive in the output.
describe('dereferenced schemas', () => {
const files = ['settings.json', 'suborgs.json', 'repos.json']

files.forEach(file => {
describe(file, () => {
const schema = JSON.parse(fs.readFileSync(path.join(__dirname, '../../schema/dereferenced', file)))
Comment thread
tdabasinskas marked this conversation as resolved.
Outdated

it('contains no OpenAPI `nullable` keywords', () => {
const found = []
const walk = (node, at) => {
if (Array.isArray(node)) {
node.forEach((v, i) => walk(v, `${at}/${i}`))
} else if (node && typeof node === 'object') {
if ('nullable' in node) {
found.push(at)
}
Object.entries(node).forEach(([k, v]) => walk(v, `${at}/${k}`))
}
}
walk(schema, '')
expect(found).toEqual([])
})
})
})

it('allows null for required-but-nullable branch protection fields', () => {
const schema = JSON.parse(fs.readFileSync(path.join(__dirname, '../../schema/dereferenced/settings.json')))
Comment thread
tdabasinskas marked this conversation as resolved.
Outdated
const protection = schema.properties.branches.items.properties.protection
const protectionObject = protection.anyOf.find(variant => variant.type === 'object')
expect(protectionObject.properties.required_status_checks.type).toContain('null')
expect(protectionObject.properties.enforce_admins.type).toContain('null')
expect(protectionObject.properties.restrictions.type).toContain('null')
})

// `protection: null` is safe-settings' own delete-branch-protection semantic
// (see isEmpty in lib/plugins/branches.js); the GitHub API's PUT body it is
// validated against does not model that, so the schema allows null explicitly.
it('allows `protection: null` in every schema that has branches', () => {
files.forEach(file => {
const schema = JSON.parse(fs.readFileSync(path.join(__dirname, '../../schema/dereferenced', file)))
Comment thread
tdabasinskas marked this conversation as resolved.
Outdated
const protection = schema.properties.branches.items.properties.protection
expect(protection.anyOf).toEqual(expect.arrayContaining([expect.objectContaining({ type: 'null' })]))
})
})
Comment thread
tdabasinskas marked this conversation as resolved.
})