Fakultas Ilmu Komputer UI

Commit d4478931 authored by Fata Nugraha's avatar Fata Nugraha
Browse files

Initial commit

parents
Pipeline #9891 failed with stages
in 1 minute and 32 seconds
variables:
LC_ALL: C.UTF-8
NETLIFY_API_ID: f6415942-1f66-4616-ba66-13150c19be45
HTTP_PROXY: http://proxy.cs.ui.ac.id:8080
HTTPS_PROXY: http://proxy.cs.ui.ac.id:8080
stages:
- build
- deploy
build:
image: ruby:2.6.2-alpine3.9
stage: build
script:
- bundle install
- bundle exec jekyll build -d public
artifacts:
paths:
- $BLOG_ROOT_PATH/public
only:
refs:
- master
deploy:
stage: deploy
image: alpine:3.9
script:
- apk add curl zip
- sh deploy.sh
dependencies:
- build
only:
refs:
- master
---
layout: default
---
<style type="text/css" media="screen">
h1 {
margin: 30px 0;
font-size: 4em;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>
source "http://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 3.8.5"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minima", "~> 2.0"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.6"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0" if Gem.win_platform?
The MIT License (MIT)
Copyright (c) 2016 David Lin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Usage
```
cd blog
docker run --rm \
--volume="$PWD:/srv/jekyll" \
-p 4040:4000 \
-it jekyll/jekyll:3.8 \
jekyll serve
```
Access [127.0.0.1:4040](http://127.0.0.1:4040)
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely need to edit after that.
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'jekyll serve'. If you change this file, please restart the server process.
# Site settings
title: PPLC7
email: email@email.com
description: > # this means to ignore newlines until "baseurl:"
Blog Proyek Perangkat Lunak Fasilkom UI Kelompok C7.
baseurl: "" # the subpath of your site, e.g. /blog
url: "https://yeay.xyz" # the base hostname & protocol for your site
# Build settings
markdown: kramdown
kramdown:
input: GFM
# Third-party services
# just leave someone empty to disable it
# google_analytics:
disqus_shortname:
# used this for post_excerpt at index_page
excerpt_separator: <!--more-->
This diff is collapsed.
<footer class="site-footer">
<div class="container">
<div class="footer left column one-half">
<section class="small-font">
Powered by <a href="https://github.com/jekyll/jekyll">jekyll</a>
</section>
</div>
</div>
</footer>
\ No newline at end of file
{% if site.google_analytics %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '{{ site.google_analytics }}', 'auto');
ga('send', 'pageview');
</script>
{% endif %}
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">
<!-- evil icon -->
<link rel="stylesheet" href="{{"/assets/evil-icons.min.css" | prepend:site.baseurl }}">
<script src="{{"/assets/evil-icons.min.js" | prepend:site.baseurl }}"></script>
<!-- todo: include this into main.css -->
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">
</head>
<header class="site-header">
<h2 class="logo"><a href="{{ site.baseurl }}/">{{ site.title }}</a></h2>
<div class="nav">
<label for="menu-toggle" class="menu-icon">
<!--div data-icon="ei-navicon"></div-->
<svg viewBox="0 0 18 15">
<path fill="#424242"
d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z" />
<path fill="#424242"
d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z" />
<path fill="#424242"
d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z" />
</svg>
</label>
<input type="checkbox" id="menu-toggle">
<div class="site-nav">
<nav>
<ul class="page-link">
<li><a href="{{ "/" | prepend: site.baseurl }}">Home</a></li>
<li><a href="{{ "/archive" | prepend: site.baseurl }}">Posts</a></li>
<li><a href="{{ "/about" | prepend: site.baseurl }}">About</a></li>
</ul>
</nav>
</div>
</div>
</header>
\ No newline at end of file
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
<div class="page-content">
<div class="container">
<div class="three columns">
{% include header.html %}
</div>
<div class="nine columns" style="z-index:100;">
<div class="wrapper">
{{ content }}
</div>
</div>
</div>
{% include footer.html %}
</div>
</body>
</html>
---
layout: default
---
<article class="post">
<header class="post-header">
<h1 class="post-title">{{ page.title }}</h1>
</header>
<div class="article-content">
{{ content }}
</div>
</article>
---
layout: default
---
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="artilce_header">
<h1 class="artilce_title" itemprop="name headline">{{ page.title }}</h1>
<p class="artilce_meta"><time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%b %-d, %Y" }}</time>{% if page.author %} by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">{{ page.author }}</span></span>{% endif %}</p>
</header>
<div class="article-content" itemprop="articleBody">
{{ page.content }}
</div>
</artice>
---
layout: post
title: "DISKLAIMER"
date: 2019-02-21 20:28:47 +0700
author: all
---
Grrr... memo blog ini terutama ditulis untuk **KEPERLUAN SENDIRI**. Tulisan ini
berbasis "_Google Sana, Google Sini, Coba Itu, Coba Ini, Lalu Tanya-tanyi_".
Entah ini **PLAGIAT**, entah ini **RISET**, yang jelas tidak pernah ada klaim
bahwa ini merupakan karya asli, serta belum tentu pula merupakan solusi terbaik,
serta bukan untuk konsumsi Scopus :). Mohon kiranya memberikan tanggapan,
terutama jika memiliki solusi alternatif. Semoga catatan ini akan bermanfaat
di masa mendatang, saat sudah lupa cara menyelesaikan masalah trivia ini.
-- Rahmat M. Samik-Ibrahim
---
layout: post
title: "Introduction"
date: 2019-02-26 15:17:46 +0700
author: ragil
---
# Hello All,
Perkenalkan kami dari tim PPLC7 yang harusnya bernama propensi, tapi karena
ada tim lain yang namanya sama, jadinya ga _kewl_ :'( Kalau kamu penasaran,
di tim kami ada:
<!--more-->
__Fata Nugraha__ dan __Ragil Al Badrun Pasaribu__
![fata](/assets/images/fata-edit.jpeg)
![ragil](/assets/images/ragil-edit.jpeg)
__Tirta Abimanyu Purnomo__ dan __Usama__
![abi](/assets/images/abi-edit.jpeg)
![usama](/assets/images/usama-edit.jpeg)
dan...
__Yogi Lesmana__
![yogi](/assets/images/yogi-edit.jpeg)
*Foto-foto di atas diambil saat _study tour_ tentang kapal.
Dalam satu semester ini, tim kami akan mengembangkan suatu sistem untuk
memanajemen *log* yang merupakan proyek dari Badan Pengkajian dan Penerapan
Teknologi (BPPT).
Sistem manajemen log ini bertugas untuk menerima log serangan dari server-server
yang berada di *data center* BPPT dan mengelola log tersebut agar pengguna dapat
mendapat laporan tentang serangan yang sedang terjadi, mencari informasi yang
terkait dengan log serangan, dan menganalisa suatu serangan.
![Mockup](/assets/images/mockup.jpeg)
Gambar 1: Mockup Dashboard
Salah satu tantangan yang saat ini berusaha kami pecahkan adalah masalah
*performance*. Kami harus membuat sistem ini dapat menerima banyak log dan
menampilkannya secara _seamless_.
Doakan agar kami berhasil ya..!!!
---
layout: post
title: "Agile & TDD"
date: 2019-02-27 22:13:38 +0700
author: abi
---
Halo, di post kali ini saya akan menjelaskan tentang _workflow_ tim kami dengan Agile dan TDD.
<!--more-->
Di Agile, semua pekerjaan yang akan dilakukan dibagi-bagi kedalam **Product Backlog Item** (PBI). Contoh: Fitur Login/Logout
![pbi](/assets/images/pbi.jpg)
Lalu akan dipilih PBI apa yang akan dikerjakan pada rentang 2 minggu dari sekarang. Rentang 2 minggu tersebut disebut dengan **sprint**
![sprint](/assets/images/pbisprint.jpg)
Sebelum memulai sprint, PBI yang dipilih dipecah lagi menjadi unit pekerjaan terkecil yang disebut **task**. Contoh: Membuat test fungsi login.
Task-task tersebut akan diassign ke anggota tim setiap **Daily Stand Up**. Daily Stand Up seharusnya dilakukan setiap hari, namun karena masih ada kuliah dilakukan seminggu 2 kali.
Setiap daily stand up, task-task yang sudah selesai ditandai menjadi done dan anggota tersebut bisa mengerjakan task yang lain.
![tasks](/assets/images/tasks.jpg)
Jika menggunakan project management tools seperti jira, dapat dilihat grafik jumlah task yang sudah selesai dikerjakan selama sprint berjalan. Disebut juga dengan **Burndown Chart**.
![burndown](/assets/images/burndownchart.png)
Setelah sprint selesai, dilakukan Sprint Retrospective untuk meninjau apakah ada kekurangan atau kelebihan kerja tim pada satu sprint sebelumnya.
Karena kami memakai **TDD**, maka untuk setiap fitur paling tidak ada 2 task yang dibuat, yaitu membuat test dan implementasi kode. Untuk mempermudah development, biasanya kedua task tersebut diassign ke orang yang sama.
Task untuk membuat test harus dikerjakan terlebih dahulu sebelum mulai implementasi. Dengan begitu jumlah bug yang mungkin terjadi bisa diminimalisir.
Untuk fitur backend, kami menggunakan library **unittest** bawaan Django. Untuk frontend, kami menggunakan library **jest** untuk React.
Selama test belum _pass_, setiap commit message harus diawali dengan tag \[RED\]. Baru setelah semua test berhasil dipenuhi, commit message diawali dengan tag \[GREEN\].
![tddcycle](/assets/images/tddcycle.png)
---
layout: post
title: GitLab CI/CD
date: 2019-02-27 15:17:46 +0700
author: fata
---
Di dalam repository utama kami, terdapat 3 service yaitu `blog`, `backend`, dan
`frontend`. `blog` dibuat menggunakan Jekyll, `backend` menggunakan Django
(yang sebelumnya berniat ditulis dengan Go), dan `frontend` menggunakan React.
<!--more-->
Kami menggunakan Docker sebagai sarana deployment untuk `backend` dan `frontend`.
Pipeline untuk CI/CD kedua service ini hampir sama. Keduanya terdiri dari 3
stages yaitu `build`, `test`, dan `deploy`.
Di dalam stage `build`, kami mem-build image dan men-tag menggunakan hash dari
commit sekarang, lalu mempush image tersebut ke registry.
```yml
backend:build:
stage: build
script:
- cd $BACKEND_ROOT_PATH
- docker build -t backend:$CI_COMMIT_SHORT_SHA .
- docker tag backend:$CI_COMMIT_SHORT_SHA $REGISTRY/pplc7/backend:$CI_COMMIT_SHORT_SHA
- docker push $REGISTRY/pplc7/backend:$CI_COMMIT_SHORT_SHA
tags:
- docker
only:
changes:
- backend/**/*
- .gitlab-ci.yml
```
Di dalam stage `test`, kami mempull image sebelumnya yang di push pada stage
`build` dan menjalankan command test di dalam image tersebut.
```yml
backend:test:
stage: test
script:
- docker run -i $REGISTRY/pplc7/backend:$CI_COMMIT_SHORT_SHA make test
coverage: '/coverage: (\d+.\d+\%) of statements/'
tags:
- docker
only:
changes:
- backend/**/*
- .gitlab-ci.yml
```
lalu jika test semua pass dan berhasil di merge ke branch `development`,
perubahan ini akan di deploy ke environment `development` dengan mempush image
sebelumnya dengan tag `development`.
```yml
backend:deploy:development:
stage: deploy
script:
- docker pull $REGISTRY/pplc7/backend:$CI_COMMIT_SHORT_SHA
- docker tag $REGISTRY/pplc7/backend:$CI_COMMIT_SHORT_SHA $REGISTRY/pplc7/backend:development
- docker push $REGISTRY/pplc7/backend:development
tags:
- docker
only:
refs:
- development
changes:
- backend/**/*
- .gitlab-ci.yml
```
Apabila perubahan berhasil masuk ke branch `staging`, tidak berbeda jauh dengan
deployment ke `development` sebelumnya.
```yml
backend:deploy:staging:
stage: deploy
script:
- docker pull $REGISTRY/pplc7/backend:development
- docker tag $REGISTRY/pplc7/backend:development $REGISTRY/pplc7/backend:staging
- docker push $REGISTRY/pplc7/backend:staging
tags:
- docker
only:
refs:
- staging
changes:
- backend/**/*
- .gitlab-ci.yml
```
![Paralel Pipeline](/assets/images/paralel-pipeline.png)
Karena kami menggunakan strategi __monorepo__, GitLab CI/CD di versi terbaru
menyediakan fitur yang cukup membantu dengan subtag `changes` dari tag `only`
yang akan hanya menjalankan suatu job apabila ada changes di suatu file.
Ada satu lagi yang seharusnya kami tambahkan pada pipeline yaitu untuk memanggil
API Portainer agar men-redeploy container untuk environment `staging`/`development`
jika ada versi lebih baru image dengan tag yang bersangkutan.
Mungkin pada post selanjutnya script tersebut bisa selesai dan bisa di share di
sini.
Semoga Bermanfaat
---
layout: post
title: git
date: 2019-02-28 10:13:46 +0700
author: usama
last_modified: 2019-03-20 18:11:12 +0700
---
Saat melakukan kegiatan PPL kami selalu berurusan dengan git, berikut ini adalah beberapa cerita saya saat berurusan dengan git
<!--more-->
Saat *commit-commit* awalnya saya lupa untuk mengubah *config* git saya. Saat PPW dulu `git config --global user.email "<personal-email>"`. Akhirnya *commit* saya pun menggunakan email tersebut, setelah menyadari hal tersebut saya mengganti config dengan `git config --local user.email "<email-ui>"`.
Kebiasaan saya saat melakukan push adalah `git push origin <branch-name>`. Hal ini menyebabkan saya terkadang malas untuk nge-*push* pekerjaan saya dikarenakan panjangnya *command* yang harus diketik :(. Untungnya Ragil melihat hal yang saya lakukan ini kemudian memberi tips agar menggunakan `git push -u origin <branch-name>` diawal melakukan *push* agar setelahnya hanya perlu melakukan `git push` di branch tersebut. Hal ini sangat membantu saya dalam melakukan pekerjaan selanjutnya. Terima kasih Ragil.
Saat melakukan pengerjaan saya juga pernah mengalami *conflict* yang selama ini kami coba untuk hindari. Untungnya saat terjadi *conflict* kami sedang ngoding bareng, sehingga saat itu juga kami diskusikan penyelesaian-nya.
Ohiya baru-baru ini juga saya melakukan install ulang, dan saat mengerjakan PPL saya lupa lagi melakukan **config**.
Jika ada kejadian-kejadian menarik tentang git, postingan ini akan diupdate.
\ No newline at end of file
---
layout: post
title: Unlocked New Way To Think
date: 2019-02-27 15:17:46 +0700
author: fata
---
Meskipun kami memutuskan untuk beralih menggunakan Django, kami mendapatkan
ilmu berharga yang semoga bisa membuat kami menjadi programmer lebih baik
yang kami dapatkan saat mencoba membuat API menggunakan Go.
<!--more-->
Ternyata testing di dalam Go tidak semudah yang saya bayangkan.
![](/assets/images/pikachu.jpeg)
Karena selama ini saya dimanjakan dengan mudahnya mock function di bahasa yang
bisa melakukan dynamic loading seperti `python` dan `Java`, ternyata melakukan
mocking dalam Go tidak semudah itu.
Dalam membuat kode, saya juga harus memikirkan bagaimana fungsi ini kelak akan
di testing.
Pertanyaan [ini](https://stackoverflow.com/questions/19167970/mock-functions-in-go)
yang saya temukan di stackoverflow cukup membuka wawasan jika kita mendesain
kode kita dengan benar dan semodular mungkin, maka proses mocking tidak akan
menjadi masalah.
Pada saat pertama kali saya membaca ini, saya memikirkan hal yang sama dengan
apa yang dinyatakan oleh orang ini
![](/assets/images/comment-1.png)
Tetapi saat saya membaca komentar ini, saya cukup setuju juga.
![](/assets/images/comment-2.png)
**fair enough**
Kode yang didesain dengan bagus, selain memudahkan untuk testing, memudahkan kita
meng-extend kode tersebut, seperti yang dikatakan orang random di internet,
_Dont Repeat Yourself_ (DRY).
Context:
Yang sebelumnya testing fungsi koneksi ke DB susah di test
```go
package main
import (
"database/sql"
"fmt"
"log"
"os"
_ "github.com/lib/pq"
)
var (
dbhost = os.Getenv("DB_HOST")
dbport = os.Getenv("DB_PORT")
dbuser = os.Getenv("DB_USER")
dbpassword = os.Getenv("DB_PASSWORD")
dbname = os.Getenv("DB_NAME")
)
func connectDB() (db *sql.DB) {
psqlInfo := fmt.Sprintf("host=%s port=%s user=%s "+
"password=%s dbname=%s sslmode=disable",
dbhost, dbport, dbuser, dbpassword, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
log.Fatal(err)
}
return
}
```
Menjadi lebih mudah di test (pada saat di test dan development, kami menggunakan
SQLite3 yang ternyata bisa membuat kami tidak perlu mengetes fungsi ini dengan
postgres yang asli :D)
```go
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
type database struct {
Driver string
ConnectionString string
Connection *sql.DB
}
func (db *database) Connect() (err error) {
conn, err := sql.Open(db.Driver, db.ConnectionString)
db.Connection = conn
return
}
func getDB(environment string) (db *database) {
if environment == "development" {
return &database{
Driver: "sqlite3",