├── bin ├── detect ├── release ├── common.sh └── compile ├── .gitignore ├── test ├── release_test.sh ├── detect_test.sh ├── compile_test.sh └── get_play_version_test.sh ├── LICENSE ├── opt └── build-play-heroku └── README.md /bin/detect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # bin/use 3 | 4 | BUILD_DIR=$1 5 | 6 | play_confs=$(cd $BUILD_DIR; find . -wholename "*/conf/application.conf" ! -wholename "*modules*" -type f) 7 | 8 | if [ -n "$play_confs" ] && [ ! -f "$BUILD_DIR/project/Build.scala" ]; then 9 | echo "Play!" && exit 0 10 | else 11 | echo "no" && exit 1 12 | fi 13 | -------------------------------------------------------------------------------- /bin/release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # bin/release 3 | 4 | BUILD_DIR=$1 5 | 6 | cat <>>>>>> 181f51991dad1e5ff5bc489d653989aaf35d1e5c 28 | -------------------------------------------------------------------------------- /test/release_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ${BUILDPACK_TEST_RUNNER_HOME}/lib/test_utils.sh 4 | 5 | testReleasedYamlDoesNotIncludeDefaultProcWhenProcfileIsPresent() { 6 | touch ${BUILD_DIR}/Procfile 7 | expectedReleaseYAML=`cat < Installing Play! $VER_TO_INSTALL....." 30 | curl --silent --max-time 150 --location $PLAY_URL -o $PLAY_TAR_FILE 31 | if [ ! -f $PLAY_TAR_FILE ]; then 32 | echo "-----> Error downloading Play! framework. Please try again..." 33 | exit 1 34 | fi 35 | if [ -z "`file $PLAY_TAR_FILE | grep gzip`" ]; then 36 | echo "-----> Error installing Play! framework or unsupported Play! framework version specified. Please review Dev Center for a list of supported versions." 37 | exit 1 38 | fi 39 | tar xzf $PLAY_TAR_FILE 40 | rm $PLAY_TAR_FILE 41 | chmod +x $PLAY_PATH/play 42 | echo "-----> done" 43 | } 44 | -------------------------------------------------------------------------------- /opt/build-play-heroku: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | BUILD_DIR=$PWD 4 | 5 | PLAY_FILE=$1 6 | 7 | # We specified a release zip 8 | if [[ -n $PLAY_FILE && -f $PLAY_FILE ]]; then 9 | mkdir -p unzipped/ 10 | unzip $PLAY_FILE -d unzipped/ 11 | 12 | PLAY_BUILD_DIR=$(find -name 'framework' -type d | sed 's/framework//') 13 | 14 | # Build Play! framework 15 | else 16 | PLAY_BUILD_DIR=~/release/play 17 | PLAY_BRANCH=1.2.x 18 | PLAY_TAG=HEAD 19 | 20 | cd $PLAY_BUILD_DIR 21 | if [ "$PLAY_TAG" == "HEAD" ]; then 22 | git checkout $PLAY_BRANCH 23 | /usr/bin/ant -buildfile $PLAY_BUILD_DIR/framework/build.xml 24 | else 25 | git checkout $PLAY_TAG 26 | /usr/bin/ant -buildfile $PLAY_BUILD_DIR/framework/build.xml -Dversion=$PLAY_TAG 27 | fi 28 | 29 | git checkout $PLAY_BRANCH 30 | fi 31 | 32 | 33 | # Clean old tarball 34 | cd $BUILD_DIR 35 | rm -fr build/play-heroku.tar.gz 36 | 37 | # Create tmp space for tar'ing 38 | mkdir -p tmp/.play/framework/src/play 39 | 40 | # Add Play! framework 41 | cp -r $PLAY_BUILD_DIR/framework/dependencies.yml tmp/.play/framework 42 | cp -r $PLAY_BUILD_DIR/framework/lib/ tmp/.play/framework 43 | cp -r $PLAY_BUILD_DIR/framework/play-*.jar tmp/.play/framework 44 | cp -r $PLAY_BUILD_DIR/framework/pym/ tmp/.play/framework 45 | cp -r $PLAY_BUILD_DIR/framework/src/play/version tmp/.play/framework/src/play 46 | cp -r $PLAY_BUILD_DIR/framework/templates/ tmp/.play/framework 47 | 48 | # Add Play! core modules 49 | cp -r $PLAY_BUILD_DIR/modules tmp/.play 50 | 51 | # Add Play! Linux executable 52 | cp -r $PLAY_BUILD_DIR/play tmp/.play 53 | 54 | # Add Resources 55 | cp -r $PLAY_BUILD_DIR/resources tmp/.play 56 | 57 | # Run tar and remove tmp space 58 | if [ ! -d build ]; then 59 | mkdir build 60 | fi 61 | 62 | tar cvzf build/play-heroku.tar.gz -C tmp/ .play 63 | rm -fr tmp/ 64 | 65 | if [[ -n $PLAY_FILE && -f $PLAY_FILE ]]; then 66 | rm -fr unzipped/ 67 | echo "*** BUILT FROM ZIP FILE: $PLAY_FILE" 68 | else 69 | echo "*** BUILT FROM BRANCH $PLAY_BRANCH AT TAG $PLAY_TAG" 70 | fi 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | heroku-buildpack-custom 2 | ======================= 3 | 4 | Custom setup of play where it does not run from the root but a folder call cloud 5 | This is a [Heroku buildpack](http://devcenter.heroku.com/articles/buildpack) for [Play! framework](http://www.playframework.org/) apps. 6 | 7 | *Note: This buildpack only applies to Play 1.2.x apps. Play 2.0.x apps are handled by the [Scala buildpack](https://github.com/heroku/heroku-buildpack-scala)* 8 | 9 | Usage 10 | ----- 11 | 12 | Example usage: 13 | 14 | $ ls 15 | app conf lib public test 16 | 17 | $ heroku create --stack cedar --buildpack http://github.com/heroku/heroku-buildpack-play.git 18 | 19 | $ git push heroku master 20 | ... 21 | -----> Heroku receiving push 22 | -----> Fetching custom build pack... done 23 | -----> Play! app detected 24 | -----> Installing Play!..... done 25 | -----> Installing ivysettings.xml..... done 26 | -----> Building Play! application... 27 | ~ _ _ 28 | ~ _ __ | | __ _ _ _| | 29 | ~ | '_ \| |/ _' | || |_| 30 | ~ | __/|_|\____|\__ (_) 31 | ~ |_| |__/ 32 | ~ 33 | ~ play! 1.2.3, http://www.playframework.org 34 | ~ 35 | 1.2.3 36 | Building Play! application at directory ./ 37 | ... 38 | 39 | The buildpack will detect your app as using the Play! framework if it has an `application.conf` in a `conf` directory. Your dependencies will be resolved using `play dependencies` and your app precompiled with `play precompile`. If you don't provide a Procfile the build pack will default to launching your app with `play run --%prod -Dprecompiled=true`. 40 | 41 | Play Versions 42 | ------------- 43 | 44 | The buildpack will read the Play! version that your application expects from your dependencies.yml file. The version comes on the same line where you already declare a dependency on the Play! framework itself: 45 | 46 | - play 1.2.4 47 | 48 | If you don't specify a version it will be defaulted for you and you'll see a warning message in your build output. It is a best practice to specify the version off the framework that you intend to use. 49 | 50 | Once your application is live you can upgrade the Play! version simply by changing the version in your dependencies.yml. If you don't specify a version and use the default version your application will not be updated when the default version is updated. This is so that you don't have to deal with your application being upgraded unexpectedly. 51 | 52 | Hacking 53 | ------- 54 | 55 | To use this buildpack, fork it on Github.  Push up changes to your fork, then create a test app with `--buildpack ` and push to it. 56 | 57 | For example one of the things that the build pack does is download and install the Play! framework that will be used to run your app. If you want to use a version of the framework other than those that are supported place a tar.gz of the framework in a public location and then alter the line that sets this variable in the compile script to point there: 58 | 59 | PLAY_URL="https://s3.amazonaws.com/heroku-jvm-langpack-play/play-heroku-$VER_TO_INSTALL.tar.gz" 60 | 61 | This will alter the behaviour to pull down and install your chosen version of Play! rather than the default. 62 | 63 | Commit and push the changes to your buildpack to your Github fork, then push your sample app to Heroku to test. Once the push succeeds you should be able to run: 64 | 65 | $ heroku run bash 66 | 67 | and then: 68 | 69 | $ play version 70 | 71 | and you'll see the your chosen play version printed. 72 | 73 | License 74 | ------- 75 | 76 | Licensed under the MIT License. See LICENSE file. 77 | -------------------------------------------------------------------------------- /bin/compile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # bin/compile 3 | 4 | # Parse args 5 | BUILD_DIR=$1 6 | CACHE_DIR=$2 7 | 8 | BIN_DIR=$(cd $(dirname $0); pwd) # absolute path 9 | 10 | # source in common functions 11 | . $BIN_DIR/common.sh 12 | 13 | PLAY_PATH=".play" 14 | IVY_PATH=".ivy2" 15 | 16 | # Change dir to handle relative paths 17 | cd $BUILD_DIR 18 | 19 | # Unpack cache 20 | for DIR in $PLAY_PATH $IVY_PATH ; do 21 | rm -rf $DIR 22 | if [ -d $CACHE_DIR/$DIR ]; then 23 | cp -r $CACHE_DIR/$DIR $DIR 24 | fi 25 | done 26 | 27 | PLAY_VERSION=$(get_play_version cloud/conf/dependencies.yml) 28 | DEFAULT_PLAY_VERSION="1.2.4" 29 | VERSION_DECLARED=true 30 | 31 | if [ -z "$PLAY_VERSION" ] ; then 32 | PLAY_VERSION=$DEFAULT_PLAY_VERSION 33 | VERSION_DECLARED=false 34 | echo "-----> WARNING: Play! version not specified in dependencies.yml. Default version: $PLAY_VERSION being used...." 35 | fi 36 | 37 | # Install Play! or update the version 38 | if [ ! -f $PLAY_PATH/play ]; then 39 | install_play $PLAY_VERSION 40 | else 41 | INSTALLED_PLAY_VERSION=`cat $PLAY_PATH/framework/src/play/version` 42 | if [ "$INSTALLED_PLAY_VERSION" != "$PLAY_VERSION" ] && $VERSION_DECLARED ; then 43 | echo "-----> Updating Play! version. Previous version was $INSTALLED_PLAY_VERSION. Updating to $PLAY_VERSION..." 44 | rm -rf $PLAY_PATH 45 | install_play $PLAY_VERSION 46 | fi 47 | fi 48 | 49 | PLAY_SETTINGS_URL="http://s3.amazonaws.com/heroku-jvm-langpack-play/ivysettings.xml" 50 | 51 | echo "-----> Installing ivysettings.xml....." 52 | if [ -f .ivy2/ivysettings.xml ]; then 53 | echo -n " ---> Removing old ivysettings.xml..." 54 | rm .ivy2/ivysettings.xml 55 | echo "done" 56 | fi 57 | if [ -f cloud/conf/ivysettings.xml ]; then 58 | echo -n " ---> Installing custom ivysettings.xml..." 59 | [ -d .ivy2 ] || mkdir .ivy2 60 | cp cloud/conf/ivysettings.xml .ivy2/ivysettings.xml 61 | else 62 | echo -n " ---> Installing Heroku default ivysettings.xml..." 63 | curl --silent --max-time 10 --location $PLAY_SETTINGS_URL --create-dirs --output .ivy2/ivysettings.xml 64 | fi 65 | echo " done" 66 | 67 | # Build app 68 | echo "-----> Building Play! application..." 69 | $PLAY_PATH/play version | sed -u 's/^/ /' 70 | 71 | # Precompile the Play! application at the root of $BUILD_DIR 72 | APP_DIR=./cloud/ 73 | echo " Building Play! application at directory $APP_DIR" 74 | 75 | #for om 76 | DEPENDENCIES_CMD="$PLAY_PATH/play dependencies $APP_DIR/../om --forProd --forceCopy --silent --clearcache -Duser.home=$BUILD_DIR 2>&1" 77 | echo " Resolving dependencies: $DEPENDENCIES_CMD" 78 | eval "$DEPENDENCIES_CMD" | sed -u 's/^/ /' 79 | check_compile_status 80 | 81 | #for cloud 82 | DEPENDENCIES_CMD="$PLAY_PATH/play dependencies $APP_DIR --forProd --forceCopy --silent --clearcache -Duser.home=$BUILD_DIR 2>&1" 83 | echo " Resolving dependencies: $DEPENDENCIES_CMD" 84 | eval "$DEPENDENCIES_CMD" | sed -u 's/^/ /' 85 | check_compile_status 86 | 87 | PRECOMPILE_CMD="$PLAY_PATH/play precompile $APP_DIR --silent 2>&1" 88 | echo " Precompiling: $PRECOMPILE_CMD" 89 | eval "$PRECOMPILE_CMD" | sed -u 's/^/ /' 90 | check_compile_status 91 | 92 | # Repack Play! framework into cache 93 | mkdir -p $CACHE_DIR 94 | for DIR in $PLAY_PATH $IVY_PATH ; do 95 | rm -rf $CACHE_DIR/$DIR 96 | cp -r $DIR $CACHE_DIR/$DIR 97 | done 98 | 99 | # Remove build time dependencies from slug 100 | # (Note: runtime modules are copied to slug with --forceCopy option) 101 | rm -fr $PLAY_PATH/modules 102 | rm -fr $IVY_PATH 103 | 104 | # Warn if no Procfile is present 105 | if [ ! -f Procfile ]; then 106 | echo "-----> No Procfile found. Will use the following default process: " 107 | echo " play run --http.port=\$PORT \$PLAY_OPTS" 108 | fi 109 | -------------------------------------------------------------------------------- /test/compile_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . ${BUILDPACK_TEST_RUNNER_HOME}/lib/test_utils.sh 4 | 5 | PLAY_TEST_CACHE="/tmp/play-test-cache" 6 | DEFAULT_PLAY_VERSION=1.2.4 7 | 8 | _full_play() { 9 | local playVersion=${1:-${DEFAULT_PLAY_VERSION}} 10 | local playBaseDir="${2:-${PLAY_TEST_CACHE}/full}" 11 | local playExe="${playBaseDir}/play-${playVersion}/play" 12 | local playUrl="http://s3.amazonaws.com/heroku-jvm-buildpack-play-test/play-${playVersion}.tar.gz" 13 | local playCommand="$(installPlay ${playVersion} ${playBaseDir} ${playExe} ${playUrl})" 14 | echo "${playCommand}" 15 | } 16 | 17 | installPlay() { 18 | local playVersion=$1 19 | local playBaseDir=$2 20 | local playExe=$3 21 | local playURL=$4 22 | if [ ! -x ${playExe} ]; then 23 | mkdir -p ${playBaseDir} 24 | local currentDir="$(pwd)" 25 | cd ${playBaseDir} 26 | curl --silent --max-time 300 --location ${playURL} | tar xz 27 | chmod +x ${playExe} 28 | cd ${currentDir} 29 | fi 30 | echo "${playExe}" 31 | } 32 | 33 | getPlayApp() { 34 | local playVersion=${1:-${DEFAULT_PLAY_VERSION}} 35 | local appBaseDir="${PLAY_TEST_CACHE}/app-${playVersion}" 36 | if [ ! -f ${appBaseDir}/conf/application.conf ]; then 37 | $(_full_play ${playVersion}) new ${appBaseDir} --name app >/dev/null 38 | fi 39 | cp -r ${appBaseDir}/. ${BUILD_DIR} 40 | assertTrue "${BUILD_DIR}/conf/application.conf should be present after creating a new app." "[ -f ${BUILD_DIR}/conf/application.conf ]" 41 | } 42 | 43 | definePlayAppVersion() { 44 | local playVersion=$1 45 | cat > ${BUILD_DIR}/conf/dependencies.yml < ${BUILD_DIR}/conf/dependencies.yml < guava 11.0 77 | EOF 78 | compile 79 | assertTrue \ 80 | "Dependencies should have been resolved for guava." \ 81 | "[ -f ${BUILD_DIR}/lib/guava-11.0.jar ]" 82 | assertTrue \ 83 | "A precompiled app should have an Application.class" \ 84 | "[ -f ${BUILD_DIR}/precompiled/java/controllers/Application.class ]" 85 | } 86 | 87 | testHerokuIvySettingsAreInstalled() { 88 | getPlayApp 89 | compile 90 | assertTrue "Ivy settings file should be installed." "[ -f ${CACHE_DIR}/.ivy2/ivysettings.xml ]" 91 | assertContains \ 92 | "s3pository.heroku.com" \ 93 | "$(cat ${CACHE_DIR}/.ivy2/ivysettings.xml)" 94 | } 95 | 96 | testBuildTimeArtifactsAreDeleted() { 97 | getPlayApp 98 | compile 99 | assertFalse \ 100 | "Play modules should not be present in the slug." \ 101 | "[ -d ${BUILD_DIR}/.play/modules ]" 102 | assertFalse \ 103 | "Ivy should not be present in the slug." \ 104 | "[ -d ${BUILD_DIR}/.ivy2 ]" 105 | } 106 | 107 | testCacheNotCopiedForFailedBuild() { 108 | getPlayApp 109 | 110 | rm ${BUILD_DIR}/conf/application.conf 111 | mkdir -p ${CACHE_DIR}/.play 112 | touch ${CACHE_DIR}/.play/test-cached 113 | 114 | compile 115 | 116 | assertTrue \ 117 | "Files in ${CACHE_DIR}/.play should have been cleared after a failed build." \ 118 | "[ ! -f ${CACHE_DIR}/.play/test-cached ]" 119 | assertTrue \ 120 | "${CACHE_DIR}/.play/play should have been cleared after a failed build." \ 121 | "[ ! -f ${CACHE_DIR}/.play/play ]" 122 | } 123 | 124 | testProcfileWarningIsDisplayedWhenNoProcfileIsPresent() { 125 | getPlayApp 126 | assertTrue "No procfile should be present in an empty app." "[ ! -f ${BUILD_DIR}/Procfile ]" 127 | 128 | compile 129 | 130 | assertCaptured "No Procfile found. Will use the following default process" 131 | } 132 | 133 | testPlayRCVersion() { 134 | local rc_version="1.2.5rc3" 135 | getPlayApp ${rc_version} 136 | definePlayAppVersion ${rc_version} 137 | 138 | compile 139 | 140 | assertCaptured "Installing Play! ${rc_version}" 141 | } 142 | 143 | testPlayVersionIsPickedUpFromDependenciesFile() { 144 | getPlayApp "1.2.4" 145 | definePlayAppVersion "1.2.4" 146 | 147 | compile 148 | 149 | assertCaptured "Installing Play! 1.2.4" 150 | assertNotCaptured "WARNING: Play! version not specified in dependencies.yml." 151 | } 152 | 153 | testPlayInstalledInBuildDirSlashDotPlayDir() { 154 | compile 155 | assertTrue "${BUILD_DIR}/.play should be present in build dir after a successful build" "[ -x ${BUILD_DIR}/.play/play ]" 156 | } 157 | 158 | testPlayCopiedToCacheDirForSuccessfulBuild() { 159 | getPlayApp 160 | compile 161 | assertTrue "${CACHE_DIR}/.play should be present in cache dir after a successful build." "[ -f ${CACHE_DIR}/.play/play ]" 162 | } 163 | 164 | testValidVersionOfPlayThatIsNotInS3Bucket() { 165 | getPlayApp 166 | definePlayAppVersion "1.0.1" 167 | 168 | compile 169 | 170 | assertCaptured "Installing Play! 1.0.1" 171 | assertCaptured "Error installing Play! framework or unsupported Play! framework version specified." 172 | } 173 | 174 | testUpgradePlayProject() { 175 | getPlayApp "1.2.3" 176 | definePlayAppVersion "1.2.3" 177 | compile 178 | definePlayAppVersion "1.2.4" 179 | compile 180 | assertCaptured "Updating Play! version." 181 | } 182 | 183 | testCacheIsDeletedDuringUpgrade() { 184 | getPlayApp "1.2.3" 185 | definePlayAppVersion "1.2.3" 186 | compile 187 | 188 | mkdir -p ${CACHE_DIR}/.play 189 | touch ${CACHE_DIR}/.play/test-cached 190 | 191 | definePlayAppVersion "1.2.4" 192 | compile 193 | assertFalse \ 194 | "${CACHE_DIR}/.play/test-cached should have been deleted during play upgrade." \ 195 | "[ -f ${CACHE_DIR}/.play/test-cached ]" 196 | } 197 | -------------------------------------------------------------------------------- /test/get_play_version_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . ${BUILDPACK_TEST_RUNNER_HOME}/lib/test_utils.sh 4 | . ${BUILDPACK_HOME}/bin/common.sh 5 | 6 | EXPECTED_VERSION=0.1.5.9 7 | 8 | testGetPlayVersionFileMissing() 9 | { 10 | capture get_play_version missing.properties 11 | 12 | assertCapturedSuccess 13 | assertCapturedEquals "" 14 | } 15 | 16 | testGetPlayVersionMissing() 17 | { 18 | cat > ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < secure 91 | EOF 92 | 93 | capture get_play_version ${OUTPUT_DIR}/dependencies.yaml 94 | 95 | assertCapturedSuccess 96 | assertCapturedEquals "1.2.4" 97 | } 98 | 99 | testGetPlayVersionOnMutipleLines_PlayMultipleBlank() 100 | { 101 | cat > ${OUTPUT_DIR}/dependencies.yaml < secure 105 | EOF 106 | 107 | capture get_play_version ${OUTPUT_DIR}/dependencies.yaml 108 | 109 | assertCapturedSuccess 110 | assertCapturedEquals "" 111 | } 112 | 113 | testGetPlayVersionOnMutipleLines_PlayMultipleNotFirst() 114 | { 115 | cat > ${OUTPUT_DIR}/dependencies.yaml < secure 118 | - play 1.2.4 119 | EOF 120 | 121 | capture get_play_version ${OUTPUT_DIR}/dependencies.yaml play 122 | 123 | assertCapturedSuccess 124 | assertCapturedEquals "1.2.4" 125 | } 126 | 127 | testGetPlayVersionOnMutipleLines_PlayMultipleNotFirst_FirstHasVersion() 128 | { 129 | cat > ${OUTPUT_DIR}/dependencies.yaml < secure 1.2.3 132 | - play 1.2.4 133 | EOF 134 | 135 | capture get_play_version ${OUTPUT_DIR}/dependencies.yaml play 136 | 137 | assertCapturedSuccess 138 | assertCapturedEquals "1.2.4" 139 | } 140 | 141 | testGetPlayVersionOnMutipleLines_PlayMultipleDiffPropertyName() 142 | { 143 | cat > ${OUTPUT_DIR}/dependencies.yaml < secure 147 | EOF 148 | 149 | capture get_play_version ${OUTPUT_DIR}/dependencies.yaml 150 | 151 | assertCapturedSuccess 152 | assertCapturedEquals "1.2.4" 153 | } 154 | 155 | 156 | testGetPlayVersionOnMutipleLines_PlaySingle() 157 | { 158 | cat > ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml < ${OUTPUT_DIR}/dependencies.yaml <