diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 1d8a5fa..8579f85 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -13,5 +13,6 @@ Alex Humesky Damien Martin-Guillerez David Chen Erik Kuefler +James O'Kane Kristina Chodorow Lukacs Berki diff --git a/README.md b/README.md index 3f2a1f1..dc9c4a5 100644 --- a/README.md +++ b/README.md @@ -24,36 +24,71 @@ support but can be easily modified to handle a standard web application. ## Setup -To be able to use the Java App Engine rules, you must make the App Engine SDK -available to Bazel. The easiest way to do so is by adding the following to your +To be able to use the rules, you must make the App Engine SDK available to +Bazel. The easiest way to do so is by adding the following to your `WORKSPACE` file: +Note: The `${LANG}_appengine_repository()` lines are only needed for the languages you plan to use. + ```python git_repository( name = "io_bazel_rules_appengine", remote = "https://github.com/bazelbuild/rules_appengine.git", # Check https://github.com/bazelbuild/rules_appengine/releases for the latest version. - tag = "0.0.4", + tag = "0.0.7", ) # Java -load("@io_bazel_rules_appengine//appengine:appengine.bzl", "appengine_repositories") -appengine_repositories() +load( + "@io_bazel_rules_appengine//appengine:java_appengine.bzl", + "java_appengine_repositories", +) + +java_appengine_repositories() + # Python -load("@io_bazel_rules_appengine//appengine:py_appengine.bzl", "py_appengine_repositories") +load( + "@io_bazel_rules_appengine//appengine:py_appengine.bzl", + "py_appengine_repositories", +) + py_appengine_repositories() ``` -The AppEngine rules download the AppEngine SDK, which is a few hundred megabytes -in size. To avoid downloading this multiple times for multiple projects or -inadvertently re-downloading it, you might want to add the following line to -your `$HOME/.bazelrc` file: +The App Engine rules download the App Engine SDK, which is a few hundred +megabytes in size. To avoid downloading this multiple times for multiple +projects or inadvertently re-downloading it, you might want to add the +following lines to your `$HOME/.bazelrc` file: ``` build --experimental_repository_cache=/home/user/.bazel/cache +fetch --experimental_repository_cache=/home/user/.bazel/cache +``` + +### Requesting a specific App Engine SDK + +All ${LANG}_appengine_repository macros accept optional arguments `version` +and `sha256`. + +```python +py_appengine_repositories( + version = '1.9.67', + sha256 = 'f9f45150643424cb164185d9134b86511c2bec3001499247ef9027f1605ef8a3', +) +``` + +### Using a predownloaded SDK version + +You can, optionally, specify the environment variable +`${LANG}_APPENGINE_SDK_PATH` to use an SDK that is unzipped on your filesystem +(instead of downloading a new one). + +``` +PY_APPENGINE_SDK_PATH=/path/to/google_appengine bazel build //whatever +JAVA_APPENGINE_SDK_PATH=/path/to/appengine-java-sdk-1.9.50 bazel build //whatever ``` -## Basic Example +## Basic Java Example Suppose you have the following directory structure for a simple App Engine application: @@ -77,7 +112,7 @@ application: Then, to build your webapp, your `hello_app/BUILD` can look like: ```python -load("@io_bazel_rules_appengine//appengine:appengine.bzl", "appengine_war") +load("@io_bazel_rules_appengine//appengine:java_appengine.bzl", "appengine_war") java_library( name = "mylib", @@ -100,7 +135,7 @@ For simplicity, you can use the `java_war` rule to build an app from source. Your `hello_app/BUILD` file would then look like: ```python -load("@io_bazel_rules_appengine//appengine:appengine.bzl", "java_war") +load("@io_bazel_rules_appengine//appengine:java_appengine.bzl", "java_war") java_war( name = "myapp", @@ -135,7 +170,7 @@ Another target `//hello_app:myapp.deploy` allows you to deploy your application to App Engine. It takes an optional argument: the `APP_ID`. If not specified, it uses the default `APP_ID` provided in the application. This target needs to open a browser to authenticate -with AppEngine, then have you copy-paste a "key" from the browser in +with App Engine, then have you copy-paste a "key" from the browser in the terminal. Since Bazel closes standard input, you can only input this by building the target and then running: @@ -148,14 +183,16 @@ App Engine so you can just do a normal `bazel run //hello_app:myapp.deploy -- APP_ID` to deploy next versions of your application. -*Note:* AppEngine uses Java 7. If you are using a more recent version of Java, +## Java specific details + +*Note:* App Engine uses Java 7. If you are using a more recent version of Java, you will get the following error message when you try to deploy: ``` java.lang.IllegalArgumentException: Class file is Java 8 but max supported is Java 7 ``` -To build with Java 7, use the toolchain bundled with these AppEngine rules: +To build with Java 7, use the toolchain bundled with these App Engine rules: ``` $ bazel build --java_toolchain=@io_bazel_rules_appengine//appengine:jdk7 //my-project @@ -292,6 +329,8 @@ java_war(name, data, data_path, **kwargs) +## Python specific details + ## py_appengine_binary ```python @@ -399,29 +438,3 @@ py_appengine_test(name, srcs, deps=[], data=[], libraries={}) - -## Using a local AppEngine SDK - -### Java - -If you already have a local copy of the AppEngine SDK, you can specify the path to -that in your WORKSPACE file (instead of Bazel downloading another copy): - -``` -load('@io_bazel_rules_appengine//appengine:appengine.bzl', 'APPENGINE_BUILD_FILE') -new_local_repository( - name = 'com_google_appengine_java', - path = '/path/to/appengine-java-sdk-version', - build_file_content = APPENGINE_BUILD_FILE, -) -``` - - -### Python - -You can, optionally, specify the environment variable PY_APPENGINE_SDK_PATH to use -an SDK that is on your filesystem (instead of downloading a new one). - -``` -PY_APPENGINE_SDK_PATH=/path/to/appengine-python-sdk-1.9.50 bazel build //whatever -``` diff --git a/WORKSPACE b/WORKSPACE index 9847985..69ffad7 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,4 +1,8 @@ workspace(name = "io_bazel_rules_appengine") -load("//appengine:appengine.bzl", "appengine_repositories") -appengine_repositories() +load("//appengine:java_appengine.bzl", "java_appengine_repositories") +load("//appengine:py_appengine.bzl", "py_appengine_repositories") + +java_appengine_repositories() + +py_appengine_repositories() diff --git a/appengine/BUILD b/appengine/BUILD index 0dbb26d..ba8dc73 100644 --- a/appengine/BUILD +++ b/appengine/BUILD @@ -3,19 +3,7 @@ java_library( name = "javax.servlet.api", neverlink = 1, visibility = ["//visibility:public"], - exports = ["@javax_servlet_api//jar:jar"], -) - -filegroup( - name = "runner_template", - srcs = ["appengine_runner.sh.template"], - visibility = ["//visibility:public"], -) - -filegroup( - name = "deploy_template", - srcs = ["appengine_deploy.sh.template"], - visibility = ["//visibility:public"], + exports = ["@javax_servlet_api//jar"], ) filegroup( diff --git a/appengine/appengine.bzl b/appengine/appengine.bzl index f17c12e..dd35d9f 100644 --- a/appengine/appengine.bzl +++ b/appengine/appengine.bzl @@ -11,310 +11,25 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Java AppEngine support for Bazel. - -For now, it only support bundling a WebApp and running locally. - -To create a WebApp for Google AppEngine, add the rules: -appengine_war( - name = "MyWebApp", - # Jars to use for the classpath in the webapp. - jars = ["//java/com/google/examples/mywebapp:java"], - # data to put in the webapp, the directory structure of the data set - # will be maintained. - data = ["//java/com/google/examples/mywebapp:data"], - # Data's root path, it will be considered as the root of the data files. - # If unspecified, the path to the current package will be used. The path is - # relative to current package or, relative to the workspace root if starting - # with a leading slash. - data_path = "/java/com/google/examples/mywebapp", -) - -To test locally: -bazel run :MyWebApp - -To deploy on Google app engine: -bazel run :MyWebApp.deploy - -You can also make directly a single target for it with: - -java_war( - name = "MyWebApp", - srcs = glob(["**/*.java"]), - resources = ["..."], - data = ["..."], - data_path = "...", -) - -Resources will be put in the classpath whereas data will be bundled at the root -of the war file. This is strictly equivalent to (it is actually a convenience -macros that translate to that): - -java_library( - name = "libMyWebApp", - srcs = glob(["**/*.java"]), - resources = ["..."], -) - -appengine_war( - name = "MyWebApp", - jars = [":libMyWebApp"], - data = ["..."], - data_path = "...", -) - -Finally, the appengine macro also create a .deploy target that will try to use the -AppEngine SDK to upload your application to AppEngine. It takes an optional argument: the -APP_ID. If not specified, it uses the default APP_ID provided in the application -web.xml. +""" +Use of this file is deprecated. Use the functions in java_appengine.bzl directly. """ -jar_filetype = FileType([".jar"]) - -def _add_file(in_file, output, path = None): - output_path = output - input_path = in_file.path - if path and in_file.short_path.startswith(path): - output_path += in_file.short_path[len(path):] - return [ - "mkdir -p $(dirname %s)" % output_path, - "test -L %s || ln -s $(pwd)/%s %s" % (output_path, input_path, output_path) - ] - -def _make_war(zipper, input_dir, output): - return [ - "(root=$(pwd);" + - ("cd %s &&" % input_dir) + - ("find . ! -type d > $root/file_list &&") + - ("${root}/%s Cc ${root}/%s @${root}/file_list)" % (zipper.path, output.path)) - ] - -def _common_substring(str1, str2): - i = 0 - res = "" - for c in str1: - if str2[i] != c: - return res - res += c - i += 1 - return res - -def _short_path_dirname(path): - sp = path.short_path - return sp[0:len(sp)-len(path.basename)-1] - -def _war_impl(ctxt): - """Implementation of the rule that creates - - the war - - the script to deploy - """ - zipper = ctxt.file._zipper - - data_path = ctxt.attr.data_path - if not data_path: - data_path = _short_path_dirname(ctxt.outputs.war) - elif data_path[0] == "/": - data_path = data_path[1:] - else: # relative path - data_path = _short_path_dirname(ctxt.outputs.war) + "/" + data_path - - war = ctxt.outputs.war - build_output = war.path + ".build_output" - cmd = [ - "set -e;rm -rf " + build_output, - "mkdir -p " + build_output - ] - - inputs = [zipper] - cmd += ["mkdir -p %s/WEB-INF/lib" % build_output] - - transitive_deps = depset() - for jar in ctxt.attr.jars: - if hasattr(jar, "java"): # java_library, java_import - transitive_deps += jar.java.transitive_runtime_deps - elif hasattr(jar, "files"): # a jar file - transitive_deps += jar.files - - for dep in transitive_deps: - cmd += _add_file(dep, build_output + "/WEB-INF/lib") - inputs.append(dep) - - for jar in ctxt.files._appengine_deps: - cmd += _add_file(jar, build_output + "/WEB-INF/lib") - inputs.append(jar) - - inputs += ctxt.files.data - for res in ctxt.files.data: - # Add the data file - cmd += _add_file(res, build_output, path = data_path) - - cmd += _make_war(zipper, build_output, war) - - ctxt.action( - inputs = inputs, - outputs = [war], - mnemonic="WAR", - command="\n".join(cmd), - use_default_shell_env=True) - - executable = ctxt.outputs.executable - appengine_sdk = None - for f in ctxt.files._appengine_sdk: - if not appengine_sdk: - appengine_sdk = f.short_path - elif not f.path.startswith(appengine_sdk): - appengine_sdk = _common_substring(appengine_sdk, f.short_path) - if not appengine_sdk: - fail("could not find appengine files", - attr = str(ctxt.attr._appengine_sdk.label)) - - classpath = ["${JAVA_RUNFILES}/%s" % jar.short_path for jar in transitive_deps] - classpath += [ - "${JAVA_RUNFILES}/%s" % jar.short_path - for jar in ctxt.files._appengine_deps - ] - - substitutions = { - "%{workspace_name}" : ctxt.workspace_name, - "%{zipper}": ctxt.file._zipper.short_path, - "%{war}": ctxt.outputs.war.short_path, - "%{java}": ctxt.file._java.short_path, - "%{appengine_sdk}": appengine_sdk, - "%{classpath}": (":".join(classpath)), - "%{data_path}": data_path - } - - ctxt.template_action( - output = executable, - template = ctxt.file._runner_template, - substitutions = substitutions, - executable = True) - ctxt.template_action( - output = ctxt.outputs.deploy_sh, - template = ctxt.file._deploy_template, - substitutions = substitutions) - - runfiles = ctxt.runfiles(files = [war, executable] - + list(transitive_deps) - + inputs - + ctxt.files._appengine_sdk - + [ctxt.file._java, ctxt.file._zipper]) - return struct(runfiles = runfiles) - -appengine_war_base = rule( - _war_impl, - attrs = { - "_java": attr.label( - default = Label("@bazel_tools//tools/jdk:java"), - single_file = True, - ), - "_zipper": attr.label( - default = Label("@bazel_tools//tools/zip:zipper"), - single_file = True, - ), - "_runner_template": attr.label( - default = Label("//appengine:runner_template"), - single_file = True, - ), - "_deploy_template": attr.label( - default = Label("//appengine:deploy_template"), - single_file = True, - ), - "_appengine_sdk": attr.label( - default = Label("@com_google_appengine_java//:sdk"), - ), - "_appengine_deps": attr.label_list( - default = [Label("@com_google_appengine_java//:api")], - ), - "jars": attr.label_list( - allow_files = jar_filetype, - mandatory = True, - ), - "data": attr.label_list(allow_files = True), - "data_path": attr.string(), - }, - executable = True, - outputs = { - "war": "%{name}.war", - "deploy_sh": "%{name}_deploy.sh", - }, -) - -def java_war(name, data=[], data_path=None, **kwargs): - """Convenience macro to call appengine_war with Java sources rather than jar. - """ - native.java_library(name = "lib%s" % name, **kwargs) - appengine_war(name = name, - jars = ["lib%s" % name], - data=data, - data_path=data_path) - -def appengine_war(name, jars, data, data_path, testonly = 0): - """Convenience macro that builds the war and offers an executable - target to deploy on Google app engine. - """ - appengine_war_base( - name = name, - jars = jars, - data = data, - data_path = data_path, - testonly = testonly, - ) - # Create the executable rule to deploy - native.sh_binary( - name = "%s.deploy" % name, - srcs = ["%s_deploy.sh" % name], - data = [name], - testonly = testonly, - ) - - -APPENGINE_VERSION = "1.9.57" - -APPENGINE_DIR = "appengine-java-sdk-" + APPENGINE_VERSION - -APPENGINE_BUILD_FILE = """ -# BUILD file to use the Java AppEngine SDK with a remote repository. -java_import( - name = "jars", - jars = glob(["lib/**/*.jar"]), - visibility = ["//visibility:public"], +load( + ":java_appengine.bzl", + _appengine_war = "appengine_war", + _appengine_war_base = "appengine_war_base", + _jar_filetype = "jar_filetype", + _java_appengine_repositories = "java_appengine_repositories", + _java_war = "java_war", ) -java_import( - name = "user", - jars = glob(["lib/user/*.jar"]), - visibility = ["//visibility:public"], -) +appengine_war = _appengine_war -java_import( - name = "api", - jars = [ - "lib/agent/appengine-agent.jar", - "lib/appengine-tools-api.jar", - "lib/impl/appengine-api.jar", - ], - visibility = ["//visibility:public"], - neverlink = 1, -) +appengine_war_base = _appengine_war_base -filegroup( - name = "sdk", - srcs = glob(["**"]), - visibility = ["//visibility:public"], -) -""" +jar_filetype = _jar_filetype -def appengine_repositories(): - native.new_http_archive( - name = "com_google_appengine_java", - url = "http://central.maven.org/maven2/com/google/appengine/appengine-java-sdk/%s/%s.zip" % (APPENGINE_VERSION, APPENGINE_DIR), - sha256 = "63f89be498d1e7462c03fe2b66d7773a9e5dd04ffb71e3b59a5fa74a7b810997", - build_file_content = APPENGINE_BUILD_FILE, - strip_prefix = APPENGINE_DIR, - ) +java_appengine_repositories = _java_appengine_repositories - native.maven_jar( - name = "javax_servlet_api", - artifact = "javax.servlet:servlet-api:2.5", - ) +java_war = _java_war diff --git a/appengine/java/BUILD b/appengine/java/BUILD new file mode 100644 index 0000000..223ce5f --- /dev/null +++ b/appengine/java/BUILD @@ -0,0 +1,17 @@ +filegroup( + name = "runner_template", + srcs = ["appengine_runner.sh.template"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "deploy_template", + srcs = ["appengine_deploy.sh.template"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "sdk_build_file", + srcs = ["sdk.BUILD"], + visibility = ["//visibility:public"], +) diff --git a/appengine/appengine_deploy.sh.template b/appengine/java/appengine_deploy.sh.template similarity index 100% rename from appengine/appengine_deploy.sh.template rename to appengine/java/appengine_deploy.sh.template diff --git a/appengine/appengine_runner.sh.template b/appengine/java/appengine_runner.sh.template similarity index 99% rename from appengine/appengine_runner.sh.template rename to appengine/java/appengine_runner.sh.template index 4f796f5..787f609 100644 --- a/appengine/appengine_runner.sh.template +++ b/appengine/java/appengine_runner.sh.template @@ -78,6 +78,7 @@ ARGS=( "${JVM_FLAGS_CMDLINE[@]}" "-Dappengine.sdk.root=${APP_ENGINE_ROOT}" ${main_class} + "--disable_update_check" "${ARGS[@]}" . ) diff --git a/appengine/java/sdk.BUILD b/appengine/java/sdk.BUILD new file mode 100644 index 0000000..1b89dc6 --- /dev/null +++ b/appengine/java/sdk.BUILD @@ -0,0 +1,29 @@ +# BUILD file to use the Java AppEngine SDK with a remote repository. +java_import( + name = "jars", + jars = glob(["lib/**/*.jar"]), + visibility = ["//visibility:public"], +) + +java_import( + name = "user", + jars = glob(["lib/user/*.jar"]), + visibility = ["//visibility:public"], +) + +java_import( + name = "api", + jars = [ + "lib/agent/appengine-agent.jar", + "lib/appengine-tools-api.jar", + "lib/impl/appengine-api.jar", + ], + neverlink = 1, + visibility = ["//visibility:public"], +) + +filegroup( + name = "sdk", + srcs = glob(["**"]), + visibility = ["//visibility:public"], +) diff --git a/appengine/java_appengine.bzl b/appengine/java_appengine.bzl new file mode 100644 index 0000000..d749c16 --- /dev/null +++ b/appengine/java_appengine.bzl @@ -0,0 +1,289 @@ +# Copyright 2015 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Java AppEngine support for Bazel. + +For now, it only support bundling a WebApp and running locally. + +To create a WebApp for Google AppEngine, add the rules: +appengine_war( + name = "MyWebApp", + # Jars to use for the classpath in the webapp. + jars = ["//java/com/google/examples/mywebapp:java"], + # data to put in the webapp, the directory structure of the data set + # will be maintained. + data = ["//java/com/google/examples/mywebapp:data"], + # Data's root path, it will be considered as the root of the data files. + # If unspecified, the path to the current package will be used. The path is + # relative to current package or, relative to the workspace root if starting + # with a leading slash. + data_path = "/java/com/google/examples/mywebapp", +) + +To test locally: +bazel run :MyWebApp + +To deploy on Google app engine: +bazel run :MyWebApp.deploy + +You can also make directly a single target for it with: + +java_war( + name = "MyWebApp", + srcs = glob(["**/*.java"]), + resources = ["..."], + data = ["..."], + data_path = "...", +) + +Resources will be put in the classpath whereas data will be bundled at the root +of the war file. This is strictly equivalent to (it is actually a convenience +macros that translate to that): + +java_library( + name = "libMyWebApp", + srcs = glob(["**/*.java"]), + resources = ["..."], +) + +appengine_war( + name = "MyWebApp", + jars = [":libMyWebApp"], + data = ["..."], + data_path = "...", +) + +Finally, the appengine macro also create a .deploy target that will try to use the +AppEngine SDK to upload your application to AppEngine. It takes an optional argument: the +APP_ID. If not specified, it uses the default APP_ID provided in the application +web.xml. +""" + +load(":variables.bzl", "JAVA_SDK_VERSION", "JAVA_SDK_SHA256") +load(":sdk.bzl", "find_locally_or_download") + +jar_filetype = FileType([".jar"]) + +def _add_file(in_file, output, path = None): + output_path = output + input_path = in_file.path + if path and in_file.short_path.startswith(path): + output_path += in_file.short_path[len(path):] + return [ + "mkdir -p $(dirname %s)" % output_path, + "test -L %s || ln -s $(pwd)/%s %s" % (output_path, input_path, output_path) + ] + +def _make_war(zipper, input_dir, output): + return [ + "(root=$(pwd);" + + ("cd %s &&" % input_dir) + + ("find . ! -type d > $root/file_list &&") + + ("${root}/%s Cc ${root}/%s @${root}/file_list)" % (zipper.path, output.path)) + ] + +def _common_substring(str1, str2): + i = 0 + res = "" + for c in str1: + if str2[i] != c: + return res + res += c + i += 1 + return res + +def _short_path_dirname(path): + sp = path.short_path + return sp[0:len(sp)-len(path.basename)-1] + +def _war_impl(ctxt): + """Implementation of the rule that creates + - the war + - the script to deploy + """ + zipper = ctxt.file._zipper + + data_path = ctxt.attr.data_path + if not data_path: + data_path = _short_path_dirname(ctxt.outputs.war) + elif data_path[0] == "/": + data_path = data_path[1:] + else: # relative path + data_path = _short_path_dirname(ctxt.outputs.war) + "/" + data_path + + war = ctxt.outputs.war + build_output = war.path + ".build_output" + cmd = [ + "set -e;rm -rf " + build_output, + "mkdir -p " + build_output + ] + + inputs = [zipper] + cmd += ["mkdir -p %s/WEB-INF/lib" % build_output] + + transitive_deps = depset() + for jar in ctxt.attr.jars: + if hasattr(jar, "java"): # java_library, java_import + transitive_deps += jar.java.transitive_runtime_deps + elif hasattr(jar, "files"): # a jar file + transitive_deps += jar.files + + for dep in transitive_deps: + cmd += _add_file(dep, build_output + "/WEB-INF/lib") + inputs.append(dep) + + for jar in ctxt.files._appengine_deps: + cmd += _add_file(jar, build_output + "/WEB-INF/lib") + inputs.append(jar) + + inputs += ctxt.files.data + for res in ctxt.files.data: + # Add the data file + cmd += _add_file(res, build_output, path = data_path) + + cmd += _make_war(zipper, build_output, war) + + ctxt.action( + inputs = inputs, + outputs = [war], + mnemonic="WAR", + command="\n".join(cmd), + use_default_shell_env=True) + + executable = ctxt.outputs.executable + appengine_sdk = None + for f in ctxt.files._appengine_sdk: + if not appengine_sdk: + appengine_sdk = f.short_path + elif not f.path.startswith(appengine_sdk): + appengine_sdk = _common_substring(appengine_sdk, f.short_path) + if not appengine_sdk: + fail("could not find appengine files", + attr = str(ctxt.attr._appengine_sdk.label)) + + classpath = ["${JAVA_RUNFILES}/%s" % jar.short_path for jar in transitive_deps] + classpath += [ + "${JAVA_RUNFILES}/%s" % jar.short_path + for jar in ctxt.files._appengine_deps + ] + + substitutions = { + "%{workspace_name}" : ctxt.workspace_name, + "%{zipper}": ctxt.file._zipper.short_path, + "%{war}": ctxt.outputs.war.short_path, + "%{java}": ctxt.file._java.short_path, + "%{appengine_sdk}": appengine_sdk, + "%{classpath}": (":".join(classpath)), + "%{data_path}": data_path + } + + ctxt.actions.expand_template( + output = executable, + template = ctxt.file._runner_template, + substitutions = substitutions, + is_executable = True) + ctxt.actions.expand_template( + output = ctxt.outputs.deploy_sh, + template = ctxt.file._deploy_template, + substitutions = substitutions, + is_executable = True) + + runfiles = ctxt.runfiles(files = [war, executable] + + list(transitive_deps) + + inputs + + ctxt.files._appengine_sdk + + [ctxt.file._java, ctxt.file._zipper]) + return struct(runfiles = runfiles) + +appengine_war_base = rule( + _war_impl, + attrs = { + "_java": attr.label( + default = Label("@bazel_tools//tools/jdk:java"), + single_file = True, + ), + "_zipper": attr.label( + default = Label("@bazel_tools//tools/zip:zipper"), + single_file = True, + ), + "_runner_template": attr.label( + default = Label("//appengine/java:runner_template"), + single_file = True, + ), + "_deploy_template": attr.label( + default = Label("//appengine/java:deploy_template"), + single_file = True, + ), + "_appengine_sdk": attr.label( + default = Label("@com_google_appengine_java//:sdk"), + ), + "_appengine_deps": attr.label_list( + default = [Label("@com_google_appengine_java//:api")], + ), + "jars": attr.label_list( + allow_files = jar_filetype, + mandatory = True, + ), + "data": attr.label_list(allow_files = True), + "data_path": attr.string(), + }, + executable = True, + outputs = { + "war": "%{name}.war", + "deploy_sh": "%{name}_deploy.sh", + }, +) + +def java_war(name, data=[], data_path=None, **kwargs): + """Convenience macro to call appengine_war with Java sources rather than jar. + """ + native.java_library(name = "lib%s" % name, **kwargs) + appengine_war(name = name, + jars = ["lib%s" % name], + data=data, + data_path=data_path) + +def appengine_war(name, jars, data, data_path, testonly = 0): + """Convenience macro that builds the war and offers an executable + target to deploy on Google app engine. + """ + appengine_war_base( + name = name, + jars = jars, + data = data, + data_path = data_path, + testonly = testonly, + ) + # Create the executable rule to deploy + native.sh_binary( + name = "%s.deploy" % name, + srcs = ["%s_deploy.sh" % name], + data = [name], + testonly = testonly, + ) + +def java_appengine_repositories(version=JAVA_SDK_VERSION, + sha256=JAVA_SDK_SHA256): + find_locally_or_download( + name = "com_google_appengine_java", + lang = "java", + sha256 = sha256, + version = version, + filename_pattern = "appengine-java-sdk-{version}.zip", + strip_prefix_pattern = "appengine-java-sdk-{version}", + ) + + native.maven_jar( + name = "javax_servlet_api", + artifact = "javax.servlet:servlet-api:2.5", + ) diff --git a/appengine/py/BUILD b/appengine/py/BUILD new file mode 100644 index 0000000..223ce5f --- /dev/null +++ b/appengine/py/BUILD @@ -0,0 +1,17 @@ +filegroup( + name = "runner_template", + srcs = ["appengine_runner.sh.template"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "deploy_template", + srcs = ["appengine_deploy.sh.template"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "sdk_build_file", + srcs = ["sdk.BUILD"], + visibility = ["//visibility:public"], +) diff --git a/appengine/py/appengine_deploy.sh.template b/appengine/py/appengine_deploy.sh.template new file mode 100644 index 0000000..5cd3ed7 --- /dev/null +++ b/appengine/py/appengine_deploy.sh.template @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +case "$0" in +/*) self="$0" ;; +*) self="$PWD/$0";; +esac +if [[ -e "$self.runfiles/%{workspace_name}" ]]; then + RUNFILES="$self.runfiles/%{workspace_name}" + cd $RUNFILES +fi + +ROOT=$PWD +tmp_dir=$(mktemp -d ${{TMPDIR:-/tmp}}/war.XXXXXXXX) +cp -R $ROOT $tmp_dir +trap "{{ cd ${{root_path}}; rm -rf $tmp_dir; }}" EXIT +rm -Rf $tmp_dir/%{workspace_name}/external/com_google_appengine_py +if [ -n "${{1-}}" ]; then + has_app_yaml=$(echo ${{@:2}} | grep -E "^([^ ]+ +)*app.yaml") + other_mod_cfgs=$(echo ${{@:2}} | xargs printf "%s\n" | grep -v "^app\.yaml$" | xargs echo) + ret_code=0 + # Secondary modules need to be uploaded first because if any of them are + # referenced in dispatch.yaml, App Engine must have a version of that module + # prior to the app.yaml upload. + if [ -n "$other_mod_cfgs" ]; then + (cd $tmp_dir/%{workspace_name} && $ROOT/%{appcfg} -A "$1" update $other_mod_cfgs) + ret_code=$? + fi + if [ $ret_code -eq 0 ] && [ -n "$has_app_yaml" ] || [ -z "$other_mod_cfgs" ]; then + $ROOT/%{appcfg} -A "$1" update $tmp_dir/%{workspace_name} + ret_code=$? + fi + +else + echo "\033[1;31mERROR:\033[0m Application ID must be provided as first argument + USAGE: bazel run path/to/my/gae_binary_target.deploy -- my-project-id [module.yaml files ...]" + ret_code=-1 +fi + +rm -Rf $tmp_dir +trap - EXIT + +exit $ret_code diff --git a/appengine/py/appengine_runner.sh.template b/appengine/py/appengine_runner.sh.template new file mode 100644 index 0000000..14014f6 --- /dev/null +++ b/appengine/py/appengine_runner.sh.template @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +case "$0" in +/*) self="$0" ;; +*) self="$PWD/$0";; +esac +if [[ -e "$self.runfiles/%{workspace_name}" ]]; then + RUNFILES="$self.runfiles/%{workspace_name}" + cd $RUNFILES +fi + +%{devappserver} --skip_sdk_update_check 1 app.yaml diff --git a/appengine/pysdk.BUILD b/appengine/py/sdk.BUILD similarity index 97% rename from appengine/pysdk.BUILD rename to appengine/py/sdk.BUILD index 3bdef5f..d94c7b0 100755 --- a/appengine/pysdk.BUILD +++ b/appengine/py/sdk.BUILD @@ -18,7 +18,10 @@ package(default_visibility = ["//visibility:public"]) py_library( name = "appengine", srcs = glob(["**/*.py"]), - data = glob(["**/*"], exclude=["**/*.py"]), + data = glob( + ["**/*"], + exclude = ["**/*.py"], + ), ) py_binary( @@ -91,8 +94,8 @@ py_library( py_library( name = "webapp2-2.5.2", srcs = glob(["lib/webapp2-2.5.2/**/*.py"]), - deps = [":webob-1.2.3"], imports = ["lib/webapp2-2.5.2"], + deps = [":webob-1.2.3"], ) py_library( @@ -113,7 +116,6 @@ py_library( imports = ["lib/yaml-3.10"], ) - py_library( name = "endpoints-latest", deps = [":endpoints-1.0"], diff --git a/appengine/py_appengine.bzl b/appengine/py_appengine.bzl index 216fb3a..04c1a1c 100644 --- a/appengine/py_appengine.bzl +++ b/appengine/py_appengine.bzl @@ -43,45 +43,33 @@ project ID as the first argument and takes 0 or more module YAML files. If no YAML files are specified, only "app.yaml", the main module, will be deployed. """ -def _find_locally_or_download_impl(repository_ctx): - if 'PY_APPENGINE_SDK_PATH' in repository_ctx.os.environ: - path = repository_ctx.os.environ['PY_APPENGINE_SDK_PATH'] - if path == "": - fail("PY_APPENGINE_SDK_PATH set, but empty") - repository_ctx.symlink(path, ".") - else: - repository_ctx.download_and_extract( - url="https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.61.zip", - output=".", - sha256="65f2092e671ae80b316ac8f70b14df687f91959cc8926bd4eb4c26b780ea0af5", - stripPrefix="google_appengine") - repository_ctx.template("BUILD", Label("//appengine:pysdk.BUILD")) - - -_find_locally_or_download = repository_rule( - local = False, - implementation = _find_locally_or_download_impl, -) - - -def py_appengine_repositories(): - _find_locally_or_download(name = "com_google_appengine_python") - +load(":variables.bzl", "PY_SDK_VERSION", "PY_SDK_SHA256") +load(":sdk.bzl", "find_locally_or_download") + +def py_appengine_repositories(version=PY_SDK_VERSION, + sha256=PY_SDK_SHA256): + find_locally_or_download( + name = "com_google_appengine_py", + lang = 'py', + sha256 = sha256, + version = version, + filename_pattern = "google_appengine_{version}.zip", + strip_prefix_pattern = "google_appengine", + ) def py_appengine_test(name, srcs, deps=[], data=[], libraries={}, size=None): """A variant of py_test that sets up an App Engine environment.""" - extra_deps = ["@com_google_appengine_python//:appengine"] + extra_deps = ["@com_google_appengine_py//:appengine"] for l in libraries: - extra_deps.append("@com_google_appengine_python//:{0}-{1}".format(l, libraries[l])) + extra_deps.append("@com_google_appengine_py//:{0}-{1}".format(l, libraries[l])) native.py_test( - name=name, - deps=deps + extra_deps, - srcs=srcs, - data=data, - size=size, + name = name, + deps = deps + extra_deps, + srcs = srcs, + data = data, + size = size, ) - def _py_appengine_binary_base_impl(ctx): """Implementation of the rule that creates - the script to run locally @@ -131,84 +119,45 @@ sys.path.extend([d for d in repo_dirs if os.path.isdir(d)]) symlinks=symlinks, ).merge(ctx.attr.binary.data_runfiles).merge(ctx.attr.appcfg.data_runfiles) - ctx.actions.write( - output=ctx.outputs.executable, - content=""" -#!/bin/bash - -case "$0" in -/*) self="$0" ;; -*) self="$PWD/$0";; -esac -if [[ -e "$self.runfiles/{1}" ]]; then - RUNFILES="$self.runfiles/{1}" - cd $RUNFILES -fi - -{0} --skip_sdk_update_check 1 app.yaml -""".format(ctx.attr.devappserver.files_to_run.executable.short_path, ctx.workspace_name), - is_executable=True, - ) + substitutions = { + "%{appcfg}": ctx.attr.appcfg.files_to_run.executable.short_path, + "%{devappserver}": + ctx.attr.devappserver.files_to_run.executable.short_path, + "%{workspace_name}": ctx.workspace_name, + } - ctx.actions.write( - output=ctx.outputs.deploy_sh, - content=""" -#!/bin/bash - -case "$0" in -/*) self="$0" ;; -*) self="$PWD/$0";; -esac -if [[ -e "$self.runfiles/{1}" ]]; then - RUNFILES="$self.runfiles/{1}" - cd $RUNFILES -fi - -ROOT=$PWD -tmp_dir=$(mktemp -d ${{TMPDIR:-/tmp}}/war.XXXXXXXX) -cp -R $ROOT $tmp_dir -trap "{{ cd ${{root_path}}; rm -rf $tmp_dir; }}" EXIT -rm -Rf $tmp_dir/{1}/external/com_google_appengine_python -if [ -n "${{1-}}" ]; then - has_app_yaml=$(echo ${{@:2}} | grep -E "^([^ ]+ +)*app.yaml") - other_mod_cfgs=$(echo ${{@:2}} | xargs printf "%s\n" | grep -v "^app\.yaml$" | xargs echo) - ret_code=0 - # Secondary modules need to be uploaded first because if any of them are - # referenced in dispatch.yaml, App Engine must have a version of that module - # prior to the app.yaml upload. - if [ -n "$other_mod_cfgs" ]; then - (cd $tmp_dir/{1} && $ROOT/{0} -A "$1" update $other_mod_cfgs) - ret_code=$? - fi - if [ $ret_code -eq 0 ] && [ -n "$has_app_yaml" ] || [ -z "$other_mod_cfgs" ]; then - $ROOT/{0} -A "$1" update $tmp_dir/{1} - ret_code=$? - fi - -else - echo "\033[1;31mERROR:\033[0m Application ID must be provided as first argument - USAGE: bazel run path/to/my/gae_binary_target.deploy -- my-project-id [module.yaml files ...]" - ret_code=-1 -fi - -rm -Rf $tmp_dir -trap - EXIT - -exit $ret_code -""".format(ctx.attr.appcfg.files_to_run.executable.short_path, ctx.workspace_name), - is_executable=True, - ) + ctx.actions.expand_template( + output = ctx.outputs.executable, + template = ctx.file._runner_template, + substitutions = substitutions, + is_executable = True) - return struct(runfiles=runfiles, py=ctx.attr.binary.py) + ctx.actions.expand_template( + output = ctx.outputs.deploy_sh, + template = ctx.file._deploy_template, + substitutions = substitutions, + is_executable = True) + return struct(runfiles=runfiles, py=ctx.attr.binary.py) py_appengine_binary_base = rule( _py_appengine_binary_base_impl, attrs = { "binary": attr.label(), - "devappserver": attr.label(default=Label("@com_google_appengine_python//:dev_appserver")), - "appcfg": attr.label(default=Label("@com_google_appengine_python//:appcfg")), - "configs": attr.label_list(allow_files=FileType([".yaml", ".py"])), + "devappserver": attr.label(default = Label("@com_google_appengine_py//:dev_appserver")), + "appcfg": attr.label(default = Label("@com_google_appengine_py//:appcfg")), + "configs": attr.label_list(allow_files = FileType([ + ".yaml", + ".py", + ])), + "_deploy_template": attr.label( + default = Label("//appengine/py:deploy_template"), + single_file = True, + ), + "_runner_template": attr.label( + default = Label("//appengine/py:runner_template"), + single_file = True, + ), }, executable = True, outputs = { @@ -216,7 +165,6 @@ py_appengine_binary_base = rule( }, ) - def py_appengine_binary(name, srcs, configs, deps=[], data=[]): """Convenience macro that builds the app and offers an executable target to deploy on Google app engine. @@ -225,10 +173,11 @@ def py_appengine_binary(name, srcs, configs, deps=[], data=[]): fail("srcs should not be empty.") # uses py_binary because it generates __init__.py files native.py_binary( - name="_py_appengine_" + name, + name = "_py_appengine_" + name, srcs = srcs, - deps=deps, - main=srcs[0], # no entry point, use arbitrary source file + deps = deps, + data = data, + main = srcs[0], # no entry point, use arbitrary source file ) py_appengine_binary_base( name=name, diff --git a/appengine/sdk.bzl b/appengine/sdk.bzl new file mode 100644 index 0000000..08d2aa9 --- /dev/null +++ b/appengine/sdk.bzl @@ -0,0 +1,70 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Language agnostic utility functions for use in the other .bzl files. +""" + +load(":variables.bzl", "SDK_URL_PREFIX") + +def _find_locally_or_download_impl(repository_ctx): + lang = repository_ctx.attr.lang + env_var = lang.upper() + "_APPENGINE_SDK_PATH" + if env_var in repository_ctx.os.environ: + path = repository_ctx.os.environ[env_var] + if path == "": + fail(env_var + " set, but empty") + repository_ctx.symlink(path, ".") + else: + substitutions = { + 'version': repository_ctx.attr.version, + } + repository_ctx.download_and_extract( + url="{}/{}".format( + SDK_URL_PREFIX, + repository_ctx.attr.filename_pattern.format(**substitutions)), + output=".", + sha256=repository_ctx.attr.sha256, + stripPrefix=repository_ctx.attr.strip_prefix_pattern.format( + **substitutions)) + repository_ctx.template( + "BUILD", Label("//appengine:{}/sdk.BUILD".format(lang.lower()))) + +find_locally_or_download = repository_rule( + attrs = { + "lang": attr.string( + mandatory = True, + doc = "The language of the SDK to download.", + values = ["java", "py"], + ), + "sha256": attr.string( + mandatory = True, + doc = "The sha256sum of the sdk zip file.", + ), + "version": attr.string( + mandatory = True, + doc = "The SDK version to download. Usually of the form 1.9.57.", + ), + "strip_prefix_pattern": attr.string( + default = "google_appengine", + mandatory = True, + doc = "When the zip file is extracted, remove this prefix from all paths. If it includes '{version}', it will be replaced with the version.", + ), + "filename_pattern": attr.string( + default = "google_appengine_{version}.zip", + mandatory = True, + doc = "The filename of the SDK zip file to download. If it includes '{version}', it will be replaced with the version.", + ), + }, + local = False, + implementation = _find_locally_or_download_impl, +) diff --git a/appengine/variables.bzl b/appengine/variables.bzl new file mode 100644 index 0000000..bee09e7 --- /dev/null +++ b/appengine/variables.bzl @@ -0,0 +1,15 @@ +"""This file is a central location for configuring new SDK versions. +""" +# Not all languages are released for every SDK version. Whenever possible, set +# ${LANG}_SDK_VERSION = APPENGINE_VERSION. +APPENGINE_VERSION = "1.9.57" + +SDK_URL_PREFIX = "https://storage.googleapis.com/appengine-sdks/featured" + +JAVA_SDK_SHA256 = "63f89be498d1e7462c03fe2b66d7773a9e5dd04ffb71e3b59a5fa74a7b810997" + +JAVA_SDK_VERSION = APPENGINE_VERSION + +PY_SDK_SHA256 = "d5c4fad8afa2ce9005481575c01558248a0fbe0b4554c6de060e925899cfbf66" + +PY_SDK_VERSION = APPENGINE_VERSION diff --git a/examples/BUILD b/examples/BUILD deleted file mode 100644 index a926e49..0000000 --- a/examples/BUILD +++ /dev/null @@ -1,8 +0,0 @@ -load("//appengine:appengine.bzl", "appengine_war") - -appengine_war( - name = "examples", - data = ["//examples/webapp"], - data_path = "/examples/webapp", - jars = ["//examples/src:src_deploy.jar"], -) diff --git a/examples/java/BUILD b/examples/java/BUILD new file mode 100644 index 0000000..d555a4f --- /dev/null +++ b/examples/java/BUILD @@ -0,0 +1,8 @@ +load("//appengine:java_appengine.bzl", "appengine_war") + +appengine_war( + name = "examples", + data = ["//examples/java/webapp"], + data_path = "/examples/java/webapp", + jars = ["//examples/java/src:src_deploy.jar"], +) diff --git a/examples/src/App.java b/examples/java/src/App.java similarity index 100% rename from examples/src/App.java rename to examples/java/src/App.java diff --git a/examples/src/BUILD b/examples/java/src/BUILD similarity index 77% rename from examples/src/BUILD rename to examples/java/src/BUILD index 3b72f69..20deb10 100644 --- a/examples/src/BUILD +++ b/examples/java/src/BUILD @@ -1,7 +1,7 @@ java_binary( name = "src", srcs = ["App.java"], - visibility = ["//examples:__pkg__"], + visibility = ["//examples/java:__pkg__"], deps = [ "//appengine:javax.servlet.api", "@com_google_appengine_java//:api", diff --git a/examples/webapp/BUILD b/examples/java/webapp/BUILD similarity index 56% rename from examples/webapp/BUILD rename to examples/java/webapp/BUILD index eb3cd55..4c0471a 100644 --- a/examples/webapp/BUILD +++ b/examples/java/webapp/BUILD @@ -1,5 +1,5 @@ filegroup( name = "webapp", srcs = glob(["**"]), - visibility = ["//examples:__pkg__"], + visibility = ["//examples/java:__pkg__"], ) diff --git a/examples/webapp/WEB-INF/appengine-web.xml b/examples/java/webapp/WEB-INF/appengine-web.xml similarity index 100% rename from examples/webapp/WEB-INF/appengine-web.xml rename to examples/java/webapp/WEB-INF/appengine-web.xml diff --git a/examples/webapp/WEB-INF/web.xml b/examples/java/webapp/WEB-INF/web.xml similarity index 100% rename from examples/webapp/WEB-INF/web.xml rename to examples/java/webapp/WEB-INF/web.xml diff --git a/examples/py/hello_world/BUILD b/examples/py/hello_world/BUILD new file mode 100644 index 0000000..805981f --- /dev/null +++ b/examples/py/hello_world/BUILD @@ -0,0 +1,12 @@ +""" +Example taken from the official App Engine examples: +https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/standard/hello_world +""" + +load("//appengine:py_appengine.bzl", "py_appengine_binary") + +py_appengine_binary( + name = "main", + srcs = ["main.py"], + configs = ["app.yaml"], +) diff --git a/examples/py/hello_world/app.yaml b/examples/py/hello_world/app.yaml new file mode 100644 index 0000000..f041d38 --- /dev/null +++ b/examples/py/hello_world/app.yaml @@ -0,0 +1,7 @@ +runtime: python27 +api_version: 1 +threadsafe: true + +handlers: +- url: /.* + script: main.app diff --git a/examples/py/hello_world/main.py b/examples/py/hello_world/main.py new file mode 100644 index 0000000..c26ad7a --- /dev/null +++ b/examples/py/hello_world/main.py @@ -0,0 +1,26 @@ +# Copyright 2016 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import webapp2 + + +class MainPage(webapp2.RequestHandler): + def get(self): + self.response.headers['Content-Type'] = 'text/plain' + self.response.write('Hello, World!') + + +app = webapp2.WSGIApplication([ + ('/', MainPage), +], debug=True) diff --git a/test/BUILD b/test/java/BUILD similarity index 72% rename from test/BUILD rename to test/java/BUILD index 98880d6..cb93f97 100644 --- a/test/BUILD +++ b/test/java/BUILD @@ -1,15 +1,15 @@ -load("//appengine:appengine.bzl", "appengine_war") +load("//appengine:java_appengine.bzl", "appengine_war") appengine_war( name = "test-war", + testonly = 1, data = [ ":web-inf", - "//test/data:gen-data", - "//test/data:test-data", + "//test/java/data:gen-data", + "//test/java/data:test-data", ], - data_path = "/test", + data_path = "/test/java", jars = [":app_deploy.jar"], - testonly = 1, ) java_binary( @@ -21,9 +21,9 @@ sh_test( name = "check_war", srcs = ["check_war.sh"], data = [ + ":test-war", "@local_jdk//:jar", "@local_jdk//:jdk-default", - ":test-war", ], ) diff --git a/test/WEB-INF/appengine-web.xml b/test/java/WEB-INF/appengine-web.xml similarity index 100% rename from test/WEB-INF/appengine-web.xml rename to test/java/WEB-INF/appengine-web.xml diff --git a/test/WEB-INF/logging.properties b/test/java/WEB-INF/logging.properties similarity index 100% rename from test/WEB-INF/logging.properties rename to test/java/WEB-INF/logging.properties diff --git a/test/WEB-INF/web.xml b/test/java/WEB-INF/web.xml similarity index 100% rename from test/WEB-INF/web.xml rename to test/java/WEB-INF/web.xml diff --git a/test/check_war.sh b/test/java/check_war.sh similarity index 93% rename from test/check_war.sh rename to test/java/check_war.sh index c5554d7..40820cb 100755 --- a/test/check_war.sh +++ b/test/java/check_war.sh @@ -6,7 +6,7 @@ RUNFILES="$TEST_SRCDIR" if [ -d "${TEST_SRCDIR}/io_bazel_rules_appengine" ]; then RUNFILES="${TEST_SRCDIR}/io_bazel_rules_appengine" fi -TEST_WAR="${RUNFILES}/test/test-war.war" +TEST_WAR="${RUNFILES}/test/java/test-war.war" JAR="${TEST_SRCDIR}/local_jdk/bin/jar" function assert_war_contains() { diff --git a/test/data/BUILD b/test/java/data/BUILD similarity index 79% rename from test/data/BUILD rename to test/java/data/BUILD index 8695e8b..80ff454 100644 --- a/test/data/BUILD +++ b/test/java/data/BUILD @@ -1,6 +1,6 @@ package( - default_visibility = ["//test:__pkg__"], default_testonly = 1, + default_visibility = ["//test/java:__pkg__"], ) filegroup( @@ -10,6 +10,6 @@ filegroup( genrule( name = "gen-data", - cmd = "echo hi > $@", outs = ["gen-data.out"], + cmd = "echo hi > $@", ) diff --git a/test/data/welcome.jsp b/test/java/data/welcome.jsp similarity index 100% rename from test/data/welcome.jsp rename to test/java/data/welcome.jsp