Rakefile 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. #
  2. # Copyright (c) 2008-2016 the Urho3D project.
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. # THE SOFTWARE.
  21. #
  22. require 'pathname'
  23. require 'json'
  24. require 'yaml'
  25. ### Tasks for general users ###
  26. # Usage: rake scaffolding dir=/path/to/new/project/root [project=Scaffolding] [target=Main]
  27. desc 'Create a new project using Urho3D as external library'
  28. task :scaffolding do
  29. abort 'Usage: rake scaffolding dir=/path/to/new/project/root [project=Scaffolding] [target=Main]' unless ENV['dir']
  30. project = ENV['project'] || 'Scaffolding'
  31. target = ENV['target'] || 'Main'
  32. abs_path = scaffolding ENV['dir'], project, target
  33. puts "\nNew project created in #{abs_path}.\n\n"
  34. puts "In order to configure and generate your project build tree you may need to first set"
  35. puts "'URHO3D_HOME' environment variable or use 'URHO3D_HOME' build option to point to the"
  36. puts "Urho3D project build tree or custom Urho3D SDK installation location.\n\n"
  37. puts "Please see http://urho3d.github.io/documentation/HEAD/_using_library.html for more detail.\nFor example:\n\n"
  38. puts "$ cd #{abs_path}\n$ rake cmake URHO3D_HOME=/path/to/Urho3D/build-tree\n$ rake make\n\n"
  39. end
  40. # Usage: rake cmake [<generator>] [<platform>] [<option>=<value> [<option>=<value>]] [[<platform>_]build_tree=/path/to/build-tree] [fix_scm]
  41. # e.g.: rake cmake clean android; or rake cmake android URHO3D_LIB_TYPE=SHARED; or rake cmake ios URHO3D_LUA=1 build_tree=~/ios-Build
  42. #
  43. # To avoid repeating the customized build tree locations, you can set and export them as environment variables.
  44. # e.g.: export native_build_tree=~/custom-native-Build android_build_tree=~/custom-android-Build mingw_build_tree=~/custom-mingw-Build rpi_build_tree=~/custom-rpi-Build
  45. # rake cmake rpi URHO3D_LUAJIT=1 URHO3D_LUAJIT_AMALG=1 && rake make rpi
  46. # The RPI build tree will be generated in the ~/custom-rpi-Build and then build from there
  47. desc 'Invoke one of the build scripts with the build tree location predetermined based on the target platform'
  48. task :cmake do
  49. script = 'cmake_generic'
  50. platform = 'native'
  51. build_options = ''
  52. # TODO: Need to find a way to automatically populate the array with all the Urho3D supported build options, at the moment it only contains those being used in CI
  53. ['URHO3D_64BIT', 'URHO3D_LIB_TYPE', 'URHO3D_STATIC_RUNTIME', 'URHO3D_PCH', 'URHO3D_BINDINGS', 'URHO3D_OPENGL', 'URHO3D_D3D11', 'URHO3D_TESTING', 'URHO3D_TEST_TIMEOUT', 'URHO3D_UPDATE_SOURCE_TREE', 'URHO3D_TOOLS', 'URHO3D_DEPLOYMENT_TARGET', 'URHO3D_USE_LIB64_RPM', 'CMAKE_BUILD_TYPE', 'CMAKE_OSX_DEPLOYMENT_TARGET', 'IOS', 'IPHONEOS_DEPLOYMENT_TARGET', 'WIN32', 'ANDROID', 'ANDROID_ABI', 'ANDROID_NATIVE_API_LEVEL', 'RPI', 'RPI_ABI', 'WEB', 'EMSCRIPTEN_SHARE_DATA', 'EMSCRIPTEN_EMRUN_BROWSER'].each { |var|
  54. ARGV << "#{var}=\"#{ENV[var]}\"" if ENV[var] && !ARGV.find { |arg| /#{var}=/ =~ arg }
  55. }
  56. ARGV.each { |option|
  57. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  58. case option
  59. when 'cmake', 'generic'
  60. # do nothing
  61. when 'clean', 'codeblocks', 'codelite', 'eclipse', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'xcode'
  62. script = "cmake_#{option}" unless script == 'cmake_clean'
  63. when 'android', 'web', 'ios', 'mingw', 'rpi'
  64. platform = option
  65. build_options = "#{build_options} -D#{option == 'mingw' ? 'WIN32' : option.upcase}=1" unless script == 'cmake_clean'
  66. script = 'cmake_xcode' if option == 'ios'
  67. script = 'cmake_mingw' if option == 'mingw' && ENV['OS']
  68. when 'fix_scm'
  69. build_options = "#{build_options} --fix-scm" if script == 'cmake_eclipse'
  70. else
  71. build_options = "#{build_options} -D#{option}" unless /build_tree=.*/ =~ option || script == 'cmake_clean'
  72. end
  73. }
  74. build_tree = ENV["#{platform}_build_tree"] || ENV['build_tree'] || "../#{platform}-Build"
  75. unless ENV['OS']
  76. ccache_envvar = ENV['CCACHE_SLOPPINESS'] ? '' : 'CCACHE_SLOPPINESS=pch_defines,time_macros' # Only attempt to do the right thing when user hasn't done it
  77. ccache_envvar = "#{ccache_envvar} CCACHE_COMPRESS=1" unless ENV['CCACHE_COMPRESS']
  78. end
  79. system "#{ccache_envvar} ./#{script}#{ENV['OS'] ? '.bat' : '.sh'} \"#{build_tree}\" #{build_options}" or abort
  80. end
  81. # Usage: rake make [<platform>] [<option>=<value> [<option>=<value>]] [[<platform>_]build_tree=/path/to/build-tree] [numjobs=n] [clean_first] [unfilter]
  82. # e.g.: rake make android; or rake make android doc; or rake make ios config=Debug sdk=iphonesimulator build_tree=~/ios-Build
  83. desc 'Build the generated project in its corresponding build tree'
  84. task :make do
  85. numjobs = ENV['numjobs'] || ''
  86. platform = 'native'
  87. cmake_build_options = ''
  88. build_options = ''
  89. unfilter = false
  90. ['config', 'target', 'sdk', 'ARCHS', 'ARGS', 'unfilter', 'verbosity'].each { |var|
  91. ARGV << "#{var}=\"#{ENV[var]}\"" if ENV[var] && !ARGV.find { |arg| /#{var}=/ =~ arg }
  92. }
  93. ARGV.each { |option|
  94. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  95. case option
  96. when 'codeblocks', 'codelite', 'eclipse', 'generic', 'make', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'xcode'
  97. # do nothing
  98. when 'android', 'web', 'ios', 'mingw', 'rpi'
  99. platform = option
  100. when 'clean_first'
  101. cmake_build_options = "#{cmake_build_options} --clean-first"
  102. when 'unfilter'
  103. unfilter = true
  104. else
  105. if /(?:config|target)=.*/ =~ option
  106. cmake_build_options = "#{cmake_build_options} --#{option.gsub(/=/, ' ')}"
  107. elsif /(?:ARCHS|ARGS)=.*/ =~ option
  108. # The ARCHS option is only applicable for xcodebuild, useful to specify a non-default arch to build when in Debug build configuration where ONLY_ACTIVE_ARCH is set to YES
  109. # The ARGS option is only applicable for make, useful to pass extra arguments while building a specific target, e.g. ARGS=-VV when the target is 'test' to turn on extra verbose mode
  110. build_options = "#{build_options} #{option}"
  111. elsif /unfilter=\W*?(?<unfilter_value>\w+)/ =~ option
  112. unfilter = !(/(?:true|yes|1)/i =~ unfilter_value).nil?
  113. elsif /verbosity=.*/ =~ option
  114. # The verbosity option is only applicable for msbuild when building RUN_TESTS, useful to specify the verbosity of the test output
  115. if ARGV.include?('target=RUN_TESTS')
  116. build_options = "#{build_options} /#{option.gsub(/=/, ':')}"
  117. unfilter = true
  118. end
  119. elsif /(?:build_tree|numjobs)=.*/ !~ option
  120. build_options = "#{build_options} #{/=/ =~ option ? '-' + option.gsub(/=/, ' ') : option}"
  121. end
  122. end
  123. }
  124. build_tree = ENV["#{platform}_build_tree"] || ENV['build_tree'] || "../#{platform}-Build"
  125. unless ENV['OS']
  126. ccache_envvar = ENV['CCACHE_SLOPPINESS'] ? '' : 'CCACHE_SLOPPINESS=pch_defines,time_macros' # Only attempt to do the right thing when user hasn't done it
  127. ccache_envvar = "#{ccache_envvar} CCACHE_COMPRESS=1" unless ENV['CCACHE_COMPRESS']
  128. end
  129. if !Dir.glob("#{build_tree}/*.xcodeproj").empty?
  130. # xcodebuild
  131. if !numjobs.empty?
  132. build_options = "-jobs #{numjobs}#{build_options}"
  133. end
  134. filter = !unfilter && !ARGV.include?('target=RUN_TESTS') && system('xcpretty -v >/dev/null 2>&1') ? '|xcpretty -c && exit ${PIPESTATUS[0]}' : ''
  135. elsif !Dir.glob("#{build_tree}\\*.sln".gsub(/\\/, '/')).empty?
  136. # msbuild
  137. numjobs = ":#{numjobs}" unless numjobs.empty?
  138. build_options = "/maxcpucount#{numjobs}#{build_options}"
  139. filter = unfilter ? '' : '/nologo /verbosity:minimal'
  140. filter = filter + ' /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"' if ENV['APPVEYOR']
  141. elsif !Dir.glob("#{build_tree}/*.ninja").empty?
  142. # ninja
  143. if !numjobs.empty?
  144. build_options = "-j#{numjobs}#{build_options}"
  145. end
  146. filter = ''
  147. else
  148. # make
  149. if numjobs.empty?
  150. case RUBY_PLATFORM
  151. when /linux/
  152. numjobs = (platform == 'web' ? `grep 'core id' /proc/cpuinfo |sort |uniq |wc -l` : `grep -c processor /proc/cpuinfo`).chomp
  153. when /darwin/
  154. numjobs = `sysctl -n hw.#{platform == 'web' ? 'physical' : 'logical'}cpu`.chomp
  155. when /win32|mingw|mswin/
  156. require 'win32ole'
  157. WIN32OLE.connect('winmgmts://').ExecQuery("select NumberOf#{platform == 'web' ? '' : 'Logical'}Processors from Win32_ComputerSystem").each { |out| numjobs = platform == 'web' ? out.NumberOfProcessors : out.NumberOfLogicalProcessors }
  158. else
  159. numjobs = 1
  160. end
  161. end
  162. build_options = "-j#{numjobs}#{build_options}"
  163. filter = ''
  164. end
  165. system "cd \"#{build_tree}\" && #{ccache_envvar} cmake --build . #{cmake_build_options} -- #{build_options} #{filter}" or abort
  166. end
  167. # Usage: rake android [parameter='--es pickedLibrary Urho3DPlayer:Scripts/NinjaSnowWar.as'] [intent=.SampleLauncher] [package=com.github.urho3d] [success_indicator='Initialized engine'] [payload='sleep 30'] [api=21] [abi=armeabi-v7a] [avd=test_#{api}_#{abi}] [retries=10] [retry_interval=10] [install]
  168. desc 'Test run APK in Android (virtual) device, default to Urho3D Samples APK if no parameter is given'
  169. task :android do
  170. parameter = ENV['parameter'] || '--es pickedLibrary Urho3DPlayer:Scripts/NinjaSnowWar.as'
  171. intent = ENV['intent'] || '.SampleLauncher'
  172. package = ENV['package'] || 'com.github.urho3d'
  173. success_indicator = ENV['success_indicator'] || 'Initialized engine'
  174. payload = ENV['payload'] || 'sleep 30'
  175. api = ENV['api'] || 21
  176. abi = ENV['abi'] || 'armeabi-v7a'
  177. avd = ENV['avd'] || "test_#{api}_#{abi}"
  178. retries = ENV['retries'] || 10 # minutes
  179. retry_interval = ENV['retry_interval'] || 10 # seconds
  180. build_tree = ENV['android_build_tree'] || ENV['build_tree'] || '../android-Build'
  181. install = false
  182. ARGV.each { |option|
  183. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  184. case option
  185. when 'install'
  186. install = true
  187. end
  188. }
  189. android_prepare_device api, abi, avd or abort 'Failed to prepare Android (virtual) device for test run'
  190. if install
  191. system 'rake make android' or abort 'Failed to build shared library using Android NDK'
  192. Dir.chdir build_tree do
  193. system 'android update project -p .' unless File.exist? 'local.properties'
  194. system 'ant debug' or abort 'Failed to generate APK using Android SDK'
  195. end
  196. end
  197. android_wait_for_device retries, retry_interval or abort 'Failed to start Android (virtual) device'
  198. if install
  199. system "cd \"#{build_tree}\" && ant -Dadb.device.arg='-s #{$specific_device}' installd" or abort 'Failed to install APK'
  200. end
  201. android_test_run parameter, intent, package, success_indicator, payload or abort "Failed to test run #{package}/#{intent}"
  202. end
  203. ### Tasks for Urho3D maintainers ###
  204. # Usage: rake git remote_add|sync|subtree
  205. desc 'Collections of convenience git commands, multiple git commands may be executed in one rake command'
  206. task :git do
  207. success = true
  208. consumed = false
  209. ARGV.each_with_index { |command, index|
  210. task command.to_sym do ; end; Rake::Task[command].clear # No-op hack
  211. next if consumed
  212. case command
  213. when 'remote_add', 'sync', 'subtree'
  214. success = system "rake git_#{ARGV[index, ARGV.length - index].delete_if { |arg| /=/ =~ arg }.join ' '}"
  215. consumed = true
  216. else
  217. abort 'Usage: rake git remote_add|sync|subtree' unless command == 'git' && ARGV.length > 1
  218. end
  219. }
  220. abort unless success
  221. end
  222. # Usage: rake git remote_add [remote=<local-name>] url=<remote-url>'
  223. desc 'Add a new remote and configure it so that its tags will be fetched into a unique namespace'
  224. task :git_remote_add do
  225. abort 'Usage: rake git remote_add [remote=<name>] url=<remote-url>' unless ENV['url']
  226. remote = ENV['remote'] || /\/(.*?)\.git/.match(ENV['url'])[1]
  227. system "git remote add #{remote} #{ENV['url']} && git config --add remote.#{remote}.fetch +refs/tags/*:refs/tags/#{remote}/* && git config remote.#{remote}.tagopt --no-tags && git fetch #{remote}" or abort
  228. end
  229. # Usage: rake git sync [master=master] [upstream=upstream]
  230. desc "Fetch and merge an upstream's remote branch to a fork's local branch then pushing the local branch to the fork's corresponding remote branch"
  231. task :git_sync do
  232. master = ENV['master'] || 'master'
  233. upstream = ENV['upstream'] || 'upstream'
  234. system "git fetch #{upstream} && git checkout #{master} && git merge -m 'Sync at #{Time.now.localtime}.' #{upstream}/#{master} && git push && git checkout -" or abort
  235. end
  236. # Usage: rake git subtree split|rebase|add|push|pull
  237. desc 'Misc. sub-commands for git subtree operations'
  238. task :git_subtree do
  239. ARGV.each { |subcommand|
  240. task subcommand.to_sym do ; end; Rake::Task[subcommand].clear # No-op hack
  241. case subcommand
  242. when 'split'
  243. abort 'Usage: rake git subtree split subdir=</path/to/subdir/to/be/split> [split_branch=<name>]' unless ENV['subdir']
  244. ENV['split_branch'] = "#{Pathname.new(ENV['subdir']).basename}-split" unless ENV['split_branch']
  245. system "git subtree split --prefix #{ENV['subdir']} -b #{ENV['split_branch']}" or abort
  246. when 'rebase'
  247. abort 'Usage: rake git subtree rebase baseline=<commit|branch|tag> split_branch=<name>' unless ENV['baseline'] && ENV['split_branch']
  248. ENV['rebased_branch'] = "#{Pathname.new(ENV['baseline']).basename}-#{ENV['rebased_branch_suffix'] || 'modified-for-urho3d'}"
  249. head = `git log --pretty=format:'%H' #{ENV['split_branch']} |head -1`.chomp
  250. tail = `git log --reverse --pretty=format:'%H' #{ENV['split_branch']} |head -1`.chomp
  251. system "git rebase --onto #{ENV['baseline']} #{tail} #{head} && git checkout -b #{ENV['rebased_branch']}" or abort "After resolving all the conflicts, issue this command manually:\ngit checkout -b #{ENV['rebased_branch']}"
  252. when 'add'
  253. abort 'Usage: rake git subtree add subdir=</path/to/subdir/to/be/split> remote=<name> baseline=<commit|branch|tag>' unless ENV['subdir'] && ENV['remote'] && ENV['baseline']
  254. ENV['rebased_branch'] = "#{Pathname.new(ENV['baseline']).basename}-#{ENV['rebased_branch_suffix'] || 'modified-for-urho3d'}"
  255. system "git push -u #{ENV['remote']} #{ENV['rebased_branch']} && git rm -r #{ENV['subdir']} && git commit -qm 'Replace #{ENV['subdir']} subdirectory with subtree.' && git subtree add --prefix #{ENV['subdir']} #{ENV['remote']} #{ENV['rebased_branch']} --squash" or abort
  256. when 'push'
  257. abort 'Usage: rake git subtree push subdir=</path/to/subdir/to/be/split> remote=<name> baseline=<commit|branch|tag>' unless ENV['subdir'] && ENV['remote'] && ENV['baseline']
  258. ENV['rebased_branch'] = "#{Pathname.new(ENV['baseline']).basename}-#{ENV['rebased_branch_suffix'] || 'modified-for-urho3d'}"
  259. system "git subtree push --prefix #{ENV['subdir']} #{ENV['remote']} #{ENV['rebased_branch']}" or abort
  260. when 'pull'
  261. abort 'Usage: rake git subtree pull subdir=</path/to/subdir/to/be/split> remote=<name> baseline=<commit|branch|tag>' unless ENV['subdir'] && ENV['remote'] && ENV['baseline']
  262. ENV['rebased_branch'] = "#{Pathname.new(ENV['baseline']).basename}-#{ENV['rebased_branch_suffix'] || 'modified-for-urho3d'}"
  263. system "git subtree pull --prefix #{ENV['subdir']} #{ENV['remote']} #{ENV['rebased_branch']} --squash" or abort
  264. else
  265. abort 'Usage: rake git subtree split|rebase|add|push|pull' unless subcommand == 'git_subtree' && ARGV.length > 1
  266. end
  267. }
  268. end
  269. ### Tasks for CI builds and tests ###
  270. # Usage: NOT intended to be used manually
  271. desc 'Build and run the Annotate tool (temporary)'
  272. task :ci_annotate do
  273. system 'rake cmake URHO3D_CLANG_TOOLS=1 && rake make annotate' or abort 'Failed to annotate'
  274. system "git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git && if git fetch origin clang-tools:clang-tools 2>/dev/null; then git push -qf origin --delete clang-tools; fi && git checkout -B clang-tools && git stash -q && git reset --hard HEAD~ && git stash pop -q && sed -i \"s/COVERITY_SCAN_THRESHOLD/URHO3D_PCH=0 URHO3D_BINDINGS=1 COVERITY_SCAN_THRESHOLD/g\" .travis.yml && git add -A .travis.yml Source/Urho3D && if git commit -qm 'Result of Annotator tool. [skip appveyor] [ci only: clang-tools]'; then git push -q -u origin clang-tools >/dev/null 2>&1; fi" or abort 'Failed to push clang-tools branch'
  275. end
  276. # Usage: NOT intended to be used manually
  277. desc 'Push the generated binding source files to clang-tools branch (temporary)'
  278. task :ci_push_bindings do
  279. abort "Skipped pushing to #{ENV['TRAVIS_BRANCH']} branch due to moving HEAD" unless `git fetch -qf origin #{ENV['TRAVIS_PULL_REQUEST'] == 'false' ? ENV['TRAVIS_BRANCH'] : %Q{+refs/pull/#{ENV['TRAVIS_PULL_REQUEST']}/head'}}; git log -1 --pretty=format:'%H' FETCH_HEAD` == ENV['TRAVIS_COMMIT']
  280. system "rm -rf fastcomp-clang && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git && git add -A Source/Urho3D && if git commit -qm 'Result of AutoBinder tool. [ci skip]'; then git push -q origin HEAD:#{ENV['TRAVIS_BRANCH']} >/dev/null 2>&1; fi" or abort "Failed to push #{ENV['TRAVIS_BRANCH']} branch"
  281. end
  282. # Usage: NOT intended to be used manually
  283. desc 'Configure, build, and test Urho3D project'
  284. task :ci do
  285. $start_time = Time.now - ENV['ELAPSED'].to_i - 30 if ENV['ELAPSED'] # Adjustment for rounding up to the next nearest minute
  286. # Skip if only performing CI for selected branches and the current branch is not in the list
  287. unless ENV['RELEASE_TAG']
  288. next if ENV['TRAVIS'] && /\[skip travis\]/ =~ ENV['COMMIT_MESSAGE'] # For feature parity with AppVeyor's [skip appveyor]
  289. matched = /\[ci only:(.*?)\]/.match(ENV['COMMIT_MESSAGE'])
  290. next if matched && !matched[1].split(/[ ,]/).reject!(&:empty?).map { |i| /#{i}/ =~ (ENV['TRAVIS_BRANCH'] || ENV['APPVEYOR_REPO_BRANCH']) }.any?
  291. end
  292. # Obtain our custom data, if any
  293. if ENV['APPVEYOR']
  294. # AppVeyor does not provide job number environment variable in the same semantics as TRAVIS_JOB_NUMBER nor it supports custom data in its .appveyor.yml document
  295. if ENV['excluded_sample']
  296. pairs = ENV['excluded_sample'].split
  297. samples = pairs.pop.split ','
  298. matched = true
  299. pairs.each { |pair|
  300. kv = pair.split '='
  301. matched = false if ENV[kv.first] != kv.last
  302. }
  303. samples.each { |name| ENV["EXCLUDE_SAMPLE_#{name}"] = '1' } if matched
  304. end
  305. else
  306. data = YAML::load(File.open('.travis.yml'))['data']
  307. data['excluded_sample']["##{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"].each { |name| ENV["EXCLUDE_SAMPLE_#{name}"] = '1' } if data && data['excluded_sample'] && data['excluded_sample']["##{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"]
  308. end
  309. # Unshallow the clone's history when necessary
  310. if ENV['CI'] && ENV['PACKAGE_UPLOAD'] && !ENV['RELEASE_TAG']
  311. system "bash -c 'git fetch --unshallow'" or abort 'Failed to unshallow cloned repository'
  312. end
  313. # Show CMake version
  314. system "bash -c 'echo && cmake --version && echo'" or abort 'Failed to find CMake'
  315. # Using out-of-source build tree when using Travis-CI; 'build_tree' environment variable is already set when on AppVeyor
  316. ENV['build_tree'] = '../Build' unless ENV['APPVEYOR']
  317. # Always use a same build configuration to keep ccache's cache size small; single-config generator needs the option when configuring, while multi-config when building
  318. ENV[ENV['XCODE'] ? 'config' : 'CMAKE_BUILD_TYPE'] = 'Release' if ENV['USE_CCACHE']
  319. # Only able to test run when targeting 64-bit native Linux platform, 64-bit native OSX platform, and Web platform; and when not packaging due to time constraint
  320. ENV['URHO3D_TESTING'] = '1' if ((ENV['LINUX'] && !ENV['URHO3D_64BIT']) || (ENV['OSX'] && !ENV['IOS']) || ENV['WEB'] || ENV['APPVEYOR']) && !ENV['PACKAGE_UPLOAD']
  321. # When not explicitly specified then use generic generator
  322. generator = ENV['XCODE'] ? 'xcode' : (ENV['APPVEYOR'] ? 'vs2015' : '')
  323. # LuaJIT on MinGW build is not possible on Travis-CI with Ubuntu LTS 12.04 as its GCC cross-compiler version is too old, wait until we have Ubuntu LTS 14.04
  324. # LuaJIT on Web platform is not possible
  325. jit = (ENV['WIN32'] && ENV['TRAVIS']) || ENV['WEB'] ? '' : 'JIT=1 URHO3D_LUAJIT_AMALG='
  326. system "bash -c 'rake cmake #{generator} URHO3D_LUA#{jit}=1 URHO3D_DATABASE_SQLITE=1 URHO3D_EXTRAS=1'" or abort 'Failed to configure Urho3D library build'
  327. if ENV['AVD'] && !ENV['PACKAGE_UPLOAD'] # Skip APK test run when packaging
  328. # Prepare a new AVD in another process to avoid busy waiting
  329. android_prepare_device ENV['AVD'], ENV['ANDROID_ABI'] or abort 'Failed to prepare Android (virtual) device for test run'
  330. end
  331. # Temporarily put the logic here for clang-tools migration until everything else are in their places
  332. if ENV['URHO3D_BINDINGS']
  333. system 'rake make' or abort 'Failed to build or test Urho3D library with annotated source files'
  334. system 'rake ci_push_bindings' or abort
  335. next
  336. end
  337. system "bash -c 'rake make'" or abort 'Failed to build Urho3D library'
  338. if ENV['URHO3D_TESTING'] && !timeup
  339. # Multi-config CMake generators use different test target name than single-config ones for no good reason
  340. test = "rake make target=#{ENV['OS'] || ENV['XCODE'] ? 'RUN_TESTS' : 'test'}"
  341. system "bash -c '#{test}'" or abort 'Failed to test Urho3D library'
  342. test = "&& echo && #{test}"
  343. else
  344. test = ''
  345. end
  346. # Skip scaffolding test when time up or packaging for iOS and Web platform
  347. unless ENV['CI'] && (ENV['IOS'] || ENV['WEB']) && ENV['PACKAGE_UPLOAD'] || ENV['XCODE_64BIT_ONLY'] || timeup
  348. # Staged-install Urho3D SDK when on Travis-CI; normal install when on AppVeyor
  349. ENV['DESTDIR'] = ENV['HOME'] || Dir.home unless ENV['APPVEYOR']
  350. puts "Installing Urho3D SDK to #{ENV['DESTDIR'] ? "#{ENV['DESTDIR']}/usr/local" : 'default system-wide location'}..."; $stdout.flush
  351. system "bash -c 'rake make target=install >/dev/null'" or abort 'Failed to install Urho3D SDK'
  352. # Alternate to use in-the-source build tree for test coverage
  353. ENV['build_tree'] = '.' unless ENV['APPVEYOR']
  354. # Ensure the following variables are auto-discovered during scaffolding test
  355. ENV['URHO3D_64BIT'] = nil unless ENV['APPVEYOR'] # AppVeyor uses VS generator which always requires URHO3D_64BIT as input variable
  356. ['URHO3D_LIB_TYPE', 'URHO3D_STATIC_RUNTIME', 'URHO3D_OPENGL', 'URHO3D_D3D11', 'URHO3D_SSE', 'URHO3D_DATABASE_ODBC', 'URHO3D_DATABASE_SQLITE', 'URHO3D_LUAJIT', 'URHO3D_TESTING'].each { |var| ENV[var] = nil }
  357. # Alternate the scaffolding location between Travis CI and AppVeyor for test coverage; Travis CI uses build tree while AppVeyor using source tree
  358. # First scaffolding test uses absolute path while second test uses relative path, also for test converage
  359. # First test - create a new project on the fly that uses newly installed Urho3D SDK
  360. org = (ENV['TRAVIS_REPO_SLUG'] || ENV['APPVEYOR_PROJECT_SLUG']).split('/').first
  361. Dir.chdir scaffolding "#{ENV['APPVEYOR'] ? "C:/projects/#{org}/" : (ENV['TRAVIS'] ? "#{ENV['HOME']}/build/#{org}/Build/" : '../Build/')}UsingSDK" do # The last rel path is for non-CI users, just in case
  362. puts "\nConfiguring downstream project using Urho3D SDK...\n\n"; $stdout.flush
  363. # SDK installation to a system-wide location does not need URHO3D_HOME to be defined, staged-installation does
  364. system "bash -c '#{ENV['DESTDIR'] ? 'URHO3D_HOME=~/usr/local' : ''} rake cmake #{generator} URHO3D_LUA=1 && rake make #{test}'" or abort 'Failed to configure/build/test temporary downstream project using Urho3D as external library'
  365. end
  366. # Second test - create a new project on the fly that uses newly built Urho3D library in the build tree
  367. Dir.chdir scaffolding "#{ENV['APPVEYOR'] ? '' : '../Build/'}UsingBuildTree" do
  368. puts "\nConfiguring downstream project using Urho3D library in its build tree...\n\n"; $stdout.flush
  369. system "bash -c 'rake cmake #{generator} URHO3D_HOME=#{ENV['APPVEYOR'] ? '../../Build' : '..'} URHO3D_LUA=1 && rake make #{test}'" or abort 'Failed to configure/build/test temporary downstream project using Urho3D as external library'
  370. end
  371. end
  372. # Make, deploy, and test run Android APK in an Android (virtual) device
  373. if ENV['AVD'] && !ENV['PACKAGE_UPLOAD']
  374. puts "\nTest deploying and running Urho3D Samples APK..."
  375. Dir.chdir '../Build' do
  376. system 'android update project -p . && ant debug' or abort 'Failed to make Urho3D Samples APK'
  377. if android_wait_for_device
  378. system "ant -Dadb.device.arg='-s #{$specific_device}' installd" or abort 'Failed to deploy Urho3D Samples APK'
  379. android_test_run or abort 'Failed to test run Urho3D Samples APK'
  380. else
  381. puts 'Skipped test running Urho3D Samples APK as emulator failed to start in time'
  382. end
  383. end
  384. end
  385. end
  386. # Usage: NOT intended to be used manually
  387. desc 'Setup build cache'
  388. task :ci_setup_cache do
  389. clear = /\[ccache clear\]/ =~ ENV['COMMIT_MESSAGE']
  390. # Use internal cache store instead of using Travis CI one (this is a workaround for using ccache on Travis CI legacy build infra)
  391. if ENV['USE_CCACHE'].to_i == 2
  392. puts 'Setting up build cache'
  393. job_number = ".#{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"
  394. repo_slug = "#{ENV['TRAVIS_REPO_SLUG'].split('/').first}/cache-store.git"
  395. matched = /.*-([^-]+-[^-]+)$/.match(ENV['TRAVIS_BRANCH'])
  396. base_mirror = matched ? matched[1] : nil
  397. # Do not abort even when it fails here
  398. system "if ! `git clone -q --depth 1 --branch #{ENV['TRAVIS_BRANCH']}#{job_number} https://github.com/#{repo_slug} ~/.ccache 2>/dev/null`; then if ! [ #{base_mirror} ] || ! `git clone -q --depth 1 --branch #{base_mirror}#{job_number} https://github.com/#{repo_slug} ~/.ccache 2>/dev/null`; then git clone -q --depth 1 https://github.com/#{repo_slug} ~/.ccache 2>/dev/null; fi && cd ~/.ccache && git checkout -qf -b #{ENV['TRAVIS_BRANCH']}#{job_number}; fi"
  399. # Preserving .git directory before clearing the cache on Linux host system (ccache on Mac OSX does not have this problem)
  400. `mv ~/.ccache/.git /tmp` if clear && ENV['OSX'].to_i != 1
  401. end
  402. # Clear ccache on demand
  403. system "ccache -z -M #{ENV['CCACHE_MAXSIZE']} #{clear ? '-C' : ''}"
  404. # Restoring .git directory if its backup exists
  405. `if [ -e /tmp/.git ]; then mv /tmp/.git ~/.ccache; fi`
  406. end
  407. # Usage: NOT intended to be used manually
  408. desc 'Teardown build cache'
  409. task :ci_teardown_cache do
  410. # Upload cache to internal cache store if it is our own
  411. if ENV['USE_CCACHE'].to_i == 2
  412. puts 'Storing build cache'
  413. job_number = ".#{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"
  414. repo_slug = "#{ENV['TRAVIS_REPO_SLUG'].split('/').first}/cache-store.git"
  415. # Do not abort even when it fails here
  416. system "cd ~/.ccache && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/#{repo_slug} && git add -A . && git commit --amend -qm 'Travis CI: cache update at #{Time.now.utc}.' && git push -qf -u origin #{ENV['TRAVIS_BRANCH']}#{job_number} >/dev/null 2>&1"
  417. end
  418. system 'ccache -s'
  419. end
  420. # Usage: NOT intended to be used manually
  421. desc 'Update site on GitHub Pages (and source tree on GitHub while we are at it)'
  422. task :ci_site_update do
  423. # Skip when :ci rake task was skipped
  424. next unless File.exist?('../Build/CMakeCache.txt')
  425. $start_time = Time.now - ENV['ELAPSED'].to_i - 30 if ENV['ELAPSED'] # Adjustment for rounding up to the next nearest minute
  426. next if timeup
  427. puts "Updating site...\n\n"
  428. system 'git clone --depth 1 -q https://github.com/urho3d/urho3d.github.io.git ../urho3d.github.io' or abort 'Failed to clone urho3d/urho3d.github.io'
  429. # Update credits from README.md to about.yml
  430. system "ruby -lne 'BEGIN { credits = false }; puts $_ if credits; credits = true if /bugfixes by:/; credits = false if /^$/' README.md |ruby -i -le 'credits = STDIN.read; puts ARGF.read.gsub(/(?<=contributors:\n).*?\n\n/m, credits)' ../urho3d.github.io/_data/about.yml" or abort 'Failed to update credits'
  431. # Setup doxygen to use minimal theme
  432. system "ruby -i -pe 'BEGIN { a = {%q{HTML_HEADER} => %q{minimal-header.html}, %q{HTML_FOOTER} => %q{minimal-footer.html}, %q{HTML_STYLESHEET} => %q{minimal-doxygen.css}, %q{HTML_COLORSTYLE_HUE} => 200, %q{HTML_COLORSTYLE_SAT} => 0, %q{HTML_COLORSTYLE_GAMMA} => 20, %q{DOT_IMAGE_FORMAT} => %q{svg}, %q{INTERACTIVE_SVG} => %q{YES}, %q{COLS_IN_ALPHA_INDEX} => 3} }; a.each {|k, v| gsub(/\#{k}\s*?=.*?\n/, %Q{\#{k} = \#{v}\n}) }' ../Build/Docs/generated/Doxyfile" or abort 'Failed to setup doxygen configuration file'
  433. system 'cp ../urho3d.github.io/_includes/Doxygen/minimal-* ../Build/Docs' or abort 'Failed to copy minimal-themed template'
  434. release = ENV['RELEASE_TAG'] || 'HEAD'
  435. unless release == 'HEAD'
  436. system "mkdir -p ../urho3d.github.io/documentation/#{release}" or abort 'Failed to create directory for new document version'
  437. system "ruby -i -pe 'gsub(/HEAD/, %q{#{release}})' ../Build/Docs/minimal-header.html" or abort 'Failed to update document version in YAML Front Matter block'
  438. append_new_release release or abort 'Failed to add new release to document data file'
  439. end
  440. # Generate and sync doxygen pages
  441. system "cd ../Build && make -j$numjobs doc >/dev/null 2>&1 && ruby -i -pe 'gsub(/(<\\/?h)3([^>]*?>)/, %q{\\14\\2}); gsub(/(<\\/?h)2([^>]*?>)/, %q{\\13\\2}); gsub(/(<\\/?h)1([^>]*?>)/, %q{\\12\\2})' Docs/html/_*.html && rsync -a --delete Docs/html/ ../urho3d.github.io/documentation/#{release}" or abort 'Failed to generate/rsync doxygen pages'
  442. # Supply GIT credentials to push site documentation changes to urho3d/urho3d.github.io.git
  443. system "cd ../urho3d.github.io && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/urho3d/urho3d.github.io.git && git add -A . && if git commit -qm \"Travis CI: site documentation update at #{Time.now.utc}.\n\nCommit: https://github.com/$TRAVIS_REPO_SLUG/commit/$TRAVIS_COMMIT\n\nMessage: $COMMIT_MESSAGE\"; then git push -q >/dev/null 2>&1 && echo Site updated successfully; fi" or abort 'Failed to update site'
  444. next if timeup
  445. # Skip detecting source tree changes when HEAD has moved or it is too late already as a release tag has just been pushed
  446. unless ENV['RELEASE_TAG'] || `git fetch -qf origin #{ENV['TRAVIS_BRANCH']}; git log -1 --pretty=format:'%H' FETCH_HEAD` != ENV['TRAVIS_COMMIT']
  447. puts "Updating source tree...\n\n"
  448. # Supply GIT credentials to push source tree changes to urho3d/Urho3D.git
  449. system 'git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git'
  450. system "git add Source && git commit -qm 'Travis CI: source tree update at #{Time.now.utc}.' >/dev/null 2>&1" # Use extra quiet mode as there could be no changes at all
  451. if /2008-([0-9]{4}) the Urho3D project/.match(File.read('Rakefile'))[1].to_i != Time.now.year
  452. # Automatically bump copyright when crossing a new year and give instruction to clear the cache if so since the cache is of no use anyway because of massive changes
  453. system "git add #{bump_copyright_year.join ' '} && if git commit -qm 'Travis CI: bump copyright to #{Time.now.year}.\n[ccache clear]'; then git push origin HEAD:#{ENV['TRAVIS_BRANCH']} -q >/dev/null 2>&1 && echo Bumped copyright - Happy New Year!; fi" or abort "Failed to push copyright update for #{ENV['TRAVIS_BRANCH']}"
  454. ['urho3d.github.io master', 'android-ndk ndk-update-trigger', 'rpi-sysroot sysroot-update-trigger', 'emscripten-sdk sdk-update-trigger'].each { |var| pair = var.split; system "if [ ! -d ../#{pair.first} ]; then git clone -q --depth 1 --branch #{pair.last} https://github.com/urho3d/#{pair.first} ../#{pair.first}; fi" or abort "Failed to clone urho3d/#{pair.first}"; system "cd ../#{pair.first} && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/urho3d/#{pair.first} && git add #{bump_copyright_year("../#{pair.first}").join ' '} && if git commit -qm 'Travis CI: bump copyright to #{Time.now.year}.\n[ci skip]'; then git push -q >/dev/null 2>&1; fi" or abort "Failed to push copyright update for urho3d/#{pair.first}"; }
  455. elsif system("git add Docs/*API* && git commit -qm 'Test commit to detect API documentation changes'")
  456. # Automatically give instruction to do packaging when API has changed, unless the instruction is already given in this commit
  457. bump_soversion 'Source/Urho3D/.soversion' or abort 'Failed to bump soversion'
  458. system "git add Source/Urho3D/.soversion && git commit --amend -qm \"Travis CI: API documentation update at #{Time.now.utc}.\n#{ENV['PACKAGE_UPLOAD'] ? '' : '[ci package]'}\n\nCommit: https://github.com/$TRAVIS_REPO_SLUG/commit/$TRAVIS_COMMIT\n\nMessage: #{ENV['COMMIT_MESSAGE'].gsub(/\[.*\]/, '')}\" && echo Source tree updated successfully" or abort 'Failed to commit API documentation'
  459. end
  460. else
  461. puts 'Skipped detecting source tree changes due to moving HEAD' unless ENV['RELEASE_TAG']
  462. end
  463. end
  464. # Usage: NOT intended to be used manually
  465. desc 'Update web samples to GitHub Pages'
  466. task :ci_emscripten_samples_update do
  467. $start_time = Time.now - ENV['ELAPSED'].to_i - 30 if ENV['ELAPSED'] # Adjustment for rounding up to the next nearest minute
  468. next if timeup
  469. puts '"Updating Web samples in main website...'
  470. system 'git clone --depth 1 -q https://github.com/urho3d/urho3d.github.io.git ../urho3d.github.io' or abort 'Failed to clone urho3d/urho3d.github.io'
  471. system "rsync -a --delete --exclude tool --exclude *.pak ../Build/bin/ ../urho3d.github.io/samples" or abort 'Failed to rsync Web samples'
  472. update_web_samples_data or abort 'Failed to update Web json data file'
  473. root_commit, _ = get_root_commit_and_recipients
  474. system "cd ../urho3d.github.io && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/urho3d/urho3d.github.io.git && git add -A . && ( git commit -qm \"Travis CI: Web samples update at #{Time.now.utc}.\n\nCommit: https://github.com/$TRAVIS_REPO_SLUG/commit/#{root_commit}\n\nMessage: #{`git log --format=%B -n 1 #{root_commit}`}\" || true) && git push -q >/dev/null 2>&1" or abort 'Failed to update Web samples'
  475. end
  476. # Usage: NOT intended to be used manually
  477. desc 'Create all CI mirror branches'
  478. task :ci_create_mirrors do
  479. # Skip all CI branches creation if there are more commits externally
  480. abort 'Skipped creating mirror branches due to moving remote HEAD' unless `git fetch -qf origin #{ENV['TRAVIS_PULL_REQUEST'] == 'false' ? ENV['TRAVIS_BRANCH'] : %Q{+refs/pull/#{ENV['TRAVIS_PULL_REQUEST']}/head'}}; git log -1 --pretty=format:'%H' FETCH_HEAD` == ENV['TRAVIS_COMMIT'] # This HEAD movement detection logic is more complex than usual as the original intention was to allow mirror creation on PR, however, we have scaled it back for now
  481. # Skip non-mandatory branches if there are pending commits internally
  482. head = `git log -1 --pretty=format:'%H' HEAD`
  483. head_moved = head != ENV['TRAVIS_COMMIT'] # Local head may be moved because of API documentation update
  484. # Reset the head to the original commit position for mirror creation
  485. system 'git checkout -qf $TRAVIS_COMMIT' if head_moved
  486. system 'git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git' or abort 'Failed to re-checkout commit'
  487. # Limit the scanning to only master branch and limit the frequency of scanning
  488. scan = ENV['TRAVIS_BRANCH'] == 'master' && ((/\[ccache clear\]/ !~ ENV['COMMIT_MESSAGE'] && `ccache -s |grep 'cache miss'`.split.last.to_i >= ENV['COVERITY_SCAN_THRESHOLD'].to_i) || /\[ci scan\]/ =~ ENV['COMMIT_MESSAGE']) && /\[ci only:.*?\]/ !~ ENV['COMMIT_MESSAGE']
  489. # Check if it is time to generate annotation
  490. annotate = ENV['TRAVIS_BRANCH'] == 'master' && (ENV['PACKAGE_UPLOAD'] || /\[ci annotate\]/ =~ ENV['COMMIT_MESSAGE']) && /\[ci only:.*?\]/ !~ ENV['COMMIT_MESSAGE']
  491. # Determine which CI mirror branches to be auto created
  492. unless ENV['RELEASE_TAG']
  493. skip_travis = /\[skip travis\]/ =~ ENV['COMMIT_MESSAGE'] # For feature parity with AppVeyor's [skip appveyor]
  494. matched = /\[ci only:(.*?)\]/.match(ENV['COMMIT_MESSAGE'])
  495. ci_only = matched ? matched[1].split(/[ ,]/).reject!(&:empty?) : nil
  496. if ci_only
  497. ci_only.push('Coverity-Scan') if scan
  498. ci_only.push('Annotate') if annotate
  499. end
  500. else
  501. ci_only = nil
  502. end
  503. # Escape double quotes in the commit message so they do not interfere with the string interpolation below
  504. escaped_commit_message = ENV['COMMIT_MESSAGE'].gsub(/"/, '\"')
  505. # Obtain the whole stream and process the rest of documents except the first one since travis-build does not do that at the moment
  506. stream = YAML::load_stream(File.open('.travis.yml'))
  507. notifications = stream[0]['notifications']
  508. notifications['email']['recipients'] = get_root_commit_and_recipients().last unless notifications['email']['recipients']
  509. stream.drop(1).each { |doc| branch = doc.delete('branch'); ci = branch['name']; ci_branch = ENV['RELEASE_TAG'] || (ENV['TRAVIS_BRANCH'] == 'master' && ENV['TRAVIS_PULL_REQUEST'] == 'false') ? ci : (ENV['TRAVIS_PULL_REQUEST'] == 'false' ? "#{ENV['TRAVIS_BRANCH']}-#{ci}" : "PR ##{ENV['TRAVIS_PULL_REQUEST']}-#{ci}"); is_appveyor_ci = branch['appveyor']; next if skip_travis && !is_appveyor_ci; unless (branch['mandatory'] || !head_moved) && ((ci_only && ci_only.map { |i| /#{i}/ =~ ci }.any?) || (!ci_only && (branch['active'] || (scan && /Scan/ =~ ci) || (annotate && /Annotate/ =~ ci)))); system "if git fetch origin #{ci_branch}:#{ci_branch} 2>/dev/null; then git push -qf origin --delete #{ci_branch}; fi"; puts "Skipped creating #{ci_branch} mirror branch due to moving HEAD" if !ci_only && branch['active'] && head_moved; next; end; unless is_appveyor_ci; lastjob = [(doc['env']['matrix'] ? doc['env']['matrix'].length : 0) + (doc['matrix'] && doc['matrix']['include'] ? doc['matrix']['include'].length : 0), 1].max; doc['after_script'] = [*doc['after_script']] << (lastjob == 1 ? '%s' : "if [ ${TRAVIS_JOB_NUMBER##*.} == #{lastjob} ]; then %s; fi") % 'rake ci_delete_mirror'; doc['notifications'] = notifications unless doc['notifications']; doc_name = '.travis.yml'; File.open("#{doc_name}.new", 'w') { |file| file.write doc.to_yaml } else doc['on_finish'] = [*doc['on_finish']] << "if \"%PLATFORM%:%URHO3D_LIB_TYPE%\" == \"#{branch['last_job']}\" rake ci_delete_mirror"; doc_name = '.appveyor.yml'; File.open("#{doc_name}.new", 'w') { |file| file.write doc.to_yaml }; if ENV['TRAVIS']; replaced_content = File.read("#{doc_name}.new").gsub(/! /, ''); File.open("#{doc_name}.new", 'w') { |file| file.puts replaced_content }; end; end; puts "Creating #{ci_branch} mirror branch..."; system "git checkout -qB #{ci_branch} && rm .appveyor.yml .travis.yml && mv #{doc_name}.new #{doc_name} && git add -A . && git commit -qm \"#{escaped_commit_message}\" && git push -qf -u origin #{ci_branch} >/dev/null 2>&1 && git checkout -q -" or abort "Failed to create #{ci_branch} mirror branch" }
  510. # Push pending commits if any
  511. system "git push origin #{head}:#{ENV['TRAVIS_BRANCH']} -q >/dev/null 2>&1" or abort "Failed to push pending commits to #{ENV['TRAVIS_BRANCH']}" if head_moved
  512. end
  513. # Usage: NOT intended to be used manually
  514. desc 'Delete CI mirror branch'
  515. task :ci_delete_mirror do
  516. # Skip if the mirror branch has been forced pushed remotely or when we are performing a release (in case we need to rerun the job to recreate the package)
  517. unless `git log -1 --pretty=format:'%H' origin/#{ENV['TRAVIS_BRANCH'] || ENV['APPVEYOR_REPO_BRANCH']}`.gsub(/'/, '') == (ENV['TRAVIS_COMMIT'] || ENV['APPVEYOR_REPO_COMMIT']).chop && !ENV['RELEASE_TAG']
  518. # Do not use "abort" here because AppVeyor, unlike Travis, also handles the exit status of the processes invoked in the "on_finish" section of the .appveyor.yml
  519. # Using "abort" may incorrectly (or correctly, depends on your POV) report the whole CI as failed when the CI mirror branch deletion is being skipped
  520. $stderr.puts "Skipped deleting #{ENV['TRAVIS_BRANCH'] || ENV['APPVEYOR_REPO_BRANCH']} mirror branch"
  521. next
  522. end
  523. system "bash -c 'git config user.name #{ENV['GIT_NAME']} && git config user.email #{ENV['GIT_EMAIL']} && git remote set-url --push origin https://#{ENV['GH_TOKEN']}@github.com/#{ENV['TRAVIS_REPO_SLUG'] || ENV['APPVEYOR_REPO_NAME']}.git'"
  524. system "bash -c 'git push -qf origin --delete #{ENV['TRAVIS_BRANCH'] || ENV['APPVEYOR_REPO_BRANCH']} >/dev/null 2>&1'" or abort "Failed to delete #{ENV['TRAVIS_BRANCH'] || ENV['APPVEYOR_REPO_BRANCH']} mirror branch"
  525. end
  526. # Usage: NOT intended to be used manually
  527. desc 'Make binary package and upload it to a designated central hosting server'
  528. task :ci_package_upload do
  529. # Using out-of-source build tree when using Travis-CI; 'build_tree' environment variable is already set when on AppVeyor
  530. ENV['build_tree'] = '../Build' unless ENV['APPVEYOR']
  531. # Always use Release build configuration when using Xcode; 'config' environment variable is already set when on AppVeyor
  532. ENV['config'] = 'Release' if ENV['XCODE']
  533. # Skip when :ci rake task was skipped
  534. next unless File.exist?("#{ENV['build_tree']}/CMakeCache.txt")
  535. $start_time = Time.now - ENV['ELAPSED'].to_i - 30 if ENV['ELAPSED'] # Adjustment for rounding up to the next nearest minute
  536. next if timeup
  537. # Generate the documentation if necessary
  538. if ENV['SITE_UPDATE']
  539. if File.exist?('.site_updated')
  540. # Skip if site is already updated before
  541. ENV['SITE_UPDATE'] = nil
  542. end
  543. elsif !File.exists?("#{ENV['build_tree']}/Docs/html/index.html")
  544. puts "Generating documentation...\n\n"; $stdout.flush
  545. # Ignore the exit status from 'make doc' on Windows host system only due to Doxygen may not return exit status correctly on Windows
  546. system "bash -c 'rake make target=doc >/dev/null'" or ENV['OS'] or abort 'Failed to generate documentation'
  547. end
  548. # Make the package
  549. puts "Packaging artifacts...\n\n"; $stdout.flush
  550. if ENV['IOS']
  551. # There is a bug in CMake/CPack that causes the 'package' target failed to build for IOS platform, workaround by calling cpack directly; CMake 3.4 runs the target successfully, however, the result tarball is incomplete (somehow it misses packaging the library itself, another bug?)
  552. system 'cd ../Build && cpack -G TGZ 2>/dev/null' or abort 'Failed to make binary package'
  553. else
  554. if ENV['ANDROID']
  555. if !ENV['NO_SDK_SYSIMG']
  556. system 'cd ../Build && android update project -p . && ant debug' or abort 'Failed to make Urho3D Samples APK'
  557. end
  558. system 'rm -rf ~/usr/local $(dirname $(which android))/../*' if ENV['TRAVIS'] # Clean up some disk space before packaging on Travis CI
  559. end
  560. if ENV['URHO3D_USE_LIB64_RPM']
  561. system 'rake cmake' or abort 'Failed to reconfigure to generate 64-bit RPM package'
  562. system "rm #{ENV['build_tree']}/Urho3D-*" or abort 'Failed to remove previously generated artifacts' # This task can be invoked more than one time
  563. end
  564. system "bash -c '#{!ENV['OS'] && (ENV['URHO3D_64BIT'] || ENV['RPI']) ? 'setarch i686' : ''} rake make target=package'" or abort 'Failed to make binary package'
  565. end
  566. # Determine the upload location
  567. setup_digital_keys
  568. repo = ENV[ENV['TRAVIS'] ? 'TRAVIS_REPO_SLUG' : 'APPVEYOR_REPO_NAME']
  569. unless ENV['RELEASE_TAG']
  570. upload_dir = "/home/frs/project/#{repo}/Snapshots"
  571. if ENV['SITE_UPDATE']
  572. # Download source packages from GitHub
  573. system "export SNAPSHOT_VER=$(git describe $TRAVIS_COMMIT |ruby -pe 'gsub(/-(?!g)/, %q{.})'); wget -q https://github.com/$TRAVIS_REPO_SLUG/tarball/$TRAVIS_COMMIT -O Urho3D-$SNAPSHOT_VER-Source-snapshot.tar.gz && wget -q https://github.com/$TRAVIS_REPO_SLUG/zipball/$TRAVIS_COMMIT -O Urho3D-$SNAPSHOT_VER-Source-snapshot.zip" or abort 'Failed to get source packages'
  574. # Only keep the snapshots from the last 30 revisions
  575. system "for v in $(sftp [email protected] <<EOF |tr ' ' '\n' |grep Urho3D- |cut -d '-' -f1,2 |uniq |tail -n +31
  576. cd #{upload_dir}
  577. ls -1r
  578. bye
  579. EOF
  580. ); do echo rm #{upload_dir}/${v}*; done |sftp -b - [email protected] >/dev/null 2>&1" or abort 'Failed to housekeep snapshots'
  581. end
  582. else
  583. upload_dir = "/home/frs/project/#{repo}/#{ENV['RELEASE_TAG']}"
  584. if ENV['SITE_UPDATE']
  585. # Download source packages from GitHub
  586. system 'wget -q https://github.com/$TRAVIS_REPO_SLUG/archive/$RELEASE_TAG.tar.gz -O Urho3D-$RELEASE_TAG-Source.tar.gz && wget -q https://github.com/$TRAVIS_REPO_SLUG/archive/$RELEASE_TAG.zip -O Urho3D-$RELEASE_TAG-Source.zip' or abort 'Failed to get source packages'
  587. end
  588. # Make sure the release directory exists remotely, do this in all the build jobs as we don't know which one would start uploading first
  589. system "bash -c 'sftp [email protected] <<EOF >/dev/null 2>&1
  590. mkdir #{upload_dir}
  591. bye
  592. EOF'" or abort 'Failed to create release directory remotely'
  593. end
  594. if ENV['SITE_UPDATE']
  595. # Upload the source package
  596. system "scp Urho3D-* [email protected]:#{upload_dir}" or abort 'Failed to upload source package'
  597. if ENV['RELEASE_TAG']
  598. # Mark the source tarball as default download for host systems other than Windows/Mac/Linux
  599. system "curl -H 'Accept: application/json' -X PUT -d 'default=bsd&default=solaris&default=others' -d \"api_key=$SF_API\" https://sourceforge.net/projects/%s/files/%s/#{ENV['RELEASE_TAG']}/Urho3D-#{ENV['RELEASE_TAG']}-Source.tar.gz" % ENV['TRAVIS_REPO_SLUG'].split('/') or abort 'Failed to set source tarball as default download'
  600. end
  601. # Sync readme and license files, just in case they are updated in the repo
  602. system 'for f in README.md License.txt; do mtime=$(git log --format=%ai -n1 $f); touch -d "$mtime" $f; done' or abort 'Failed to acquire file modified time'
  603. system 'rsync -e ssh -az README.md License.txt [email protected]:/home/frs/project/$TRAVIS_REPO_SLUG' or abort 'Failed to sync readme and license files'
  604. # Mark that the site has been updated
  605. File.open('.site_updated', 'w') {}
  606. end
  607. # Upload the binary package
  608. system "bash -c 'scp #{ENV['build_tree']}/Urho3D-* [email protected]:#{upload_dir}'" or abort 'Failed to upload binary package'
  609. if ENV['RELEASE_TAG'] && ENV['SF_DEFAULT']
  610. # Mark the corresponding binary package as default download for each Windows/Mac/Linux host systems
  611. system "bash -c \"curl -H 'Accept: application/json' -X PUT -d 'default=%s' -d \"api_key=$SF_API\" https://sourceforge.net/projects/%s/files/%s/#{ENV['RELEASE_TAG']}/Urho3D-#{ENV['RELEASE_TAG']}-%s\"" % ENV['SF_DEFAULT'].split(':').insert(1, repo.split('/')).flatten or abort 'Failed to set binary tarball/zip as default download'
  612. end
  613. end
  614. # Always call this function last in the multiple conditional check so that the checkpoint message does not being echoed unnecessarily
  615. def timeup
  616. unless $start_time
  617. puts; $stdout.flush
  618. return nil
  619. end
  620. elapsed_time = (Time.now - $start_time) / 60
  621. puts "\n=== Checkpoint reached, elapsed time: #{elapsed_time.to_i} minutes ===\n\n" unless $already_timeup
  622. $stdout.flush
  623. return $already_timeup = elapsed_time > 40
  624. end
  625. def scaffolding dir, project = 'Scaffolding', target = 'Main'
  626. begin
  627. dir = Pathname.new(dir).realdirpath.to_s
  628. rescue
  629. abort "Failed to scaffolding due to invalid parent directory in '#{dir}'"
  630. end
  631. dir.gsub!(/\//, '\\') if ENV['OS']
  632. build_script = <<EOF
  633. # Set CMake minimum version and CMake policy required by Urho3D-CMake-common module
  634. if (WIN32)
  635. cmake_minimum_required (VERSION 3.2.3) # Going forward all platforms will use this as minimum version
  636. else ()
  637. cmake_minimum_required (VERSION 2.8.6)
  638. endif ()
  639. if (COMMAND cmake_policy)
  640. cmake_policy (SET CMP0003 NEW)
  641. if (CMAKE_VERSION VERSION_GREATER 2.8.12 OR CMAKE_VERSION VERSION_EQUAL 2.8.12)
  642. # INTERFACE_LINK_LIBRARIES defines the link interface
  643. cmake_policy (SET CMP0022 NEW)
  644. endif ()
  645. if (CMAKE_VERSION VERSION_GREATER 3.0.0 OR CMAKE_VERSION VERSION_EQUAL 3.0.0)
  646. # Disallow use of the LOCATION target property - so we set to OLD as we still need it
  647. cmake_policy (SET CMP0026 OLD)
  648. # MACOSX_RPATH is enabled by default
  649. cmake_policy (SET CMP0042 NEW)
  650. endif ()
  651. endif ()
  652. # Set project name
  653. project (#{project})
  654. # Set CMake modules search path
  655. set (CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
  656. # Include Urho3D CMake common module
  657. include (Urho3D-CMake-common)
  658. # Define target name
  659. set (TARGET_NAME #{target})
  660. # Define source files
  661. define_source_files ()
  662. # Setup target with resource copying
  663. setup_main_executable ()
  664. # Setup test cases
  665. if (URHO3D_ANGELSCRIPT)
  666. setup_test (NAME ExternalLibAS OPTIONS Scripts/12_PhysicsStressTest.as -w)
  667. endif ()
  668. if (URHO3D_LUA)
  669. setup_test (NAME ExternalLibLua OPTIONS LuaScripts/12_PhysicsStressTest.lua -w)
  670. endif ()
  671. EOF
  672. # TODO: Rewrite in pure Ruby when it supports symlink creation on Windows platform and avoid forward/backward slash conversion
  673. if ENV['OS']
  674. system("@echo off && mkdir \"#{dir}\"\\bin && copy Source\\Tools\\Urho3DPlayer\\Urho3DPlayer.* \"#{dir}\" >nul && (for %f in (*.bat Rakefile) do mklink \"#{dir}\"\\%f %cd%\\%f >nul) && mklink /D \"#{dir}\"\\CMake %cd%\\CMake && (for %d in (CoreData,Data) do mklink /D \"#{dir}\"\\bin\\%d %cd%\\bin\\%d >nul)") && File.write("#{dir}/CMakeLists.txt", build_script) or abort 'Failed to scaffolding'
  675. else
  676. system("bash -c \"mkdir -p '#{dir}'/bin && cp Source/Tools/Urho3DPlayer/Urho3DPlayer.* '#{dir}' && for f in {.,}*.sh Rakefile CMake; do ln -sf `pwd`/\\$f '#{dir}'; done && ln -sf `pwd`/bin/{Core,}Data '#{dir}'/bin\"") && File.write("#{dir}/CMakeLists.txt", build_script) or abort 'Failed to scaffolding'
  677. end
  678. return dir
  679. end
  680. def get_root_commit_and_recipients
  681. # Root commit is a commit submitted by human
  682. root_commit = `git show -s --format='%H' #{ENV['TRAVIS_COMMIT']}`.rstrip
  683. recipients = `git show -s --format='%ae %ce' #{root_commit}`.chomp.split.uniq
  684. if recipients.include? '[email protected]'
  685. matched = /Commit:.*commit\/(.*?)\n/.match(ENV['COMMIT_MESSAGE'])
  686. if (matched)
  687. root_commit = matched[1]
  688. recipients = `git show -s --format='%ae %ce' #{root_commit}`.chomp.split.uniq
  689. end
  690. end
  691. return root_commit, recipients
  692. end
  693. def android_find_device api = nil, abi = nil
  694. # Return the previously found matching device or if not found yet then try to find the matching device now
  695. return $specific_device if $specific_device
  696. $specific_api = api.to_s if api
  697. $specific_abi = abi.to_s if abi
  698. loop do
  699. for i in `adb devices |tail -n +2`.split "\n"
  700. device = i.split.first
  701. if `adb -s #{device} wait-for-device shell getprop ro.build.version.sdk`.chomp == $specific_api && `adb -s #{device} shell getprop ro.product.cpu.abi`.chomp == $specific_abi
  702. return $specific_device = device
  703. end
  704. end
  705. break if api
  706. end
  707. nil
  708. end
  709. def android_prepare_device api, abi = 'armeabi-v7a', name = 'test'
  710. system 'if ! ps |grep -cq adb; then adb start-server; fi'
  711. if !android_find_device api, abi
  712. # Don't have any matching (virtual) device attached, try to attach the named device (create the named device as AVD if necessary)
  713. if !system "android list avd |grep -cq 'Name: #{name}$'"
  714. system "echo 'no' |android create avd -n #{name} -t android-#{api} --abi #{abi}" or abort "Failed to create '#{name}' Android virtual device"
  715. end
  716. system "if [ $CI ]; then export OPTS='-no-skin -no-audio -no-window -no-boot-anim -gpu off'; else export OPTS='-gpu on'; fi; emulator -avd #{name} $OPTS &"
  717. end
  718. return 0
  719. end
  720. def android_wait_for_device retries = -1, retry_interval = 10, package = 'android.process.acore' # Waiting for HOME by default
  721. # Wait until the indicator process is running or it is killed externally by user via Ctrl+C or when it exceeds the number of retries (if the retries parameter is provided)
  722. str = "\nWaiting for device..."
  723. thread = Thread.new { android_find_device }; sleep 0.5
  724. process_ready = false
  725. retries = retries * 60 / retry_interval unless retries == -1
  726. until retries == 0
  727. if thread.status == false
  728. thread.join
  729. break if process_ready
  730. process_ready = thread = Thread.new { `adb -s #{$specific_device} shell 'until ps |grep -c #{package} >/dev/null; do sleep #{retry_interval}; done; while ps |grep -c bootanimation >/dev/null; do sleep 1; done'` }; sleep 0.5
  731. next
  732. end
  733. print str; str = '.'; $stdout.flush # Flush the standard output stream in case it is buffered to prevent Travis-CI into thinking that the build/test has stalled
  734. sleep retry_interval
  735. retries -= 1 if retries > 0
  736. end
  737. puts "\n\n" if str == '.'; $stdout.flush
  738. return retries == 0 ? nil : 0
  739. end
  740. def android_test_run parameter = '--es pickedLibrary Urho3DPlayer:Scripts/NinjaSnowWar.as', intent = '.SampleLauncher', package = 'com.github.urho3d', success_indicator = 'Added resource path /apk/CoreData/', payload = 'sleep 30'
  741. # The device should have been found at this point
  742. return nil unless $specific_device
  743. # Capture adb's stdout and interpret it because adb neither uses stderr nor returns proper exit code on error
  744. begin
  745. IO.popen("adb -s #{$specific_device} shell <<EOF
  746. # Try to unlock the device just in case it is locked
  747. input keyevent 82; input keyevent 4
  748. # Clear the log
  749. logcat -c
  750. # Start the app
  751. am start -a android.intent.action.MAIN -n #{package}/#{intent} #{parameter}
  752. # Wait until the process is running
  753. until ps |grep -c #{package} 1>/dev/null; do sleep 1; done
  754. # Execute the payload
  755. #{payload}
  756. # Exit and stop the app
  757. input keyevent 4 && am force-stop #{package}
  758. # Dump the log
  759. logcat -d
  760. # Bye bye
  761. exit
  762. ##
  763. EOF") { |stdout| echo = false; while output = stdout.gets do if echo && /#\s#/ !~ output then puts output else echo = true if /^##/ =~ output end; return nil if /^error/i =~ output end }
  764. # Result of the test run is determined based on the presence of the success indicator string in the log
  765. system "adb -s #{$specific_device} logcat -d |grep -cq '#{success_indicator}'"
  766. rescue
  767. nil
  768. end
  769. end
  770. # Usage: wait_for_block("This is a long function call...") { Thread.current[:exit_code] = call_a_func } or abort
  771. # wait_for_block("This is a long system call...") { system "do_something"; Thread.current[:exit_code] = $?.exitstatus } or abort
  772. def wait_for_block comment = '', retries = -1, retry_interval = 60, exit_code_sym = 'exit_code', &block
  773. # Wait until the code block is completed or it is killed externally by user via Ctrl+C or when it exceeds the number of retries (if the retries parameter is provided)
  774. thread = Thread.new &block
  775. str = comment
  776. retries = retries * 60 / retry_interval unless retries == -1
  777. until retries == 0
  778. if thread.status == false
  779. thread.join
  780. break
  781. end
  782. print str; str = '.'; $stdout.flush # Flush the standard output stream in case it is buffered to prevent Travis-CI into thinking that the build/test has stalled
  783. sleep retry_interval
  784. retries -= 1 if retries > 0
  785. end
  786. puts "\n" if str == '.'; $stdout.flush
  787. return retries == 0 ? nil : (exit_code_sym ? thread[exit_code_sym] : 0)
  788. end
  789. def append_new_release release, filename = '../urho3d.github.io/_data/urho3d.json'
  790. begin
  791. urho3d_hash = JSON.parse File.read filename
  792. unless urho3d_hash['releases'].last == release
  793. urho3d_hash['releases'] << release
  794. end
  795. File.open(filename, 'w') { |file| file.puts urho3d_hash.to_json }
  796. return 0
  797. rescue
  798. nil
  799. end
  800. end
  801. def update_web_samples_data dir = '../urho3d.github.io/samples', filename = '../urho3d.github.io/_data/web.json'
  802. begin
  803. web = JSON.parse File.read filename
  804. Dir.chdir(dir) { web['samples'] = Dir['*.html'].sort }
  805. File.open(filename, 'w') { |file| file.puts web.to_json }
  806. return 0
  807. rescue
  808. nil
  809. end
  810. end
  811. def bump_copyright_year dir='.'
  812. begin
  813. Dir.chdir dir do
  814. copyrighted = `git grep -El '2008-[0-9]{4} the Urho3D project'`.split
  815. copyrighted.each { |filename|
  816. replaced_content = File.read(filename).gsub(/2008-[0-9]{4} the Urho3D project/, "2008-#{Time.now.year} the Urho3D project")
  817. File.open(filename, 'w') { |file| file.puts replaced_content }
  818. }
  819. return copyrighted
  820. end
  821. rescue
  822. abort 'Failed to bump copyright year'
  823. end
  824. end
  825. def bump_soversion filename
  826. begin
  827. version = File.read(filename).split '.'
  828. bump_version version, 2
  829. File.open(filename, 'w') { |file| file.puts version.join '.' }
  830. return 0
  831. rescue
  832. nil
  833. end
  834. end
  835. def bump_version version, index
  836. if index > 0 && version[index].to_i == 255
  837. version[index] = 0
  838. bump_version version, index - 1
  839. else
  840. version[index] = version[index].to_i + 1
  841. end
  842. end
  843. def setup_digital_keys
  844. system "bash -c 'mkdir -p ~/.ssh && chmod 700 ~/.ssh'" or abort 'Failed to create ~/.ssh directory'
  845. system "bash -c 'ssh-keyscan frs.sourceforge.net >>~/.ssh/known_hosts 2>/dev/null'" or abort 'Failed to append frs.sourceforge.net server public key to known_hosts'
  846. # Workaround travis encryption key size limitation. Rather than using the solution in their FAQ (using AES to encrypt/decrypt the file and check in the encrypted file into repo), our solution is more pragmatic. The private key below is incomplete. Only the missing portion is encrypted. Much less secure than the original 2048-bit RSA has to offer but good enough for our case.
  847. system "bash -c 'cat <<EOF >~/.ssh/id_rsa
  848. -----BEGIN RSA PRIVATE KEY-----
  849. MIIEpQIBAAKCAQEAnZGzFEypdXKY3KDT0Q3NLY4Bv74yKgJ4LIgbXothx8w4CfM0
  850. VeWBL/AE2iRISEWGB07LruM9y+U/wt58WlCVu001GuJuvXwWenlljsvH8qQlErYi
  851. oXlCwAeVVeanILGL8CPS7QlyzOwwnVF6NdcmfDJjTthBVFbvHrWGo5if86zcZyMR
  852. 2BB5QVEr5fU0yOPFp0+2p7J3cA6HQSKwjUiDtJ+lM62UQp7InCCT3qeh5KYHQcYb
  853. KVJTyj5iycVuBujHDwNAivLq82ojG7LcKjP+Ia8fblardCOQyFk6pSDM79NJJ2Dg
  854. 3ZbYIJeUmqSqFhRW/13Bro7Z1aNGrdh/XZkkHwIDAQABAoIBACHcBFJxYtzVIloO
  855. yVWcFKIcaO3OLjNu0monWVJIu1tW3BfvRijLJ6aoejJyJ4I4RmPdn9FWDZp6CeiT
  856. LL+vn21fWvELBWb8ekwZOCSmT7IpaboKn4h5aUmgl4udA/73iC2zVQkQxbWZb5zu
  857. vEdDk4aOwV5ZBDjecYX01hjjnEOdZHGJlF/H/Xs0hYX6WDG3/r9QCJJ0nfd1/Fk2
  858. zdbZRtAbyRz6ZHiYKnFQ441qRRaEbzunkvTBEwu9iqzlE0s/g49LJL0mKEp7rt/J
  859. 4iS3LZTQbJNx5J0ti8ZJKHhvoWb5RJxNimwKvVHC0XBZKTiLMrhnADmcpjLz53F8
  860. $SF_KEY
  861. sx27yCaeBeKXV0tFOeZmgK664VM9EgesjIX4sVOJ5mA3xBJBOtz9n66LjoIlIM58
  862. dvsAnJt7MUBdclL/RBHEjbUxgGBDcazfWSuJe0sGczhnXMN94ox4MSECgYEAx5cv
  863. cs/2KurjtWPanDGSz71LyGNdL/xQrAud0gi49H0tyYr0XmzNoe2CbZ/T5xGSZB92
  864. PBcz4rnHQ/oujo/qwjNpDD0xVLEU70Uy/XiY5/v2111TFC4clfE/syZPywKAztt3
  865. y2l5z+QdsNigRPDhKw+7CFYaAnYBEISxR6nabT8CgYEAqHrM8fdn2wsCNE6XvkZQ
  866. O7ZANHNIKVnaRqW/8HW7EFAWQrlQTgzFbtR4uNBIqAtPsvwSx8Pk652+OR1VKfSv
  867. ya3dtqY3rY/ErXWyX0nfPQEbYj/oh8LbS6zPw75yIorP3ACIwMw3GRNWIvkdAGTn
  868. BMUgpWHUDLWWpWRrSzNi90ECgYEAkxxzQ6vW5OFGv17/NdswO+BpqCTc/c5646SY
  869. ScRWFxbhFclOvv5xPqYiWYzRkmIYRaYO7tGnU7jdD9SqVjfrsAJWrke4QZVYOdgG
  870. cl9eTLchxLGr15b5SOeNrQ1TCO4qZM3M6Wgv+bRI0h2JW+c0ABpTIBzehOvXcwZq
  871. 6MhgD98CgYEAtOPqc4aoIRUy+1oijpWs+wU7vAc8fe4sBHv5fsv7naHuPqZgyQYY
  872. 32a54xZxlsBw8T5P4BDy40OR7fu+6miUfL+WxUdII4fD3grlIPw6bpNE0bCDykv5
  873. RLq28S11hDrKf/ZetXNuIprfTlhl6ISBy+oWQibhXmFZSxEiXNV6hCQ=
  874. -----END RSA PRIVATE KEY-----
  875. EOF'" or abort 'Failed to create user private key to id_rsa'
  876. system "bash -c 'chmod 600 ~/.ssh/id_rsa'" or abort 'Failed to change id_rsa file permission'
  877. end
  878. # Load custom rake scripts
  879. Dir['.rake/*.rake'].each { |r| load r }
  880. # vi: set ts=2 sw=2 expandtab: