February 25, 2020

1015 words 5 mins read

GitHub Pages Autodeploy

GitHub Pages Autodeploy

Untuk beberapa case, menggunakan GitHub Pages (GHP) untuk hosting web statik merupakan cara yg cepat dan efektif. Biasanya hanya perlu menunggu proses sekitar kurang dari satu menit dari push kode sampai berstatus daring (online). Tulisan singkat kali ini akan mendokumentasikan prosedur auto-deploy GHP dengan rendering web statik menggunakan remote server tersendiri.

GitHub Pages

GitHub Pages (GHP) adalah layanan hosting situs statik yang menggunakan kode sumber web (HTML, CSS, JavaScript) langsung dari repositori GitHub. Ada 2 jenis GHP:

  • Halaman pengguna / organisasi (diakses melalui https://<USERNAME | ORGANISASI>.github.io/ - untuk selanjutnya kita sebut Tipe-1). Untuk tiap akun pengguna / organisasi hanya dapat dibuat satu halaman.
  • Halaman proyek (diakses melalui https://<USERNAME | ORGANISASI>.github.io/<PROJECT>/ - untuk selanjutnya disebut Tipe-2). Jumlah proyek per akun tidak dibatasi, artinya kita bisa mempunyai banyak web proyek, masing-masing dengan path yang berbeda.

Contoh GHP Tipe-1 misalnya: https://eueung.github.io, atau menjadi root web, tanpa path tambahan. Bedakan dengan contoh GHP Tipe-2 seperti: https://eueung.github.io/012017/nodemcu, dimana mempunyai path 012017/nodemcu.

Untuk level pemula, GitHub juga menyediakan panduan untuk membuat GHP dengan pre-defined template yang seluruhnya bisa dilakukan melalui antar-muka web. Panduan dapat dilihat disini Getting Started with GitHub Pages · GitHub Guides. Referensi yang lain : GitHub Pages (halaman utama), dan Working with GitHub Pages (halaman dokumentasi / bantuan GitHub).

Sebagai overview, untuk GHP Tipe-1 prosedur pembuatannya sebagai berikut:

  • Buat repositori dengan nama <USERNAME>.github.io misalnya eueung.github.io.
  • Siapkan kode sumber web statik yang akan dipasang. Apabila menggunakan generator seperti hugo, gatsby, pelican dll, kode sumber web yang dimaksud adalah hasil semua berkas hasil render, bukan kode sumber asal (non HTML, CSS, clientside JavaScript).
  • Upload (push dalam terminologi git) semua kode sumber ke repositori pada default branch master.

Untuk GHP Tipe-2 prosedur pembuatannya agak berbeda sebagai berikut:

  • Buat repositori dengan nama <PROJECT> misalnya 012017. Buat branch baru dengan nama gh-pages.
  • Siapkan kode sumber web statik yang akan dipasang. Apabila menggunakan generator seperti hugo, gatsby, pelican dll, kode sumber web yang dimaksud adalah hasil semua berkas hasil render, bukan kode sumber asal (non HTML, CSS, clientside JavaScript).
  • push semua kode sumber ke repositori pada branch gh-pages.

Sebagai catatan, karena GHP Tipe-2 hanya menggunakan data / kode dari branch gh-pages, branch yang lain (termasuk branch master) bisa digunakan untuk keperluan lain atau tidak digunakan sama sekali. Walaupun demikian lazimnya, branch gh-pages ini digunakan sebagai presensi web untuk proyek terbuka yang disimpan di branch master (atau branch lain). Kerap juga digunakan sebagai halaman dokumentasi proyek, sehingga mudah diakses oleh komunitas / pengguna.

Arsitektur

Gambar di atas menunjukan arsitektur sistem yang digunakan dalam pembahasan selanjutnya. Kita menggunakan GHP Tipe-2 dengan konvensi sebagai berikut:

  • Branch master dipakai untuk menyimpan kode sumber asal (non-render), misalnya kode sumber konten untuk diproses lebih lanjut dengan hugo, pelican atau prosedur rendering privat.
  • Proses pembaruan kode sumber / konten dilakukan pada mesin lokal, yang apabila sudah selesai akan di push ke GitHub (branch master).
  • Begitu terjadi perubahan konten branch master, branch gh-pages juga harus di-update. Untuk pembahasan disini, digunakan proses rendering yang dijalankan di sebuah server remote.
  • Setelah proses commit ke branch master sukse, server GitHub melalukan operasi webhook ke alamat server remote. Terlebih dahulu, fitur hook ini harus diaktifkan melalui halaman setting repository.
  • Terakhir, apabila semua proses di atas berjalan dengan baik, server akan melakukan proses rendering yang bisa jadi terdiri dari serangkaian proses, sampai hasil akhirnya di-push kembali ke branch gh-pages repositori GitHub.

Mengapa dipilih arsitektur seperti ini? Setidaknya karena dua alasan. Pertama, konfigurasi ini cukup fleksibel dan applicable untuk semua web statik, selama kita membuat proses render yang sesuai. Kedua, tidak membebani mesin lokal untuk proses deploy sehingga bisa lebih fokus ke kode sumber dan testing lokal (proses rendering remote sudah dikonfigurasi untuk deployment).

Repo Webhook

Proses mengaktifkan webhook untuk repo cukup simpel: masuk ke halaman setting repo, kemudian pilih menu navigasi webhooks di sebelah kiri dan tuliskan url untuk webhook di form yang disediakan. Contoh tampilan akhir dapat dilihat pada gambar di atas.

Render Script

Sebagai contoh untuk proses rendering, disini sy menggunakan kode yang ditulis menggunakan vanilla JavaScript. Proses sebenarnya banyak melibatkan shell, sehingga mestinya bisa menggunakan bahasa lain, selama sistem dapat menerima dan membaca data webhook dari GitHub dan melakukan aksi rendering yang sesuai.

Dalam script di bawah, digunakan dua pustaka JavaScript githubhook dan shelljs dengan insiasi dan konfigurasi sebagai berikut.

var githubhook = require('githubhook');
var shell      = require('shelljs');

var trepo   = 'eueung/012017';
var tbranch = 'master';

var github = githubhook({
  host: "0.0.0.0",
  port: 8000,
  path: "/unyilusroucrit",
  secret: "pakogahableh"  
});

Berikutnya pada bagian utama script berisi penerimaan dan pengecekan data webhook, serta proses rendering apabila data yg diterima sesuai.

github.on('push', function (repo, ref, data) {
  var branchName = ref.match(/\/([0-9a-z\-]+)$/i)[1];
  var fullNameRepository = data.repository.full_name;  

  if((branchName==tbranch)&&(fullNameRepository==trepo)) {
    shell.exec('rm -rf temp && mkdir temp');
    
    shell.cd('source');
    if (shell.exec('git pull origin master').code !== 0) { shell.echo('Error: git pull failed'); shell.exit(1); } 
    else console.log('source');
    
    varlist = shell.ls('*.rmd');
    pressname = 'default';
    if (varlist.length>0) pressname = varlist[0].slice(0,-4);
    
    shell.cd('..');    
    shell.exec('cp -a source/. temp/');
    shell.exec('mkdir -p temp/static');

    shell.cd('view');
    if (shell.exec('git pull origin gh-pages').code !== 0) { shell.echo('Error: git pull failed'); shell.exit(1); } 
    else console.log('view');

    shell.exec('mkdir -p '+pressname);
    shell.cd('..');    
    
    var varcmd = 'docker run -t --rm --name remark -v $(pwd)/temp:/work eueung/remark:v1';
    if (shell.exec(varcmd).code !== 0) { 
      shell.echo('Error: docker run failed'); shell.exit(1); 
    } 

    shell.exec('cp -a temp/static/. view/'+pressname+'/');
    shell.exec('cp -a temp/bkgs view/'+pressname+'/');
    shell.exec('cp -a temp/assets view/'+pressname+'/');
    
    shell.cd('view');
    if (shell.exec('git add .').code !== 0) { shell.echo('Error: git add failed'); shell.exit(1); } 
    if (shell.exec('git commit -am "automatic build"').code !== 0) { shell.echo('Error: git commit failed'); shell.exit(1); } 
    if (shell.exec('git push origin gh-pages').code !== 0) { shell.echo('Error: git push failed'); shell.exit(1); } 
    shell.cd('..');
  }
  else {console.log(branchName);}
});

github.listen();

Untuk proses rendering, pada case di atas ditunjukan contoh operasi render untuk presentasi berbasis web menggunakan remark.js. Tahapan prosesnya adalah:

  • Melakukan operasi git pull kode sumber dari branch master.
  • Melakukan operasi git pull kode aktual dari branch gh-pages (untuk menghindari konflik apabila terdapat beberapa pihak yang menjadi kontributor atau kontributor dengan beberapa mesin kerja yang berbeda).
  • Melakukan proses rendering. Dalam contoh di atas menggunakan container (docker) yang sebelumnya sudah disiapkan. Pembahasan tentang docker diluar konteks artikel ini. Intinya, dengan docker kita menyiapkan semua konfigurasi aplikasi sehingga siap eksekusi (secara portabel).
  • Apabila semua proses berhasil, langkah terakhir adalah melakukan push ke branch gh-pages repositori.
comments powered by Disqus