Skip to content

Commit

Permalink
[core] GraphQL: Check for breaking changes when deploying GraphQL API (
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars authored and saasen committed Feb 27, 2020
1 parent 1366a9a commit 0b824d8
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
12 changes: 9 additions & 3 deletions packages/@sanity/core/src/actions/graphql/deleteApiAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@ module.exports = async function deleteApiAction(args, context) {
requireProject: true
})

const dataset = flags.dataset || client.config().dataset
const tag = flags.tag || 'default'

const confirmMessage =
tag === 'default'
? 'Are you absolutely sure you want to delete the current GraphQL API?'
: `Are you absolutely sure you want to delete the GraphQL API tagged "${tag}"?`

if (
!(await prompt.single({
type: 'confirm',
message: `Are you absolutely sure you want to delete the current GraphQL API?`,
message: confirmMessage,
default: false
}))
) {
return
}

const dataset = flags.dataset || client.config().dataset
const tag = flags.tag || 'default'
try {
await client.request({
url: `/apis/graphql/${dataset}/${tag}`,
Expand Down
66 changes: 63 additions & 3 deletions packages/@sanity/core/src/actions/graphql/deployApiAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = async function deployApiActions(args, context) {
await tryInitializePluginConfigs({workDir, output, env: 'production'})

const flags = args.extOptions
const {force, playground} = flags

const client = apiClient({
requireUser: true,
Expand All @@ -20,13 +21,13 @@ module.exports = async function deployApiActions(args, context) {
const dataset = flags.dataset || client.config().dataset
const tag = flags.tag || 'default'
const enablePlayground =
typeof flags.playground === 'undefined'
typeof playground === 'undefined'
? await prompt.single({
type: 'confirm',
message: `Do you want to enable a GraphQL playground?`,
message: 'Do you want to enable a GraphQL playground?',
default: true
})
: flags.playground
: playground

let spinner = output.spinner('Generating GraphQL schema').start()

Expand All @@ -50,6 +51,25 @@ module.exports = async function deployApiActions(args, context) {
}

spinner.succeed()

spinner = output.spinner('Validating GraphQL API').start()
let valid
try {
valid = await client.request({
url: `/apis/graphql/${dataset}/${tag}/validate`,
method: 'POST',
body: {enablePlayground, schema},
maxRedirects: 0
})
} catch (err) {
spinner.fail()
throw err
}

if (!(await confirmValidationResult(valid, {spinner, output, prompt, force}))) {
return
}

spinner = output.spinner('Deploying GraphQL API').start()

try {
Expand All @@ -68,3 +88,43 @@ module.exports = async function deployApiActions(args, context) {
throw err
}
}

async function confirmValidationResult(valid, {spinner, output, prompt, force}) {
const {validationError, breakingChanges, dangerousChanges} = valid
if (validationError) {
spinner.fail()
throw new Error(`GraphQL schema is not valid:\n\n${validationError}`)
}

const hasProblematicChanges = breakingChanges.length > 0 || dangerousChanges.length > 0
if (force && hasProblematicChanges) {
spinner.text = 'Validating GraphQL API: Dangerous changes. Forced with `--force`.'
spinner.warn()
return true
} else if (force || !hasProblematicChanges) {
spinner.succeed()
return true
}

spinner.warn()

if (dangerousChanges.length > 0) {
output.print('\nFound potentially dangerous changes from previous schema:')
dangerousChanges.forEach(change => output.print(` - ${change.description}`))
}

if (breakingChanges.length > 0) {
output.print('\nFound BREAKING changes from previous schema:')
breakingChanges.forEach(change => output.print(` - ${change.description}`))
}

output.print('')

const shouldDeploy = await prompt.single({
type: 'confirm',
message: 'Do you want to deploy a new API despite the dangerous changes?',
default: false
})

return shouldDeploy
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ Options
--tag <tag> Deploy API to given tag (defaults to 'default')
--playground Deploy a GraphQL playground for easily testing queries (public)
--no-playground Skip playground prompt (do not deploy a playground)
--force Deploy API without confirming breaking changes
Examples
sanity graphql deploy
sanity graphql deploy --playground
sanity graphql deploy --dataset staging --no-playground
sanity graphql deploy --dataset staging --tag next --no-playground
sanity graphql deploy --no-playground --force
`

export default {
Expand Down

0 comments on commit 0b824d8

Please sign in to comment.