Setel Otomatisasi Deploy - MappingSystem/Tutorial-Buka-Toko GitHub Wiki

Table of Contents

Arsitektur

Secara garis besar otomatisasi dilakukan untuk merespon setiap perubahan baik di sumber code (upstream) maupun custom design/chart di cabang yang kita buat dari master fork repository.

Seperti yang digambarkan di atas maka secara garis besar otomatisasi deploy akan meliputi 4 (empat) bagian yang terintegrasi dimana trigger untuk masuk ke proses berikutnya diatur sedemikian rupa secara berjenjang.

Masterisasi

Adalah mekanisme yang dilakukan untuk memperoleh update secara berkesinambungan antara master project dengan upstream dari repository.

Pip-Environment

Adalah mekanisme yang dilakukan untuk update cabang dari master yang akan dipakai untuk membuat image docker. Docker Hub akan otomatis di trigger begitu cabang di update.

Docker-Compose

Setelah image docker selesai dibuat maka penempatannya dilanjutkan dengan membuat docker-compose. Yaitu integrasi Saleor dengan Postgres, Redis, dan Celery.

Backend-Compose

Step ini adalah step yang memindahkan compose di container docker ke sistem secara permanen (mode produksi).

Konfigurasi

Internal

Proses internal dilakukan bedasarkan konsep Continuous Delivery

Gcloud

Gcloud dapat digunakan untuk koneksi via SSH Key, namun untuk gcloud dalam script nya kita harus pakai yang ada dalam instance. Walaupun gcloud sudah tersedia namun tidak dapat digunakan.

$ gcloud.components.update
ERROR: (gcloud.components.update) 
You cannot perform this action because the Cloud SDK component manager 
is disabled for this installation. You can run the following command 
to achieve the same result for this installation: 

$ sudo apt-get update && sudo apt-get --only-upgrade install \
kubectl google-cloud-sdk google-cloud-sdk-app-engine-grpc \
google-cloud-sdk-pubsub-emulator google-cloud-sdk-app-engine-go \
google-cloud-sdk-cloud-build-local google-cloud-sdk-datastore-emulator \
google-cloud-sdk-app-engine-python google-cloud-sdk-cbt \
google-cloud-sdk-bigtable-emulator google-cloud-sdk-app-engine-python-extras \
google-cloud-sdk-datalab google-cloud-sdk-app-engine-java

Karena itu kita harus melakukan instalasi terpisah agar dapat dijalankan didalam script oleh Cloud Builder. Lihat caranya di Separasi

Cloud Build

steps:

- name: 'gcr.io/cloud-builders/git'
  args: ['clone', '${_REPOSITORY}']

- name: 'python'
  args: ['bash', './scripts/github/init.sh']

- name: 'gcr.io/cloud-builders/gcloud' 
  args: ['compute', 'scp', '--zone', '${_ZONE}', 
         '--recurse', '--force-key-file-overwrite', 
         '${_LOCAL_PATH}', '${_INSTANCE_NAME}:${_INSTANCE_PATH}']

- name: 'gcr.io/cloud-builders/gcloud'
  args: ['compute', 'ssh', '--zone', '${_ZONE}', '${_INSTANCE_NAME}', 
         '--command', 'cd ${_INSTANCE_PATH}/.docker && ./init.sh']

substitutions:
  _ZONE: us-central1-c
  _LOCAL_PATH: /workspace/.docker
  _INSTANCE_PATH: /home/chetabahana
  _INSTANCE_NAME: chetabahana@backend
  _REPOSITORY: https://github.com/mirumee/saleor.git

timeout: "1800s"

Setup Aplikasi

#Environtment
export APP="gunicorn gevent"
export PATH=$HOME/.local/bin:$PATH
export BRANCH=/workspace/.docker/branch
export DEBIAN_FRONTEND=noninteractive 
export LC_ALL=C.UTF-8 && export LANG=C.UTF-8

#Get Utilities
cd /workspace/saleor
pip3 install --user pipenv > /dev/null && pipenv sync > /dev/null
pipenv install $APP > /dev/null && cat Pipfile

#Run test
#pipenv install --dev > /dev/null
#pipenv run pytest > /dev/null
#pipenv run tox > /dev/null
pipenv check

#Lock
pipenv lock -r -d > requirements_dev.txt && cat requirements_dev.txt
pipenv lock -r > requirements.txt && cat requirements.txt
mv -fv Pipfile Pipfile.lock requirements.txt requirements_dev.txt -t $BRANCH

Eksternal

Proses eksternal dapat dirangkum sbb:

Berikutnya kita uraikan step di atas secara detail.

Step-1: Crontab

Proses update di atur setiap terjadi perubahan kode di upstream ke master dan cabang sbb:

  1. Master
  2. Cabang
  3. Remote
  4. Current
  5. Next
Crontab disetel perjam:
$ crontab -e
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command

0 * * * * sh ~/.docker/cron.sh

Step-2: Upstream

Proses update dari masing² repository diatur via Pipfile.lock sbb:

#!/bin/sh
if grep -Fqe "Image is up to date" << EOF
`docker pull chetabahana/saleor`
EOF
then
    cd ~/.docker/compose && rm -rf Tutorial-Buka-Toko
    eval `ssh-agent` && expect ~/.ssh/agent && ssh-add -l
    git clone [email protected]:MarketLeader/Tutorial-Buka-Toko.git
    cd Tutorial-Buka-Toko && git checkout master
    git remote add upstream git://github.com/mirumee/saleor.git
    git fetch --prune upstream > /dev/null
    if [ `git rev-list HEAD...upstream/master --count` -eq 0 ]
    then
        echo "all the same, do nothing"
    else
        echo "update exist, do delivery!"
        git reset --hard upstream/master && git push origin master --force
    fi
    cd .. && rm -rf Tutorial-Buka-Toko
    eval `ssh-agent -k`
else
    echo "latest exist, do compose!"
fi

Step-3: Docker Hub

#Environtment
CURRENT=gunicorn
NEXT=taxonomy

echo "\nREMOTE\n"
git checkout Chetabahana
git fetch --prune origin && git reset --hard origin/master
cp -frpvT ~/.docker/branch ~/.docker/backend/Tutorial-Buka-Toko
cp -frpT ~/.docker/branch ~/.docker/backend/.docker/branch
git status && git add . && git commit -m "Add support for ${CURRENT}"
git push origin Chetabahana --force
cd .. && rm -rf Tutorial-Buka-Toko

echo "\nMASTER\n"
[ -d saleor ] && rm -rf saleor || echo "cloning.."
git clone [email protected]:chetabahana/saleor.git saleor && cd saleor
git remote add upstream git://github.com/MarketLeader/Tutorial-Buka-Toko.git
git fetch --prune upstream Chetabahana && git reset --hard upstream/Chetabahana
git push origin master --force

echo "\nCURRENT\n"
git checkout "${CURRENT}"
git fetch --prune origin master && git reset --hard origin/master
git push origin "${CURRENT}" --force

echo "\nNEXT\n"
git checkout "${NEXT}"
git fetch --prune origin master && git reset --hard origin/master
tx pull --all > /dev/null
git push origin "${NEXT}" --force
cd .. && rm -rf saleor

Step-4: CodeFresh

Pada step ini kita setel Codefresh untuk mulai alur pipeline berdasarkan webhook.

Webhooks adalah permintaan POST yang dikirim ke URL yang Anda tentukan. Anda dapat gunakan webhooks untuk mentrigger tindakan di layanan lain sebagai respons terhadap suatu peristiwa.

GitHub dan Docker Hub memberikan fasilitas Webhooks ketika sebuah gambar didorong ke repo, Anda dapat mengirim secara otomatis ke alur kerja Anda pada layanan lain spt Codefresh berdasarkan webhook tersebut.

Pada projeck ini alur Webhooks dipilih berdasarkan pertimbangan sesuai tabel berikut.

Fitur Google GitHub Docker Codefresh CircleCI Spinnaker Jenkins
Build Image Yes Yes Yes Yes Yes Yes Yes
Build API Yes Yes - - Yes - -
Compose Yes Yes Yes Yes Yes Yes Yes
Deploy Yes Yes Yes Yes Yes Yes Yes
CI/CD Yes Yes Yes Yes Yes Yes Yes
Logs Yes Yes Yes Yes Yes Yes Yes
Registry Yes Yes Yes - Yes - -
Pull External Yes Yes Yes Yes Yes Yes Yes
Push External Yes Yes - - - Yes - -
Notify Yes Yes Yes Yes Yes Yes Yes
Trigger Yes Yes Yes Yes Yes Yes Yes
Webhooks Yes Yes Yes Yes Yes Yes Yes
HELM Chart Yes - - - Yes - -
Repository Yes Yes - - - - -
Biaya Yes - - - - $121/bln -
Free Tier Yes Yes Yes Yes Yes - -

Dengan analisa seperti tabulasi di atas dan juga dengan mempertimbangkan analisa perbandingan seperti di arikel ini maka Codefresh bisa dipakai sebagai acuan untuk otomatisasi via webhooks.

Step-5: Compose

Lihat:

docker-compose config --version
docker-compose run web python --version
docker-compose run --rm web python -m pip install -r requirements_dev.txt

docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py collectstatic --noinput
docker-compose run --rm web python manage.py populatedb --createsuperuser
docker-compose run --rm web python manage.py create_thumbnails

docker-compose run --rm web tx pull --all
docker-compose run --rm web python manage.py compilemessages
docker-compose run --rm web python manage.py makemessages -l en --extension=email,html,mjml,py,txt --ignore="templates/templated_email/compiled/*"
docker-compose run --rm web python manage.py makemessages -l en -d djangojs --ignore="_build/*" --ignore="node_modules/*" --ignore="saleor/static/assets/*"

docker-compose run web py.test
docker-compose run web tox
docker-compose up -d

Step-6: Backend

Dengan menyetel variable lingkungan di file app.yaml maka file yang ditampung dapat di deploy di App Engine. Oleh karena itu repository ini sebaiknya dibuat private sehingga dapat menyimpan file atau kunci rahasia seperti SECRET_KEY untuk jalankan Django dalam aplikasi Saleor.

Step-7: Internal

Setelah semua perangkat yang diperlukan tersedia didalam sistem maka CloudBuilder dapat ditrigger untuk melakukan proses update secara internal.

Referensi

  • https://github.com/MarketLeader/docker
  • https://docs.gitlab.com/ee/workflow/repository_mirroring.html
  • https://stackoverflow.com/a/48030992/4058484
  • https://cloud.google.com/sdk/gcloud/reference/compute/ssh
  • https://cloud.google.com/cloud-build/docs/access-private-github-repos
  • https://cloud.google.com/cloud-build/docs/securing-builds/set-service-account-permissions
  • http://howtoinstallthisapp.blogspot.com/2018/01/django-not-able-to-run-collectstatic-on.html
  • https://github.com/suecharo/SAPPORO#what-does-useful-for-continuous-testing-of-workflows-mean
⚠️ **GitHub.com Fallback** ⚠️