14

I'm building sites using Jekyll, which compiles ERB, SASS, &c. into plain HTML & CSS.

After most commits, I'd like to compile the site and commit the compiled version in a separate repository or branch so that it can be pushed to a static server.

What is the best way to go about this?

I already have a solution, but I was hoping someone might have a more elegant one.

5 Answers 5

5
+100

After most commits, I'd like to compile the site and commit the compiled version in a separate repository or branch so that it can be pushed to a static server.

The right Keyword for you is "Continuous Integration".

You can use a CI Software like Jenkins to build your system after every commit, after creating or modifying a pull request, or just nightly.

The Build Script which you configure in the CI Software is than responsible to deploy the build artefacts, in that case your compiled version, to your target system like an s3 bucket. You can also do a programmatic commit of your artefacts to a different git repo.

Have a look here: https://jenkins.io/doc/

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer. I'm afraid that might be overkill for the situation, and am hoping to find a simple way to do it with Git, so I'm going to leave the question open for now.
2

Your solution would mix in the same repo "source commits" and "delivery commits" (the _site compiled version), which is not the best practice (and will increase the size of the Git repo needlessly)

I would create a separate repo "site" that I would add as a submodule to your current repo, in a path called _site/.

cd /path/to/current/repo git rm -R _site git submodule add -- /url/repo/site _site 

That way, each time you build your delivery with bundle exec jekyll build, it is done in a separate repo (in _site), where you can add, commit, and even push directly to where you want to test it.
Then you go back to your main repo, where you add and commit the gitlink (special entry in the index), establishing a strong link between the exact version of the source, and the exact version of the delivery (the built site).

4 Comments

Ah, I forgot to mention in my solution that I used git init _site/, so the commits were actually going to a separate repository. It seems to me that, if anything, the source should be the submodule.
@Zaz Exactly: using only git init would not make it a submodule, only a nested git repo, which is bad, as I detailed in stackoverflow.com/a/41968295/6309.
I have _site/ in .gitignore, is there any way I can shoot myself in the foot with this setup?
@Zaz Yes: a submodule requires you to not ignore the root folder of the nested repo, as it is a gitlink (the special entry referencing the SHA1 of the nested repo)
2

As you requested

I do not recommend you to use the same repo to store your compiled code. Because it can be obtained from any state of source code and it will be unnesessary dublication of information.

So, in this case you want to use git as CI tool. You should create another repo for compiled site and make there commits each time you need it.

I suggest you to choose branch for "production" state of code. And when you commiting in that branch - code should be rebuilded. Lets name it "production".

  1. Make separate git repo for builded code.
  2. Put this code to post-commit hook in your src repo. It will handle all commits in the production branch, checkout the code to temporary directory, make build and commit the changes.
srcDir='../srcWorkTree' buildedRepo='../buildedRepo' if [ `git rev-parse --abbrev-ref HEAD` == "production" ]; then echo "making builded code commit..." mkdir -p $srcDir # http://stackoverflow.com/questions/4479960/git-checkout-to-a-specific-folder git checkout-index -a -f --prefix=$srcDir/ bundle exec jekyll build --source $srcDir --destination $buildedRepo cd $buildedRepo git add -A commitInfo=$( git log -1 --pretty="%h %B" ) git commit -m "autobuild for $commitInfo" # git push fi 

Another variant

As i can suppose, you have access to your production server. At least you mention that you have git repo there. So it will be reasonable to make there post-receive hook to build your code into target directory. It will be more clear and simple instead of doing it on the local machine as i described.

I suppose that this repo is "bare" because you shouldn't have possibility to make changes on the server.

post-receive hook:

#!/bin/sh siteDir='/var/www/site' tmpSrcDir='/var/www/site' echo "**** [builder's post-receive hook]" while read oldrev newrev refname do if [ $refname = refs/heads/production ] then GIT_WORK_TREE=$tmpSrcDir git checkout --detach $newrev bundle exec jekyll build --source $tmpSrcDir --destination $siteDir fi done exit 0 

And few comments

I see, you tryed to use submodule to store your builded site. I don't recommend that. There is no sense because your source code not depends on builded code.

Comments

2

I'll just suggest another option : do not store the compiled versions in git, store them somewhere else.

To give you our workflow as an example :

  • when we need to test a particular commit, we run it through our CI process which produces a .tar.gz archive, and we use our deploy tool to test it on a staging server ;

  • when we select a commit for a release version, we tag this commit in git, we run it through out CI process, the .tar.gz is marked with the version number and stored in some releases/ directory on our deployment server.

We have a backup of our releases/ folder, but should we loose it, we could also rebuild any particular build from source (based on the tag).

Comments

1

Initialize a Git repo in _site/, then add a Git post-commit hook, .git/hooks/post-commit:

echo -n "Add commit to compiled version? (y/N) " read answer < /dev/tty if [ "$answer" != "y" ]; then exit; fi message=$( git log -1 --pretty=%B ) git stash --all bundle exec jekyll build cd _site git add --all git commit -m "$message" cd .. git stash pop 

Now, every time you commit, you will be asked whether you would like to add a commit to the compiled version.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.