hey, can we define schema in `debug` source sets, ...
# apollo-kotlin
a
hey, can we define schema in
debug
source sets, and then consume it in
debug
directories only and have apollo generate debug only sources? use case we want to include mock schema in our app without needing to introspect a local mock server but want to ensure it doesnt leak into production
or in this case, would we then need to use the
Copy code
apollo {
  service("service") {
    outputDirConnection {
      connectToAndroidSourceSet("demoDebug")
    }
  }
}
m
I'm using per variant schema so per build type gotta be supported as well
a
so we’d need to utilize per variant schema here. ie. define one in release and one in debug
a
ah interesting. so we’d need to copy some portion of the schema over, whether all or some
m
You could have two completely different schemas, or extend a common one, depending on your needs
a
how do you extend a common one @Marco Pierucci?
found it. nvm!
createAllAndroidVariantServices
seems to do the trick.
m
createAllAndroidVariantServices
does work. Heads up it's running a different codegen instance for each of your variants.
I was actually thinking about deprecating this one, I'm not sure there's a good use case for it.
If your debug schema is a super set of your release schema (i.e. it's a newer version), you can do stuff like this:
Copy code
apollo {
  service("release") {
    schemaFile.set(releaseSchemaFile)
    srcDir(operationFiles)
    outputDirConnection {
      connectToAndroidSourceSet("release")
    }
  }
  service("debug") {
    schemaFile.set(debugSchemaFile)

    # Reuse the main source files
    srcDir(operationFiles)
    # And add some debug only
    srcDir(debugOnlyOperationFiles)

    outputDirConnection {
      connectToAndroidSourceSet("debug")
    }
  }
}
You could also have some release specific queries. You just have to make sure there's no overlap or D8 will complain
a
we also have another dimension of different services
meaning we have multiple services. so we’d want api1Debug and api1Release for example
what we want is:
Copy code
src / main / graphql
 -> api1
    -> schema.graphqls, operations.graphl, etc
  -> api2

src / debug / graphql
  -> api1
     -> mock_extra_schema.graphqls + schema.graphqls, operations.graphql, etc
with debug inheriting all of the stuff from api / main, including scalars etc. but providing extra schema and
extend type
on main schema for development ahead of production inclusion
how would we achieve extending it, with mechanism you mentioned above?
or does not it not work this way
m
Processing... 😅
with debug inheriting all of the stuff from api / main, including scalars etc. but providing extra schema and
extend type
on main schema for development ahead of production inclusion
Are your api1Debug and api1Release .graphql files the same or are they different too?
if you're using the same graphql files for debug and release, it's going to simplify things quite a bunch
a
we’d want consuming modules to only need
src/debug/graphql
if theyre using any operations or fields defined from the
src/debug/graphql
of the schema module
and the generated code to exist for those operations only debug source sets
m
Oh man, mutlimodule as well?
a
but anything in
main
generated for both debug and release (or just in normal output)
m
multi module, multi service, multi variant 😅
a
haha yeah!! our app no no joke 😆
i think i have an idea.
Copy code
api1
debugApi1 extends api1
releaseApi1 extends api1

api2
all as service configurations. where they inherit from base
api
or whatever
and then connect the debug and release ones using the
outputDirConnection
and they share same scalars, operations, and schema in main schema. but then can define /add their own. would that even work?
m
TBH that's quite the setup
Defining custom scalars in child modules might not work
You need a central schema module that has access to all the type definitions
a
yeah we’re doing that. 1 schema module with all scalars
in reality we only need debug specific stuff so its not leaking into release builds. but dont want to lose ability for shared fragments in our consuming modules that use debug only operations
m
our consuming modules that use debug only operations
that use debug only fragments, right?
You can't reuse operations
a
i think itll be ok if we connect the sources from the main service
so we’re developing new schema that is considered “mock” and not deployed to production. we want to use existing types and reusable fragments from those existing types. But we only want generation of those operations to exist in debug source sets
m
My canonical way to do this would be
Copy code
// schema/build.Gradle.kts
apollo {
  service("api1Release") {
    schemaFile.set(file("src/release/graphql/api1/schema.graphqls"))
    srcDir("src/main/graphql")
    outputDirConnection {
      connectToAndroidSourceSet("release")
    }
  }
  service("api1Debug") {
    schemaFiles.set(files("src/release/graphql/api1/schema.graphqls", "src/debug/graphql/api1/extra.graphqls"))

    srcDir("src/main/graphql")

    outputDirConnection {
      connectToAndroidSourceSet("debug")
    }
  }

  // Same for api2Release and api2Debug
}
But it's hard to tell without your complete setup, this stuff is complicated
a
ok ill try this. and see if it can get it working, and shoot back here with how I did it
thank you for the help!
m
Sure thing!
a
oh the file not found bug for apollo used coordinates surfaced
Copy code
build/generated/usedCoordinates/apollo/api1Debug/usedCoordinates.json (No such file or directory)
i think its fixed by gradle syncing + some gradle plugin improvements ive made to our superplugin
actually can repo now. if I use configuration cache, it looks for the file not found on used coordinates. ill post the error here in a sec. then if we need a ticket
Copy code
FAILURE: Build failed with an exception.

* What went wrong:
Configuration cache state could not be cached: field '__alwaysGenerateTypesMatching__' from type 'com.apollographql.apollo3.gradle.internal.ApolloGenerateSourcesTask': error writing value of type 'org.gradle.api.internal.provider.DefaultSetProperty'
> java.io.FileNotFoundException: /**/**-graphql/build/generated/usedCoordinates/apollo/api1Debug/usedCoordinates.json (No such file or directory)
Copy code
at okio.Okio__JvmOkioKt.source(JvmOkio.kt:182)
	at okio.Okio.source(Unknown Source)
	at com.apollographql.apollo3.compiler.ApolloUsedCoordinatesKt.toUsedCoordinates(ApolloUsedCoordinates.kt:25)
	at com.apollographql.apollo3.gradle.internal.DefaultApolloExtension$registerCodeGenTask$1.invoke$lambda$15(DefaultApolloExtension.kt:741)
	at org.gradle.api.internal.provider.DefaultProvider.calculateOwnValue(DefaultProvider.java:72)
m
What task name did you invoke for that Gradle run?
a
just trying to assemble our
app
m
assembleDebug
?
a
but it seems any invocation of
generateApolloSources
was doing it. we have that run prior to using our wrapper tasks
yeah
m
I would expect
assembleDebug
to run all the tasks so to populate the
usedCoordinates.json
all the time. Given that
Configuration cache state could not be cached
happens at the end of the build, it's weird that the json is not there
a
ill send a redacted log. its the beginning of the build right after configure step completes
m
ahhhh
Makes sense, at the end of the configuration step
not the end of the build...
a
redacted build log
yeah. we’re using
Copy code
add("apollo${service.capitalized()}DebugUsedCoordinatesConsumer", project)
    add("apollo${service.capitalized()}ReleaseUsedCoordinatesConsumer", project)
not the main
apolloUsedCoordinates
configurations
removing debug / release tags does not work.
Copy code
org.gradle.api.artifacts.UnknownConfigurationException: Configuration with name 'apolloApi1UsedCoordinatesConsumer' not found.
happens even if i switch all modules to using both api services and
apolloUsedCoordinates
configuration as expected, it still results in similiar configuration time error
m
This is on
3.7.4
, right?
It's a bit late for today but I'll try tomorrow see if I can reproduce
a
yeah on 3.7.4
no problem! our services are also connected to sourceset variants:
Copy code
service("api1Debug") {
  srcDir(...) // src/debug, src/main
  outputDirConnection {
    connectToKotlinSourceSet("debug")
  }
}
"api1Release" ^ same as above except release
"api2Debug"
"api2Release"
filed an issue to track here
m
Thanks!