Living life and Make it Better

life, learn, contribute

Endy Muhardin

Software Developer berdomisili di Jabodetabek, berkutat di lingkungan open source, terutama Java dan Linux.

Continuous Integration dengan Luntbuild

Setelah pada artikel sebelumnya kita menggunakan CruiseControl –sempat dikomentari sebagai XML Sit Ups– kali ini kita akan menggunakan Luntbuild, Continuous Integration Tools yang konfigurasinya tidak menggunakan XML sama sekali.

Sama seperti CruiseControl, untuk menjalankan Continuous Integration, kita memerlukan:

  • Repository Subversion yang berisi source code, lengkap dengan folder trunk dan release

  • Code Review, Unit Test, Integration Test, Coverage Test yang lengkap

  • File build.xml yang memiliki target untuk menjalankan semua test

Struktur folder repository juga masih sama seperti artikel sebelumnya. Kita tidak membuat baru, melainkan langsung menggunakan repository pada artikel sebelumnya.

Untuk menjalankan Luntbuild, kita memerlukan:

  • Luntbuild installer

  • Apache Ant 1.7.0

  • Apache Tomcat 5.5

  • Java SDK 6.0

Installer Luntbuild dapat diunduh di sini.

Cara instalasinya tidak sulit, begitu kita dapatkan file instalasinya, buka command prompt, dan masuk ke folder tempat installer tersebut berada. Kemudian jalankan installernya.

$ cd Downloads
$ java -jar luntbuild-1.4.2-installer.jar

Tampilan instalasi Luntbuild akan segera tampil. Klik saja Next untuk melewati Release Note dan License Agreement, sampai pada pertanyaan lokasi instalasi.

Lokasi Instalasi Luntbuild

Di komputer saya, saya pilih lokasi /opt/luntbuild-1.4.2 sebagai lokasi instalasi. Klik Next, dan lanjutkan ke konfigurasi database.

Instalasi Database

Di sini saya tidak mengubah setting apa-apa. Langsung saja lanjutkan sampai menemui pertanyaan username dan password administrator.

Setup Administrator Password

Saya masukkan luntbuild123 sebagai passwordnya. Kita juga akan ditanyai lokasi instalasi Tomcat agar Luntbuild bisa segera menginstal aplikasi webnya di sana. Entah apa yang terjadi, di komputer saya pilihan ini tidak berpengaruh apa-apa. Seharusnya installer akan membuat folder luntbuild di dalam [TOMCAT_INSTALL]/webapps. Setelah instalasi selesai saya tetap harus membuat folder luntbuild di dalam [TOMCAT_INSTALL]/webapps secara manual dan mengkopi semua isi [LUNTBUILD_INSTALL]/web ke dalamnya.

Setelah semua layar berhasil dilalui, instalasi selesai. Kita bisa langsung jalankan Tomcat, dan browse ke http://localhost:8080/luntbuild. Jika instalasi berjalan benar, maka kita akan disambut oleh Luntbuild

Halaman Depan Luntbuild

Secara default, kita login secara anonymous. Untuk bisa mengkonfigurasi project, kita harus logout dulu. Kita akan segera melihat halaman login.

Login Page

Masukkan username luntbuild dan password luntbuild123, sesuai yang kita isikan pada waktu instalasi. Kita akan melihat daftar builder yang masih kosong.

Segera klik tab Project, dan klik tombol New Project di kanan atas. User interface Luntbuild kurang intuitif, sehingga saya harus berusaha keras mencari tombol tersebut. Halaman New Project segera tampil.

Create New Project

Masukkan nama project dan berikan keterangan, lalu Save.

Selanjutnya, kita klik tab VCS.

No VCS Yet

Di tab ini kita melakukan konfigurasi untuk version control. Luntbuild mendukung berbagai merek version control. Pilih Subversion pada drop down yang tersedia.

Add New Subversion Repo

Untuk konfigurasi di komputer saya, isinya adalah sebagai berikut:

  1. Repository url base : svn://localhost

  2. Directory for trunk : trunk

  3. Directory for branches : kosongkan saja, karena project contoh ini tidak memiliki branch

  4. Directory for releases : releases/daily-build

  5. Username : endy. Ini adalah username yang digunakan Luntbuild untuk checkout dan membuat tag. Idealnya kita buatkan user khusus untuk Luntbuild

  6. Password : 123

  7. Quiet Period : kosongkan saja, ini tidak dibutuhkan untuk Subversion yang sudah mendukung atomic commit.

Ada sedikit keanehan Luntbuild. Dia mengharuskan kita membuat modul. Kalau dia tidak menemukan modul, maka akan keluar pesan error. Oleh karena itu, kita klik New Module, lalu langsung saja save tanpa mengisi apa-apa.

Hasil akhir dari tab VCS kita akan nampak seperti ini.

VCS Subversion

Berikutnya, kita masuk ke tab berikutnya untuk konfigurasi Builder.

No Builder Yet

Satu project bisa memiliki banyak builder. Dengan builder, kita bisa mengatur sejauh mana kita ingin melakukan build. Contoh beberapa build yang mungkin digunakan adalah:

  • Unit test: hanya menjalankan unit test saja, mungkin dijalankan setiap 1 jam sekali.

  • Full test: menjalankan semua jenis test, dijalankan sebelum jam makan siang dan sore sebelum pulang

  • Nightly/Daily build : dijalankan sekali sehari, selain menjalankan semua test, juga menghasilkan *jar atau *war. Jenis build ini biasanya dikonfigurasi untuk menghasilkan tag di version control apabila sukses.

Klik tombol New Builder untuk mengkonfigurasi build. Karena kita menggunakan Ant, pilih Ant pada dropdown yang tersedia.

Ant Builder

Pada contoh ini, kita akan mengkonfigurasi Build Jar. Sekali sudah paham konsepnya, tidak sulit untuk mengkonfigurasi jenis build yang lain. Berikut adalah nilai yang saya isikan:

  1. Name : Build Jar

  2. Command for Ant : /opt/apache-ant-1.7.0/bin/ant. Ini adalah path menuju Ant kita.

  3. Build script path : build.xml. Ini adalah nama file build.xml yang ada di project kita

  4. Build target : build-jar. Target Ant yang dipanggil pada saat build berjalan. Saya pilih target build-jar yang mengeksekusi semua test, kemudian membuat *.jar bila test tidak ada yang gagal.

  5. Field sisanya, biarkan saja sesuai default.

Terakhir, kita mengkonfigurasi Schedule, alias jadwal. Ini menentukan kapan build dieksekusi. Untuk Build Jar yang sudah kita konfigurasi, kita ingin dia dijalankan setiap jam 01 dini hari, setiap hari. Berikut isian konfigurasinya.

  1. Name : Nightly Build

  2. Description : build setiap jam 01 dini hari

  3. Next build version : nightly-${#currentDay=system.(year+"-"+numericMonth+"-"+dayOfMonth), #lastDay=project.var["day"].setValue(#currentDay), #dayIterator=project.var["dayIterator"].intValue, project.var["dayIterator"].setIntValue(#currentDay==#lastDay?#dayIterator+1:1), #currentDay}.${project.var["dayIterator"]}. Ini adalah label yang akan diberikan untuk setiap build. String di atas akan menghasilkan label nightly-2007-08-17.1 bila dijalankan pada tanggal 17 Agustus 2007.

  4. Trigger Type: cron. Luntbuild menyediakan dua jenis trigger. Pertama, simple trigger yang berbasis interval.

Dengan simple trigger, kita dapat menjadwalkan build untuk berjalan misalnya setiap dua jam, atau setiap 30 menit. Kedua, cron trigger, yang berbasis waktu. Dengan cron trigger, kita dapat menjalankan build setiap waktu tertentu, misalnya setiap Sabtu, atau setiap hari jam 1 pagi. Untuk menjalankan build setiap jam satu pagi, gunakan cron trigger dengan konfigurasi 0 0 1 * * ?. Luntbuild menggunakan pustaka Quartz untuk melakukan penjadwalan ini. Lebih lanjut tentang konfigurasi jadwal Quartz dapat dilihat di websitenya.

  1. Build necessary condition: vcsModified or dependencyNewer. Buat apa melakukan build kalau belum ada perubahan sejak terakhir kali build berjalan? Inilah maksud dari field ini. Dengan menyebutkan vcsModified, kita menjelaskan bahwa kalau tidak ada perubahan di dalam version control, tidak perlu lakukan build. Selain nilai ini, kita juga bisa menggunakan nilai always, yang artinya tetap build walaupun tidak ada yang commit.

  2. Associated builders. Di sini kita memilih builder mana yang ingin dijalankan.

  3. Associated post builder. Misalnya setelah build sukses dijalankan, kita ingin membuat installer yang siap diunduh. Kita bisa sebutkan hal tersebut di sini.

  4. Label strategy: Label if success. Hanya buat tag di version control bila build sukses.

  5. Notify strategy: notify if status change. Artinya, kirim pemberitahuan apabila status build berbeda dari sebelumnya, misalnya tadinya gagal menjadi sukses, atau sebaliknya.

Demikian sebagian nilai yang harus diisikan. Untuk field yang tidak saya jelaskan, silahkan baca keterangannya atau ikuti saja default.

Setelah semua konfigurasi selesai, kembali ke halaman depan untuk menyaksikan hasil pekerjaan kita. Di sana akan terpampang semua build yang sudah dikonfigurasi.

Daftar build

Kita bisa menjalankan build tersebut secara manual tanpa harus menunggu jatuh temponya. Biasanya kita lakukan build manual untuk mengetes konfigurasi. Build yang sedang berjalan ditandai dengan ikon roda gigi.

Building

Build yang gagal akan ditandai dengan warna merah, sedangkan build yang berhasil diwarnai hijau.

Build Successful

Bila build gagal, tentunya kita ingin melihat apa yang terjadi. Klik build info untuk menampilkan informasinya.

Build Info

Kurang detail? Buka saja lognya. Di sini akan terlihat di langkah yang mana build tersebut berhenti.

Build Log

Demikianlah cara penggunaan Luntbuild. Mudah-mudahan dengan menggunakan perangkat ini proyek software Anda bisa dikelola dengan baik dan teratur.


Cruise Control

Kalau Anda programmer Java, tentunya sudah tidak asing lagi dengan Tomcat atau Eclipse. Yang satu adalah application server, satunya lagi adalah Integrated Development Environment (IDE). Ada satu kesamaan dalam kedua produk ini, keduanya adalah proyek open source yang dikelola secara profesional.

Coba buka halaman download di website masing-masing proyek tersebut. Di sana bisa kita temukan beberapa jenis download, yaitu Nightly Builds dan Stable Builds. Stable builds adalah aplikasi yang sudah melalui berbagai fase testing dan dinyatakan lulus uji. Nightly builds, seperti namanya, adalah build yang dibuat setiap malam dan dirilis kepada publik agar bisa diuji coba beramai-ramai. Dengan besarnya jumlah penguji, diharapkan bug yang ada dalam aplikasi bisa ditemukan semuanya.

Build, dalam dunia Java, terdiri dari serangkaian aktifitas, diantaranya sebagai berikut:

  1. Menjalankan review kode otomatis

  2. Kompilasi kode program

  3. Menjalankan unit test

  4. Menjalankan integration test

  5. Menjalankan coverage test (kalau ada)

  6. Menjalankan platform test, untuk aplikasi yang berbeda antar OS (seperti Eclipse)

  7. Bila lulus semua ujian di atas, buat tag di version control

  8. Siapkan executable (*.jar, *.war, *exe, dan sebagainya)

  9. Publish executable di website supaya bisa didownload orang banyak

Wow, daftar aktifitasnya cukup banyak. Kalau ini dikerjakan setiap malam, betapa membosankan. Saya tidak dapat membayangkan ada satu orang yang ditugaskan khusus untuk melakukan hal ini. Pasti setelah beberapa hari saja dia akan bosan dan mengundurkan diri. Apalagi dalam project open source di mana sebagian besar kontributornya tidak dibayar.

Untuk itulah ada tools khusus untuk melakukan hal membosankan ini. Toolsnya disebut Continuous Integration Tools, berdasarkan tulisan Martin Fowler tentang Continuous Integration. Ada beberapa tools yang tersedia di pasaran, diantaranya:

Dalam tulisan kali ini, kita akan bahas tentang penggunaan CruiseControl, salah satu Continuous Integration Tool yang populer dan open source.

CI Tool yang baik haruslah memiliki fitur sebagai berikut:

  • Mendukung berbagai jenis version control, minimal Subversion dan CVS

  • Dapat menggunakan Ant atau Maven

  • Mendukung banyak project

  • Dapat mengelola artifact (hasil build)

  • Dapat memberitahu orang tentang hasil build (gagal atau sukses) melalui berbagai cara (email, instant message, sms, dan sebagainya)

  • Memiliki aplikasi pelaporan yang mudah diakses melalui web

Yang dilakukan oleh CI Tools adalah sebagai berikut:

  1. Periksa repository source code, apakah ada perubahan terbaru

  2. Bila ada, ambil perubahan terbaru tersebut

  3. Lakukan build (compile, testing, dsb)

  4. Laporkan hasilnya (gagal atau berhasil) melalui email atau media lainnya

  5. Buat juga laporan di website

  6. Bila sukses, publish artifact yang dihasilkan

Cruise Control membutuhkan beberapa file konfigurasi:

  • config.xml: Hanya satu, digunakan untuk mendaftarkan project yang akan dikelola

  • build-namaproject.xml : Satu per project. Bila kita punya tiga project, maka akan ada tiga build-namaproject.xml, dengan nama file disesuaikan dengan masing-masing project.Buildfile ini bertugas untuk sinkronisasi dengan version control dan membuat tag di version control

  • build.xml : Satu per project. Ini adalah buildfile yang biasa kita gunakan di project untuk melakukan kompilasi, menjalankan test, dan menghasilkan *jar atau *war.

Kita butuh satu folder kerja untuk CruiseControl melakukan tugasnya. Sebaiknya folder ini dipisahkan dari folder instalasi CruiseControl agar memudahkan kita pada waktu melakukan upgrade CruiseControl. Untuk kepentingan ilustrasi, folder instalasi CruiseControl akan ditulis [CC_INSTALL] dan folder kerja akan ditulis [CC_WORK].

Berikut adalah struktur folder [CC_INSTALL]:

Struktur Folder Instalasi CruiseControl

dan folder kerja [CC_WORK] akan berisi seperti ini:

Folder Kerja CruiseControl

Struktur folder di dalam repository Subversion kita seperti ini:

Struktur Folder Subversion

Pada contoh ini, kita akan menjalankan build untuk satu project TestingTraining dengan konfigurasi sebagai berikut:

  1. Memiliki dua build, yang satu berjalan setiap satu menit, satu lagi berjalan setiap jam 18.00 sore

  2. Version control yang digunakan adalah Subversion

  3. Bila build sukses, buat tag di folder releases/daily-build/build-NN-yyyyMMddhhmmss

Konfigurasi tersebut ditulis di config.xml sebagai berikut.

<cruisecontrol>
    <project name="TestingTraining" buildafterfailed="true">
      <listeners>
        <currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
      </listeners>

      <modificationset quietperiod="10">
          <svn RepositoryLocation="svn://172.16.2.252/trunk" />
      </modificationset>

      <schedule interval="60">
          <ant anthome="/opt/apache-ant-1.6.5"
               antWorkingDir="/home/endy/tmp/cruise-work/projects/${project.name}"
               buildfile="/home/endy/tmp/cruise-work/build-${project.name}.xml"
               target="build"
               uselogger="true"
               usedebug="false"
	       />
      </schedule>

      <log>
          <merge dir="/home/endy/tmp/cruise-work/projects/${project.name}/build/report/junit"/>
      </log>

      <publishers>
            <onsuccess>
                <antpublisher anthome="/opt/apache-ant-1.6.5"
                              antWorkingDir="/home/endy/tmp/cruise-work/projects/${project.name}"
                              buildfile="/home/endy/tmp/cruise-work/build-${project.name}.xml"
                            target="tag"
                            uselogger="true"
                            usedebug="false"
                />
		<artifactspublisher
		    dir="/home/endy/tmp/cruise-work/projects/${project.name}/dist"
		    dest="artifacts/${project.name}"/>
            </onsuccess>
        </publishers>
    </project>
</cruisecontrol>

Berikut adalah penjelasannya.

  • Konfigurasi CruiseControl dibuat dengan format XML. Tag paling luar adalah <cruisecontrol>

  • Satu file konfigurasi bisa memuat banyak project. Masing-masing project dikonfigurasi dalam tag <project>

  • Di halaman depan CruiseControl, akan ada status untuk masing-masing project. Status ini akan disimpan di file status.txt

  • Modification Set: Beberapa produk version control tidak mengenal atomic commit, misalnya CVS. Karena itu, bila kita commit (misalnya) 7 file sekaligus, bisa saja CruiseControl terbangun pada saat baru 3 file yang tercommit. Bila CruiseControl melakukan build pada saat itu juga, bisa dipastikan akan terjadi error. Oleh karena itu, kita suruh CruiseControl membatalkan build bila kurang dari 10 detik yang lalu ada orang yang commit. Tentu saja bila kita menggunakan Subversion, hal ini tidak relevan.

  • Schedule: Ini adalah daftar build schedule yang ingin kita daftarkan. Tag ini bisa memuat banyak build. Kita menggunakan interval 60 detik, yang artinya setiap menit CruiseControl akan melakukan build. Selain schedule yang berbasis interval, kita juga bisa mendaftarkan schedule yang menggunakan waktu tertentu, misalnya berjalan setiap jam 12 malam.

  • Merge log yang dihasilkan JUnit, tersimpan di folder build/report/junit ke dalam tampilan report CruiseControl.

  • Publisher : pada bagian ini kita daftarkan Ant Publisher pada kategori onsuccess. Artinya, kalau build sukses, jalankan target tag untuk membuat tag di dalam repository. Selain itu, kita juga menggunakan Artifact Publisher, yang berguna untuk mengkopi file *.jar yang dihasilkan ke dalam folder CruiseControl sehingga bisa didownload melalui website.

Di file konfigurasi tersebut, kita memanggil file build-TestingTraining.xml. Ini adalah isi dari file tersebut.

<project name="CruiseControl Builder"
    	 default="build"
         basedir="projects/TestingTraining">

  <property name="repository.url" value="svn://localhost"/>
  <property name="branch" value="trunk"/>
  <property name="release.folder" value="releases/daily-build" />
  <property name="svn.username" value="endy" />
  <property name="svn.password" value="123" />
  <property name="message" value="Created automatically by CruiseControl" />

  <path id="cc-classpath">
    <fileset dir="../../lib" includes="**/*jar"/>
  </path>  

  <target name="update">
    <java classname="org.tmatesoft.svn.cli.SVN" fork="true"
          classpathref="cc-classpath">
      <arg value="update"/>      
    </java>
  </target>

  <target name="build" depends="update">
    <ant inheritAll="false" target="build-jar"/>
  </target>

  <target name="tag">
    <java classname="org.tmatesoft.svn.cli.SVN"
              fork="true" classpathref="cc-classpath">
            <arg value="--username"/>
            <arg value="${svn.username}"/>

            <arg value="--password"/>
            <arg value="${svn.password}"/>

            <arg value="cp"/>
            <arg value="${repository.url}/${branch}"/>
            <arg value="${repository.url}/${release.folder}/${label}-${cctimestamp}"/>

            <arg value="-m"/>
            <arg value="${message}"/>

        </java>
  </target>

</project>

Penjelasannya sebagai berikut.

  • Kita menggunakan pustaka yang disediakan SVNKit (dulunya JavaSVN) agar bisa menggunakan Subversion melalui Ant. Sebetulnya tanpa SVNKit juga bisa, yaitu dengan target exec yang dimiliki Ant untuk memanggil perintah di command line. Dengan menggunakan SVNKit, kita tidak perlu menginstal Subversion command line di build server kita.

  • Ada tiga target utama dalam buildfile ini: update, build, dan tag. Target update berguna untuk mengambil perubahan terbaru dari repository ke folder kerja CruiseControl. Target build memanggil target build-jar di dalam build.xml yang dimiliki project. Target build-jar ini hanya bisa berhasil kalau semua test sudah berjalan dengan sempurna. Target tag berguna untuk membuat tag di repository. Kita bisa mengirim variabel yang dihasilkan CruiseControl, dalam hal ini ${label} dan ${cctimestamp}.

Agar file ini bisa dijalankan, kita harus memiliki folder projects/TestingTraining yang berisi hasil checkout dari repository. Mari kita checkout dulu.

$ cd projects
$ svn co svn://localhost/trunk TestingTraining

Untuk menguji apakah file build-TestingTraining.xml ini bisa dijalankan dengan baik, masuk ke folder projects/TestingTraining dan panggil file tersebut dari folder ini.

$ ant -f ../../build-TestingTraining.xml build
Buildfile: ../../build-TestingTraining.xml

update:
     [java] At revision 71.

build:

clean:
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/bin
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/debug
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/cobertura
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/report/junit
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/report/pmd
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/report/cobertura
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/dist

prepare:
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/build/bin
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/build/debug
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/build/cobertura
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/build/report/junit
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/build/report/pmd
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/build/report/cobertura
    [mkdir] Created dir: /home/endy/tmp/cruise-work/projects/TestingTraining/dist

code-review:

compile:
    [javac] Compiling 11 source files to /home/endy/tmp/cruise-work/projects/TestingTraining/build/bin

compile-cobertura:
    [javac] Compiling 11 source files to /home/endy/tmp/cruise-work/projects/TestingTraining/build/debug
   [delete] Deleting: /home/endy/tmp/cruise-work/projects/TestingTraining/cobertura.ser
   [delete] Deleting directory /home/endy/tmp/cruise-work/projects/TestingTraining/build/cobertura
[cobertura-instrument] Cobertura 1.8 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file
[cobertura-instrument] Instrumenting 7 files to /home/endy/tmp/cruise-work/projects/TestingTraining/build/cobertura
[cobertura-instrument] Cobertura: Saved information on 7 classes.
[cobertura-instrument] Instrument time: 110ms

unit-test:
    [junit] Running tutorial.testing.CalculatorTest
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.047 sec
    [junit] Cobertura: Loaded information on 7 classes.
    [junit] Cobertura: Saved information on 7 classes.
    [junit] Running tutorial.testing.DayCounterTest
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.055 sec
    [junit] Cobertura: Loaded information on 7 classes.
    [junit] Cobertura: Saved information on 7 classes.
    [junit] Running tutorial.testing.LoginServletTest
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.159 sec
    [junit] Cobertura: Loaded information on 7 classes.
    [junit] Cobertura: Saved information on 7 classes.
    [junit] Running tutorial.testing.dbunit.PersonDaoMySQLTest
    [junit] Tests run: 3, Failures: 0, Errors: 0, Time elapsed: 0.153 sec
    [junit] Cobertura: Loaded information on 7 classes.
    [junit] Cobertura: Saved information on 7 classes.
[junitreport] Transform time: 564ms
[cobertura-report] Cobertura 1.8 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file
[cobertura-report] Cobertura: Loaded information on 7 classes.
[cobertura-report] Report time: 231ms

coverage-test:
[cobertura-check] Cobertura 1.8 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file
[cobertura-check] Cobertura: Loaded information on 7 classes.
[cobertura-check] All checks passed.

full-test:

build-jar:
      [jar] Building jar: /home/endy/tmp/cruise-work/projects/TestingTraining/dist/TutorialTesting.jar

BUILD SUCCESSFUL
Total time: 12 seconds

File build-TestingTraining.xml akan memanggil build.xml yang ada di dalam project kita. Berikut isi dari file ini.

<project name="TestingTraining" default="full-test" basedir=".">

	<property name="source.java" value="src/java"/>
	<property name="compile.normal" value="build/bin"/>
	<property name="compile.debug" value="build/debug"/>
	<property name="compile.cobertura" value="build/cobertura"/>
	<property name="distribution" value="dist" />

	<property name="report.junit" value="build/report/junit"/>
	<property name="report.pmd" value="build/report/pmd"/>
	<property name="report.cobertura" value="build/report/cobertura"/>

	<path id="devel.classpath">
		<pathelement location="${source.java}"/>
		<pathelement location="${compile.debug}"/>
		<fileset dir="lib" includes="**/*jar" />
		<fileset dir="ext" includes="**/*jar" />
	</path>

	<taskdef classpathref="devel.classpath" resource="tasks.properties"/>

	<target name="prepare">
		<mkdir dir="${compile.normal}"/>
		<mkdir dir="${compile.debug}"/>
		<mkdir dir="${compile.cobertura}"/>
		<mkdir dir="${report.junit}"/>
		<mkdir dir="${report.pmd}"/>
		<mkdir dir="${report.cobertura}"/>

		<mkdir dir="${distribution}" />
	</target>

	<target name="clean">
		<delete dir="${compile.normal}"></delete>
		<delete dir="${compile.debug}"></delete>
		<delete dir="${compile.cobertura}"></delete>
		<delete dir="${report.junit}"></delete>
		<delete dir="${report.pmd}"></delete>
		<delete dir="${report.cobertura}"></delete>
		<delete dir="${distribution}"></delete>
	</target>

	<target name="code-review" depends="prepare">
		<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="devel.classpath"/>
    	<pmd targetjdk="1.5" shortFilenames="true" failonerror="true" failonruleviolation="true" rulesetfiles="pmd-ruleset.xml">                           
	      <formatter type="net.sourceforge.pmd.renderers.HTMLRenderer"
	                 toFile="${report.pmd}/pmd.html"
	      />
	      <fileset dir="${source.java}">
	          <include name="**/*.java"/>
	          <exclude name="**/*Test.java"/>
	      </fileset>
	    </pmd>
	</target>

	<target name="compile" depends="code-review">
		<javac
			srcdir="${source.java}"
			destdir="${compile.normal}"
			classpathref="devel.classpath">
		</javac>
	</target>

	<target name="unit-test" depends="compile,compile-cobertura">
		<junit haltonfailure="true" fork="true" printsummary="true">
			<classpath location="${compile.cobertura}"></classpath>
			<classpath refid="devel.classpath"/>
            <formatter type="xml"/>
            <batchtest todir="${report.junit}">
                <fileset dir="${compile.debug}" includes="**/*Test.class" excludes="**/*Abstract*.class"/>
            </batchtest>
		</junit>

		<junitreport todir="${report.junit}">
            <fileset dir="${report.junit}">
            <include name="TEST-*.xml"/>
            </fileset>
            <report format="frames" todir="${report.junit}/html"/>
        </junitreport>

		<cobertura-report
        	datafile="cobertura.ser"
        	srcdir="${source.java}"
        	destdir="${report.cobertura}"
        />
	</target>

	<target name="compile-cobertura" depends="prepare">
		<javac
			srcdir="${source.java}"
			destdir="${compile.debug}"
			classpathref="devel.classpath"
			fork="true"
			debug="true"
		/>
        <delete file="cobertura.ser"/>
    	<delete dir="${compile.cobertura}" />

        <cobertura-instrument todir="${compile.cobertura}">
            <fileset dir="${compile.debug}">
                    <include name="**/*.class"/>
                    <exclude name="**/*Test*.class"/>
            </fileset>
        </cobertura-instrument>
	</target>

	<target name="coverage-test" depends="unit-test">
		<cobertura-check datafile="cobertura.ser"
                         branchrate="75"
                         linerate="75"
                         haltonfailure="true"
        />

	</target>

	<target name="full-test" depends="code-review,coverage-test"></target>

	<target name="build-jar" depends="clean,full-test">
		<jar destfile="${distribution}/${ant.project.name}.jar"
		       basedir="${compile.normal}"
		       excludes="**/*Test.class"
		  />
	</target>
</project>

Seperti kita lihat di atas, file tersebut memiliki target build-jar yang hanya akan dilakukan apabila target code-review, compile, unit-test, coverage-test dilakukan dengan sukses.

Baiklah, persiapan sudah selesai, sekarang jalankan CruiseControl, dan lihat hasilnya. CruiseControl dijalankan melalui command prompt dengan mensuplai config.xml yang kita miliki.

$ cd [CC_INSTALL]
$ ./cruisecontrol.sh -configfile [CC_WORK]/config.xml

Bila tidak ada error, maka kita bisa browse ke http://localhost:8080

Ini adalah halaman depan. Memuat status masing-masing project.

Halaman Depan CruiseControl

Ini adalah halaman untuk TestingTraining.

Hasil Build

Seperti kita lihat, hasilnya build failed, karena database MySQL yang diperlukan untuk test belum dijalankan. Mari kita nyalakan dan buat test ini menjadi sukses. Setelah sukses, tampilannya seperti ini.

Hasil Build yang sukses

Kita bisa melihat hasil unit test di dalam tab Test Result.

Hasil JUnit

Berapa kali gagal, berapa kali sukses? Kita bisa lihat di tab Metric.

Metric tentang hasil build

Bila kita sudah menjalankan daily build ini selama beberapa waktu, di repository kita akan dihasilkan tag sesuai dengan build yang sukses. Berikut contohnya.

Daftar Tag yang dibuat CruiseControl

Demikianlah penggunaan CruiseControl. Dengan menggunakan CruiseControl ini, para programmer bisa dibebaskan dari tugas membosankan, sehingga waktunya bisa digunakan untuk hal lain yang lebih bermanfaat, seperti misalnya menulis blog atau menambah teman baru di Friendster.


Dual Head Ubuntu

Pertanyaan : Kalau kita punya komputer, upgrade hardware apa yang paling meningkatkan produktifitas ??

Jawaban 1 : Prosesor

Jawaban 2 : Memori

Saya tidak sependapat dengan kedua jawaban di atas. Prosesor lebih kencang atau memori memang meningkatkan kemampuan komputer. Tapi ada upgrade lain yang lebih signifikan efeknya, yaitu tambah monitor.

Anda pernah menonton film Swordfish? Film ini bercerita tentang Stanley Jobson, pensiunan hacker yang dipaksa membobol bank demi menyelamatkan anaknya. Di film ini, Stanley diberikan komputer super canggih agar bisa membobol jaringan bank. Komputer tersebut memiliki enam screen.

Mereka yang sudah pernah merasakan bekerja dengan dua (atau lebih) monitor pasti mengerti maksud saya. Bayangkan coding di satu screen dan melihat Java API di screen yang satu lagi. Atau membuat desain software (UML, ERD, dsb) di screen kanan sambil melihat dokumen analisa di screen kiri. Dan masih banyak kemungkinan lain yang bisa dilakukan. Bahkan Bill Gates bekerja dengan tiga monitor sekaligus.

Pada artikel ini, saya akan membahas tentang cara setup dua monitor di Ubuntu. Komputer yang saya gunakan adalah NEC Versa 3100. Walaupun berbeda di sisi teknis, cara ini juga bisa diterapkan di komputer lain yang menggunakan X.Org sebagai X servernya.

Sebelum mulai, mari kita kenali dulu istilah-istilah yang ada di dalam konfigurasi X.Org.

  • InputDevice : Ini adalah segala alat input seperti mouse, keyboard, touchscreen, pulpen elektronik, dan teman-temannya. Dalam satu file konfigurasi bisa dimasukkan banyak device.

  • Device: Yang dimaksud device di sini adalah display adapter kita, atau lebih dikenal dengan istilah VGA Card. Bila kita memasang lebih dari satu VGA Card, maka harus ada konfigurasi Device yang sesuai agar VGA Card tersebut bisa berfungsi dengan baik.

  • Monitor: Self Explanatory. Monitor adalah yang menampilkan output dari komputer.

Untuk mengaktifkan dual head, kita membutuhkan dua monitor. Perlu diperhatikan bahwa kita belum tentu butuh lebih dari satu VGA Card, tergantung tipe yang kita gunakan. Di PC saya yang lainnya, saya menggunakan NVidia GForce yang memiliki tiga output: VGA, DVI, dan TV. Yang biasa kita gunakan di monitor CRT adalah VGA port, sedangkan beberapa tipe monitor LCD biasanya menyediakan kabel VGA dan juga DVI. TV Out tentunya kita sudah tahu bentuknya, seperti colokan dari DVD player itu lho ..

Karena saya menggunakan notebook, maka saya memiliki dua output dari VGA, yang satu adalah LCD bawaan notebook tersebut, dan satu lagi VGA port yang biasa kita gunakan untuk presentasi.

Jumlah VGA dan output port yang kita miliki sangat penting diketahui agar bisa mengkonfigurasi dual head dengan benar. Untuk mereka yang VGA outputnya cuma satu port terpaksa pasang satu card lagi agar bisa menggunakan dual head.

Baiklah, mari kita masuk ke konfigurasi. Sebagai titik awal, berikut konfigurasi X.Org saya sebelum ada modifikasi apa-apa. Ini merupakan konfigurasi yang dibuatkan Ubuntu.

# /etc/X11/xorg.conf (xorg X Window System server configuration file)
#
# This file was generated by dexconf, the Debian X Configuration tool, using
# values from the debconf database.
#
# Edit this file with caution, and see the xorg.conf(5) manual page.
# (Type "man xorg.conf" at the shell prompt.)
#
# This file is automatically updated on xserver-xorg package upgrades *only*
# if it has not been modified since the last upgrade of the xserver-xorg
# package.
#
# If you have edited this file but would like it to be automatically updated
# again, run the following command:
#   sudo dpkg-reconfigure -phigh xserver-xorg

Section "Files"
	FontPath	"/usr/share/fonts/X11/misc"
	FontPath	"/usr/share/fonts/X11/cyrillic"
	FontPath	"/usr/share/fonts/X11/100dpi/:unscaled"
	FontPath	"/usr/share/fonts/X11/75dpi/:unscaled"
	FontPath	"/usr/share/fonts/X11/Type1"
	FontPath	"/usr/share/fonts/X11/100dpi"
	FontPath	"/usr/share/fonts/X11/75dpi"
	# path to defoma fonts
	FontPath	"/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
EndSection

Section "Module"
	Load	"i2c"
	Load	"bitmap"
	Load	"ddc"
	Load	"dri"
	Load	"extmod"
	Load	"freetype"
	Load	"glx"
	Load	"int10"
	Load	"vbe"
EndSection

Section "InputDevice"
	Identifier	"Generic Keyboard"
	Driver		"kbd"
	Option		"CoreKeyboard"
	Option		"XkbRules"	"xorg"
	Option		"XkbModel"	"pc105"
	Option		"XkbLayout"	"us"
EndSection

Section "InputDevice"
	Identifier	"Configured Mouse"
	Driver		"mouse"
	Option		"CorePointer"
	Option		"Device"		"/dev/input/mice"
	Option		"Protocol"		"ImPS/2"
	Option		"ZAxisMapping"		"4 5"
	Option		"Emulate3Buttons"	"true"
EndSection

Section "InputDevice"
	Identifier	"Synaptics Touchpad"
	Driver		"synaptics"
	Option		"SendCoreEvents"	"true"
	Option		"Device"		"/dev/psaux"
	Option		"Protocol"		"auto-dev"
	Option		"HorizScrollDelta"	"0"
EndSection

Section "InputDevice"
	Driver		"wacom"
	Identifier	"stylus"
	Option		"Device"	"/dev/input/wacom"
	Option		"Type"		"stylus"
	Option		"ForceDevice"	"ISDV4"		# Tablet PC ONLY
EndSection

Section "InputDevice"
	Driver		"wacom"
	Identifier	"eraser"
	Option		"Device"	"/dev/input/wacom"
	Option		"Type"		"eraser"
	Option		"ForceDevice"	"ISDV4"		# Tablet PC ONLY
EndSection

Section "InputDevice"
	Driver		"wacom"
	Identifier	"cursor"
	Option		"Device"	"/dev/input/wacom"
	Option		"Type"		"cursor"
	Option		"ForceDevice"	"ISDV4"		# Tablet PC ONLY
EndSection

Section "Device"
	Identifier	"Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
	Driver		"i810"
	BusID		"PCI:0:2:0"
#	Option "ForceBIOS" "1920x1440=1280x768"
EndSection

Section "Monitor"
	Identifier	"Generic Monitor"
	Option		"DPMS"
EndSection

Section "Screen"
	Identifier	"Default Screen"
	Device		"Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
	Monitor		"Generic Monitor"
	DefaultDepth	24
	SubSection "Display"
		Depth		1
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		4
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		8
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		15
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		16
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		24
		Modes		"1280x768"
	EndSubSection
EndSection

Section "ServerLayout"
	Identifier	"Default Layout"
	Screen		"Default Screen"
	InputDevice	"Generic Keyboard"
	InputDevice	"Configured Mouse"
	InputDevice     "stylus"	"SendCoreEvents"
	InputDevice     "cursor"	"SendCoreEvents"
	InputDevice     "eraser"	"SendCoreEvents"
	InputDevice	"Synaptics Touchpad"
EndSection

Section "DRI"
	Mode	0666
EndSection

Perlu saya ingatkan untuk SELALU BACKUP konfigurasi awal Anda sebelum mengubah konfigurasi. Jadi bila terjadi kegagalan, kita selalu bisa kembali ke setting awal.

Penggantian Nama

Pertama, mari kita ganti dulu beberapa nama pada file konfigurasi di atas agar lebih mudah dimengerti. Yang perlu diganti adalah bagian Monitor dan Device. Saya ganti menjadi seperti ini.

Section "Device"
	Identifier	"Intel i915 LCD Output"
	Driver		"i810"
	BusID		"PCI:0:2:0"
#	Option "ForceBIOS" "1920x1440=1280x768"
EndSection

Section "Monitor"
	Identifier	"Default LCD"
	Option		"DPMS"
EndSection

Artinya, device di atas mengacu pada output yang menuju LCD screen saya. Nama monitor juga diganti menjadi LCD agar lebih jelas.

Menambah Monitor

Sekarang, kita tambah monitor dan juga port VGA output. Konfigurasinya adalah sebagai berikut.

Section "Device"
	Identifier	"Intel i915 External Output"
	Driver		"i810"
	BusID		"PCI:0:2:0"
	Option "ForceBIOS" "1920x1440=1280x768"
EndSection
Section "Monitor"
	Identifier	"External Monitor"
	Option		"DPMS"
EndSection

Karena ada tambahan output, kita perlu menjelaskan pada X.Org mana screen utama kita. Kalau kita tidak lakukan ini, maka bisa saja pada saat booting LCD screen saya blank, karena outputnya dikeluarkan ke monitor CRT yang belum tentu dipasang. Tambahkan nomor screen pada konfigurasi VGA Card seperti ini.

Section "Device"
	Identifier	"Intel i915 LCD Output"
	Driver		"i810"
	BusID		"PCI:0:2:0"
#	Option "ForceBIOS" "1920x1440=1280x768"
	Option "MonitorLayout" "CRT,LFP"
	Screen		0
EndSection
Section "Device"
	Identifier	"Intel i915 External Output"
	Driver		"i810"
	BusID		"PCI:0:2:0"
	Option "ForceBIOS" "1920x1440=1280x768"
	Screen		1
EndSection

Dari konfigurasi di atas dapat terlihat bahwa screen utama (screen 0) adalah LCD Output. Di atas juga ada tambahan konfigurasi MonitorLayout. Ini ditambahkan agar secara default kedua output langsung aktif. Biasanya kalau kita pakai laptop, ada kombinasi tombol untuk mengaktifkan VGA Output, misalnya Fn+F5 atau Fn+F3. Nah, dengan opsi ini, VGA output langsung aktif tanpa harus menekan Fn+Something.

Konfigurasi Screen

Selanjutnya, kita akan mengkonfigurasi Screen. Screen adalah kombinasi antara Device dan Monitor. Artinya, konfigurasi ini akan menentukan VGA Output mana yang terhubung ke Monitor mana, berikut resolusi tampilannya. Karena tadi kita mengganti nama monitor dan VGA Output, maka kita harus sesuaikan konfigurasi Screen yang sudah ada. Berikut hasilnya.

Section "Screen"
	Identifier	"Default Screen"
	Device		"Intel i915 LCD Output"
	Monitor		"Default LCD"
	DefaultDepth	24
	SubSection "Display"
		Depth		1
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		4
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		8
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		15
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		16
		Modes		"1280x768"
	EndSubSection
	SubSection "Display"
		Depth		24
		Modes		"1280x768"
	EndSubSection
EndSection

dan selanjutnya, ini adalah tambahan untuk screen kedua kita.

Section "Screen"
	Identifier	"External Screen"
	Device		"Intel i915 External Output"
	Monitor		"External Monitor"
	DefaultDepth	24
	SubSection "Display"
		Depth		1
		Modes		"1024x768" "800x600"
	EndSubSection
	SubSection "Display"
		Depth		4
		Modes		"1024x768" "800x600"
	EndSubSection
	SubSection "Display"
		Depth		8
		Modes		"1024x768" "800x600"
	EndSubSection
	SubSection "Display"
		Depth		16
		Modes		"1024x768" "800x600"
	EndSubSection
	SubSection "Display"
		Depth		16
		Modes		"1024x768" "800x600"
	EndSubSection
	SubSection "Display"
		Depth		24
		Modes		"1024x768" "800x600"
	EndSubSection
EndSection

Kedua screen siap digunakan. Sekarang tinggal satu langkah terakhir.

ServerLayout

Kita perlu memberitahu X.Org screen mana yang ada di kiri, dan mana yang sebelah kanan. Gunanya agar mouse pointer kita bisa ‘menembus batas’ dengan benar. Misalnya monitor CRT kita pasang di sebelah kiri laptop, maka seharusnya kalau mouse pointer digerakkan ke pinggir kiri LCD, dia akan muncul di pinggir kanan CRT.

Berikut adalah konfigurasi ServerLayout.

Section "ServerLayout"
	Identifier	"Multihead Layout"
	Screen		0 "Default Screen" 0 0
	Screen		1 "External Screen" LeftOf "Default Screen"
	InputDevice	"Generic Keyboard"
	InputDevice	"Configured Mouse"
	InputDevice     "stylus"	"SendCoreEvents"
	InputDevice     "cursor"	"SendCoreEvents"
	InputDevice     "eraser"	"SendCoreEvents"
	InputDevice	"Synaptics Touchpad"
#	Option		"Xinerama" "true"
EndSection

Pada konfigurasi di atas, saya menon-aktifkan opsi Xinerama. Kalau opsi ini dijalankan, kita akan memiliki desktop super lebar. Kita bisa drag satu window menembus batas. Tapi kalau opsi ini dimatikan, seolah-olah ada dua desktop yang terpisah, mouse pointer bisa tembus, tapi window aplikasi tidak.

Kalau Anda menonton Swordfish, Stanley Jobson mendapatkan konfigurasi Xinerama. Ini dapat dilihat dari screensaver komet yang berjalan mengelilingi keenam screen yang tersedia. Tergantung kebutuhan, opsi ini bisa dinyalakan atau dimatikan.

Setelah selesai, logout dari desktop. Untuk memastikan, restart X server dengan kombinasi tombol Ctrl+Alt+Backspace. Kalau segalanya berjalan lancar, dual head akan tampil di hadapan kita. Perlu diperhatikan, kadang resolusi layar tidak berjalan sesuai harapan. Kadang kita perlu reboot agar resolusinya benar.

Demikian artikel kali ini, semoga bermanfaat.


Konfigurasi SVN-HTTP di OpenSuSE 10.2

Artikel ini akan menjelaskan tentang konfigurasi Apache dan OpenLDAP di OpenSuSE 10.2 agar Subversion Repository yang kita miliki bisa diakses melalui protokol HTTP.

Pertama, instal software yang dibutuhkan. Jalankan Yast dan instal paket-paket berikut:

  • subversion

  • apache2

  • subversion-server

  • yast2-http-server

Setelah itu, modifikasi executable Subversion agar repository yang dihasilkan memiliki nilai umask yang tepat. Caranya dapat dilihat di sini.

Lalu buat repository untuk percobaan, sebagai contoh saya akan membuat repository di folder /opt/repository/repo-percobaan.

<code>svnadmin create --fs-type fsfs /opt/repository/repo-percobaan</code>

Selanjutnya, kita akan mengkonfigurasi Apache agar membaca folder tersebut dan memetakannya ke URL /svn. Jadi, bila kita mengakses http://localhost/svn/repo-percobaan di browser, Apache akan menampilkan isi repository kita.

Caranya, buka Yast, kemudian masuk ke Network Services > HTTP Server. Yast Control Panel

Ikuti wizard tanpa perubahan sampai layar terakhir. Setelah itu, klik Expert Configuration.

Expert Configuration

Layar pertama adalah pilihan port yang dilayani Apache. Tambahkan port 443 untuk mengaktifkan SSL.

Port SSL

Setelah itu, masuk ke tab Server Modules. Aktifkan module dav, dav_fs.

Apache Module

Kita juga butuh modul tambahan untuk Subversion. Klik Add Module, tambahkan modul dav_svn dan authz_svn.

Add Subversion Module

Selesai dengan Yast. Klik OK untuk menyimpan perubahan. Sekarang kita akan mengedit konfigurasi modul Subversion agar membaca folder repository kita.

Buka file /etc/apache2/conf.d/subversion.conf. Di sana sudah disediakan template yang siap diedit sesuai kebutuhan. Untuk tahap pertama ini, ubah isi file tersebut menjadi seperti ini.

<code><IfModule mod_dav_svn.c>
<Location /svn>
   DAV svn
   SVNParentPath /opt/repository
</Location>

</IfModule></code>

Server ini akan digunakan untuk beberapa project sekaligus. Untuk setiap repository baru yang dibuat di kemudian hari, tidak perlu setting ulang Apache. Cukup buat folder repository baru di dalam /opt/repository.

Save file tersebut, dan restart Apache melalui Yast. Repository sudah bisa dibaca. Arahkan browser Anda ke http://localhost/svn/repo-percobaan. Instalasi yang sukses akan menghasilkan tampilan seperti ini.

Browse Repository Content

Silahkan baca artikel ini untuk mengaktifkan otentikasi melalui OpenLDAP.


MP3 di Linux

Distro Linux yang gratis umumnya tidak menyertakan dukungan MP3, Flash, DVD, dan berbagai format file non-open-source yang lainnya. Ini disebabkan karena format tersebut dilarang di beberapa negara, walaupun di Indonesia diperbolehkan. Ini merupakan masalah yang sudah banyak jawabannya. Bahkan beberapa distro populer sudah memudahkan cara instalasinya.

Mari kita lihat dua distro populer, Ubuntu dan OpenSuSE. Pada Ubuntu Feisty, ada paket yang khusus untuk mengatasi masalah ini, namanya ubuntu-restricted-extras. Cukup buka command prompt, dan ketikkan

sudo apt-get install ubuntu-restricted-extras

Paket ini ada di repository multiverse, jadi pastikan komputer Anda memiliki database dari repository tersebut.

Paket ubuntu-restricted-extras ini memungkinkan kita untuk:

  • Memainkan MP3

  • Memainkan DVD

  • Membuka website ber-Flash

  • Membuka website ber-Java Applet

  • Menggunakan font Arial, Trebuchet, dan font Windows lainnya

Untuk OpenSuSE 10.2, kita harus tambahkan repository packman. Buka Yast, klik Installation Source. Nanti kita akan disuguhi berbagai pilihan protokol. Pilih protokol HTTP.

Selanjutnya, kita akan ditanyai dua hal, nama server repository, dan folder tempat database paket berada. Masukkan ftp.uni-erlangen.de pada kolom nama server, dan /pub/mirrors/packman/suse/10.2 pada nama folder.

Tidak, saya tidak salah ketik, protokolnya memang HTTP dan alamat servernya diawali dengan FTP. Kalau tidak percaya coba saja sendiri, atau lihat di sini.

Setelah repository ditambah, Yast akan mendownload database aplikasi yang disediakan, untuk kemudian mengupdate database internalnya. Bila koneksi internet Anda lambat, bersabar sedikit.

Begitu repository selesai ditambah, kita bisa buka menu Software Management, dan Search dengan keyword libxine1. Ini adalah library yang dibutuhkan agar Amarok bisa memainkan MP3. Amarok adalah aplikasi pemain musik (music player) di KDE.

Instal libxine1, dan Amarok akan segera bisa menyanyikan MP3.

Selamat mencoba.