-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3061 from artsy/wip_check_gql_breaking
Adds a graphql validation script to force deploys
- Loading branch information
Showing
6 changed files
with
244 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
language: node_js | ||
node_js: 10 | ||
script: yarn danger ci |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,52 @@ | ||
import { warn, danger } from 'danger' | ||
|
||
// Warn about creating new JS files | ||
const jsFiles = danger.git.created_files.filter(f => f.endsWith('.js')) | ||
if (jsFiles.length) { | ||
const files = danger.github.utils.fileLinks(jsFiles) | ||
warn( | ||
`Please don't include .js files, we want to be using TypeScript found: ${files}.` | ||
import { warn, danger } from "danger" | ||
import { getBreakingChanges } from "./scripts/validate_schemas" | ||
import { BreakingChange } from "graphql" | ||
|
||
// tslint:disable-next-line:no-default-export | ||
export default async () => { | ||
// Warn about creating new JS files | ||
const jsFiles = danger.git.created_files.filter( | ||
f => f.includes("src") && f.endsWith(".js") | ||
) | ||
if (jsFiles.length) { | ||
const files = danger.github.utils.fileLinks(jsFiles) | ||
warn( | ||
`Please don't include .js files, we want to be using TypeScript found: ${files}.` | ||
) | ||
} | ||
|
||
// Breaking change check for Metaphysics production when deploying | ||
if (danger.github.pr.base.ref === "release") { | ||
const breakingChanges = await getBreakingChanges() | ||
const bc = breakingChanges | ||
const typesMissing = bc.filter(b => b.type === "TYPE_REMOVED") | ||
const fieldsMissing = bc.filter(b => b.type === "FIELD_REMOVED") | ||
const unionOptionsMissing = bc.filter( | ||
b => b.type === "TYPE_REMOVED_FROM_UNION" | ||
) | ||
const fieldChanged = bc.filter(b => b.type === "FIELD_CHANGED_KIND") | ||
|
||
const descriptions = { | ||
"Missing types": typesMissing, | ||
"Fields missing": fieldsMissing, | ||
"Fields changed": fieldChanged, | ||
"Union types-mismatch": unionOptionsMissing, | ||
} | ||
|
||
if (bc.length) { | ||
fail( | ||
`Metaphysics production does not have a compatible schema for force's GraphQL usage, please deploy metaphysics to production and re-run Travis CI.` | ||
) | ||
} | ||
|
||
Object.keys(descriptions).forEach(key => { | ||
const breakingChanges: BreakingChange[] = descriptions[key] | ||
if (breakingChanges.length) { | ||
const fields = breakingChanges.map( | ||
b => "`" + b.description.split(" ")[0] + "`" | ||
) | ||
fail(`${key}: ${danger.utils.sentence(fields)}`) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// @ts-check | ||
|
||
// Grab the schema for reaction out of the node_modules | ||
// to see if it is a subset of the production schema | ||
// | ||
// Used both by Danger during the deploy PR, and also | ||
// before the deployment on circle | ||
// | ||
const { readFileSync } = require("fs") | ||
const { | ||
introspectionQuery, | ||
buildClientSchema, | ||
printSchema, | ||
buildSchema, | ||
findBreakingChanges, | ||
} = require("graphql") | ||
|
||
const fetch = require("isomorphic-fetch") | ||
const metaphysicsProd = "https://metaphysics-production.artsy.net/" | ||
|
||
const downloadProductionSchema = async endpoint => { | ||
const postBody = { | ||
query: introspectionQuery, | ||
operationName: "IntrospectionQuery", | ||
} | ||
|
||
const response = await fetch(endpoint, { | ||
method: "POST", | ||
body: JSON.stringify(postBody), | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
}) | ||
const { data } = await response.json() | ||
// commentDescriptions is hidden | ||
// @ts-ignore | ||
return printSchema(buildClientSchema(data), { commentDescriptions: true }) | ||
} | ||
|
||
const downloadGitHubReaction = async release => { | ||
const response = await fetch( | ||
`https://github.com/artsy/reaction/raw/v${release}/data/schema.graphql` | ||
) | ||
|
||
const body = await response.text() | ||
return body | ||
} | ||
|
||
const getBreakingChanges = async () => { | ||
const packageJSON = JSON.parse( | ||
readFileSync(__dirname + "/../package.json", "utf8") | ||
) | ||
const reactionVersion = packageJSON["dependencies"]["@artsy/reaction"] | ||
const reactionSchema = await downloadGitHubReaction(reactionVersion) | ||
const metaphyicsSchema = await downloadProductionSchema(metaphysicsProd) | ||
return findBreakingChanges( | ||
buildSchema(metaphyicsSchema), | ||
buildSchema(reactionSchema) | ||
) | ||
} | ||
|
||
module.exports = { | ||
getBreakingChanges, | ||
} | ||
|
||
// @ts-ignore | ||
if (require.main === module) { | ||
// When this is being called as a script via `node scripts/validate_schemas.js` | ||
getBreakingChanges().then(changes => { | ||
if (changes.length) { | ||
process.exitCode = 1 | ||
console.error( | ||
"Failing due to breaking changes between Force and Metaphysics Production\n\n" | ||
) | ||
console.error(changes) | ||
console.error( | ||
"\n\nYou should deploy metaphysics production, and re-deploy force" | ||
) | ||
} | ||
}) | ||
} |
Oops, something went wrong.