Penyajian
Delivering High Quality Elixir
Code into Your Production
Line
Oleh
Tonny Adhi Sabastian
Jakarta, 2020
tonny.adhi@ui.ac.id / tonny.adhi@ruma.co.id | http://kambing.ui.ac.id
● 13 years of experiences at IT Industry and Academy
● Former chief of Network Administrator at Universitas
Indonesia and volunteer System Administrator for
kambing.ui.ac.id F/OSS repository
● Former (part time) lecturer and researcher at Faculty of
Computer Science Universitas Indonesia and also
Universitas Gunadarma
● Currently work at MAPAN ( Gojek Group ) as Tech. Architect
and Senior Engineer
● Topics of interest:
○ Linux Kernel, especially in Networking Stack, Kernel
Performance and Network Security
○ Distributed System in general - including Cloud
Computing
○ System Performance and Optimization
○ Pervasive Computing and Internet of Things
Tonny Adhi Sabastian
Sekilas
Agenda
MAPAN 101
Quick Bootstrapping on Elixir
Quality Assurance on Elixir Code
Elixir Pipeline on Gitlab
(1) MAPAN 101
source https://mapan.id
license limited use, only for MAPAN Publication
Gb. Tangkapan Layar
Kami percaya bahwa semua orang berhak untuk mengakses
layanan yang membantu mereka mencapai hidup mapan
- Bagian dari Ikrar Mapan
A Short History of MAPAN
● Founded in 2009 as PT Ruma by Aldi Haryopratomo
○ Selling Airtime
● Adding Bill Payment Product in 2012
● Branchless Banking Pilot with Bank of Indonesia in 2013
● Started serving physical goods to member in 2014
● Launching Arisan Mapan in 2015
● Member of Gojek Group since 2017
● Selling Digital Product from Gojek since 2019
● New Mapan App is launched on March 2020
○ Enabling various services on the platform
Arisan MAPAN
● We sell Household Goods
○ Cooking Pans
○ Furnitures
● Enabling community engagement in the spirit of
“Gotong Royong”
● Members will pay through “Arisan” Installments
○ More here:
https://www.mapan.id/apa-itu-arisan-mapan/arisan-
barang/
MAPAN Tech Stack
source various respective sources
license Apache License 2.0, Fair Use, and Public Domain
(2) Bootstrapping Elixir
source various respective sources
license CC-BY-SA, Fair Use
fn ( , ) ->
Elixir is Awesome
source self()
license CC-BY-SA
Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule Collection do
...(1)> def add_element_to_collection(collection, element) do
...(1)> collection ++ [element]
...(1)> end
...(1)> end
iex(2)> collection = [1,2,3,4]
[1, 2, 3, 4]
iex(3)> Collection.add_element_to_collection(collection, 5)
[1, 2, 3, 4, 5]
iex(4)> IO.inspect collection
[1, 2, 3, 4]
Immutable
# Elixir Shell
Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(7)> handle_result = fn
...(7)> {:ok, result} -> IO.puts "Handling result..."
...(7)> {:ok} -> IO.puts "Single Item"
...(7)> {:error} -> IO.puts "An error has occurred!"
...(7)> end
iex(8)> some_result = 2
2
iex(9)> handle_result.({:ok, some_result})
Handling result...
:ok
iex(10)> handle_result.({:ok})
Single Item
:ok
Pattern Matching
# Elixir Shell
Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(14)> 1..1_000_000 
...(14)> |> Enum.map(&(Task.async(fn -> &1 * &1 end)))
...(14)> |> Enum.map(&Task.await/1)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324,
361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089,
1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116,
2209, 2304, 2401, 2500, ...]
Processes (1)
# Elixir Shell
$ iex --sname bejo@localhost
Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10]
[async-threads:1] [hipe]
Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(bejo@localhost)1> defmodule Bejo do
...(bejo@localhost)1> def say_name do
...(bejo@localhost)1> IO.puts "Halo, Nama gue bejo."
...(bejo@localhost)1> end
...(bejo@localhost)1> end
$iex --sname surti@localhost
Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10]
[async-threads:1] [hipe]
Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(surti@localhost)1> Node.spawn_link(:bejo@localhost, fn -> Bejo.say_name end)
Halo, Nama gue bejo.
#PID<10888.124.0>
Processes (2)
# Elixir Shell
(3) Quality Assurance
on Elixir Code
source various respective sources
license CC-BY-SA
-> ->
Code Review by Peers ( senior
engineer, tech lead / head,
architect ).
1) Code Review
Run unit test on pipeline. Block
if it bellow coverage
2) Unit
Testing Run credo linter of pipeline.
Block if linter state that part
of code need more review
3) Code Lint
Typespec, Unreachable Code,
Pattern that never match. Block if
discrepancy found
4) Discrepancy
Check
Check if any dependencies
for a project contain CVE.
Block if a CVE found
5) CVE
Checking
Elixir Pipeline with Quality as
Concern
Same with previous step. The
different is only we do CVE
check on Docker Image that
use for a project deployment
6)Docker
Image CVE
Checking
Elixir Pipeline with Quality as
Concern
Functional Test done by QA
officer. It can be automated and
embedded within pipeline
7)Functional
Testing
Code Linting using
Credo (1)
https://github.com/rrrene/credo
Code Linting using
Credo (2)
https://github.com/rrrene/credo
# Bash Shell
# add credo in your project
$ vi mix.exs
…
defp deps do
[
{:credo, "~> 1.3", only: [:dev, :test], runtime: false}
]
end
…
Code Linting using
Credo (3)
https://github.com/rrrene/credo
Discrepancy Check
using Dialyxir (1)
https://github.com/jeremyjh/dialyxir
# Bash Shell
# add dialyxir in your project
$ vi mix.exs
…
def project do
[
dialyzer: [
plt_add_deps: :transitive,
plt_add_apps: [:mix, :ex_unit],
check_plt: true,
ignore_warnings: "dialyzer.ignore-warnings"
]
end
…
defp deps do
[
{:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}
]
end
…
Discrepancy Check
using Dialyxir (2)
https://github.com/jeremyjh/dialyxir
Unit Test Coverage
using Excoveralls (1)
https://github.com/parroty/excoveralls
# Bash Shell
# coveralls.json
$ cat coveralls.json
…
{
"coverage_options": {
"minimum_coverage": 90
},
"skip_files": [
"lib/phxchat_web.ex"
]
}
…
Unit Test Coverage
using Excoveralls (2)
https://github.com/parroty/excoveralls
# Bash Shell
# add excoverallw into your project
$ vi mix.exs
…
def project do
[
…
test_coverage: [tool: ExCoveralls],
preferred_cli_env: [
coveralls: :test,
"coveralls.detail": :test,
"coveralls.post": :test,
"coveralls.html": :test
],
…
]
end
…
defp deps do
[
{:excoveralls, "~> 0.12", only: [:dev, :test]}
]
end
…
Unit Test Coverage
using Excoveralls (3)
https://github.com/parroty/excoveralls
Showcase
( https://gitlab.mapan.io/tonny.adhi/phxchat/ )
Reference List for Elixir Study
Sites :
○ https://elixircasts.io/
○ https://elixirschool.com/en/
○ https://alchemist.camp/
○ https://elixirweekly.net/
○ https://elixirstatus.com/
○ https://www.nerves-project.org/
Books :
○ Learn Functional Programming with Elixir, by Ulises
Amelia
○ Functional Web Development with Elixir, OTP, and
Phoenix, by Lance Halvorsen
○ Elixir in Action Second Edition, by Sasa Juric
Q & A
Terima Kasih!

Delivering High Quality Elixir Code using Gitlab

  • 1.
    Penyajian Delivering High QualityElixir Code into Your Production Line Oleh Tonny Adhi Sabastian Jakarta, 2020 tonny.adhi@ui.ac.id / tonny.adhi@ruma.co.id | http://kambing.ui.ac.id
  • 2.
    ● 13 yearsof experiences at IT Industry and Academy ● Former chief of Network Administrator at Universitas Indonesia and volunteer System Administrator for kambing.ui.ac.id F/OSS repository ● Former (part time) lecturer and researcher at Faculty of Computer Science Universitas Indonesia and also Universitas Gunadarma ● Currently work at MAPAN ( Gojek Group ) as Tech. Architect and Senior Engineer ● Topics of interest: ○ Linux Kernel, especially in Networking Stack, Kernel Performance and Network Security ○ Distributed System in general - including Cloud Computing ○ System Performance and Optimization ○ Pervasive Computing and Internet of Things Tonny Adhi Sabastian Sekilas
  • 3.
    Agenda MAPAN 101 Quick Bootstrappingon Elixir Quality Assurance on Elixir Code Elixir Pipeline on Gitlab
  • 4.
    (1) MAPAN 101 sourcehttps://mapan.id license limited use, only for MAPAN Publication Gb. Tangkapan Layar
  • 5.
    Kami percaya bahwasemua orang berhak untuk mengakses layanan yang membantu mereka mencapai hidup mapan - Bagian dari Ikrar Mapan
  • 6.
    A Short Historyof MAPAN ● Founded in 2009 as PT Ruma by Aldi Haryopratomo ○ Selling Airtime ● Adding Bill Payment Product in 2012 ● Branchless Banking Pilot with Bank of Indonesia in 2013 ● Started serving physical goods to member in 2014 ● Launching Arisan Mapan in 2015 ● Member of Gojek Group since 2017 ● Selling Digital Product from Gojek since 2019 ● New Mapan App is launched on March 2020 ○ Enabling various services on the platform
  • 7.
    Arisan MAPAN ● Wesell Household Goods ○ Cooking Pans ○ Furnitures ● Enabling community engagement in the spirit of “Gotong Royong” ● Members will pay through “Arisan” Installments ○ More here: https://www.mapan.id/apa-itu-arisan-mapan/arisan- barang/
  • 8.
    MAPAN Tech Stack sourcevarious respective sources license Apache License 2.0, Fair Use, and Public Domain
  • 9.
    (2) Bootstrapping Elixir sourcevarious respective sources license CC-BY-SA, Fair Use fn ( , ) ->
  • 10.
    Elixir is Awesome sourceself() license CC-BY-SA
  • 11.
    Interactive Elixir (1.10.2)- press Ctrl+C to exit (type h() ENTER for help) iex(1)> defmodule Collection do ...(1)> def add_element_to_collection(collection, element) do ...(1)> collection ++ [element] ...(1)> end ...(1)> end iex(2)> collection = [1,2,3,4] [1, 2, 3, 4] iex(3)> Collection.add_element_to_collection(collection, 5) [1, 2, 3, 4, 5] iex(4)> IO.inspect collection [1, 2, 3, 4] Immutable # Elixir Shell
  • 12.
    Interactive Elixir (1.10.2)- press Ctrl+C to exit (type h() ENTER for help) iex(7)> handle_result = fn ...(7)> {:ok, result} -> IO.puts "Handling result..." ...(7)> {:ok} -> IO.puts "Single Item" ...(7)> {:error} -> IO.puts "An error has occurred!" ...(7)> end iex(8)> some_result = 2 2 iex(9)> handle_result.({:ok, some_result}) Handling result... :ok iex(10)> handle_result.({:ok}) Single Item :ok Pattern Matching # Elixir Shell
  • 13.
    Interactive Elixir (1.10.2)- press Ctrl+C to exit (type h() ENTER for help) iex(14)> 1..1_000_000 ...(14)> |> Enum.map(&(Task.async(fn -> &1 * &1 end))) ...(14)> |> Enum.map(&Task.await/1) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, ...] Processes (1) # Elixir Shell
  • 14.
    $ iex --snamebejo@localhost Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help) iex(bejo@localhost)1> defmodule Bejo do ...(bejo@localhost)1> def say_name do ...(bejo@localhost)1> IO.puts "Halo, Nama gue bejo." ...(bejo@localhost)1> end ...(bejo@localhost)1> end $iex --sname surti@localhost Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help) iex(surti@localhost)1> Node.spawn_link(:bejo@localhost, fn -> Bejo.say_name end) Halo, Nama gue bejo. #PID<10888.124.0> Processes (2) # Elixir Shell
  • 15.
    (3) Quality Assurance onElixir Code source various respective sources license CC-BY-SA -> ->
  • 16.
    Code Review byPeers ( senior engineer, tech lead / head, architect ). 1) Code Review Run unit test on pipeline. Block if it bellow coverage 2) Unit Testing Run credo linter of pipeline. Block if linter state that part of code need more review 3) Code Lint Typespec, Unreachable Code, Pattern that never match. Block if discrepancy found 4) Discrepancy Check Check if any dependencies for a project contain CVE. Block if a CVE found 5) CVE Checking Elixir Pipeline with Quality as Concern
  • 17.
    Same with previousstep. The different is only we do CVE check on Docker Image that use for a project deployment 6)Docker Image CVE Checking Elixir Pipeline with Quality as Concern Functional Test done by QA officer. It can be automated and embedded within pipeline 7)Functional Testing
  • 18.
    Code Linting using Credo(1) https://github.com/rrrene/credo
  • 19.
    Code Linting using Credo(2) https://github.com/rrrene/credo # Bash Shell # add credo in your project $ vi mix.exs … defp deps do [ {:credo, "~> 1.3", only: [:dev, :test], runtime: false} ] end …
  • 20.
    Code Linting using Credo(3) https://github.com/rrrene/credo
  • 21.
    Discrepancy Check using Dialyxir(1) https://github.com/jeremyjh/dialyxir
  • 22.
    # Bash Shell #add dialyxir in your project $ vi mix.exs … def project do [ dialyzer: [ plt_add_deps: :transitive, plt_add_apps: [:mix, :ex_unit], check_plt: true, ignore_warnings: "dialyzer.ignore-warnings" ] end … defp deps do [ {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false} ] end … Discrepancy Check using Dialyxir (2) https://github.com/jeremyjh/dialyxir
  • 23.
    Unit Test Coverage usingExcoveralls (1) https://github.com/parroty/excoveralls
  • 24.
    # Bash Shell #coveralls.json $ cat coveralls.json … { "coverage_options": { "minimum_coverage": 90 }, "skip_files": [ "lib/phxchat_web.ex" ] } … Unit Test Coverage using Excoveralls (2) https://github.com/parroty/excoveralls
  • 25.
    # Bash Shell #add excoverallw into your project $ vi mix.exs … def project do [ … test_coverage: [tool: ExCoveralls], preferred_cli_env: [ coveralls: :test, "coveralls.detail": :test, "coveralls.post": :test, "coveralls.html": :test ], … ] end … defp deps do [ {:excoveralls, "~> 0.12", only: [:dev, :test]} ] end … Unit Test Coverage using Excoveralls (3) https://github.com/parroty/excoveralls
  • 26.
  • 27.
    Reference List forElixir Study Sites : ○ https://elixircasts.io/ ○ https://elixirschool.com/en/ ○ https://alchemist.camp/ ○ https://elixirweekly.net/ ○ https://elixirstatus.com/ ○ https://www.nerves-project.org/ Books : ○ Learn Functional Programming with Elixir, by Ulises Amelia ○ Functional Web Development with Elixir, OTP, and Phoenix, by Lance Halvorsen ○ Elixir in Action Second Edition, by Sasa Juric
  • 28.
  • 29.