Egen kontakthantering

För mer än ett år sedan bestämde jag mig för att flytta kalendern från Google Calendar till Owncloud. Jag är nöjd med flytten och det har fungerat mycket bra att köra det i egen regi.

Idag utforskade jag nya Owncloud 8 och hittade appen för kontakter. Denna har förmodligen funnits sedan tidigare men tyckte det var dags att ta tag i flytten av kontakter nu.

Sagt och gjort, nu kör jag även kontakter i Owncloud och synkroniserar mot min Androidtelefon och Thunderbird.

Sugen på att göra detsamma? Lite länkar som hjälpte mig:

Vad står på tur efter detta tror ni?

Symfony Sverige

På årsmötet för Symfony Sverige blev jag invald i deras styrelse. Det ska bli ett spännande uppdrag eftersom jag gillar både webbutveckling, Symfony och föreningsliv. 🙂

Vi har redan börjat planera nästa November Camp och jag tänkte att jag skulle försöka dra ihop någon slags meetup för PHP-utvecklare här i Göteborg. Det kommer inte att vara endast för Symfony-utvecklare i så fall, så hör gärna av er om ni är intresserade av att vara med på något sådant.

Automatisk cache busting i Symfony ~2.3

Tidigare skrev jag om hur man kan göra för att få klienter att automatisk ladda uppdaterad JavaScript och CSS när man gör en deploy i Symfony 2. Från och med version 2.3 har detta blivit mycket enklare eftersom man nu använder incenteev/composer-parameter-handler för att uppdatera parameters.yml efter att man gjort composer install eller update.

Där finns stöd för att använda en miljövariabel för att sätta ett värde på en parameter. Med följande i composer.json:

"extra": {
    "incenteev-parameters": {
        "file": "app/config/parameters.yml",
        "env-map": {
            "assets_version": "ASSETS_VERSION"
        }
    }
}

blir deploysteget istället:

rev=`git rev-parse HEAD | cut -c 1-8`

ASSETS_VERSION=$rev composer --no-dev --optimize-autoloader install

Open source installation med git

Jag har ganska så länge haft webbaserade open source projekt installerade på egen server. Vissa av dessa, som t.ex. WordPress, har varit relativt enkla att uppdatera med endast ett kommando. För roundcube däremot har jag varit tvungen att ladda hem den nya versionen, packa upp, kopiera över konfiguration och sedan peka om en länk till vilken version som ska användas för närvarande.

Detta gör att det har tagit flera minuter (!) av min tid för att uppdatera mjukvara, inte acceptabelt. Så istället har jag provat att installera roundcube via git, och använda git tags för att byta version.

Än så länge har det fungerat bra, och jag uppdaterade precis till version 1.0-rc med tre kommandon:

git fetch
git checkout v1.0-rc
rm -rf installer

På ungefär samma vis uppdaterar jag thinkup, mediawiki (jobbet) och owncloud uppdateras genom ett apt-repository.

Det ska vara enkelt att uppdatera, annars blir det lätt så att man skjuter på det.

Versionsangivelser, composer vs bower

Edit 140201: Spoiler alert! Efter lite grävande såhär på lördagskvällen hittar jag att detta är en bugg i bower: bower/bower#1017.

Jag var på väg att slänga upp detta på twitter men inser att det knappast får plats på 140 tecken.

Något jag har stört mig på ett tag är att composer och bower verkar ha olika uppfattning om hur man anger versioner i sina JSON filer.

Om jag anger t.ex. ~1.0 i composer så får jag den senaste versionen i 1.x trädet som är stabil:

$ composer require nelmio/security-bundle 
Please provide a version constraint for the nelmio/security-bundle requirement: ~1.0
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
(...) 
  - Installing nelmio/security-bundle (1.3.0)

Medan om jag gör samma sak i bower så får jag senaste i 1.0 trädet:

$ bower install 'ember#~1.0'
bower ember#~1.0                cached git://github.com/components/ember.git#1.0.1
bower ember#~1.0              validate 1.0.1 against git://github.com/components/ember.git#~1.0

(...)

ember#1.0.1 bower_components/ember

Provar jag med ~1 så får jag senaste beta versionen:

$ bower install 'ember#~1'
bower ember#~1                  cached git://github.com/components/ember.git#1.4.0-beta.3
bower ember#~1                validate 1.4.0-beta.3 against git://github.com/components

(...)

ember#1.4.0-beta.3 bower_components/ember

Är det någon av dem som har mer “rätt”? ..och hur fasen får jag bower att installera version 1.3.1 (senaste stabila) av Ember?

Egen kalenderhantering

Calendar

Jag håller sakteligen på att flytta ansvaret för min digitala närvaro till egna installerade tjänster istället för att lita på en tredje part. Detta gör jag framförallt för att jag vill ha kontroll över min egen data och kunna lita på att tjänster inte försvinner helt plötsligt. (I’m looking at you Google Reader)

E-post och webb kör jag sedan länge på min egen server, men min kalender har stannat kvar hos Google eftersom att deras tjänst har fungerat väldigt bra, både webbkalendern och mobilkalendern. Detta beroende av Google kändes som nästa naturliga steg att göra sig av med.

Lösningen på att ta hem även kalenderhanteringen blev owncloud tillsammans med CalDAV Sync beta till min Android telefon. Det fungerar förvånansvärt bra och synkroniserar utan problem mellan webbkalendern och min telefon. Den största bristen är nog webbkalendern som fungerar lite sådär just nu, men med några rader hemmakodad JavaScript blir den i alla fall användbar tills vidare. Vad jag har kunnat läsa mig till så jobbar man på en större uppdatering av kalendern till nästa version av owncloud, det ska bli intressant att se vad det ger.

Utöver den bristfälliga webbkalendern saknar jag endast möjligheten att kunna bjuda in till events direkt i Android kalendern. Det kan jag utan problem leva utan.

Det verkar som att man även blir av med Google Now integrationen när man kör med extern kalender, men jag använder inte Google Now ändå så för mig är det inget problem.

Kör du också egen kalenderhantering? Har du flyttat någon annan intressant tjänst från molnet till egen regi?

CrashPlan på din Raspberry Pi

Den första idén jag fick när jag började pyssla med Raspberry Pi var att göra dem till en backupmaskin med CrashPlan som kan stå och lagra filerna åt mig. Det krävdes en del pyssel för att få igång på detta då CrashPlan inte har något officiellt stöd för ARM-arkitekturen, men till slut så fick jag igång det. Jag sparade alla anteckningar och tänkte göra det till ett blogginlägg någon gång i framtiden, men det har blivit liggande i evernote utan åtgärd.

Idag är jag på Webcoast och gick till en workshop om Raspberry Pi och pratade lite med @sundhult som också hade haft samma tanke. Så här kommer en snabbt ihoplängd guide för hur jag fick igång på CrashPlan på min Raspberry Pi. Tyvärr har jag inte någon enhet att testa detta på i dagsläget, men jag hoppas att detta ska kunna ta dig en bit på vägen.

Jag använder debian distributionen raspbian för detta.

1. Installera paket

$ sudo apt-get install openjdk-7-jre-headless build-essential libjna-java

2. Ladda ner och packa upp installationen

$ curl -O http://download.crashplan.com/installs/linux/install/CrashPlan/CrashPlan_3.4.1_Linux.tgz
$ tar zxvf CrashPlan_3.4.1_Linux.tgz

3. Kör igenom installationsprocessen

$ cd CrashPlan-install/
$ sudo ./install.sh

Följ instruktionerna på skärmen

4. Installera patchad version av jtux

$ cd ..
$ curl -O http://basepath.com/aup/jtux/jtux.tar.gz
$ tar zxvf jtux.tar.gz
$ cd jtux
$ curl -o jtux.PS3-YDL6.1.patch.txt.gz "http://forum.excito.net/download/file.php id=145&sid=35e3a13b3b22653ecc55ffcfe26f0444"
$ gunzip jtux.PS3-YDL6.1.patch.txt.gz
$ patch < jtux.PS3-YDL6.1.patch.txt

Redigera Makefile och ändra JAVA_INCLUDE till:

JAVA_INCLUDE = /usr/lib/jvm/java-7-openjdk-armhf/include

Du kan dubbelkolla att katalogen stämmer på ditt system med:

$ ls /usr/lib/jvm/java-7-openjdk-armhf/include

Om katalogen inte finns kanske den heter något annat på ditt system, testa att söka efter den med:

$ find /usr/lib/jvm -name include

Om du inte hittar något har du förmodligen inte installerat java korrekt.

Dags att bygga jtux:

$ make
$ sudo mv /usr/local/crashplan/libjtux.so /usr/local/crashplan/libjtux.so.bak
$ sudo cp libjtux.so /usr/local/crashplan/libjtux.so

Efter detta så borde du ha en fungerande installation av crashplan, starta den med:

$ sudo service crashplan start

Tänk på att uppstarten tar väldigt lång tid på din Raspberry Pi, speciellt första gången. Så låt den stå och tugga ett tag och ta en kopp kaffe medan du väntar.

För att sedan administrera din CrashPlan utan installerat desktop så kan du ansluta till den med en s.k. headless klient, detta beskriver CrashPlan själva på sin hemsida: http://support.crashplan.com/doku.php/how_to/configure_a_headless_client

Lycka till och hör av dig om något inte stämmer.

Mitt arbetsflöde med base64 bilder

Idag svarade jag på en tweet från @viktorbijlenga vilket satte av en del diskussion på twitter.

För att slippa begränsningen på 140 tecken tänkte jag slänga ihop en snabb bloggpost om hur mitt nuvarande arbetsflöde ser ut med optimering och base64 bilder.

Under hela utvecklingsfasen använder jag bilder som vanligt i min CSS, men så snart jag är nöjd med utseendet går jag igenom CSS filen och gör om alla bilder som visas på alla, eller åtminstone de flesta sidor, och gör om dem till base64 inline i min CSS-fil. Stödet för detta är oväntat bra och det är i princip bara IE7 och bakåt som inte har stöd för det. Det är dock enkelt att fixa en fallback för webbläsare som inte har stödet.

När jag är klar med projektet så börjar jag med att optimera alla bilder, för det har jag ett script som ser ut såhär:

#!/bin/bash

for x in `find . -name "*png"`;do 
        optipng -o7 "$x"
        pngcrush -rem alla -reduce "$x" "$x.tmp"
        mv "$x.tmp" "$x"
done

Detta plockar i princip bort all onödig metadata och försöker optimera hur PNG bilderna är sparade för att göra dem mindre. Efter det så använder jag ytterligare ett litet script för att göra om dem till base64 kodade strängar:

#!/usr/bin/php
<?php
$b64  = base64_encode( file_get_contents( $argv[1] ) );
echo 'background-image: url(data:image/png;base64,'. $b64 .');' . "\n";

Kör jag det på en bildfil blir resultatet en färdig CSS-regel som jag kan klistra in i min CSS:

$ base64img search.png 
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAZCAAAAAAKtWG8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAZ5JREFUGBkFwVlrFFEUhdFvn3uqOt0OUTAQFAXxwQl/gv//UR8VwYGEOKDEKTFdde/ZrqW+X3uVGyojMMJoO5Pd27H12roTgWQIxqWd62jV+7C9qNUy2yA53GOJ5sV55WzuNZURLrexRIWwdM3/FmNXGdlIPV2LY+ybgvSQbCOX5IywwjG26lWlBoNmVyNpLnvj/beTc91/FK2phmxIj5HViffvDu7tTz6+3ElSVNlZzlLy4+2DZ8n5qzcvYkkKuYUA8Hk+2Ox9+PDTMAfVDQ6wbb7nYZ/Tu+yjDaYhFADgo4s/k6v9znVua5GgsAF0nQ9/ufx6en0zr5qXRE4DwPHTd2fH8/n3Oz9vtZpiwdaXnQzq/nP6OW779OaLo2pF6EJftzEEsp1DenU2Pb/PktZFUCBkKUriyeP19cfaNGsEyEYAyGzvHms/xmWLSCMkKMCqOjr4tWtc64MMFKKHhEHrT27kGL3RcnJhjDGybu4d3uiKmqKN1SYRArgaUy6Xay0VMTczuo0tyy2G51aTNOWmD60jC5BlZ42smnba/AdZIR29b+jQRQAAAABJRU5ErkJggg==);

Det enda som behöver göras sedan är att lägga in den raden efter deklarationen av background, på så vis har man en fallback för äldre webbläsare:

background: transparent url(img/search.png) no-repeat center center;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAZCAAAAAAKtWG8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAZ5JREFUGBkFwVlrFFEUhdFvn3uqOt0OUTAQFAXxwQl/gv//UR8VwYGEOKDEKTFdde/ZrqW+X3uVGyojMMJoO5Pd27H12roTgWQIxqWd62jV+7C9qNUy2yA53GOJ5sV55WzuNZURLrexRIWwdM3/FmNXGdlIPV2LY+ybgvSQbCOX5IywwjG26lWlBoNmVyNpLnvj/beTc91/FK2phmxIj5HViffvDu7tTz6+3ElSVNlZzlLy4+2DZ8n5qzcvYkkKuYUA8Hk+2Ox9+PDTMAfVDQ6wbb7nYZ/Tu+yjDaYhFADgo4s/k6v9znVua5GgsAF0nQ9/ufx6en0zr5qXRE4DwPHTd2fH8/n3Oz9vtZpiwdaXnQzq/nP6OW779OaLo2pF6EJftzEEsp1DenU2Pb/PktZFUCBkKUriyeP19cfaNGsEyEYAyGzvHms/xmWLSCMkKMCqOjr4tWtc64MMFKKHhEHrT27kGL3RcnJhjDGybu4d3uiKmqKN1SYRArgaUy6Xay0VMTczuo0tyy2G51aTNOWmD60jC5BlZ42smnba/AdZIR29b+jQRQAAAABJRU5ErkJggg==);

Automatisk cache busting i Symfony2

Det projekt jag jobbar med just nu är mitt första projekt med Symfony2 som backend-ramverk. Jag är på det stora hela nöjd med hur det fungerar, men ett återkommande problem har varit att efter en ny deploy till testmiljön så har våra interna testare inte fått uppdaterade javascript och CSS-filer direkt, utan fått lov att göra en hård refresh för att få den senaste versionen.

Detta har berott på att vår testserver kör med `mod_expires` och sätter expire ganska så långt in i framtiden för att statiska resurser ska cachas bra på klienten. Detta kräver dock att man har ett bra sätt för att leverera fräscha resurser så snart de uppdateras. Symfony2 använder Assetic för att hantera resurser såsom javascript och CSS. Den app vi bygger har en tung frontend med mycket javascript, och har man inte den senaste versionen av koden för klientsidan så fungerar inte appen som den ska, vi har alltså ett stort behov av att kunna tömma cache på klienten så snart det behövs.

Därför satte jag mig idag och försökte ta itu med detta problem. I det ramverk vi själva har byggt internt för vår e-handelsplattform döps javascript och CSS filerna baserat på källfilernas innehåll. Det innebär att de källfilerna som ska skickas till klienten komprimeras och slås samman till en fil, som sedan namnges baserat på innehållet i alla filerna och levereras till klienten. Detta har den fördelen att så snart något ändras byter den slutgiltiga filen namn och på så vis får klienten alltid en uppdaterad version.

Det finns en liknande lösning för Assetic där man kör ett extra kommando för att döpa om alla filer i efterhand, men med den volym javascript som vår app innehåller skulle detta förlänga våra deploytider med allt för mycket för att vara realistiskt. Inbyggt i Assetic finns det stöd för att använda en query string för att sköta cache busting, men detta kräver då att man är en duktig utvecklare och kommer ihåg att ändra det värdet varje gång man gör en ny deploy.

Min lösning på detta problem blev att vid varje deploy uppdatera värdet på assets_version automatiskt, och då sätta det till nuvarande revision i vårt git repository. Vi har redan ett enkelt bash script som körs varje gång vi ska göra en deploy för att uppdatera cache och dumpa javascript filer, så i det scriptet har jag lagt till följande:

# update assets version to current git revision
rev=`git rev-parse HEAD | cut -c 1-8`
cat app/config/parameters.yml | grep -v assets_version > /tmp/parameters.yml

echo "    assets_version: $rev" >> /tmp/parameters.yml
mv /tmp/parameters.yml app/config/

Sedan hämtar jag parametern i min config.yml:

framework:
    templating:      { engines: ['twig'], assets_version: %assets_version% }

På så vis ska klienterna förhoppningsvis alltid har färska javascript och CSS filer efter en deploy.