Hopp til innholdet

cjohansen.no

Rails i Subversion

Å putte prosjekter i Subversion (svn) er både praktisk når man er alene, og en nødvendighet når man er flere. Når flere jobber på samme kodebase, eller når man jobber mot samme kodebase på forskjellige plasser kan det fort oppstå noen problemer. Disse problemene er i hovedsak knyttet til to ting; utviklingsmiljøet er forskjellig på forskjellige maskiner, og noen filer ønsker man rett og slett ikke å ha versjonskontroll på.

Det første problemet gir seg utslag i at for eksempel database-konfigurasjonen nesten garantert er forskjellig på forskjellige maskiner. Dermed blir det fort slitsomt hvis applikasjonen din kræsjer hver gang du sjekker ut kode, fordi noen andre sjekket inn sin database.yml med “feil” passord. Det samme gjelder dispatcherne, som refererer Ruby-executablen. Hvis disse ligger under versjonskontroll er alle team-medlemmene avhengig av å ha installert Ruby på samme plass, ellers vil det bli strid om disse filene. Dette er dermed filer som man ønsker å distribuere i første utsjekk, og seinere ikke i det hele tatt.

Det andre problemet består av sesjons-data, cache-data og logger. Det gir ingen mening å ha disse under versjonskontroll. Du vil for eksempel ikke like at produksjonsloggen din ble overskrevet når du deployet en ny versjon fordi en av utviklerne har sjekket inn sin lokale versjon? På samme måte har det ingen verdi å få noen andres cache av applikasjonen sjekket inn i din “working copy”.

Problemene er heldigvis enkle å løse, og har blitt en del av min rutine når jeg setter opp nye prosjekter. Problemområdene i en nyskapt Rails-applikasjon er altså tmp/ log/ config/database.yml og public/dispatch.*. Filer under tmp/ og log/ ønsker vi ikke med i det hele tatt, og de andre ønsker vi at utviklerne skal få ved første utsjekk, og så ikke oppdateres igjen.

Løsningen for det første problemet, filer som er uønsket, er enkel. Vi kan bruke svn:ignore for å få Subversion til å ignorere alle filene i disse mappene.

En mulig løsning for problem nummer to er å lage mal-filer for de filene som utviklerne skal bruke. På denne måten finnes det ikke noe database.yml i svn, men det finnes feks en database.yml.default som har fornuftige default-verdier. Når en utvikler så sjekker ut kodebasen første gang trenger hun kun å kopiere filen over til database.yml og så oppdatere innholdet til sitt miljø. Selve database.yml setter vi på svn:ignore, og dermed vil aldri slike lokalt avhengige filer bli overskrevet fra Subversion.

La oss se løsningen i praksis. Først, opprett mappen, og importer den inn i Subversion:

mkdir min_app
cd min_app
svn import . http://svn.eksempel.no/repos/min_app/trunk -m "Initial import"

Opprett Rails-skjelettet:

cd ..
call rails min_app

Så er det på tide å lage “mal-filene” og fjerne de filene som ikke skal ligge under versjonskontroll. To fluer i en smekk:

cd min_app/config
move database.yml database.yml.default
cd ../public
move dispatch.rb default.dispatch.rb
move dispatch.cgi default.dispatch.cgi
move dispatch.fcgi default.dispatch.fcgi

Neste skritt er å sjekke applikasjonen ut av Subversion igjen for å lage en “working copy”, slik at vi kan begynne å be Subversion om å ignorere ressurser.

cd ..
svn co http://svn.eksempel.no/repos/min_app/trunk .

Så, en liten detalj. Den eneste mappen som nå inneholder filer vi ikke ønsker å versjonskontrollere er log. Vi legger derfor den først til med -N-flagget for å unngå at den legges til rekursivt. Deretter legger vi til resten av treet.

svn add -N log
svn add *

Ignore time! Ok, nå ber vi Subversion om å ignorere alt som finnes under tmp/cache tmp/pids tmp/sessions, tmp/sockets og log/. På denne måten får vi mappestrukturen inn i Subversion, men ikke filene som opprettes her av Rails. Til slutt kan vi commit’e strukturen.

svn propset svn:ignore "*" tmp/cache
svn propset svn:ignore "*" tmp/pids
svn propset svn:ignore "*" tmp/sessions
svn propset svn:ignore "*" tmp/sockets
svn propset svn:ignore "*" log
svn commit -m "Create application skeleton"

Det eneste som gjenstår er nå å passe på at ingen ved et uhell adder og sjekker inn database.yml eller en av dispatcherne. Dette gjøres ved å sett ignore også på disse filene, etter å ha opprettet dem.

cd public
copy default.dispatch.rb dispatch.rb
copy default.dispatch.cgi dispatch.cgi
copy default.dispatch.fcgi dispatch.fcgi
cd ../config
copy database.yml.default database.yml
cd ..
svn propset svn:ignore "dispatch.*" public
svn propset svn:ignore "database.yml" config
svn commit -m "Ignore selected resources"

Voila! Nå har du en fungerende applikasjon som er under versjonskontroll, men som ikke sjekker inn filer som er avhengige av mijøet på din maskin. I tillegg har du brukt svn:ignore slik at ingen andre i ditt team heller trenger å komme til å sjekke inn konfigurasjon eller lignende ved en feil.

Det eneste unike her til hver gang man oppretter et prosjekt er repository-url og prosjektnavn, og er en strålende kandidat for automatisering. Jeg har laget et bat-script som kan brukes på Windows på følgende måte:

svn_rails mittprosjekt http://svn.eksempel.no/repos/

og gjør hele jobben. Tada! Dette scriptet antar at du vil ha prosjektet ditt i http://svn.eksempel.no/repos/mittprosjekt/trunk/, noe som alltid stemmer for meg idet jeg oppretter nye prosjekter. Legg scriptet i en mappe som finnes i PATH, og du kan kjøre det hvor som helst.

Dette innlegget er desverre ekstra utsatt for spam, og inntil jeg har tid til å sette opp noe spambeskyttelse har jeg sett meg nødt til å stenge kommentarer for dette innlegget. Dine innspill er velkommen på de fleste andre innlegg!

2006 - 2012 Christian Johansen Creative Commons Lisens