зеркало из https://github.com/github/docs.git
Create preview changes entries
This commit is contained in:
Родитель
96e4ea9499
Коммит
9d5af1f98d
|
@ -2,6 +2,8 @@ const { diff, ChangeType } = require('@graphql-inspector/core')
|
|||
const { loadSchema } = require('@graphql-tools/load')
|
||||
const git = require('../../lib/git-utils')
|
||||
const fs = require('fs')
|
||||
const yaml = require('js-yaml')
|
||||
|
||||
// check for required PAT
|
||||
if (!process.env.GITHUB_TOKEN) {
|
||||
console.error('Error! You must have a GITHUB_TOKEN set in an .env file to run this script.')
|
||||
|
@ -20,8 +22,18 @@ async function main() {
|
|||
const tree = await git.getTree('github', 'github', 'heads/master')
|
||||
const schemaFileBlob = tree.find(entry => entry.path.includes('config/schema.docs.graphql') && entry.type === 'blob')
|
||||
const newSchemaBuffer = await git.getContentsForBlob('github', 'github', schemaFileBlob)
|
||||
const changelogEntry = createChangelogEntry(oldSchemaString, newSchemaBuffer.toString())
|
||||
|
||||
const previewsString = fs.readFileSync('data/graphql/graphql_previews.yml')
|
||||
const previews = yaml.safeLoad(previewsString)
|
||||
|
||||
const changelogEntry = createChangelogEntry(oldSchemaString, newSchemaBuffer.toString(), previews)
|
||||
if (changelogEntry) {
|
||||
// Build a `yyyy-mm-dd`-formatted date string
|
||||
// and tag the changelog entry with it
|
||||
const today = new Date()
|
||||
const todayString = String(today.getFullYear()) + '-' + String(today.getMonth() + 1).padStart(2, '0') + '-' + String(today.getDate()).padStart(2, '0')
|
||||
changelogEntry.date = todayString
|
||||
|
||||
const previousChangelogString = fs.readFileSync('lib/graphql/static/changelog.json')
|
||||
const previousChangelog = JSON.parse(previousChangelogString)
|
||||
// add a new entry to the changelog data
|
||||
|
@ -35,7 +47,7 @@ async function main() {
|
|||
// Compare `oldSchemaString` to `newSchemaString`, and if there are any
|
||||
// changes that warrant a changelog entry, return a changelog entry.
|
||||
// Otherwise, return null.
|
||||
async function createChangelogEntry(oldSchemaString, newSchemaString) {
|
||||
async function createChangelogEntry(oldSchemaString, newSchemaString, previews) {
|
||||
// Create schema objects out of the strings
|
||||
const oldSchema = await loadSchema(oldSchemaString)
|
||||
const newSchema = await loadSchema(newSchemaString)
|
||||
|
@ -53,15 +65,10 @@ async function createChangelogEntry(oldSchemaString, newSchemaString) {
|
|||
}
|
||||
})
|
||||
|
||||
const { schemaChangesToReport, previewChangesToReport } = segmentPreviewChanges(changesToReport)
|
||||
const { schemaChangesToReport, previewChangesToReport } = segmentPreviewChanges(changesToReport, previews)
|
||||
// If there were any changes, create a changelog entry
|
||||
if (schemaChangesToReport.length > 0 || previewChangesToReport.length > 0) {
|
||||
// Build a `yyyy-mm-dd`-formatted date string
|
||||
const today = new Date()
|
||||
const todayString = String(today.getFullYear()) + '-' + String(today.getMonth() + 1).padStart(2, '0') + '-' + String(today.getDate()).padStart(2, '0')
|
||||
|
||||
const changelogEntry = {
|
||||
date: todayString,
|
||||
schemaChanges: [],
|
||||
previewChanges: [],
|
||||
upcomingChanges: [],
|
||||
|
@ -70,19 +77,19 @@ async function createChangelogEntry(oldSchemaString, newSchemaString) {
|
|||
const schemaChange = {
|
||||
title: 'The GraphQL schema includes these changes:',
|
||||
// Replace single quotes which wrap field/argument/type names with backticks
|
||||
changes: changesToReport.map(function (change) { return change.message.replace(/'([a-zA-Z\. :!]+)'/g, '`$1`') })
|
||||
changes: cleanMessagesFromChanges(schemaChangesToReport)
|
||||
}
|
||||
changelogEntry.schemaChanges.push(schemaChange)
|
||||
|
||||
// TODO how are these populated?
|
||||
// {
|
||||
// "title": "The [Checks preview](/graphql/overview/schema-previews#checks-preview) includes these changes:",
|
||||
// "changes": [
|
||||
// "Enum value `STALE` was added to enum `CheckConclusionState`",
|
||||
// "Enum value `SKIPPED` was added to enum `CheckConclusionState`"
|
||||
// ]
|
||||
// }
|
||||
const previewChanges = []
|
||||
for (const previewTitle in previewChangesToReport) {
|
||||
let previewChanges = previewChangesToReport[previewTitle]
|
||||
let cleanTitle = cleanPreviewTitle(previewTitle)
|
||||
let entryTitle = "The [" + cleanTitle + "](/graphql/overview/schema-previews#" + previewAnchor(cleanTitle) + ") includes these changes:"
|
||||
changelogEntry.previewChanges.push({
|
||||
title: entryTitle,
|
||||
changes: cleanMessagesFromChanges(previewChanges.changes),
|
||||
})
|
||||
}
|
||||
|
||||
// TODO how are these populated?
|
||||
// "upcomingChanges": [
|
||||
|
@ -101,12 +108,76 @@ async function createChangelogEntry(oldSchemaString, newSchemaString) {
|
|||
}
|
||||
}
|
||||
|
||||
function segmentPreviewChanges(changesToReport) {
|
||||
// TODO: read the previews yaml file and
|
||||
// split the list of changes based on whether the change's path
|
||||
// (or any "parents" in the change's path) are in a preview.
|
||||
// See: https://github.com/github/graphql-docs/blob/master/lib/graphql_docs/update_internal_developer/change_log.rb#L230
|
||||
return { schemaChangesToReport: changesToReport, previewChangesToReport: [] }
|
||||
// prepare the preview title from github/github source for the docs.
|
||||
// ported from build-changelog-from-markdown
|
||||
function cleanPreviewTitle(title) {
|
||||
if (title == "UpdateRefsPreview") {
|
||||
title = "Update refs preview"
|
||||
} else if (title == "MergeInfoPreview") {
|
||||
title = "Merge info preview"
|
||||
} else if (!title.endsWith("preview")) {
|
||||
title = title + " preview"
|
||||
}
|
||||
return title
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [previewTitle]
|
||||
* @return {string}
|
||||
*/
|
||||
function previewAnchor(previewTitle) {
|
||||
// ported from https://github.com/github/graphql-docs/blob/master/lib/graphql_docs/update_internal_developer/change_log.rb#L281
|
||||
return previewTitle
|
||||
.toLowerCase()
|
||||
.replace(/ /g, '-')
|
||||
.replace(/[^\w-]/g, '')
|
||||
}
|
||||
|
||||
function cleanMessagesFromChanges(changes) {
|
||||
return changes.map(function (change) {
|
||||
// replace single quotes around graphql names with backticks,
|
||||
// to match previous behavior from graphql-schema-comparator
|
||||
return change.message.replace(/'([a-zA-Z\. :!]+)'/g, '`$1`')
|
||||
})
|
||||
}
|
||||
|
||||
function segmentPreviewChanges(changesToReport, previews) {
|
||||
// Build a map of `{ path => previewTitle` }
|
||||
// for easier lookup of change to preview
|
||||
const pathToPreview = {}
|
||||
previews.forEach(function (preview) {
|
||||
preview.toggled_on.forEach(function (path) {
|
||||
pathToPreview[path] = preview.title
|
||||
})
|
||||
})
|
||||
const schemaChanges = []
|
||||
const changesByPreview = {}
|
||||
|
||||
changesToReport.forEach(function (change) {
|
||||
// For each change, see if its path _or_ one of its ancestors
|
||||
// is covered by a preview. If it is, mark this change as belonging to a preview
|
||||
const pathParts = change.path.split(".")
|
||||
let testPath = null
|
||||
let previewTitle = null
|
||||
let previewChanges = null
|
||||
while (pathParts.length > 0 && !previewTitle) {
|
||||
testPath = pathParts.join(".")
|
||||
previewTitle = pathToPreview[testPath]
|
||||
// If that path didn't find a match, then we'll
|
||||
// check the next ancestor.
|
||||
pathParts.pop()
|
||||
}
|
||||
if (previewTitle) {
|
||||
previewChanges = changesByPreview[previewTitle] || (changesByPreview[previewTitle] = {
|
||||
title: previewTitle,
|
||||
changes: []
|
||||
})
|
||||
previewChanges.changes.push(change)
|
||||
} else {
|
||||
schemaChanges.push(change)
|
||||
}
|
||||
})
|
||||
return { schemaChangesToReport: schemaChanges, previewChangesToReport: changesByPreview }
|
||||
}
|
||||
|
||||
const CHANGES_TO_REPORT = [
|
||||
|
@ -169,4 +240,4 @@ const CHANGES_TO_IGNORE = [
|
|||
|
||||
|
||||
|
||||
module.exports = { createChangelogEntry }
|
||||
module.exports = { createChangelogEntry, cleanPreviewTitle, previewAnchor }
|
||||
|
|
|
@ -2,8 +2,15 @@
|
|||
|
||||
exports[`creating a changelog from old schema and new schema finds a diff of schema changes, upcoming changes, and preview changes 1`] = `
|
||||
Object {
|
||||
"date": "2020-11-20",
|
||||
"previewChanges": Array [],
|
||||
"previewChanges": Array [
|
||||
Object {
|
||||
"changes": Array [
|
||||
"Field \`Query.previewField\` changed type from \`PreviewType\` to \`PreviewType!\`",
|
||||
"Type for argument \`changeTypeArgument\` on field 'PreviewType.field1\` changed from \`Int\` to \`Float'",
|
||||
],
|
||||
"title": "The [Test preview](/graphql/overview/schema-previews#test-preview) includes these changes:",
|
||||
},
|
||||
],
|
||||
"schemaChanges": Array [
|
||||
Object {
|
||||
"changes": Array [
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
const { createChangelogEntry } = require('../../script/graphql/build-changelog')
|
||||
const yaml = require("js-yaml")
|
||||
const { createChangelogEntry, cleanPreviewTitle, previewAnchor } = require('../../script/graphql/build-changelog')
|
||||
|
||||
describe('creating a changelog from old schema and new schema', () => {
|
||||
it('finds a diff of schema changes, upcoming changes, and preview changes', async () => {
|
||||
const oldSchemaString = `
|
||||
type PreviewType {
|
||||
field1(changeTypeArgument: Int): Int
|
||||
}
|
||||
|
||||
type Query {
|
||||
stableField: String
|
||||
removedField: Boolean
|
||||
|
@ -12,21 +17,39 @@ describe('creating a changelog from old schema and new schema', () => {
|
|||
argumentMadeRequired: Int
|
||||
argumentMadeOptional: Int!
|
||||
): String
|
||||
previewField: PreviewType
|
||||
}
|
||||
`
|
||||
|
||||
const newSchemaString = `
|
||||
type PreviewType {
|
||||
field1(changeTypeArgument: Float): Int
|
||||
}
|
||||
|
||||
type Query {
|
||||
stableField: String
|
||||
argumentsField(
|
||||
argumentMadeRequired: Int!
|
||||
argumentMadeOptional: Int
|
||||
): String
|
||||
previewField: PreviewType!
|
||||
}
|
||||
`
|
||||
|
||||
previews = yaml.safeLoad(`
|
||||
- title: Test preview
|
||||
description: This preview is just for test
|
||||
toggled_by: ':test_preview'
|
||||
announcement: null
|
||||
updates: null
|
||||
toggled_on:
|
||||
- PreviewType
|
||||
- Query.previewField
|
||||
owning_teams:
|
||||
- '@github/engineering'
|
||||
`)
|
||||
|
||||
const entry = await createChangelogEntry(oldSchemaString, newSchemaString)
|
||||
const entry = await createChangelogEntry(oldSchemaString, newSchemaString, previews)
|
||||
expect(entry).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -36,7 +59,24 @@ describe('creating a changelog from old schema and new schema', () => {
|
|||
i: Int!
|
||||
}`
|
||||
|
||||
const nullEntry = await createChangelogEntry(schemaString, schemaString)
|
||||
const nullEntry = await createChangelogEntry(schemaString, schemaString, [])
|
||||
expect(nullEntry).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe("Preparing preview links", () => {
|
||||
it("fixes preview names", () => {
|
||||
// These two are special cases
|
||||
expect(cleanPreviewTitle("UpdateRefsPreview")).toEqual("Update refs preview")
|
||||
expect(cleanPreviewTitle("MergeInfoPreview")).toEqual("Merge info preview")
|
||||
// Previews that don't end in " preview" have it added
|
||||
expect(cleanPreviewTitle("something interesting")).toEqual("something interesting preview")
|
||||
// Other things are left as-is
|
||||
expect(cleanPreviewTitle("nice preview")).toEqual("nice preview")
|
||||
})
|
||||
|
||||
it("creates anchors from preview titles", () => {
|
||||
expect(previewAnchor("Merge info preview")).toEqual("merge-info-preview")
|
||||
expect(previewAnchor("some.punct123 preview")).toEqual("somepunct123-preview")
|
||||
})
|
||||
})
|
||||
|
|
Загрузка…
Ссылка в новой задаче