diff --git a/Guardfile b/Guardfile new file mode 100644 index 000000000..51dddedc8 --- /dev/null +++ b/Guardfile @@ -0,0 +1,12 @@ +require 'asciidoctor' +require 'erb' +require './src/main/ruby/readme.rb' + +options = {:mkdirs => true, :safe => :unsafe, :attributes => ['linkcss', 'allow-uri-read']} + +guard 'shell' do + watch(/^src\/[A-Z-a-z][^#]*\.adoc$/) {|m| + SpringCloud::Build.render_file('src/main/asciidoc/README.adoc', :to_file => './README.adoc') + Asciidoctor.render_file('src/main/asciidoc/spring-cloud-cli.adoc', options.merge(:to_dir => 'target/generated-docs')) + } +end diff --git a/README.adoc b/README.adoc index 065e623a2..d05e7f11d 100644 --- a/README.adoc +++ b/README.adoc @@ -1,12 +1,25 @@ -Spring Cloud Function provides a new programming model for Spring Boot -applications, abstracting away all of the transport details and +// Do not edit this file (e.g. go instead to src/main/asciidoc) + +image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch=master[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-function] + +== Introduction + +Spring Cloud Function is a project with the following high-level goals: + +* _Promote the implementation of business logic via functions._ +* _Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task._ +* _Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS)._ +* _Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers._ + +It abstracts away all of the transport details and infrastructure, allowing the developer to keep all the familiar tools and processes, and focus firmly on business logic. Here's a complete, executable, testable Spring Boot application (implementing a simple string manipulation): -``` +[source,java] +---- @SpringBootApplication public class Application { @@ -19,7 +32,7 @@ public class Application { SpringApplication.run(Application.class, args); } } -``` +---- It's just a Spring Boot application, so it can be built, run and tested, locally and in a CI build, the same way as any other Spring @@ -47,34 +60,34 @@ JVM. Build from the command line (and "install" the samples): -``` +---- $ ./mvnw clean install -``` +---- (If you like to YOLO add `-DskipTests`.) Run one of the samples, e.g. -``` +---- $ java -jar spring-cloud-function-samples/spring-cloud-function-sample/target/*.jar -``` +---- This runs the app and exposes its functions over HTTP, so you can convert a string to uppercase, like this: -``` +---- $ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello HELLO -``` +---- You can convert multiple strings (a `Flux`) by separating them with new lines -``` +---- $ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello > World' HELLOWORLD -``` +---- (You can use `^Q^J` in a terminal to insert a new line in a literal string like that.) @@ -197,3 +210,141 @@ MESSAGE-8 MESSAGE-9 ... ---- + +== Building + +:jdkversion: 1.7 + +=== Basic Compile and Test + +To build the source you will need to install JDK {jdkversion}. + +Spring Cloud uses Maven for most build-related activities, and you +should be able to get off the ground quite quickly by cloning the +project you are interested in and typing + +---- +$ ./mvnw install +---- + +NOTE: You can also install Maven (>=3.3.3) yourself and run the `mvn` command +in place of `./mvnw` in the examples below. If you do that you also +might need to add `-P spring` if your local Maven settings do not +contain repository declarations for spring pre-release artifacts. + +NOTE: Be aware that you might need to increase the amount of memory +available to Maven by setting a `MAVEN_OPTS` environment variable with +a value like `-Xmx512m -XX:MaxPermSize=128m`. We try to cover this in +the `.mvn` configuration, so if you find you have to do it to make a +build succeed, please raise a ticket to get the settings added to +source control. + +For hints on how to build the project look in `.travis.yml` if there +is one. There should be a "script" and maybe "install" command. Also +look at the "services" section to see if any services need to be +running locally (e.g. mongo or rabbit). Ignore the git-related bits +that you might find in "before_install" since they're related to setting git +credentials and you already have those. + +The projects that require middleware generally include a +`docker-compose.yml`, so consider using +http://compose.docker.io/[Docker Compose] to run the middeware servers +in Docker containers. See the README in the +https://github.com/spring-cloud-samples/scripts[scripts demo +repository] for specific instructions about the common cases of mongo, +rabbit and redis. + +NOTE: If all else fails, build with the command from `.travis.yml` (usually +`./mvnw install`). + +=== Documentation + +The spring-cloud-build module has a "docs" profile, and if you switch +that on it will try to build asciidoc sources from +`src/main/asciidoc`. As part of that process it will look for a +`README.adoc` and process it by loading all the includes, but not +parsing or rendering it, just copying it to `${main.basedir}` +(defaults to `${basedir}`, i.e. the root of the project). If there are +any changes in the README it will then show up after a Maven build as +a modified file in the correct place. Just commit it and push the change. + +=== Working with the code +If you don't have an IDE preference we would recommend that you use +http://www.springsource.com/developer/sts[Spring Tools Suite] or +http://eclipse.org[Eclipse] when working with the code. We use the +http://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools +should also work without issue as long as they use Maven 3.3.3 or better. + +==== Importing into eclipse with m2eclipse +We recommend the http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with +eclipse. If you don't already have m2eclipse installed it is available from the "eclipse +marketplace". + +NOTE: Older versions of m2e do not support Maven 3.3, so once the +projects are imported into Eclipse you will also need to tell +m2eclipse to use the right profile for the projects. If you +see many different errors related to the POMs in the projects, check +that you have an up to date installation. If you can't upgrade m2e, +add the "spring" profile to your `settings.xml`. Alternatively you can +copy the repository settings from the "spring" profile of the parent +pom into your `settings.xml`. + +==== Importing into eclipse without m2eclipse +If you prefer not to use m2eclipse you can generate eclipse project metadata using the +following command: + +[indent=0] +---- + $ ./mvnw eclipse:eclipse +---- + +The generated eclipse projects can be imported by selecting `import existing projects` +from the `file` menu. + + +== Contributing + +Spring Cloud is released under the non-restrictive Apache 2.0 license, +and follows a very standard Github development process, using Github +tracker for issues and merging pull requests into master. If you want +to contribute even something trivial please do not hesitate, but +follow the guidelines below. + +=== Sign the Contributor License Agreement +Before we accept a non-trivial patch or pull request we will need you to sign the +https://cla.pivotal.io/sign/spring[Contributor License Agreement]. +Signing the contributor's agreement does not grant anyone commit rights to the main +repository, but it does mean that we can accept your contributions, and you will get an +author credit if we do. Active contributors might be asked to join the core team, and +given the ability to merge pull requests. + +=== Code of Conduct +This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of +conduct]. By participating, you are expected to uphold this code. Please report +unacceptable behavior to spring-code-of-conduct@pivotal.io. + +=== Code Conventions and Housekeeping +None of these is essential for a pull request, but they will all help. They can also be +added after the original pull request but before a merge. + +* Use the Spring Framework code format conventions. If you use Eclipse + you can import formatter settings using the + `eclipse-code-formatter.xml` file from the + https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring + Cloud Build] project. If using IntelliJ, you can use the + http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter + Plugin] to import the same file. +* Make sure all new `.java` files to have a simple Javadoc class comment with at least an + `@author` tag identifying you, and preferably at least a paragraph on what the class is + for. +* Add the ASF license header comment to all new `.java` files (copy from existing files + in the project) +* Add yourself as an `@author` to the .java files that you modify substantially (more + than cosmetic changes). +* Add some Javadocs and, if you change the namespace, some XSD doc elements. +* A few unit tests would help a lot as well -- someone has to do it. +* If no-one else is using your branch, please rebase it against the current master (or + other target branch in the main project). +* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], + if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit + message (where XXXX is the issue number). \ No newline at end of file diff --git a/docs/pom.xml b/docs/pom.xml new file mode 100644 index 000000000..5aeae40f8 --- /dev/null +++ b/docs/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + spring-cloud-function-docs + + org.springframework.cloud + spring-cloud-function-parent + 1.0.0.BUILD-SNAPSHOT + + pom + Spring Cloud Function Docs + Spring Cloud Function Docs + + spring-cloud-function + ${basedir}/.. + 1.0.x + + + + + + maven-deploy-plugin + + true + + + + + + + docs + + + + org.asciidoctor + asciidoctor-maven-plugin + false + + + org.apache.maven.plugins + maven-antrun-plugin + false + + + org.codehaus.mojo + build-helper-maven-plugin + false + + + + + + diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc new file mode 100644 index 000000000..3355be042 --- /dev/null +++ b/docs/src/main/asciidoc/README.adoc @@ -0,0 +1,17 @@ +image::https://travis-ci.org/spring-cloud/spring-cloud-function.svg?branch=master[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-function] + +== Introduction + +include::intro.adoc[] + +== Getting Started + +include::getting-started.adoc[] + +== Building + +include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[] + +== Contributing + +include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] diff --git a/docs/src/main/asciidoc/getting-started.adoc b/docs/src/main/asciidoc/getting-started.adoc new file mode 100644 index 000000000..f09bd5f67 --- /dev/null +++ b/docs/src/main/asciidoc/getting-started.adoc @@ -0,0 +1,152 @@ +Build from the command line (and "install" the samples): + +---- +$ ./mvnw clean install +---- + +(If you like to YOLO add `-DskipTests`.) + +Run one of the samples, e.g. + +---- +$ java -jar spring-cloud-function-samples/spring-cloud-function-sample/target/*.jar +---- + +This runs the app and exposes its functions over HTTP, so you can +convert a string to uppercase, like this: + +---- +$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d Hello +HELLO +---- + +You can convert multiple strings (a `Flux`) by separating them +with new lines + +---- +$ curl -H "Content-Type: text/plain" localhost:8080/uppercase -d 'Hello +> World' +HELLOWORLD +---- + +(You can use `^Q^J` in a terminal to insert a new line in a literal +string like that.) + +== Building and Running a Function + +The sample `@SpringBootApplication` above has a function that can be +decorated at runtime by Spring Cloud Function to be an HTTP endpoint, +or a Stream processor, for instance with RabbitMQ, Apache Kafka or +JMS. + +The `@Beans` can be `Function`, `Consumer` or `Supplier` (all from +`java.util`), and their parametric types can be String or POJO. A +`Function` is exposed as an HTTP POST if `spring-cloud-function-web` +is on the classpath, and as a Spring Cloud Stream `Processor` if +`spring-cloud-function-stream` is on the classpath and a +`spring.cloud.function.stream.endpoint` property is configured in the Spring +environment. A `Consumer` is also exposed as an HTTP POST, or as a Stream +`Sink`. A `Supplier` translates to an HTTP GET, or a Stream `Source`. + +Functions can be of `Flux` or `Flux` and Spring Cloud +Function takes care of converting the data to and from the desired +types, as long as it comes in as plain text or (in the case of the +POJO) JSON. TBD: support for `Flux>` and maybe plain +`Pojo` types (Fluxes implied and implemented by the framework). + +Functions can be grouped together in a single application, or deployed +one-per-jar. It's up to the developer to choose. An app with multiple +functions can be deployed multiple times in different "personalities", +exposing different functions over different physical transports. + +== Deploying a Packaged Function + +TBD: describe the deployer app. + +== Dynamic Compilation + +To run these examples, change into the `scripts` directory: + +---- +cd scripts +---- + +Also, start a RabbitMQ server locally (e.g. execute `rabbitmq-server`). + +=== Start the Function Registry Service: + +---- +./function-registry.sh +---- + +=== Register a Function: + +---- +./registerFunction.sh -n uppercase -f "f->f.map(s->s.toString().toUpperCase())" +---- + +=== Run a REST Microservice using that Function: + +---- +./web.sh -f uppercase -p 9000 +curl -H "Content-Type: text/plain" -H "Accept: text/plain" localhost:9000/uppercase -d foo +---- + +=== Register a Supplier: + +---- +./registerSupplier.sh -n words -f "()->Flux.just(\"foo\",\"bar\")" +---- + +=== Run a REST Microservice using that Supplier: + +---- +./web.sh -s words -p 9001 +curl -H "Accept: application/json" localhost:9001/words +---- + +=== Register a Consumer: + +---- +./registerConsumer.sh -n print -t String -f "System.out::println" +---- + +=== Run a REST Microservice using that Consumer: + +---- +./web.sh -c print -p 9002 +curl -X POST -H "Content-Type: text/plain" -d foo localhost:9002/print +---- + +=== Run Stream Processing Microservices: + +First register a streaming words supplier: + +---- +./registerSupplier.sh -n wordstream -f "()->Flux.intervalMillis(1000).map(i->\"message-\"+i)" +---- + +Then start the source (supplier), processor (function), and sink (consumer) apps +(in reverse order): + +---- +./stream.sh -p 9103 -i uppercaseWords -c print +./stream.sh -p 9102 -i words -f uppercase -o uppercaseWords +./stream.sh -p 9101 -s wordstream -o words +---- + +The output will appear in the console of the sink app (one message per second, converted to uppercase): + +---- +MESSAGE-0 +MESSAGE-1 +MESSAGE-2 +MESSAGE-3 +MESSAGE-4 +MESSAGE-5 +MESSAGE-6 +MESSAGE-7 +MESSAGE-8 +MESSAGE-9 +... +---- \ No newline at end of file diff --git a/docs/src/main/asciidoc/ghpages.sh b/docs/src/main/asciidoc/ghpages.sh new file mode 100755 index 000000000..57c5da3a3 --- /dev/null +++ b/docs/src/main/asciidoc/ghpages.sh @@ -0,0 +1,330 @@ +#!/bin/bash -x + +set -e + +# Set default props like MAVEN_PATH, ROOT_FOLDER etc. +function set_default_props() { + # The script should be executed from the root folder + ROOT_FOLDER=`pwd` + echo "Current folder is ${ROOT_FOLDER}" + + if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then + echo "You're not in the root folder of the project!" + exit 1 + fi + + # Prop that will let commit the changes + COMMIT_CHANGES="no" + MAVEN_PATH=${MAVEN_PATH:-} + echo "Path to Maven is [${MAVEN_PATH}]" + REPO_NAME=${PWD##*/} + echo "Repo name is [${REPO_NAME}]" + SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git} + echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}" +} + +# Check if gh-pages exists and docs have been built +function check_if_anything_to_sync() { + git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'` + + if ! (git remote set-branches --add origin gh-pages && git fetch -q); then + echo "No gh-pages, so not syncing" + exit 0 + fi + + if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then + echo "No gh-pages sources in docs/target/generated-docs, so not syncing" + exit 0 + fi +} + +function retrieve_current_branch() { + # Code getting the name of the current branch. For master we want to publish as we did until now + # http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch + # If there is a branch already passed will reuse it - otherwise will try to find it + CURRENT_BRANCH=${BRANCH} + if [[ -z "${CURRENT_BRANCH}" ]] ; then + CURRENT_BRANCH=$(git symbolic-ref -q HEAD) + CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/} + CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD} + fi + echo "Current branch is [${CURRENT_BRANCH}]" + git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script" +} + +# Switches to the provided value of the release version. We always prefix it with `v` +function switch_to_tag() { + git checkout v${VERSION} +} + +# Build the docs if switch is on +function build_docs_if_applicable() { + if [[ "${BUILD}" == "yes" ]] ; then + ./mvnw clean install -P docs -pl docs -DskipTests + fi +} + +# Get the name of the `docs.main` property +# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile +function retrieve_doc_properties() { + MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \ + -Dexec.executable="echo" \ + -Dexec.args='${docs.main}' \ + --non-recursive \ + org.codehaus.mojo:exec-maven-plugin:1.3.1:exec) + echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]" + + + WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"} + WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \ + -Dexec.executable="echo" \ + -Dexec.args="\${${WHITELIST_PROPERTY}}" \ + org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \ + -P docs \ + -pl docs) + echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]" +} + +# Stash any outstanding changes +function stash_changes() { + git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1") + if [ "$dirty" != "0" ]; then git stash; fi +} + +# Switch to gh-pages branch to sync it with current branch +function add_docs_from_target() { + local DESTINATION_REPO_FOLDER + if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then + DESTINATION_REPO_FOLDER=${ROOT_FOLDER} + elif [[ "${CLONE}" == "yes" ]]; then + mkdir -p ${ROOT_FOLDER}/target + local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static + if [[ ! -e "${clonedStatic}/.git" ]]; then + echo "Cloning Spring Cloud Static to target" + git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages + else + echo "Spring Cloud Static already cloned - will pull changes" + cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages + fi + DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME} + mkdir -p ${DESTINATION_REPO_FOLDER} + else + if [[ ! -e "${DESTINATION}/.git" ]]; then + echo "[${DESTINATION}] is not a git repository" + exit 1 + fi + DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME} + mkdir -p ${DESTINATION_REPO_FOLDER} + echo "Destination was provided [${DESTINATION}]" + fi + cd ${DESTINATION_REPO_FOLDER} + git checkout gh-pages + git pull origin gh-pages + + # Add git branches + ################################################################### + if [[ -z "${VERSION}" ]] ; then + copy_docs_for_current_version + else + copy_docs_for_provided_version + fi + commit_changes_if_applicable +} + + +# Copies the docs by using the retrieved properties from Maven build +function copy_docs_for_current_version() { + if [[ "${CURRENT_BRANCH}" == "master" ]] ; then + echo -e "Current branch is master - will copy the current docs only to the root folder" + for f in docs/target/generated-docs/*; do + file=${f#docs/target/generated-docs/*} + if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then + # Not ignored... + cp -rf $f ${ROOT_FOLDER}/ + git add -A ${ROOT_FOLDER}/$file + fi + done + COMMIT_CHANGES="yes" + else + echo -e "Current branch is [${CURRENT_BRANCH}]" + # http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin + if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then + mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH} + echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder" + for f in docs/target/generated-docs/*; do + file=${f#docs/target/generated-docs/*} + if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then + # Not ignored... + # We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html + if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then + # We don't want to copy the spring-cloud-sleuth.html + # we want it to be converted to index.html + cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html + git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html + else + cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH} + git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file + fi + fi + done + COMMIT_CHANGES="yes" + else + echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in + [docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch." + fi + fi +} + +# Copies the docs by using the explicitly provided version +function copy_docs_for_provided_version() { + local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION} + mkdir -p ${FOLDER} + echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder" + for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do + file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*} + copy_docs_for_branch ${file} ${FOLDER} + done + COMMIT_CHANGES="yes" + CURRENT_BRANCH="v${VERSION}" +} + +# Copies the docs from target to the provided destination +# Params: +# $1 - file from target +# $2 - destination to which copy the files +function copy_docs_for_branch() { + local file=$1 + local destination=$2 + if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then + # Not ignored... + # We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html + if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then + # We don't want to copy the spring-cloud-sleuth.html + # we want it to be converted to index.html + cp -rf $f ${destination}/index.html + git add -A ${destination}/index.html + else + cp -rf $f ${destination} + git add -A ${destination}/$file + fi + fi +} + +function commit_changes_if_applicable() { + if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then + COMMIT_SUCCESSFUL="no" + git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes" + + # Uncomment the following push if you want to auto push to + # the gh-pages branch whenever you commit to master locally. + # This is a little extreme. Use with care! + ################################################################### + if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then + git push origin gh-pages + fi + fi +} + +# Switch back to the previous branch and exit block +function checkout_previous_branch() { + # If -version was provided we need to come back to root project + cd ${ROOT_FOLDER} + git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script" + if [ "$dirty" != "0" ]; then git stash pop; fi + exit 0 +} + +# Assert if properties have been properly passed +function assert_properties() { +echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]" +if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi +if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi +if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi +} + +# Prints the usage +function print_usage() { +cat </` +- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will + switch to gh-pages of that repo and copy the generated docs to `docs//` + +USAGE: + +You can use the following options: + +-v|--version - the script will apply the whole procedure for a particular library version +-d|--destination - the root of destination folder where the docs should be copied. You have to use the full path. + E.g. point to spring-cloud-static folder. Can't be used with (-c) +-b|--build - will run the standard build process after checking out the branch +-c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination. + Obviously can't be used with (-d) + +EOF +} + + +# ========================================== +# ____ ____ _____ _____ _____ _______ +# / ____|/ ____| __ \|_ _| __ \__ __| +# | (___ | | | |__) | | | | |__) | | | +# \___ \| | | _ / | | | ___/ | | +# ____) | |____| | \ \ _| |_| | | | +# |_____/ \_____|_| \_\_____|_| |_| +# +# ========================================== + +while [[ $# > 0 ]] +do +key="$1" +case ${key} in + -v|--version) + VERSION="$2" + shift # past argument + ;; + -d|--destination) + DESTINATION="$2" + shift # past argument + ;; + -b|--build) + BUILD="yes" + ;; + -c|--clone) + CLONE="yes" + ;; + -h|--help) + print_usage + exit 0 + ;; + *) + echo "Invalid option: [$1]" + print_usage + exit 1 + ;; +esac +shift # past argument or value +done + +assert_properties +set_default_props +check_if_anything_to_sync +if [[ -z "${VERSION}" ]] ; then + retrieve_current_branch +else + switch_to_tag +fi +build_docs_if_applicable +retrieve_doc_properties +stash_changes +add_docs_from_target +checkout_previous_branch \ No newline at end of file diff --git a/docs/src/main/asciidoc/images/remove.txt b/docs/src/main/asciidoc/images/remove.txt new file mode 100644 index 000000000..bbd40769d --- /dev/null +++ b/docs/src/main/asciidoc/images/remove.txt @@ -0,0 +1 @@ +please remove once this directory is not empty \ No newline at end of file diff --git a/docs/src/main/asciidoc/intro.adoc b/docs/src/main/asciidoc/intro.adoc new file mode 100644 index 000000000..47d6c275c --- /dev/null +++ b/docs/src/main/asciidoc/intro.adoc @@ -0,0 +1,51 @@ +Spring Cloud Function is a project with the following high-level goals: + +* _Promote the implementation of business logic via functions._ +* _Decouple the development lifecycle of business logic from any specific runtime target so that the same code can run as a web endpoint, a stream processor, or a task._ +* _Support a uniform programming model across serverless providers, as well as the ability to run standalone (locally or in a PaaS)._ +* _Enable Spring Boot features (auto-configuration, dependency injection, metrics) on serverless providers._ + +It abstracts away all of the transport details and +infrastructure, allowing the developer to keep all the familiar tools +and processes, and focus firmly on business logic. + +Here's a complete, executable, testable Spring Boot application +(implementing a simple string manipulation): + +[source,java] +---- +@SpringBootApplication +public class Application { + + @Bean + public Function, Flux> uppercase() { + return flux -> flux.map(value -> value.toUpperCase()); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} +---- + +It's just a Spring Boot application, so it can be built, run and +tested, locally and in a CI build, the same way as any other Spring +Boot application. The `Function` is from `java.util` and `Flux` is a +http://www.reactive-streams.org/[Reactive Streams] `Publisher` from +https://projectreactor.io/[Project Reactor]. The function can be +accessed over HTTP or messaging. + +Spring Cloud Function has 4 main features: + +1. Wrappers for `@Beans` of type `Function`, `Consumer` and +`Supplier`, exposing them to the outside world as either HTTP +endpoints and/or message stream listeners/publishers with RabbitMQ, Kafka etc. + +2. Compiling strings which are Java function bodies into bytecode, and +then turning them into `@Beans` that can be wrapped as above. + +3. Deploying a JAR file containing such an application context with an +isolated classloader, so that you can pack them together in a single +JVM. + +4. Adapters for https://github.com/markfisher/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-aws[AWS Lambda], https://github.com/markfisher/spring-cloud-function/tree/master/spring-cloud-function-adapters/spring-cloud-function-adapter-openwhisk[Apache OpenWhisk] and possibly other "serverless" service providers. \ No newline at end of file diff --git a/docs/src/main/asciidoc/spring-cloud-function.adoc b/docs/src/main/asciidoc/spring-cloud-function.adoc new file mode 100644 index 000000000..5c62a6824 --- /dev/null +++ b/docs/src/main/asciidoc/spring-cloud-function.adoc @@ -0,0 +1,20 @@ += Spring Cloud Function + +Mark Fisher, Dave Syer + +--- + +:github: https://github.com/spring-cloud/spring-cloud-function +:githubmaster: {github}/tree/master +:docslink: {githubmaster}/docs/src/main/asciidoc +:nofooter: + +== Introduction + +include::intro.adoc[] + +include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing-docs.adoc[] + +== Getting Started + +include::getting-started.adoc[] diff --git a/docs/src/main/ruby/generate_readme.sh b/docs/src/main/ruby/generate_readme.sh new file mode 100755 index 000000000..6d0ce9dc5 --- /dev/null +++ b/docs/src/main/ruby/generate_readme.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env ruby + +base_dir = File.join(File.dirname(__FILE__),'../../..') +src_dir = File.join(base_dir, "/src/main/asciidoc") +require 'asciidoctor' +require 'optparse' + +options = {} +file = "#{src_dir}/README.adoc" + +OptionParser.new do |o| + o.on('-o OUTPUT_FILE', 'Output file (default is stdout)') { |file| options[:to_file] = file unless file=='-' } + o.on('-h', '--help') { puts o; exit } + o.parse! +end + +file = ARGV[0] if ARGV.length>0 + +# Copied from https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/master/scripts/asciidoc-coalescer.rb +doc = Asciidoctor.load_file file, safe: :unsafe, header_only: true, attributes: options[:attributes] +header_attr_names = (doc.instance_variable_get :@attributes_modified).to_a +header_attr_names.each {|k| doc.attributes[%(#{k}!)] = '' unless doc.attr? k } +attrs = doc.attributes +attrs['allow-uri-read'] = true +puts attrs + +out = "// Do not edit this file (e.g. go instead to src/main/asciidoc)\n\n" +doc = Asciidoctor.load_file file, safe: :unsafe, parse: false, attributes: attrs +out << doc.reader.read + +unless options[:to_file] + puts out +else + File.open(options[:to_file],'w+') do |file| + file.write(out) + end +end diff --git a/pom.xml b/pom.xml index ca504c914..16c7568cb 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ Chelsea.SR1 1.0.5.RELEASE 1.5.4.RELEASE + spring-cloud-function @@ -58,6 +59,7 @@ spring-cloud-function-samples spring-cloud-function-deployer spring-cloud-function-adapters + docs