Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dariuszkuc committed Sep 21, 2022
0 parents commit e455810
Show file tree
Hide file tree
Showing 19 changed files with 809 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

# space indentation for JSON and YML
[*.{json,yml}]
indent_size = 2

# space indentation for Java
[*.{kt, kts}]
indent_size = 4
max_line_length = 200
63 changes: 63 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: PR Checks

on:
pull_request:
branches:
- main

jobs:
test:
name: Build and Test
runs-on: ubuntu-latest
timeout-minutes: 60
env:
SCHEMA_FILE: schema.graphql
SCHEMA_ARTIFACT: schema
outputs:
schema: ${{ env.SCHEMA_FILE }}
schema_artifact: ${{ env.SCHEMA_ARTIFACT }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Set up Java 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Execute Gradle build
run: ./gradlew check graphqlGenerateSDL
- name: Upload schema artifact
uses: actions/upload-artifact@v3
with:
path: build/${{ env.SCHEMA_FILE }}
name: ${{ env.SCHEMA_ARTIFACT }}

check_schema:
name: Check Schema with Apollo Studio
needs: [ test ]
runs-on: ubuntu-latest
timeout-minutes: 30
env:
APOLLO_KEY: ${{ secrets.APOLLO_KEY }}
APOLLO_GRAPH_REF: ${{ secrets.APOLLO_GRAPH_REF }}
# rename this to a valid subgraph name
SUBGRAPH_NAME: foo-bar
steps:
- uses: actions/download-artifact@v3
with:
name: ${{ needs.test.outputs.schema_artifact }}
- name: Install Rover
run: |
curl -sSL https://rover.apollo.dev/nix/latest | sh
echo "$HOME/.rover/bin" >> $GITHUB_PATH
- name: Schema Check
if: env.APOLLO_KEY != '' && env.APOLLO_GRAPH_REF != ''
run: rover subgraph check ${{ secrets.APOLLO_GRAPH_REF }} --schema ${{ needs.test.outputs.schema }} --name ${{ env.SUBGRAPH_NAME }}
- name: APOLLO_KEY is not set
if: env.APOLLO_KEY == ''
run: echo "::warning file=.github/workflows/checks.yaml,line=54,col=1,endColumn=1::No Apollo Studio Api Key is set in repository. Set this in the repository secrets under APOLLO_KEY"
- name: APOLLO_GRAPH_REF is not set
if: env.APOLLO_GRAPH_REF == ''
run: echo "::warning file=.github/workflows/checks.yaml,line=54,col=1,endColumn=1::No Apollo Studio Graph Name is set in repository. Set this in the repository secrets under APOLLO_GRAPH_REF"
76 changes: 76 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Deploy

on:
push:
branches:
- main
workflow_dispatch:

jobs:
build:
name: Build
runs-on: ubuntu-latest
timeout-minutes: 60
env:
SCHEMA_FILE: schema.graphql
SCHEMA_ARTIFACT: schema
outputs:
schema: ${{ env.SCHEMA_FILE }}
schema_artifact: ${{ env.SCHEMA_ARTIFACT }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Set up Java 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Execute Gradle build
run: ./gradlew clean build graphqlGenerateSDL
- name: Upload schema artifact
uses: actions/upload-artifact@v3
with:
path: build/${{ env.SCHEMA_FILE }}
name: ${{ env.SCHEMA_ARTIFACT }}

deploy:
name: Deploy Application
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Deploy
run: echo "::warning file=.github/workflows/deploy.yaml,line=43,endLine=44,title=No Deploy step defined::Define your custom workflow for deploying your subgraph here."

publish_schema:
name: Publish new schema to Apollo Studio
needs: [ deploy ]
env:
APOLLO_VCS_COMMIT: ${{ github.event.pull_request.head.sha }}
APOLLO_KEY: ${{ secrets.APOLLO_KEY }}
APOLLO_GRAPH_REF: ${{ secrets.APOLLO_GRAPH_REF }}
PRODUCTION_URL: ${{ secrets.PRODUCTION_URL }}
# rename this to a valid subgraph name
SUBGRAPH_NAME: foo-bar
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
name: ${{ needs.prepare_schema.outputs.schema_artifact }}
- name: Install Rover
run: |
curl -sSL https://rover.apollo.dev/nix/latest | sh
echo "$HOME/.rover/bin" >> $GITHUB_PATH
- name: Publish Schema
if: env.APOLLO_KEY != '' && env.APOLLO_GRAPH_REF != '' && env.PRODUCTION_URL != ''
run: rover subgraph publish ${{ secrets.APOLLO_GRAPH_REF }} --schema ${{ needs.prepare_schema.outputs.schema }} --name ${{ env.SUBGRAPH_NAME }} --routing-url ${{ secrets.PRODUCTION_URL }}
- name: APOLLO_KEY is not set
if: env.APOLLO_KEY == ''
run: echo "::warning file=.github/workflows/deploy.yaml,line=65,col=1,endColumn=1::No Apollo Studio Api Key is set in repository. Set this in the repository secrets under APOLLO_KEY"
- name: APOLLO_GRAPH_REF is not set
if: env.APOLLO_GRAPH_REF == ''
run: echo "::warning file=.github/workflows/deploy.yaml,line=65,col=1,endColumn=1::No Apollo Studio Graph Name is set in repository. Set this in the repository secrets under APOLLO_GRAPH_REF"
- name: PRODUCTION_URL is not set
if: env.PRODUCTION_URL == ''
run: echo "::warning file=.github/workflows/deploy.yaml,line=65,col=1,endColumn=1::No Production URL is set in repository. Set this in the repository secrets under PRODUCTION_URL"
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### VS Code ###
.vscode/
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Example Federated GraphQL Kotlin Subgraph

This is an example application template that can be used to create Federated GraphQL subgraph using [GraphQL Kotlin](https://github.com/ExpediaGroup/graphql-kotlin).

GraphQL Kotlin uses reflection API to generate schema directly from your source code. All public functions in classes
implementing `Query`/`Mutation` will be exposed as corresponding queries and mutations.

This example application implements following GraphQL schema:

```graphql
schema
@contact(description : "send urgent issues to [#oncall](https://yourteam.slack.com/archives/oncall).", name : "FooBar Server Team", url : "https://myteam.slack.com/archives/teams-chat-room-url")
@link(import : ["key"], url : "https://www.apollographql.com/docs/federation/federation-spec/") {
query: Query
}

type Foo @key(fields : "id", resolvable : true) {
id: ID!
name: String!
}

type Query {
foo(id: ID!): Foo
}
```

## Build

This project uses [Gradle](https://gradle.com/) and requires Java 17+ runtime. In order to build the project locally (which
will also execute all the tests), simply run the `build` task.

```shell
./gradlew build
```

> NOTE: in order to ensure you use the right version of Gradle we highly recommend to use the provided wrapper script
### Code Quality

Build is configured with [`detekt`](https://detekt.dev/) plugin that runs static code analysis and also [`JaCoCo`](https://www.eclemma.org/jacoco/)
plugin that measures the code coverage. Both plugins are configured to run as part of the build lifecycle and will generate
their reports under `build/reports`. You can invoke both plugins directly using their corresponding tasks.

```shell
./gradlew detekt
./gradlew jacocoTestReport
```

Example integration test is provided. It starts up the SpringBoot server and executes example queries against it.

```shell
./gradlew test
```

### Generating SDL

Build is configured to automatically generate SDL file upon completion. If you need to regenerate the file without running
whole build, you can run the `graphqlGenerateSDL` task directly.

```shell
./gradlew graphqlGenerateSDL
```

### Continuous Integration

This project comes with some example build actions that will trigger on PR requests and commits to the main branch.

## Run

To start the GraphQL server:

* Run `Application.kt` directly from your IDE
* Alternatively you can also run the Spring Boot plugin directly from the command line

```shell script
./gradlew bootRun
```

Once the app has started you can explore the example schema by opening the GraphQL Playground endpoint at http://localhost:8080/playground.

## Additional Resources

* [GraphQL Kotlin documentation](https://opensource.expediagroup.com/graphql-kotlin/)
* [Spring Boot documentation](https://docs.spring.io/spring-boot/docs/2.7.3/reference/htmlsingle/)
* [Gradle documentation](https://docs.gradle.org)


69 changes: 69 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateSDLTask
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateTestClientTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "2.7.3"
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"

// graphql plugins
id("com.expediagroup.graphql") version "6.2.5"

// code quality plugins
id("io.gitlab.arturbosch.detekt") version "1.21.0"
jacoco
}

group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

repositories {
mavenCentral()
}

dependencies {
implementation("com.expediagroup:graphql-kotlin-spring-server:6.2.5")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

testImplementation("com.expediagroup:graphql-kotlin-spring-client:6.2.5")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.3")

graphqlSDL("com.expediagroup:graphql-kotlin-federated-hooks-provider:6.2.5")
}

tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
withType<Test> {
dependsOn("graphqlGenerateTestClient") // test client is required for running tests
useJUnitPlatform()
}

named("build").configure {
dependsOn("graphqlGenerateSDL") // generate SDL file as part of the build lifecycle
}

test {
finalizedBy("jacocoTestReport") // report is always generated after tests run
}
jacocoTestReport {
dependsOn("test") // tests are required to run before generating the report
}
}

val graphqlGenerateSDL by tasks.getting(GraphQLGenerateSDLTask::class) {
packages.set(listOf("com.example.template"))
}
val graphqlGenerateTestClient by tasks.getting(GraphQLGenerateTestClientTask::class) {
packageName.set("com.example.template.generated")
schemaFile.set(graphqlGenerateSDL.schemaFile)
}
3 changes: 3 additions & 0 deletions detekt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build:
weights:
comments: 0 # missing comments should not fail the build
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit e455810

Please sign in to comment.