GoogleCloudPlatform / gradle-appengine-plugin

Gradle plugin that provides tasks for uploading, running and managing Google App Engine projects
Apache License 2.0
236 stars 60 forks source link

project status image
NOTE: All App Engine users are encouraged to transition to the new gradle plugin for their projects. Android Studio users can migrate their projects using migration guide.

Google Cloud Platform Logo

Gradle App Engine plugin Build Status

The plugin provides tasks for uploading, downloading, running and managing Google App Engine (App Engine) projects in any given Gradle build.

Usage

To use the App Engine plugin, include in your build script:

apply plugin: 'appengine'

The plugin JAR needs to be defined in the classpath of your build script. It is directly available on Maven Central. Alternatively, you can download it from GitHub and deploy it to your local repository. The following code snippet shows an example on how to retrieve it from Maven Central:

buildscript {
  repositories {
    mavenCentral()
  }

  dependencies {
    classpath 'com.google.appengine:gradle-appengine-plugin:1.9.59'
  }
}

Note: The plugin requires you to set the environment variable APPENGINE_HOME or the system property appengine.sdk.root pointing to your current Google App Engine SDK installation. In case you have both variables set the system property takes precedence over the environment variable. Alternatively, you can choose to automatically download the SDK by setting the convention property downloadSdk to true. This option requires you to specify the SDK version you want to use by setting the configuration appengineSdk.

dependencies {
  appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.59'
}

Tasks

The App Engine plugin defines the following tasks:

Project layout

The App Engine plugin uses the same layout as the Gradle War plugin. The only difference is the addition of the functionalTest source set (located in src/functionalTest by default) which is used by the appengineFunctionalTest task.

Convention properties

The App Engine plugin defines the following convention properties in the appengine closure:

Within appengine you can define optional properties in a closure named appcfg:

Within appengine you can also define a closure named enhancer:

Within appengine you can also define a closure named endpoints:

The task appengineDownloadApp requires you to at least define the application ID and directory to write the files to. Define the tasks' properties in the closure app:

The task appengineLogs requires you to at least define the file to write the logs to. Define the tasks' properties in the closure logs:

The task appengineUpdate allows you to specify upload specific settings. Define the tasks' properties in the closure update:

Example

appengine {
  httpPort = 8085

  appcfg {
    email = 'benjamin.muschko@gmail.com'
      passIn = true

      logs {
        severity = 1
          outputFile = file('mylogs.txt')
      }

    app {
      id = 'sample-app'
    }
  }
}

FAQ

Can I use the plugin with a Gaelyk project?

Gaelyk's template project uses this plugin out-of-the-box so no additional configuration needs to be done. If you start your project from scratch and decide to use the plugin please refer to the following sections to configure it properly.

Gaelyk <= 1.1

Yes, you just have to configure the WAR plugin to point to the correct web application (by default war) and source code (by default src) directory. If you want to stick to the default source directory simply create the subdirectory src/main/groovy.

apply plugin: 'groovy'

sourceSets {
    main {
        groovy {
            srcDirs = ['src']
        }
    }
}

webAppDirName = file('war')

When editing a Groovlets/Groovy templates in Gaelyk the server automatically deploys the change and you see it take effect almost instantly. The plugin provides support for that. Simply set the warDir convention property and leave the server running.

appengine {
    warDir = file('war')
}

Gaelyk >= 1.2

Starting with version 1.2 Gaelyk adopted Gradle's default directory structure. The following changes are required to leverage Gaelyk's hot-reloading feature.

appengine {
    warDir = file('src/main/webapp')
}

sourceSets.main.output.classesDir = 'src/main/webapp/WEB-INF/classes'


How do I remote debug the local development server?

You can use the convention property jvmFlags to set the JVM debug parameters. Make sure to set the TCP port you want your JVM to listen on. The following example show how to set the JVM flags to listen on port 8000.

appengine {
    jvmFlags = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000']
}


How do I use OAuth2 passwordless login to authenticate?

You can configure your app to use OAuth2 with the option

appengine {
    appcfg {
        oauth2 = true
    }
}

For more details on the authentication flow see App Engine OAuth2 docs


How do I run functional tests on the local development server?

If you want to execute your tests in the container alongside the rest of your application you have to configure the appengineRun task to run in daemon mode. Starting with version 0.7 of the plugin this has become even easier. It provides the task appengineFunctionalTest which lets you define your functional test dependencies via the configuration functionalTestCompile. On top of that the task has been fully integrated into the build lifecycle.

One of the most prominent functional testing libraries in the Groovy ecosystem is Geb, an expressive and powerful browser automation solution. Please refer to this short and sweet tutorial for a quickstart.


Why is my exploded-war still using old discovery docs even though I ran appengineEndpointsGetDisoveryDocs?

The task appengineEndpointsGetDiscoveryDocs only downloads the Discovery Docs for an endpoint to a cache in build/discovery-docs, the war task copies this into the WEB-INF folder when packaging. If you want them to be copied in, just run build or appengineExplodeApp again. Why do we do this? The endpoints calls are network calls to a service and some users may not want to do this on every build. The user can update their endpoints discovery docs when they know they need to and it will be packaged in on every subsequent build without needing to be regenerated.


How do I use a compile dependency on my endpoints client libraries from another project?

Using the new configurations in the appengine plugin (endpoints/android-endpoints) you can do

 dependencies {
     compile project(path: '<appengine-module>', configuration: 'endpoints')
 }

or in an android project

dependencies {
    compile project(path: '<appengine-module>', configuration: 'android-endpoints')
}


Enhancer failed with "Java returned: 1", how do I know what's wrong?

Run using the --info flag when building to find the location of the error log file, that log file might have details on what went wrong. On linux machines it may appear as "/tmp/enhance(some number).log"


How do I deploy with gcloud?

If you're using gcloud to deploy your application, the newest version of app deploy doesn't support war directories, you will need to provide it with an app.yaml OR you can use the appengineStage task to create a directory that is deployable in <project>/build/staged-app

$ ./gradlew appengineStage
$ gcloud app deploy build/staged-app/app.yaml --project [app id] --version [some version]

NOTES:


How do I create client libraries for iOS?

You can generate a discovery document for your Api using the appengineEndpointsGetDiscoveryDocs task. Discovery documents can then be found in the <project>/build/discovery-docs directory. Follow the iOS endpoints instructions to create client libraries for your iOS application.