One of the things that got me to use Jekyll, a static site generator, was that I could easily build my blog on GitHubPages, customize URLs, host source code on GitHub and deploy it to the cloud. I also wanted to build a Jekyll blog and host it on Azure Web Apps. The problem encountered, however is that Jekyll is based on Ruby and by default, Azure App Service
does not support it.
Basically, Azure App Service
supports continuous deployment from source code control and repository tools like GitHub, BitBucket, and Visual Studio Team Services. But it does not have out-of-the-box support for Ruby, a requirement for building Jekyll sites.
Therefore I had to externalize the continuous delivery with certain batch files through Kudu. I also added an extension to Azure Web app. By the way, Kudu is the engine behind git deployments in Azure Web Sites.
Let’s start deploying Jekyll to Azure App Service
(Web app). I will assume you already have your Jekyll blog running locally and your repository on GitHub. If you don’t, follow Jekyll’s getting started guide.
Step 1 - Setup your deployment settings and scripts
You will need to create four files on your site root folder. Gemfile might have been created already.
-
.deployment
.deployment file will be seen by Kudu and will call deploy.cmd
[config]
command = deploy.cmd
-
deploy.cmd
deploy.cmd will call getruby.cmd and will ensure Ruby is installed. Also, Kudu will sync the files from Jekyll under the _site directory
@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off
:: Prerequisites
:: Verify node.js installed
where node 2>nul >nul
IF %ERRORLEVEL% NEQ 0 (
echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
goto error
)
:: Setup
setlocal enabledelayedexpansion
SET ARTIFACTS=%~dp0%..\artifacts
IF NOT DEFINED DEPLOYMENT_SOURCE (
SET DEPLOYMENT_SOURCE=%~dp0%.
)
IF NOT DEFINED DEPLOYMENT_TARGET (
SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
)
IF NOT DEFINED NEXT_MANIFEST_PATH (
SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest
IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
)
)
IF NOT DEFINED KUDU_SYNC_CMD (
:: Install kudu sync
echo Installing Kudu Sync
call npm install kudusync -g --silent
IF !ERRORLEVEL! NEQ 0 goto error
:: Locally just running "kuduSync" would also work
SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
)
ECHO CALLING GET RUBY
call :ExecuteCmd "getruby.cmd"
ECHO WE MADE IT
:: Deployment
echo Handling Basic Web Site deployment.
:: 1. KuduSync
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_SOURCE%/_site" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
)
:: Post deployment stub
IF DEFINED POST_DEPLOYMENT_ACTION call "%POST_DEPLOYMENT_ACTION%"
IF !ERRORLEVEL! NEQ 0 goto error
goto end
:: Execute command routine that will echo out when error
:ExecuteCmd
setlocal
set _CMD_=%*
call %_CMD_%
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
exit /b %ERRORLEVEL%
:error
endlocal
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul
:exitSetErrorLevel
exit /b 1
:exitFromFunction
()
:end
endlocal
echo Finished successfully.
-
getruby.cmd
getruby.cmd file will download the latest version of Ruby and will install it on your
App Service
instance. Also, the script will install all the dependencies in your Gemfile, which is below, and will execute Jekyll build command via bundler.
@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off
REM Put Ruby in Path
REM You can also use %TEMP% but it is cleared on site restart. Tools is persistent.
SET PATH=%PATH%;D:\home\site\deployments\tools\r\ruby-2.2.4-x64-mingw32\bin
REM I am in the repository folder
pushd D:\home\site\deployments
if not exist tools md tools
cd tools
if not exist r md r
cd r
if exist ruby-2.2.4-x64-mingw32 goto end
echo No Ruby, need to get it!
REM Get Ruby and Rails
REM 64bit
curl -o ruby224.zip -L https://bintray.com/artifact/download/oneclick/rubyinstaller/ruby-2.2.4-x64-mingw32.7z?direct
REM Azure puts 7zip here!
echo START Unzipping Ruby
SetLocal DisableDelayedExpansion & d:\7zip\7za x -xr!*.ri -y ruby224.zip > rubyout
echo DONE Unzipping Ruby
REM Get DevKit to build Ruby native gems
REM If you don't need DevKit, rem this out.
curl -o DevKit.zip http://cdn.rubyinstaller.org/archives/devkits/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe
echo START Unzipping DevKit
d:\7zip\7za x -y -oDevKit DevKit.zip > devkitout
echo DONE Unzipping DevKit
REM Init DevKit
ruby DevKit\dk.rb init
REM Tell DevKit where Ruby is
echo --- > config.yml
echo - D:/home/site/deployments/tools/r/ruby-2.2.4-x64-mingw32 >> config.yml
REM Setup DevKit
ruby DevKit\dk.rb install
REM Update Gem223 until someone fixes the Ruby Windows installer https://github.com/oneclick/rubyinstaller/issues/261
curl -L -o update.gem https://github.com/rubygems/rubygems/releases/download/v2.2.3/rubygems-update-2.2.3.gem
call gem install --local update.gem
call update_rubygems --no-ri --no-rdoc > updaterubygemsout
ECHO What's our new Rubygems version?
call gem --version
call gem uninstall rubygems-update -x
popd
:end
REM Need to be in Reposistory
cd %DEPLOYMENT_SOURCE%
cd
call gem install bundler
ECHO Bundler install (not update!)
call bundle install
cd %DEPLOYMENT_SOURCE%
cd
ECHO Running Jekyll
call bundle exec jekyll build
REM KuduSync is after this!
-
Gemfile
add the following:
[config]
command = deploy.cmd
Don’t miss part two, Create your Azure Web app
and Deploy.
The scripts provided were based on articles by Scott Hanselman and Khalid Abuhakmeh.