Saturday, December 1, 2012

Deploying All Dart Pub Dependencies to Heroku: Take 2

‹prev | My Chain | next›

Yesterday, I was able to deploy my full-stack Dart application to Heroku, thanks to the heroku-buildpack-dart. That buildpack installed Dart Pub dependencies on the server-side. I forked the buildpack so that I could get it to install client-side dependencies as well.

My fork was coupled to the current layout of my Dart Comics sample app. Today, I would like to generalize it to work regardless of layout. Ultimately, I will submit a pull request back to the original repository, but mostly I do not want to be tied to my current layout.

As far as I know, the only way to test buildpacks is to push a change to a repository using said buildpack. I am new to the world of Heroku buildpacks, so there may be a better way, but this is the limitation that I have to live with for now. As such, I hope to perform very few actual deploys. Instead, I write a bash script to run locally. Once it does what I expect, I will copy it in the buildpack's compile script.

What I need is for the buildpack to run through my entire app looking for Dart Pub pubspec.yaml files. In any directory with one such file, I want the buildpack to run pub install. Lastly, if that directory also has a web sub-directory, I need the buildpack to create a relative symbolic link (otherwise it results in a broken link to a build path).

Starting with just running pub install in directories with pubspec.yaml files, I use the following bash code:
root_dir=`pwd`

for filename in `find . -name pubspec.yaml`; do
    pub_dir=`dirname $filename`
    echo "Found pubspec.yaml in $root_dir/$pub_dir"
    cd $root_dir/$pub_dir
    pub install
done
Running that in my local copy of Dart Comics, I see that it does, in fact, find both pubspec.yaml files and install the requisite dependencies:
➜  dart-comics git:(master) ~/bin/pub.sh
Found pubspec.yaml in /home/chris/repos/dart-comics/.
Resolving dependencies...
Dependencies installed!
Found pubspec.yaml in /home/chris/repos/dart-comics/./public/scripts
Resolving dependencies...
Dependencies installed!
To check for the existence of the web sub-direction, I use the -e bash function:
root_dir=`pwd`

for filename in `find . -name pubspec.yaml`; do
    pub_dir=`dirname $filename`
    echo "Found pubspec.yaml in $root_dir/$pub_dir"
    cd $root_dir/$pub_dir
    pub install

    if [ -e $root_dir/$pub_dir/web/packages ]; then
        cd $root_dir/$pub_dir/web
        echo -n '*** '
        pwd
    fi
done
And that also does the trick as I see my multi-asterisked tracer bullet:
➜  dart-comics git:(master) ~/bin/pub.sh
Found pubspec.yaml in /home/chris/repos/dart-comics/.
Resolving dependencies...
Dependencies installed!
Found pubspec.yaml in /home/chris/repos/dart-comics/./public/scripts
Resolving dependencies...
Dependencies installed!
*** /home/chris/repos/dart-comics/public/scripts/web
Now for the moment of truth, I adopt this in the buildpack's compile script:
message "-----> Install packages"

cd $BUILD_DIR

for filename in `find . -name pubspec.yaml | grep -v dart-sdk | grep -v pub-cache
`; do
    pub_dir=`dirname $filename`
    message "*** Found pubspec.yaml in $BUILD_DIR/$pub_dir"
    cd $BUILD_DIR/$pub_dir

    #start pub from the /app folder to have correct symlink paths
    /app/dart-sdk/bin/pub install

    if [ -e $BUILD_DIR/$pub_dir/web/packages ]; then
        cd $BUILD_DIR/$pub_dir/web
        ln -sf ../packages
        message "Fixed web symlink"
    fi
done
For the most part this is a combination of my test bash script and my work from yesterday. The only slight change is the inclusion of two grep -v (exclude) statements in the find command. With those, I hope to avoid installing SDK and already installed Pub dependencies. I commit that to my fork, make a small change to Dart Comics and:
➜  dart-comics git:(master) gp heroku master
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 316 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)

-----> Heroku receiving push
-----> Fetching custom git buildpack... done
-----> Dart app detected
-----> Installing Dart VM, build: latest
-----> Copy Dart binaries to app root
-----> Install packages
*** Found pubspec.yaml in /tmp/build_6bf4s9ejuogj/.
Resolving dependencies...
Dependencies installed!
*** Found pubspec.yaml in /tmp/build_6bf4s9ejuogj/./public/scripts
Resolving dependencies...
Dependencies installed!
Fixed web symlink
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size: 6.2MB
-----> Launching... done, v15
       http://dart-comics.herokuapp.com deployed to Heroku
Yay! That looks to have done the trick. A quick load of the site in Dartium verifies that all is well -- both with the client-side and server-side packages. I do believe that I am good to go.


Day #586

No comments:

Post a Comment