I'd like to provide a set of rake tasks for managing a GraphQL system. I don't know a lot about Rake yet but I can imagine something like Rubocop's API:
require "graphql/rake_task"
# Define a bunch of tasks that will load the schema as needed
GraphQL::RakeTask.new(schema_name: "MyAppSchema")
One challenge is loading the schema: we may need to depend on :environment in Rails, or require a certain file to find the schema. Perhaps the user could define the task:
GraphQL::RakeTask.new do
# On Rails:
task load_schema: :environment do
MyAppSchema
end
# Off Rails:
task :load_schema do
require "app/my_app_schema"
MyAppSchema
end
end
Also, should we support multiple schemas out of the box?
Which tasks should we implement? I can only think of schema dumping:
At @quri we do have a couple of Rake task that we use in our workflow for indeed dumping both the schema.json (useful for client GraphQL Client / apps to grab the latest schema) and the IDL (useful for spotting what's changing in a PR). This was heavily inspired by the talk the folks at @shopify gave at the GraphQL Summit.
Here is what our lib/tasks/graphql.rake looks like (hermes being the name of our GraphQL layer):
require 'json'
namespace :graphql do
namespace :dump do
desc 'Dumps the IDL schema into ./app/hermes/schema.graphql'
task idl: [:environment] do
target = Rails.root.join("app/graph/schema.graphql")
schema = GraphQL::Schema::Printer.print_schema(Hermes::Schema)
File.open(target, "w+") do |f|
f.write(schema)
end
puts "Schema dumped into app/graph/schema.graphql"
end
desc 'Dumps the result of the introspection query into ./app/hermes/schema.json'
task json: [:environment] do
target = Rails.root.join("app/graph/schema.json")
result = Hermes::Schema.execute(GraphQL::Introspection::INTROSPECTION_QUERY)
File.open(target, "w+") do |f|
f.write(JSON.pretty_generate(result))
end
puts "Schema dumped into app/graph/schema.json"
end
end
desc 'Dumps both the IDL and result of introspection query in app/graph'
task dump: ["graphql:dump:idl", "graphql:dump:json"]
end
as is it's not really re-usable but I could think of an initializer where maybe we could customize where does the files get dropped?
Happy to contribute as we have been using graphql-ruby heavily for a bit more than a year now and it's become a key component in our way to build our apps
We also in spec/hermes/schema_spec.rb have that piece that let's us ensure developers don't forget to check-in the latest dump in the code:
describe Hermes::Schema do
it 'dumped schema should be up to date' do
actual_schema = GraphQL::Schema::Printer.print_schema(described_class)
dumped_schema = File.read(Rails.root.join("app/graph/schema.graphql"))
expect(actual_schema).to eq(dumped_schema), 'GraphQL Schema is out of date. Please run rake graphql:dump'
end
end
Thanks for sharing! I literally _just_ finished this post 馃槅 http://rmosolgo.github.io/blog/2017/03/16/tracking-schema-changes-with-graphql-ruby/ Nice to know it's been working well for you too, I hope we can have something built-in to make it even easier. (I'm hoping for breaking change detection, for example.)
Taking a crack at it here: https://github.com/rmosolgo/graphql-ruby/pull/687
Thanks again for sharing your solution, I took a page or two out of your book :)
Most helpful comment
Thanks for sharing! I literally _just_ finished this post 馃槅 http://rmosolgo.github.io/blog/2017/03/16/tracking-schema-changes-with-graphql-ruby/ Nice to know it's been working well for you too, I hope we can have something built-in to make it even easier. (I'm hoping for breaking change detection, for example.)