17

I would like to use git to deploy to a website to a testing server. My website is a wordpress theme built with gulp and the repository looks like

theme.git/
-- gulpfile.js
-- src/
-- build/

I've followed the steps explained here and here which are- set up a bare repository on the server, configure the location of git work tree and write a post-receive hook to checkout the repo to that location.

The problem is I'm only looking to move or copy the build/ folder to it's location on the server. My only thought was to write a post-receive hook to that pulls the repo to one work tree location (because I think I read that bare repos don't typically have a work tree at all), and then cp's the build folder into wp-content/themes/

It seems unnecessarily complicated so I'm wondering if there's a more efficient / more common way to go about it. Thanks!

rob-gordon
  • 1,099
  • 2
  • 15
  • 32

4 Answers4

5

Your approch for using git so extensively for the deployment seems a bit weird, mainly because git is primary a source code management system, not a deployment tool. It is true that you can do many kind of weird stuff with git hooks, but for some reason or another I feel those a tendency to return to haunt you.

Normally I would recommend you to use somekind of continuous integration tool for the job. One possible workflow, which I could use myself, would be

  1. Store your theme files in a public repository at GitHub. It's free, there probably are no great secrets in your theme source code, and as an additional bonus you could even open source you theme.
  2. Set up a CI job with Travis CI for your repository. You basicly get a free build machine instance in the cloud, and you can do all sorts of stuff before or after build. You could eg. run gulp build (or whatever your task name is) there, so you wouldn't have to store the build directory in the git repo at all.
  3. In the Travis after_success hook you could then copy the build directory to the target server for example by using scp. Here is an example of doing the very same thing with FTP. Travis supports encryption of sensitive data, so you don't have to worry (at least so much) about storing username and password in the git repo.

That flow is useful when you want to deploy the build everytime you commit something to the git repo. BTW, when you use it for the first time it really feels like magic: "I just made this git push, and now the change is already live on my server."

However you mentioned that you want to deploy the code to a testing server. It is true that CI tools (such as Travis) can be used to maintain a flow between different deployment steps, out of which many are testing servers. One example flow for large projects could be

development -> tests passing? -> release -> tests passing? -> integration -> tests passing? -> staging -> tests passing? -> production

...where the flow could be either partly or fully automated with a CI tool.

However you made it sound like that in your case deploying of build is kind of a one-time thing, which you sometimes just want to do manually. (I apologize if I misinterpreted you.) For these kind of one-time tasks the use of shell scripts or task management tools is more fitting.

You mentioned that you're already using gulp. That's a very handy tool for the job, especially because you can easily combine different "streams of tasks". You could have one task for building the theme (gulp build) and another for test server deployment (gulp deploy-test), which just extends the build task with an additional step for copying of files to the test server. gulp-scp looks like a fine plugin for the task (I haven't used it myself though, it was just the first search result from google). If that does not work out, you can always call scp manually with gulp-shell or similar.

You could even parametrize the deployment tasks so you could do something like: gulp deploy --test and gulp deploy --production

There you go, this was your first lesson in devops. There's a whole world of things to learn if this kind of task automation in software projects sounds interesting to you.

Community
  • 1
  • 1
cido
  • 454
  • 2
  • 1
  • While there's some good info here, it doesn't answer the question about using Git hooks. – rnevius May 13 '15 at 05:58
  • I upvoted this answer as I thought it was a *useful* response to the OP's query regarding "a more efficient / more common way" while jthill's answer was useful for the git hooks aspect. – Anthony Geoghegan May 15 '15 at 08:20
3

This is straightforward git read-tree work. Keep a manifest aka index for what's in your deployment directory and handle your updates with a pre-receive like so:

#!/bin/sh
while read old new ref; do [[ $ref = refs/heads/master ]] && {
    export GIT_INDEX_FILE=deployment-manifest
    export GIT_WORK_TREE=/path/to/deployment
    git read-tree -um `git write-tree` $new:build || exit 1
}; done

Note that if some file being deployed this way has been changed in the deployment tree, the git read-tree here and the push will fail because git won't overwrite content you haven't told it about.

jthill
  • 42,819
  • 4
  • 65
  • 113
0

I would divide your project into two repos.

  1. Source. Includes source and whatever. Excludes the /build/ directory. Use this only for source control. This never goes to the website (it may be unsafe to store your code on the website, even in the form of a git repo).

  2. Deployment. Only /build/ directory. You can initiate a new git repo inside the directory. This has a remote repo on the server; you can use the post-receive hook to deploy, as before.

Nick Volynkin
  • 11,882
  • 6
  • 39
  • 62
0

I use git for deployment all the time. There's nothing weird about it at all, and I don't know what @cido has against it. There's a great deal of value in being able to go back in time to any point on your 'deploy' branch and being able to see precisely what was live on your server at that time.

Don't confuse the git repo that you're using for storage vs the one that you're using for deployment. You should have a completely clean git tree checked out into your production area (whatever that is) and as I suggested you may want to have a separate branch called 'deploy' or 'production' or 'staging' or whatever.

Your post-receive hook then just needs to run a script that goes into your production area, and pulls your deploy branch to update.

If you need this to be robust against files being placed there outside of what git will do (e.g. temp files generated at runtime) then you may want to call git clean -dfx before pulling. And there are other things that you might want to do if you're expecting this server to be rebuilt from scratch on a regular basis (e.g. in a cloud deployment) but it sounds like doing the initial setup manually should be OK for your use case.

cping the build directory into place sounds fine, only I'd use rsync because it'll generally be faster if the changes are only incremental.

Ewan Mellor
  • 6,315
  • 1
  • 21
  • 38
  • Sorry Ewan if I sounded like I have something against for using git for deployment; that wasn't my intention at all. I work in a software agency, so I've seen quite a many projects flowing through our hands. It's just that I've literally never seen a project where git was used for deploying. Sure there are tags for releases (eg. when using git flow) and so on, but the actual deployment has always been handled with other tools. I believe you if you say that you use it all the time. It's just that from _my_ POV, and from _my_ experience, the idea of using git for deployment just feels weird. – cido May 19 '15 at 11:33