Projektépítés a távolból
Vezéreljük a virtuális gépünkben futó build rendszert a host gépről.
Most, hogy már van egy virtuális szerverünk, kellene kezdeni vele valami mókás dolgot. Lehetne mondjuk egy távolról is vezérelhető build rendszerünk (a "távolról" mondjuk ebben az esetben talán egy kicsit túlzás :)), amit a kedvenc szövegszerkesztőnk automatikusan tudna vezérelni. Az úgy kellőképp mókásan hangzik ahhoz, hogy belevágjunk. :)
Ahhoz, hogy legyen értelme a build rendszernek, nem árt, ha van mit build-elni. Tegyük fel mondjuk a példa kedvéért, hogy CSS helyett szeretnénk Sass-t, JavaScript helyett pedig CoffeeScript-et használni. Természetesen a rendszer képességei nem merülnek ki ennyiben, lehetne mondjuk olyat is csinálni, hogy a sablon fájlokat fordítsa le PHP-ra, vagy a konfigurációs XML-ekből gyártson tömböket, esetleg minden unit tesztet lefuttasson. A lehetőségek száma, ahogy mondani szokás, végtelen, de maradjunk az eredeti kettőnél, a többi a kedves olvasó fantáziájára van bízva. Kezdjük is rögtön a telepítéssel:
Sass
sudo apt-get install ruby rubygems
sudo gem install sass
A Sass [Syntactically Awesome Stylesheets] nevezetű előfeldolgozó néhány hasznos kiegészítéssel segít ráncba szedni az elvadult CSS kóddzsungelt.
CoffeeScript
sudo apt-get install nodejs npm
sudo npm install coffee-script
A CoffeeScript a funkcionális programozási nyelvekre és talán egy csöppet a Ruby-ra emlékeztető nyelv a JavaScript egy komolyabb újragondolása (a Sass-CSS viszonylathoz képest), de mentségére legyen mondva, hogy egy az egyben valid JavaScript-re fordul.
Építkezzünk
A build-elésben segítségünkre lesz a vicces nevű PHP-s build eszköz, a Phing. A következő módon érhetjük el, hogy feltelepüljön:
sudo apt-get install php-pear
sudo pear channel-discover pear.phing.info
sudo pear install phing/phing
A példához a következő minimális projekt könyvtárszerkezetet fogjuk használni:
- assets/
- coffee/
- sass/
- www/
- css/
- js/
- build.xml
Az assets/
könyvtárban vannak a nyers fájlok, a www/
könytárba mennek a generált fájlok, amiket nem árt kívülről is elérni. A kulcs pedig a build.xml
, ami a Phing számára tartalmaz utasításokat. Kezdetnek valami ilyesmi például megteszi:
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" default="assets">
<property name="sass_dir" value="${project.basedir}/assets/sass/" />
<property name="coffee_dir" value="${project.basedir}/assets/coffee/" />
<property name="css_target" value="${project.basedir}/www/css/" />
<property name="js_target" value="${project.basedir}/www/js/" />
<target name="sass">
<exec command="sass --no-cache --update "${sass_dir}:${css_target}"" />
</target>
<target name="coffee">
<exec command="coffee -o "${js_target}" "${coffee_dir}"" />
</target>
<target name="assets">
<phingcall target="sass" />
<phingcall target="coffee" />
</target>
</project>
A projekt könyvtárában (egy szinten a build.xml
-lel) állva ki tudjuk adni a következő három parancsot, amivel a Sass-t, CoffeeScript-et és mindkettőt egyszerre lefordíthatjuk (ha nem adunk meg semmit a phing
után, akkor a default assets
fog lefutni):
phing sass
phing coffee
phing assets
Az alkalmazás
Már csak azt kellene elérni, hogy a fájlok módosítása után a megfelelő parancs automatikusan lefusson. Bár mind a Sass, mind a CoffeeScript rendelkezik megoldással a problémára (--watch
), a későbbiekre is gondolva inkább valami általánosabb megoldásra lenne szükség. Mondjuk egy webes minialkalmazás, ami a kapott paraméterek függvényében meghívja a megfelelő parancsot. A kódszerkesztő alkalmazásunk pedig ezt a paraméterezett URL-t hívogathatná. Mondjuk valami ilyesmit:
http://builder.vbox/index.php?project=projektneve&target=target
Az a bizonyos index.php
pedig valami ilyen kis egyszerű dolog lenne (az egyszerűség ára az, hogy élünk azzal a feltételezéssel, hogy az egyes projektek a /var/www/projektneve.vbox/
könyvtárban vannak és eltekintünk az olyan dolgoktól, mint például a target
valódiságának az ellenőrzése):
$dir = '/var/www/' . get('project') . '.vbox/';
if (!file_exists($dir . 'build.xml')) {
exit('invalid_project');
}
$target = get('target');
if (!$target) {
exit('no_target');
}
chdir($dir);
shell_exec('phing ' . escapeshellcmd($target));
exit('ok');
function get($name) {
if (empty($_GET[$name])) {
return '';
}
return preg_replace('/[^a-z0-9\-\.]/i', '', $_GET[$name]);
}
A plugin
Ezzel meg is van a távolról is vezérelhető egyszerű kis build rendszerünk. A kedvenc szerkesztőnkhöz írhatunk egy plugin-t, ami mentésre meghívja a megfelelő URL-t, hogy legenerálódjanak a CSS/JS fájlok (vagy akár tetszőleges billentyűkombinációra tetszőleges build parancsot meghívhatunk). Sublime Text 2 esetén valahogy így nézne ki a dolog:
import sublime, sublime_plugin
import urllib, urllib2
import os, threading
class BuilderThread(threading.Thread):
def __init__(self, project, target):
threading.Thread.__init__(self)
self.project = project
self.target = target
def run(self):
try:
data = urllib.urlencode({
'project': self.project,
'target': self.target,
})
request = urllib2.Request('http://builder.vbox/index.php?' + data)
response = urllib2.urlopen(request).read()
return
except (urllib2.HTTPError) as (e):
err = '%s: HTTP error %s contacting API' % (__name__, str(e.code))
except (urllib2.URLError) as (e):
err = '%s: URL error %s contacting API' % (__name__, str(e.reason))
sublime.error_message(err)
class BuilderEventListener(sublime_plugin.EventListener):
def __init__(self):
sublime_plugin.EventListener.__init__(self)
def on_post_save(self, view):
name, ext = os.path.splitext(view.file_name())
project = view.settings().get('builder_project_name', False)
if (False == project):
return
if (ext == '.coffee'):
BuilderThread(project, 'coffee').start()
elif (ext == '.scss' or ext == '.sass'):
BuilderThread(project, 'sass').start()
A plugin használ egy builder_project_name
nevű beállítást, amit az éppen aktuális projekt .sublime-project
fájljában érdemes megadni:
{
"settings": {
"builder_project_name": "test-project"
}
}
Ezzel meg is volnánk, kellemes építkezést.