Skip to content

KKGo-Software-engineering/workshop-summer

Repository files navigation

Go summer workshop

Pre-requisites

Tools

Workshop URL

HongJot Diagram

sequenceDiagram
	Mobile App ->> HongJot API: Upload Image to S3 Bucket
	activate Mobile App
	HongJot API ->> S3 Bucket: Store Image
	HongJot API ->> Mobile App: success
	deactivate Mobile App
	S3 Bucket ->> Lambda Function: (Event Trigger)
	Lambda Function ->> Amazon Textract: Extract Text from Image
	Amazon Textract ->> Lambda Function: Slip Expense info
	Lambda Function ->> HongJot API: Send Slip Expense info
	HongJot API ->> PostgreSQL Database: Store Expense info
	Mobile App ->> HongJot API: Get Expense Summary (Spender Requests Summary) Retrieve Expense Summary
	activate Mobile App
	HongJot API ->> PostgreSQL Database: Get Expense Summary Data
	PostgreSQL Database ->> HongJot API: Return Summary Data
	HongJot API ->> Mobile App: Show Expense Summary Data
	deactivate Mobile App

Infrastructure

We have created the infrastructure by using Terraform. The infrastructure consists of the following:

  • Kubernetes Cluster (EKS) - Managed Kubernetes Service
  • PostgreSQL (RDS) - Relational Database (Managed Service)
  • SonarQube - Static Code Analysis
  • Github (see .github/workflows directory)
    • Github Action
    • Github Container Registry
  • ArgoCD - Continuous Delivery
  • Cloudflare - DNS Management

Getting Started

Step 0: IaC (Infrastructure as Code) ✅

  • Create IAM account for Terraform
  • Authenticate with AWS
    • Option 1: aws configure - Configure your AWS credentials with keypair
    • Option 2: Set environment variable
      • export AWS_ACCESS_KEY_ID=<KEY>
      • export AWS_SECRET_ACCESS_KEY=<SECRET>
  • Provision the infrastructure (ESK, RDS (Postgres), SonarQube, ArgoCD, Cloudflare, VPC)
    • cd infra/iac
    • terraform init
    • terraform apply
    • Terraform will require
      • cloudflare API key, you can get it from the Cloudflare dashboard
        • Option 1: Enter API token on Terraform prompt
        • Option 2: Export environment variable that provide for Terraform
      • RDS username, password, and database name
        • Option 1: Enter the value on Terraform prompt
        • Option 2: Export environment variable that provide for Terraform
    • And then Terraform will do things for you
    • Waiting and enjoy your coffee
  • Importantly, you need to destroy resources because it's not free 💰
    • terraform destroy
  • Note: You can see the README.md in the infra directory for more information

Step 1: Fork the repository and setup Github Actions ✅

  • Fork workshop-summer repository and name it as workshop-summer-<GROUP_NO>-<BATCH_NO> (e.g. workshop-summer-group-1-b2)
  • Enable Github Actions in the repository
  • Replace the <GROUP_NO> pattern via auto-replace-group.sh
  • Setup project on SonarQube manually
    • Create project on SonarQube with the same name as the repository
    • Generate SonarQube token and create secret on Github named as SONAR_TOKEN
    • Add SONAR_HOST_URL secret on Github with the value of https://sonarqube.werockstar.dev
  • Commit and push the changes to the repository
  • View the Github Actions and see the workflow running
  • Observe analysis result on SonarQube dashboard

Step 2: Create ArgoCD application

  • Go to ArgoCD dashboard https://argocd.werockstar.dev/
  • Setup GitOps สำหรับ Development
    • กด + New App แล้วใส่ข้อมูลดังนี้
    • Application Name: <GROUP_NO>-<BATCH_NO>-dev (e.g. group-1-b2-dev)
    • Project Name: default
    • SYNC POLICY: Automatic
    • Repository URL: https://github.com/<your-github>/workshop-summer-<GROUP_NO>-<BATCH_NO>
    • Revision: main
    • Path: infra/gitops/dev
    • Cluster URL: https://kubernetes.default.svc
    • กด Create มุมบนซ้าย
    • ภาวะณา
  • Setup GitOps สำหรับ Production env
    • กด + New App แล้วใส่ข้อมูลดังนี้
    • Application Name: <GROUP_NO>-<BATCH_NO>-prod (e.g. group-1-b2-prod)
    • Project Name: default
    • SYNC POLICY: Automatic
    • Repository URL: https://github.com/<your-github>/workshop-summer-<GROUP_NO>-<BATCH_NO>
    • Revision: main
    • Path: infra/gitops/prod
    • Cluster URL: https://kubernetes.default.svc
    • กด Create มุมบนซ้าย

🏁 Development เริ่มยังไง?

ใน Repository นี้เราใช้ Makefile ในการทำงานได้ ดังนั้นสามารถสั่งรันง่ายๆ ผ่าน make ได้เลย

1.เริ่มต้นลองสั่งติดตั้ง dependencies ของ Go มาก่อน

go mod tidy

2.จากนั้น set environment variable โดยสร้าง file ใหม่ชื่อ .env แล้ว copy content จาก .env.template มา แล้วเปลี่ยน db:5432 เป็น localhost:5432

ENV=LOCAL
LOCAL_DATABASE_POSTGRES_URI=postgres://postgres:password@localhost:5432/hongjot?sslmode=disable
LOCAL_SERVER_PORT=8080

# Features Flags
LOCAL_ENABLE_CREATE_SPENDER=false

3.Export environment variable ด้วยเครื่องมืออย่าง direnv หรือจะใช้คำสั่งนี้ก็ได้

# Using source (.)
source .env

# or using export
export $(cat .env)

4.สร้าง PostgreSQL บน local machine ผ่าน docker-compose ด้วยคำสั่ง

docker-compose up -d

5.จากนั้นสั่งรันได้เลย

make run

หรือถ้าใครใช้ Makefile ไม่ได้ก็ใช้คำสั่งตรงก็ได้ โดยเข้าไปดูแต่ละคำสั่งใน makefile ได้เลย

go run main.go

เมื่อ Server ทำงานได้ควรจะสามารถเรียกจาก http://localhost:8080/api/v1/health ได้

make health

Checking the health of the server...
curl http://localhost:8080/api/v1/health
{"message":"api is ready and connected to database","status":"ok"}

👻 รัน Test ยังไง?

โปรเจกนี้มี 2 ระดับคือ unit, integration รันได้ดังนี้

🪛 Unit

make test

⚙️ Integration

Run ผ่าน Docker

make test-it-docker

Run ตรง

make test-it

หมายเหตุ: ตอนเขียน integration test ต้องตั้งชื่อเป็น format Test...IT ไม่งั้นตอน run มันจะข้ามไป

⚓ ใช้งาน pre-commit

pre-commit คือ framework ที่ใช้ run script (hooks) ก่อน commit หรือ push ผ่าน Git โดยให้ทำการติดตั้งตามคู่มือ จากนั้น run คำสั่ง

make setup-pre-commit

ทีนี้เวลาเรา commit หรือ push มันก็จะไป run คำสั่งต่าง ๆ ที่จะดักปัญหาก่อนไม่ให้ CI/CD pipeline ของเราพังนั่นเอง

🗃️ ใช้งาน database migration

Project นี้เราใช้ goose เป็น database migration tool โดย database script จะเก็บไว้อยู่ที่ directory migration

ตอนที่เราสร้าง script ใหม่ก็สามารถ run คำสั่ง

make new-migration name=0X_name_with_underscore

หรือจะสร้างโดย copy file จาก template ชื่อ 00_example.sql.template แล้วสร้าง file ใหม่โดยต้องตั้งชื่อเป็น 0X_<script_name_with_underscore>.sql ก็ได้

Migration file ใหม่ที่ได้จะอยู่ที่ directory migration ที่มีใส่ content ดังนี้

-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query';
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query';
-- +goose StatementEnd

จากนั้นก็ทำการเขียน SQL statement ที่ต้องการ

เวลาเรา run server ขึ้นมามันจะทำการ apply migration ให้อัตโนมัติ แต่ในส่วนของ integration test ต้องเขียน apply และ rollback ด้วย ประมาณนี้

import (
	"database/sql"
	"testing"

	"github.com/KKGo-Software-engineering/workshop-summer/config"
	"github.com/KKGo-Software-engineering/workshop-summer/migration"
	_ "github.com/lib/pq"
)

func TestSomethingIT(t *testing.T) {
	t.Run("create spender succesfully when feature toggle is enable", func(t *testing.T) {
		sql, err := getTestDatabaseFromConfig()
		if err != nil {
			t.Error(err)
		}
		migration.ApplyMigrations(sql)
		defer migration.RollbackMigrations(sql)

		// เขียน test ต่อได้เลย
	})
}

func getTestDatabaseFromConfig() (*sql.DB, error) {
	cfg := config.Parse("DOCKER")
	sql, err := sql.Open("postgres", cfg.PostgresURI())
	if err != nil {
		return nil, err
	}
	return sql, nil
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published