From 11ce970ce12b9caa0cfc2b531f336fac18e08e22 Mon Sep 17 00:00:00 2001 From: ulflow_phattt2901 Date: Wed, 14 May 2025 09:42:59 +0700 Subject: [PATCH] chore: Initial --- Diagram/Diagram Image.md | 184 +++++++ Diagram/Diagrams CICD.md | 517 ++++++++++++++++++++ Docs/Bộ Rule CICD.md | 16 + Docs/FAQ.md | 4 + Docs/Thư viện cho Golang.md | 7 + Docs/Thư viện cho Nodejs.md | 1 + Docs/Tài liệu nâng cao.md | 17 + Docs/Tài liệu theo Role.md | 17 + Docs/Tài liệu theo Workflow.md | 1 + Guidlines/Quy trình cơ bản cho Dev.md | 92 ++++ Guidlines/Quy trình cơ bản cho Leader.md | 88 ++++ Knowledge Base/Branch Strategy.md | 13 + Knowledge Base/Cheatsheet.md | 38 ++ Knowledge Base/Check List Done (DEV).md | 26 + Knowledge Base/Code Convention.md | 134 +++++ Knowledge Base/Domain Driven Development.md | 40 ++ Knowledge Base/Glossary & Meaning.md | 4 + Knowledge Base/Unit Test Rules.md | 23 + Samples/Cấu hình Air Tom.md | 0 Templates/Air Tomb - Golang.md | 103 ++++ Templates/Docker Template.md | 99 ++++ Templates/Env.md | 31 ++ Templates/Git Template.md | 94 ++++ Templates/Makefile.md | 65 +++ Templates/Pipeline Template(Dev).md | 70 +++ Templates/Pipeline Template(Main).md | 393 +++++++++++++++ Templates/Workflow.md | 159 ++++++ Tổng quan.md | 58 +++ 28 files changed, 2294 insertions(+) create mode 100644 Diagram/Diagram Image.md create mode 100644 Diagram/Diagrams CICD.md create mode 100644 Docs/Bộ Rule CICD.md create mode 100644 Docs/FAQ.md create mode 100644 Docs/Thư viện cho Golang.md create mode 100644 Docs/Thư viện cho Nodejs.md create mode 100644 Docs/Tài liệu nâng cao.md create mode 100644 Docs/Tài liệu theo Role.md create mode 100644 Docs/Tài liệu theo Workflow.md create mode 100644 Guidlines/Quy trình cơ bản cho Dev.md create mode 100644 Guidlines/Quy trình cơ bản cho Leader.md create mode 100644 Knowledge Base/Branch Strategy.md create mode 100644 Knowledge Base/Cheatsheet.md create mode 100644 Knowledge Base/Check List Done (DEV).md create mode 100644 Knowledge Base/Code Convention.md create mode 100644 Knowledge Base/Domain Driven Development.md create mode 100644 Knowledge Base/Glossary & Meaning.md create mode 100644 Knowledge Base/Unit Test Rules.md create mode 100644 Samples/Cấu hình Air Tom.md create mode 100644 Templates/Air Tomb - Golang.md create mode 100644 Templates/Docker Template.md create mode 100644 Templates/Env.md create mode 100644 Templates/Git Template.md create mode 100644 Templates/Makefile.md create mode 100644 Templates/Pipeline Template(Dev).md create mode 100644 Templates/Pipeline Template(Main).md create mode 100644 Templates/Workflow.md create mode 100644 Tổng quan.md diff --git a/Diagram/Diagram Image.md b/Diagram/Diagram Image.md new file mode 100644 index 0000000..21ad0ef --- /dev/null +++ b/Diagram/Diagram Image.md @@ -0,0 +1,184 @@ +--- + +excalidraw-plugin: parsed +tags: [excalidraw] + +--- +==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: 'Decompress current Excalidraw file'. For more info check in plugin settings under 'Saving' + + +# Excalidraw Data + +## Text Elements +app ^bRI0Cx2O + +go app ^Txdl3wmz + +Postreql ^bXgL6BoQ + +db_dev ^e4jYepQE + +8080 ^JEEt9AtB + +5433 ^MIZrF7rN + +adminer ^qcAKkTjk + +adminer ^RFMkUi6c + +8081 ^wr4RORZd + +condition: service_healthy ^ckNWsRVo + +healthcheck ^4f628p0Q + +Postreql ^bAwykO3I + +db ^V1uC7eTF + +5432 ^g76zgWYB + +pgdata_dev ^zY2qJySJ + +db_data ^kfKzKMh0 + +Staging ^6znrPaDk + +%% +## Drawing +```compressed-json +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 +``` +%% \ No newline at end of file diff --git a/Diagram/Diagrams CICD.md b/Diagram/Diagrams CICD.md new file mode 100644 index 0000000..0796685 --- /dev/null +++ b/Diagram/Diagrams CICD.md @@ -0,0 +1,517 @@ +--- + +excalidraw-plugin: parsed +tags: [excalidraw] + +--- +==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠== You can decompress Drawing data with the command palette: 'Decompress current Excalidraw file'. For more info check in plugin settings under 'Saving' + + +# Excalidraw Data + +## Text Elements +Phase ^o9262IQU + +Role ^iEREG52m + +Task ^OOykyAOr + +Secret Management +(Drone Secrets) ^MpRlnZse + +Build Backlog ^LqZ5xfXH + +Setup Docker ^1eo7f7PB + +Setup CI/CD ^rIDmcxbG + +Test & Release - CD phase ^1otAOWKF + +Tool ^pRRejkFL + +FLOW ^rXlDuuiH + +Arch Eng ^xoLC7ka1 + +.env.example ^P8KLk0CU + +Setup pipeline (.yaml) +Lint ->SecScan->Test ->Build ^DrIaH0Kb + +Init Repo ^XqIzxR1O + +SEC ^dg27ao6a + +DevOps ^rvZ20cAa + +Create Repo ^mhGNCgND + +Folder Structure ^NLSKeK0x + +Security +SCA/SAST ^F2CzjdDy + +Arch Eng ^syJ8EXCy + +Support ^eBIOV9wE + +Support ^MBLn0kSH + +Setup Docker Composer +(for local) ^GlMfUYcL + +Setup DockerFile Builder ^S0f4Jc5F + +Build Template ^Ek5lYfOq + +.gitignore ^p9GjLysf + +Arch Eng ^VOdMdL3r + +Leader ^S549IYU5 + +CI Server + Runner ^cqXPMjfy + +Merge Code ^wQR5cJoG + +Create FeatureList ^JIQZGL6d + +Branch Stratery ^xrln2pRU + +Create Document ^lfgbimdI + +Foundation ^yNRYjKu0 + +Plan & Design ^fAqf4FEz + +Create Feature Branch ^KlSK3IHe + +Create UnitTest ^gVr7eNa1 + +Arch Eng ^SldOQWU2 + +Code Features ^OaHb97pk + +Pull Request ^Tk7j7rv2 + +Develop & Integrate ^ai0FdAkS + +Code Review ^gb9Dohrn + +Code Review ^xaQE4G1h + +Build with Pipeline ^NEF3fPEf + +Tester ^oSStmmXe + +CI On Server ^osdUnrG4 + +Dev Team ^ZptyTXm7 + +Make Release Version ^ub21PHbx + +Production ^oR927Bhl + +CI Server + Runner ^9OKCCr90 + +Staging ^V05ubVjs + +Deploy ^TCGnvf6w + +Notify ^wsvkcNpK + +Build Image ^ES0qwtVg + +Dev Team ^XzacjP5w + +Thiết lập môi trường kỹ thuật và quy trình ban đầu. ^IW7wDWeE + +Xác định sản phẩm, lên kế hoạch ^SWrvIGD9 + +Code Feature ^7tT6uXV5 + +Developer hiện thực hóa các tính năng ^rDBxdSYV + +Commit Code ^4huvpOzb + +Leader ^tpYV3lk4 + +Automated CI Pipeline ^3Ya0faAt + +Approval ^SC30Hp63 + +Kiểm thử & Phát hành ^Hr0u0SeB + +Deploy Staging ^jNqrS400 + +Unit Test ^sAy0Gwgm + +Training Dev Team ^ZPXmLDwn + +PR Code ^c0OjOrnA + +Push Code FirstTime ^GDzSkATd + +Smoke Test +E2E Test ^fHARAzDt + +Đánh tag Version ^pmE2YXy8 + +register Image ^1PZiWEdK + +%% +## Drawing +```compressed-json +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 + +FgIAA=== +``` +%% \ No newline at end of file diff --git a/Docs/Bộ Rule CICD.md b/Docs/Bộ Rule CICD.md new file mode 100644 index 0000000..6f4b5ad --- /dev/null +++ b/Docs/Bộ Rule CICD.md @@ -0,0 +1,16 @@ +# Quy tắc Áp dụng CI/CD – Dành cho Nhóm Phát Triển + +| Quy tắc | Diễn giải / Hành động cụ thể | +| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| Không làm việc trực tiếp trên nhánh chính (main/master/develop) | - Dev không push trực tiếp lên nhánh chính.
- Git server cấu hình "Protected Branches", yêu cầu Pull Request. | +| Đặt tên nhánh theo quy tắc (feat/, fix/, chore/, ...) | - Tuân thủ naming convention khi tạo nhánh mới.
- Có thể dùng pre-receive hook hoặc CI lint để kiểm tra tên nhánh. | +| Không hardcode biến, dùng `.env` cho local | - Không ghi trực tiếp token, URL... vào code.
- Sử dụng secret management và `.env`. | +| Document rõ nếu template CI bị chỉnh sửa lớn | - Ghi chú lại những thay đổi cấu trúc template CI/CD để chia sẻ với team, không ảnh hưởng luồng hàng ngày. | +| Mọi thay đổi qua Pull Request (có review) | - Code được review trước khi merge.
- PR trigger pipeline và cần pass + được review đầy đủ trước khi merge. | +| Test phải pass 100% (unit, integration, coverage) | - Nếu bất kỳ test nào fail → pipeline dừng.
- Kiểm tra code coverage đủ ngưỡng tối thiểu. | +| Ưu tiên giữ pipeline luôn "Xanh" (Green) | - Khi có lỗi phải fix sớm.
- Coi việc pipeline đỏ là blocker. | +| Tối ưu hóa thời gian chạy pipeline định kỳ | - Review log pipeline theo chu kỳ để giảm thời gian chờ build/test. | +| Cấu hình cảnh báo pipeline (Slack, Email, Teams...) | - Gửi notify khi lỗi hoặc deploy thành công. | +| Commit message ý nghĩa | - Viết commit rõ ràng.
- Có thể dùng pre-commit hook hoặc CI lint commit message. | +| "Definition of Done" (DoD) | - Checklist kiểm tra các bước đã pass, QA/PO đã nghiệm thu trước khi đóng task. | +| Ai chịu trách nhiệm khi pipeline lỗi? | - Người vừa push hoặc cả team (tuỳ lỗi).
- Có cơ chế phân công hoặc cảnh báo rõ người chịu trách nhiệm xử lý. | diff --git a/Docs/FAQ.md b/Docs/FAQ.md new file mode 100644 index 0000000..c695fa1 --- /dev/null +++ b/Docs/FAQ.md @@ -0,0 +1,4 @@ +> 1. git merge vs git rebase cái nào tối ưu hơn? +> 1. Nếu làm **một mình**: **Dùng `rebase`**: giữ lịch sử gọn, dễ đọc, không tạo commit merge thừa. +> 2. Nếu làm **làm việc nhóm**: **Dùng `merge`**: an toàn, tránh rủi ro khi nhiều người đang dùng chung một nhánh. Lưu ý: Nếu rebase thì **chỉ rebase trước khi push**, không rebase lại nhánh đã được người khác dùng. + diff --git a/Docs/Thư viện cho Golang.md b/Docs/Thư viện cho Golang.md new file mode 100644 index 0000000..abe8a5e --- /dev/null +++ b/Docs/Thư viện cho Golang.md @@ -0,0 +1,7 @@ +- Testing & Static Analysis: testing package, stretch/testify, golangci-lint +- SAST: securego/gosec + - Quét Secrets: gitleaks/gitleaks + - DevSecOps: aquasecurity/trivy + - ORM: gorm + - Web framework: gin-gogic + - Feature Flag: thomaspoignant/go-feature-flag \ No newline at end of file diff --git a/Docs/Thư viện cho Nodejs.md b/Docs/Thư viện cho Nodejs.md new file mode 100644 index 0000000..a0c645c --- /dev/null +++ b/Docs/Thư viện cho Nodejs.md @@ -0,0 +1 @@ +- Testing: facebook/jest, mochajs/mocha \ No newline at end of file diff --git a/Docs/Tài liệu nâng cao.md b/Docs/Tài liệu nâng cao.md new file mode 100644 index 0000000..dbaae66 --- /dev/null +++ b/Docs/Tài liệu nâng cao.md @@ -0,0 +1,17 @@ +### **1. Tích hợp Security vào Pipeline** + +- **SAST (Static Application Security Testing):** SonarQube, ESLint. +- **DAST (Dynamic Application Security Testing):** OWASP ZAP. +- **Cấu hình trong DroneCI:** +``` + - name: Run SonarQube + image: sonarsource/sonar-scanner-cli + commands: + - sonar-scanner -Dsonar.projectKey=my-project +``` + +### **2. Giám sát và Alerting** +- **Công cụ:** Prometheus (metrics) + Grafana (dashboard) + Alertmanager. +- **Metrics cần theo dõi:** + - Error rate, Latency, CPU/Memory usage. + - Số lần deploy thành công/thất bại. \ No newline at end of file diff --git a/Docs/Tài liệu theo Role.md b/Docs/Tài liệu theo Role.md new file mode 100644 index 0000000..4982c20 --- /dev/null +++ b/Docs/Tài liệu theo Role.md @@ -0,0 +1,17 @@ +#### **Developer (Người phát triển tính năng)** +**Tài liệu tham khảo:** + - Hướng dẫn dành cho người mới : Guideline Folder + - Các mẫu có sẵn: Sample Folder + - Template file cần thiết: Template Folder +**Trách nhiệm chính:** +- Tuân thủ Quy trình CI/CD [[Diagrams CICD]] +- Tuân thủ Rule [[Bộ Rule CICD]] +#### **Fresher/Thành viên mới** +**Tài liệu tham khảo:** + - Hướng dẫn dành cho người mới : Guideline Folder + - Các mẫu có sẵn: Sample Folder + - Template file cần thiết: Template Folder +**Trách nhiệm chính:** +- Tuân thủ Quy trình CI/CD [[Diagrams CICD]] +- Tuân thủ Rule [[Bộ Rule CICD]] +- Thử nghiệm trên cách nhánh & viết Unit Test diff --git a/Docs/Tài liệu theo Workflow.md b/Docs/Tài liệu theo Workflow.md new file mode 100644 index 0000000..ad45509 --- /dev/null +++ b/Docs/Tài liệu theo Workflow.md @@ -0,0 +1 @@ +Soon \ No newline at end of file diff --git a/Guidlines/Quy trình cơ bản cho Dev.md b/Guidlines/Quy trình cơ bản cho Dev.md new file mode 100644 index 0000000..35d9c3e --- /dev/null +++ b/Guidlines/Quy trình cơ bản cho Dev.md @@ -0,0 +1,92 @@ +### 1. Đồng bộ Mã nguồn và Môi trường: + +``` +git checkout main +git pull origin main + +=== Mục đích: Đảm bảo bạn có phiên bản code mới nhất từ nhánh chính trước khi bắt đầu công việc mới hoặc tiếp tục công việc cũ, tránh conflict. + +git checkout feature/your-task-branch +git merge main // Xử lý Conflict nếu có + +=== Cập nhật những thay đổi mới nhất từ `main` vào nhánh làm việc của bạn. + +``` + +### 2. Tạo môi trường (lần đầu tiên) +Chạy các lệnh cần thiết để khởi động môi trường local (nếu chưa chạy): +- Tạo Các file cần thiết: .env +- Tạo các file mẫu: .gitignore , air.toml, Dockerfile, docker-compose.yml +- Cấu hình Global ban đầu +``` + git config --global commit.template ~/.gitmessage.txt : Gắn Template commit template +- git config --global user.name "Tên của bạn" +- git config --global user.email "email@example.com" + +``` +- Sử dụng Makefile (nếu có): `make run-dev` hoặc lệnh tương tự. Tham khảo: +- Sử dụng Docker Compose: `docker-compose up -d`. Tham khảo: +- Sử dụng Air cho Golang (nếu có): Air sẽ tự động theo dõi thay đổi. Tham khảo: + +### 3. Viết Code và Unit Test +- Triển khai tính năng hoặc sửa lỗi theo yêu cầu. +- Viết Unit Test sau mỗi unit code. Tham khảo [[Unit Test Rules]] +- Thường xuyên chạy Unit Test +- Tuân thủ Coding Convention của dự án. Tham khảo [[Code Convention]] +- Chú ý đến phi chức năng & bảo mật cơ bản +- Commit code thường xuyên với các thay đổi nhỏ, có ý nghĩa +- Sử dụng commit message : [[Git Template#Git Message]] +``` +git add . +git commit +``` + +### 4. Testing & Pull Request +- Chạy tất cả các Testing như trong quy trình CI trên Server(Lint, Unit Test, Integration Test, Securtiy Scan): Tham khảo Makefile +- Cập nhật lại nhánh với những thay đổi mới nhất từ `main` trước khi Pull Request +``` +git fetch origin +git merge origin/main +``` +- Push Code +``` +git status // kiểm tra trước khi push code +git push origin feature/task +``` +- Tạo PR trên Git Server & Viết mô tả PR rõ ràng + - Link đến Task ID + - Mô tả những gì đã làm + - Hướng dẫn Test Manual cho người review (nếu có) + - Gán người Review +### 6. Theo dõi Pipeline CI/CD +- Sau khi tạo PR, Pipeline tự động kích hoạt +- Theo dõi pipeline: Tham khảo [[Diagrams CICD]] - [[Pipeline Template(Dev)]] - [[Pipeline Template(Main)]] +- Kiểm tra pipeline khi lỗi, sửa lỗi, commit và push lại. Tham khảo [[Bộ Rule CICD]] +### 7. Sau khi Merge Code +- Merge Code sẽ do Lead Approve vào nhánh main/master +- Clean Nhánh +``` +git checkout main +git pull origin main # Cập nhật local main +git branch -d feature/TASK-ID # Xóa nhánh local +git push origin --delete feature/TASK-ID # Xóa nhánh remote (nếu có quyền và team quy định) +``` +### 8. Xử lý việc cuối ngày +- Cập nhật trạng thái task & Ghi chú tiến độ cho ngày hôm sau( nếu chưa hoàn tất) +- Commit cuối ngày và push lên nhánh của mình đang thực hiện (feature/task-id) +``` +git add . +git commit +git push origin +``` + +### Short CheatSheet (Go) +- go get --package_name-- : Cài đặt dependency +- go run /path/*.go : Chay Go +- go build /path/go : tạo thành file thực thi +- go mod tidy: Dọn dẹp dependencies +- go test -v ./... : Kiểm tra unit test +- golangci-lint run : Kiểm tra code style +- go test -cover ./... : Kiểm tra coverage của code +- go clean -cache|-testcache : Clean cache build / test +- go clean -i : xóa file biên dịch \ No newline at end of file diff --git a/Guidlines/Quy trình cơ bản cho Leader.md b/Guidlines/Quy trình cơ bản cho Leader.md new file mode 100644 index 0000000..ded725c --- /dev/null +++ b/Guidlines/Quy trình cơ bản cho Leader.md @@ -0,0 +1,88 @@ +### 1. Lập kế hoạch +- Tổng thể về dự án +- Xác định backlog +- Xác định các chức năng phi tuyến tính +- Xác định Tổng quan dự án: [[Tổng quan]] +### 2. First Design +- Phác thảo kiến trúc +- Quyết định cấu trúc thư mục (U-Hierarchy) +### 3. Kiểm tra lại các tiêu & Quy ước +- Review lại tron Docs Folder, Guideline Folder + - Quy trình CI/CD + - Coding Convention + - Commit Message + - Branching Strategy - [[Branch Strategy]] +### 4. Khởi tạo repo mới +- Khởi tạo repo & Protect Branches cho main + - Yêu cầu PR để được merge vào main + - ÍT nhất 1 lượt Approval + - Pass Pipeline + - Permission Push to main +- Xây dựng Starter Kit + - Xây dựng cấu trúc folder (như phần 1) + - File cấu hình cơ bản + - `.gitignore` - [[Git Template]] + - `.gitmessage` - [[Git Template]] + - Readme.md - Thông tin dự án + - .env - File môi trường + - Dockerfile - [[Docker Template]] + - docker-compose.yml - [[Docker Template]] + - Makefile - [[Makefile]] + - Khởi tạo dự án trong ngôn ngữ lập trình + - Golang: go mod init path/to/repo + - Nodejs: npm init + - Hot reload cho golang: Cấu hình với Air Tomb [[Air Tomb - Golang]] [[Cấu hình Air Tom]] + - Thiết lập pipeline cho CI/CD + - Tạo thư mục `.gitea/workflow` + - Tạo file yaml cho Dev & Main + - Trigger khi `feature/task-id`: [[Pipeline Template(Dev)]] + - Trigger khi `main` hoặc đánh tag `v*` : [[Pipeline Template(Main)]] + - Cấu hình cơ bản pipeline cần có + - Check out + - Setup ngôn ngữ + - Caching Dependencies + - Linting + - Unit Test & Coverage report + - Security Scan + - Build Artifact + - Upload Artifact (Main Branch) + - Push to Docker (Main Branch) + - Deploy to VPS(Staging) (Main Branch) + - Deploy to VPS(Production) by Tag or Release (Main Branch) + - Xây dựng danh sách các action và library phù hợp với phiên bản hiện tại + - actions/checkout@v4 + - actions/setup-go@v5 + - actions/cache@v3 + - golangci/golangci-lint-action@v6 + - golang/govulncheck-action@v1 + - actions/upload-artifact@v3 + - actions/download-artifact@v3 + - docker/setup-buildx-action@v3 + - docker/build-push-action@v5 + - Tạo code mẫu + - Health API để check live + - Load & Read Config + - Connect to Database + - Cấu trúc thư mục & Module(U-Hierarchy) + - Unit test sample - Tham khảo [[Unit Test Rules]] +### 5. Push Starter Kit lên main +- Review lại toàn bộ file +- Tạo Branch init rồi PR vào main để chạy thử Pipeline +- Commit rõ ràng cho việc init: `chore: initial project setup and starter kit` +### 6. Checklist cho Team Lead khi Khởi tạo Repo/Service: + +- [ ] Đã xác định mục tiêu, phạm vi repo/service. +- [ ] Đã có thiết kế high-level ban đầu. +- [ ] Repository trên Gitea đã được tạo và cấu hình "Protected Branch". +- [ ] File `.gitignore` đã được thêm và tùy chỉnh. +- [ ] File `README.md` cơ bản đã được cập nhật. +- [ ] File `.env.example` đã được tạo. +- [ ] `Dockerfile` đã được tạo và tùy chỉnh. +- [ ] `docker-compose.yml` (cho local) đã được tạo. +- [ ] `Makefile` với các target cơ bản đã được thiết lập. +- [ ] Go module / `package.json` đã được khởi tạo. +- [ ] (Nếu có) Cấu hình Air cho Golang đã hoàn tất. +- [ ] CI/CD pipeline cơ bản (Dev & Main) đã được tạo trong `.gitea/workflows/`. +- [ ] Code boilerplate (Hello World, unit test mẫu) đã được thêm. +- [ ] Starter kit đã được commit và push lên nhánh `init` và PR vào `main`. +- [ ] `README.md` đã được hoàn thiện với hướng dẫn cho Developer. diff --git a/Knowledge Base/Branch Strategy.md b/Knowledge Base/Branch Strategy.md new file mode 100644 index 0000000..a739722 --- /dev/null +++ b/Knowledge Base/Branch Strategy.md @@ -0,0 +1,13 @@ +Trunk-Based Development là phương pháp quản lý nhánh trong Git, nơi tất cả thay đổi được tích hợp thường xuyên vào nhánh chính (`main`), còn gọi là "trunk". +- **Nhánh** + - Main + - Giữ trạng thái sẵn sàng deploy. + - Không commit trực tiếp; mọi thay đổi phải qua Pull Request (PR). + - Luôn phải qua CI (lint, test, build) xanh mới merge. + - **Tính năng**: `feature/` + - **Sửa lỗi**: `fix/` + - Công việc chung**: `chore/` +- **Rule** + - Tồn tại < 2 ngày và tích hợp liên tục +- Quy trình + - Tạo PR => Review Code => CI Pass => Merge \ No newline at end of file diff --git a/Knowledge Base/Cheatsheet.md b/Knowledge Base/Cheatsheet.md new file mode 100644 index 0000000..60d805d --- /dev/null +++ b/Knowledge Base/Cheatsheet.md @@ -0,0 +1,38 @@ +### **1. Git Commands** +**Command:** +- git checkout -b branch # Tạo nhánh. +- git pull origin branch # Kéo repo từ nhánh +- git add . | git add filename# Thêm file vào staging +- git commit -m "feat: content" # Commit thay đổi theo format scope + nội dung +- git push origin branch # Đẩy repo lên source code +- git merge branch # gộp tính năng vào +- git branch -d ten-nhanh # xóa local +- git push origin --delete ten-nhanh # xóa remote + + +**Commit Scope** +- **Dev Code** → `feat`, `fix` +- **Dev Refactor → `refactor`, `perf`, `style` +- DevOps → `build`, `ci`, `chore` +- **Tester|BA** → `docs`, `test` +- **Leader | Automation** → `revert` +### 2. Docker Commands +**Command:** +- docker build -t image:tag : tạo docker image từ Dockerfile +- docker build --cache-from image:tag -t image:tag : Cache +- docker run --rm -it image:tag sh : Chạy container +- docker exec -it image:tag bash: Thực hiện lệnh trong Container +- docker compose down: tắt các docker đang chạy +- docker compose up -d : chạy lại các docker (background) +- docker ps -a: Xem danh sách docker đã khởi chạy +- docker container|image|volume prune -f : Xóa các entity không dùng +- docker network inspect network:name : Xem chi tiết network + +### 3. Config Init +- git config --global commit.template ~/.gitmessage.txt : Gắn Template commit template +- git config --global user.name "Tên của bạn" +- git config --global user.email "email@example.com" + + + + diff --git a/Knowledge Base/Check List Done (DEV).md b/Knowledge Base/Check List Done (DEV).md new file mode 100644 index 0000000..fb77d07 --- /dev/null +++ b/Knowledge Base/Check List Done (DEV).md @@ -0,0 +1,26 @@ +#### Definition of Done Checklist (For Small Team) + +### 1. Functionality +- [ ] **Code passes all unit tests** and all tests pass. +- [ ] **Code does not break other functionalities** in the system. + +### 2. Code Quality +- [ ] **No linting errors**: Code should follow basic formatting rules (e.g., indentation, naming conventions). +- [ ] **Code is readable and maintainable**: Avoid complex or unclear code. + +### 3. Review Process +- [ ] **At least 1 person in the team has reviewed the code**. +- [ ] **No conflicts** with the main branch. + +### 4. Documentation +- [ ] **Documentation updated if needed**: If there are changes that affect how the API or features are used, provide a description. + +### 5. Manual Testing +- [ ] **Manual testing done** for the changed features (if required) to ensure no issues occur. + +### 6. Environment and Performance +- [ ] **Code works stable on local environment**. +- [ ] **No performance degradation** in the system (if applicable). + +### 7. Merge into Main Branch +- [ ] **No critical errors** during merge. diff --git a/Knowledge Base/Code Convention.md b/Knowledge Base/Code Convention.md new file mode 100644 index 0000000..a841002 --- /dev/null +++ b/Knowledge Base/Code Convention.md @@ -0,0 +1,134 @@ +Dưới đây là phân tích chi tiết về 5 quy ước quan trọng nhất: + +### 1. Bắt buộc Định dạng Mã bằng `gofmt`/`goimports` + +- **Quy ước:** **Tất cả** mã nguồn Go trong dự án **phải** được định dạng bằng công cụ `gofmt`. Khuyến khích mạnh mẽ sử dụng `goimports` (bao gồm `gofmt` và tự động quản lý imports) thay thế.   + +- **Giải thích:** + - `gofmt` là công cụ định dạng mã nguồn tiêu chuẩn của Go. Việc sử dụng nó đảm bảo một phong cách định dạng thống nhất (thụt lề bằng tab, cách dòng, sắp xếp, v.v.) trên toàn bộ codebase, loại bỏ hoàn toàn các cuộc tranh luận không cần thiết về định dạng.   + + - `goimports` là một bản nâng cấp của `gofmt`, ngoài việc định dạng mã, nó còn tự động sắp xếp, thêm và xóa các khai báo `import` không cần thiết, giúp giữ cho phần import luôn gọn gàng và chính xác.   + +- **Tại sao quan trọng cho đội ngũ:** + - **Tính nhất quán tuyệt đối:** Mọi người đọc và viết mã theo cùng một định dạng, giảm thiểu sự phân tâm và giúp tập trung vào logic nghiệp vụ.   + + - **Giảm thời gian review:** Người review không cần phải bình luận về các lỗi định dạng cơ học. + - **Dễ đọc hơn:** Mã được định dạng chuẩn dễ đọc và dễ theo dõi hơn đáng kể. +- **Cách thực thi:** + - **Tích hợp vào IDE/Editor:** Cấu hình trình soạn thảo mã (VS Code, GoLand, v.v.) để tự động chạy `goimports` mỗi khi lưu file.   + - **Pre-commit Hooks:** Sử dụng các công cụ như `pre-commit` để tự động chạy `goimports` trước khi commit mã nguồn. + - **CI/CD Pipeline:** Đảm bảo có một bước kiểm tra định dạng bằng `gofmt` hoặc `goimports` trong quy trình tích hợp liên tục (CI). + +### 2. Xử lý Lỗi Nhất quán và Rõ ràng + +- **Quy ước:** + - **Luôn kiểm tra lỗi:** Nếu một hàm trả về giá trị kiểu `error`, **phải** kiểm tra giá trị đó. Không bao giờ bỏ qua lỗi bằng định danh trống (`_`) trừ khi có lý do cực kỳ chính đáng và được ghi chú rõ ràng.   + - **Thêm ngữ cảnh khi cần:** Khi trả về một lỗi từ tầng dưới, hãy sử dụng `fmt.Errorf` với động từ `%w` để "wrap" lỗi gốc và thêm ngữ cảnh mô tả thao tác đang thực hiện. Ví dụ: `return fmt.Errorf("opening config file %s: %w", filename, err)`.   + + - **Xử lý lỗi một lần:** Một lỗi chỉ nên được xử lý (ví dụ: ghi log) tại một điểm duy nhất trong chuỗi gọi, thường là ở tầng cao nhất có đủ ngữ cảnh.   + + - **Tránh `panic` cho lỗi thông thường:** Chỉ sử dụng `panic` cho các lỗi nghiêm trọng, không thể phục hồi (ví dụ: lỗi lập trình, điều kiện không thể xảy ra). Luôn ưu tiên trả về `error` cho các lỗi có thể dự đoán được.   + + - **Chuỗi lỗi:** Chuỗi lỗi trả về (qua phương thức `Error()`) không nên viết hoa chữ cái đầu và không kết thúc bằng dấu chấm câu.   + +- **Giải thích:** + - Go sử dụng kiểu `error` và trả về nhiều giá trị để xử lý lỗi một cách tường minh. Việc bỏ qua kiểm tra lỗi có thể dẫn đến các hành vi không mong muốn hoặc crash chương trình.   + + - Wrapping lỗi bằng `%w` cho phép các tầng trên kiểm tra lỗi gốc bằng `errors.Is` hoặc `errors.As`, đồng thời cung cấp thông tin về đường dẫn lỗi xảy ra.   + + - Xử lý lỗi nhiều lần (ví dụ: log ở nhiều tầng) gây ra nhiễu thông tin và khó theo dõi. +- **Tại sao quan trọng cho đội ngũ:** + - **Độ tin cậy:** Đảm bảo các trạng thái lỗi được xử lý đúng cách, giúp ứng dụng ổn định hơn. + - **Khả năng gỡ lỗi:** Lỗi được wrap với ngữ cảnh rõ ràng giúp xác định nguyên nhân gốc rễ nhanh hơn nhiều. + - **Tính nhất quán:** Một cách tiếp cận xử lý lỗi thống nhất giúp mã dễ hiểu và dễ bảo trì hơn. +- **Cách thực thi:** + - **Code Review:** Chú trọng kiểm tra việc xử lý lỗi trong quá trình review mã. + - **Linters:** Sử dụng các công cụ như `errcheck` (thường có trong `golangci-lint`) để tự động phát hiện các lỗi chưa được kiểm tra.   + + +### 3. Quy ước Đặt tên Rõ ràng và Nhất quán + +- **Quy ước:** + - **`MixedCaps`:** Sử dụng `MixedCaps` hoặc `mixedCaps` (camelCase), không dùng dấu gạch dưới (`_`).   + + - **Ngắn gọn nhưng Mô tả:** Độ dài tên tỷ lệ thuận với phạm vi của nó. Tên ngắn cho biến cục bộ, tên mô tả hơn cho các biến/hàm có phạm vi lớn hơn.   + + - **Từ viết tắt (Initialisms):** Đối xử như một từ, viết hoa nhất quán (ví dụ: `userID`, `ServeHTTP`, `apiClient`, `URL`). Không dùng `UserId`, `ServeHttp`, `apiUrl`.   + + - **Tên Package:** Ngắn gọn, một từ, chữ thường, không dấu gạch dưới, không lặp lại trong định danh của package (ví dụ: trong package `http`, dùng `Client` thay vì `HttpClient`). Tránh các tên chung chung như `util`, `common`.   + + - **Tên Hàm/Phương thức:** Không tiền tố `Get` cho các hàm/phương thức chỉ trả về giá trị (ví dụ: `Counts()` thay vì `GetCounts()`).   + + - **Tên Interface:** Thường có hậu tố `-er` cho interface một phương thức (ví dụ: `Reader`, `Writer`).   + + - **Tên Receiver:** Ngắn (1-2 chữ cái), viết tắt của loại, nhất quán trong cùng một loại (ví dụ: `c` hoặc `cl` cho `*Client`).   + +- **Giải thích:** + - Tên gọi nhất quán và có ý nghĩa giúp mã nguồn dễ đọc và dễ hiểu hơn rất nhiều. + - Quy tắc về từ viết tắt và việc không lặp lại tên package là những điểm đặc trưng của Go cần tuân thủ. +- **Tại sao quan trọng cho đội ngũ:** + - **Khả năng đọc:** Giảm thời gian cần thiết để hiểu mục đích của biến, hàm, package. + - **Khả năng bảo trì:** Dễ dàng tìm kiếm, thay đổi tên và hiểu tác động của thay đổi. + - **Giảm lỗi:** Tên rõ ràng giúp tránh nhầm lẫn và sử dụng sai. +- **Cách thực thi:** + - **Code Review:** Đây là cách chính để đảm bảo tuân thủ quy ước đặt tên. + - **Linters:** Một số linter (ví dụ: `revive`, `stylecheck` trong `golangci-lint`) có thể giúp kiểm tra một phần các quy ước đặt tên. + +### 4. Quản lý Đồng thời Cẩn thận (Vòng đời Goroutine & `context.Context`) + +- **Quy ước:** + - **Quản lý Vòng đời Goroutine:** Khi khởi tạo một goroutine bằng từ khóa `go`, phải đảm bảo có cách rõ ràng để nó kết thúc. Tránh goroutine bị rò rỉ (leak) do bị chặn vô thời hạn.   + + - **Sử dụng `sync.WaitGroup`:** Dùng `WaitGroup` để chờ một nhóm các goroutine con hoàn thành trước khi goroutine cha tiếp tục.   + + - **Truyền Biến Vòng lặp:** Khi tạo goroutine trong vòng lặp, luôn truyền biến vòng lặp làm tham số cho goroutine để tránh lỗi closure phổ biến (bắt giá trị cuối cùng).   + + - **Sử dụng `context.Context`:** + - Truyền `context.Context` làm tham số **đầu tiên** (thường đặt tên là `ctx`) cho các hàm thực hiện I/O, gọi RPC, hoặc các tác vụ có thể bị hủy bỏ hoặc có deadline.   + + - Các hàm nhận `ctx` nên lắng nghe kênh `ctx.Done()` (thường trong `select`) để dừng công việc sớm khi có tín hiệu hủy bỏ hoặc hết hạn.   + + - **Không lưu trữ `Context` trong struct.** Truyền nó qua các tham số hàm/phương thức.   + +- **Giải thích:** + - Goroutine rất nhẹ và dễ tạo, nhưng nếu không quản lý cẩn thận, chúng có thể bị leak, tiêu tốn tài nguyên và gây ra các lỗi khó gỡ.   + + - `context.Context` là cơ chế tiêu chuẩn và thành ngữ của Go để xử lý việc hủy bỏ, timeout và truyền dữ liệu theo phạm vi yêu cầu một cách an toàn qua các tầng và goroutine.   + +- **Tại sao quan trọng cho đội ngũ:** + - **Độ tin cậy:** Ngăn chặn rò rỉ tài nguyên và các lỗi liên quan đến đồng thời khó gỡ lỗi (race conditions, deadlocks). + - **Khả năng kiểm soát:** Cho phép hủy bỏ các tác vụ không cần thiết hoặc đã quá hạn, giải phóng tài nguyên hệ thống. + - **Khả năng mở rộng:** Các hệ thống xử lý nhiều yêu cầu đồng thời cần cơ chế quản lý hủy bỏ và deadline hiệu quả. +- **Cách thực thi:** + - **Code Review:** Đặc biệt chú ý đến việc khởi tạo goroutine và sử dụng `context`. + - **Race Detector:** Luôn chạy kiểm thử với cờ `-race` (`go test -race`) để phát hiện data races.   + + - **Linters:** Một số linter có thể phát hiện các vấn đề liên quan đến `context` (ví dụ: `contextcheck`). + +### 5. Thiết kế Package Hợp lý (Tránh `util`, Sử dụng `internal`) + +- **Quy ước:** + - **Nhóm theo Chức năng:** Tổ chức mã vào các package dựa trên chức năng hoặc trách nhiệm nghiệp vụ, không phải theo loại (ví dụ: tránh các package `models`, `controllers`, `helpers`).   + + - **Tránh Package Chung chung:** Không tạo các package có tên mơ hồ như `util`, `common`, `shared`, `helpers`, `base`. Nếu cần chia sẻ mã, hãy tìm một tên package cụ thể hơn, mô tả rõ trách nhiệm của nó.   + + - **Sử dụng `internal`:** Đặt mã nguồn **không dành cho việc sử dụng bởi các module bên ngoài** vào thư mục `internal`. Trình biên dịch Go sẽ thực thi quy tắc này, ngăn chặn việc import mã từ `internal` bởi các dự án khác.   + + - **Thư mục `pkg` (Thận trọng):** Chỉ đặt mã vào thư mục `pkg` ở gốc nếu bạn **chắc chắn** muốn cung cấp nó như một thư viện công khai, ổn định cho các dự án khác import. Việc đặt mã ở đây tạo ra một cam kết về API. Cân nhắc kỹ lưỡng, nhiều trường hợp đặt thư viện ở gốc hoặc trong `internal` là đủ.   + + - **Bắt đầu Đơn giản:** Không cần áp dụng cấu trúc phức tạp ngay từ đầu. Bắt đầu với cấu trúc phẳng và chỉ thêm các thư mục như `internal` hay `cmd` khi dự án phát triển và thực sự cần thiết.   + +- **Giải thích:** + - Thiết kế package tốt giúp mã dễ hiểu, dễ tìm kiếm và giảm thiểu sự phụ thuộc không cần thiết. + - Các package chung chung thường trở thành nơi chứa mã không liên quan, làm tăng sự phức tạp và khó bảo trì.   + + - Thư mục `internal` là một công cụ mạnh mẽ của Go để thực thi đóng gói ở cấp độ module, giúp phân định rõ ràng API công khai và chi tiết triển khai nội bộ, cho phép tái cấu trúc an toàn hơn.   + +- **Tại sao quan trọng cho đội ngũ:** + - **Khả năng bảo trì:** Mã được tổ chức tốt dễ hiểu và dễ sửa đổi hơn. + - **Khả năng tái sử dụng:** Các package được thiết kế tốt, tập trung vào chức năng cụ thể có khả năng tái sử dụng cao hơn. + - **Kiểm soát API:** Thư mục `internal` giúp kiểm soát chặt chẽ những gì được coi là API công khai, giảm rủi ro phá vỡ các dự án phụ thuộc khi thay đổi mã nội bộ. + - **Giảm xung đột:** Tên package cụ thể giúp tránh xung đột tên. +- **Cách thực thi:** + - **Thảo luận Thiết kế:** Thảo luận về cấu trúc package khi bắt đầu dự án hoặc các tính năng lớn. + - **Code Review:** Đảm bảo các package mới tuân thủ nguyên tắc nhóm theo chức năng và sử dụng `internal` đúng cách. \ No newline at end of file diff --git a/Knowledge Base/Domain Driven Development.md b/Knowledge Base/Domain Driven Development.md new file mode 100644 index 0000000..7ec1a82 --- /dev/null +++ b/Knowledge Base/Domain Driven Development.md @@ -0,0 +1,40 @@ +**Domain-Driven Design (DDD)** là một phương pháp thiết kế và phát triển phần mềm tập trung vào **nghiệp vụ (Domain)** của một lĩnh vực đặc thù. + +---- +#### **1. Domain (Lĩnh vực/Nghiệp vụ chính):** + +- Là nghiệp vụ chính mà hệ thống phần mềm cần giải quyết. +- Đây chính là **trọng tâm** của hệ thống và là nơi tạo ra giá trị lớn nhất cho doanh nghiệp. + +#### **2. Subdomain (Nghiệp vụ con):** + +- Là các **thành phần nhỏ hơn** của Domain, hỗ trợ việc xử lý nghiệp vụ. +- **DDD** chia Subdomains thành 3 loại chính: + +| **Loại Subdomain** | **Đặc điểm** | +| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Core Subdomain** | - Nghiệp vụ cốt lõi, quan trọng nhất của hệ thống.
- Tốn nhiều tài nguyên, thời gian và sáng tạo.
- Mang lại giá trị **độc nhất** (Unique Value) cho doanh nghiệp. | +| **Supporting Subdomain** | - Hỗ trợ Core Subdomain, nhưng không phải trung tâm.
- Có thể sử dụng giải pháp từ bên thứ ba hoặc thuê ngoài (outsourcing). | +| **Generic Subdomain** | - Là các nghiệp vụ chung mà bất kỳ công ty nào cũng cần.
- Quan trọng, nhưng không tạo ra lợi thế cạnh tranh đặc biệt. | +#### **3. Bounded Context (Ngữ cảnh giới hạn):** + +- Là **ranh giới** rõ ràng cho từng Subdomain trong hệ thống. +- Mỗi Bounded Context tập trung vào một phần nghiệp vụ cụ thể và có mô hình riêng. +- Các Context giao tiếp với nhau thông qua **API** hoặc **sự kiện (event)**. + +#### **4. Ubiquitous Language (Ngôn ngữ chung):** + +- Là **ngôn ngữ chung** được cả đội ngũ kỹ thuật và chuyên gia nghiệp vụ sử dụng. +- Mục tiêu là để mọi người hiểu rõ ràng và nhất quán về nghiệp vụ và mô hình hệ thống. + +---- +### **Kết luận** + +DDD là một phương pháp thiết kế mạnh mẽ, đặc biệt phù hợp với các hệ thống phức tạp. +Nó giúp: + +- **Tập trung vào giá trị cốt lõi** của nghiệp vụ. +- **Tổ chức hệ thống rõ ràng** với các Bounded Context. +- Đảm bảo sự phối hợp chặt chẽ giữa đội ngũ **kỹ thuật** và **nghiệp vụ**. + +#develoment #tech #work \ No newline at end of file diff --git a/Knowledge Base/Glossary & Meaning.md b/Knowledge Base/Glossary & Meaning.md new file mode 100644 index 0000000..8c9b73f --- /dev/null +++ b/Knowledge Base/Glossary & Meaning.md @@ -0,0 +1,4 @@ +- `origin`: Khi bạn clone một repo, Git mặc định gọi **remote gốc** là `origin`. +- upstream: Tên remote (khi fork) | Nhánh đang tracking +- Fork: Tạo bản sao độc lập với Repo có thể Pull Request trực tiếp vào repo và trở thành Contributor +- Clone: Tạo bản sao về Local. cả fork và clone đều có thể sync thông qua gắn upstream vào repo gốc. diff --git a/Knowledge Base/Unit Test Rules.md b/Knowledge Base/Unit Test Rules.md new file mode 100644 index 0000000..bea9fec --- /dev/null +++ b/Knowledge Base/Unit Test Rules.md @@ -0,0 +1,23 @@ +- Tuân thủ nguyên tắc First(Fast, Independent, Repeatable, Self-Validating, Timely) +- Tên test rõ ràng có ý nghĩa +- Structure Test + - Arrange: Khởi tạo input + - Act: Thực thi hàm | Logic + - Assert: Kiểm tra output + - Assert: Tiếp tục test (testify/assert) + - Error: Dừng ngay lập tức +- Test tất cả giá trị + - Normal: các dữ liệu bình thường (a/b - b/a) + - Biên của hàm: các giới hạn trong hàm(0/a - 0/b) + - Lỗi: dữ liệu lỗi (a/0 - b/0) +- Tránh logic phức tạp + - Test không nên chứa vòng lặp hoặc `if` trừ khi thật sự cần + - Mỗi test nên kiểm tra một logic đơn lẻ và rõ ràng +- Mock External Dependencies + - Dùng mock: DB,API,File,Email (gomock,testify/mock) +- Test song song không phụ thuộc +- Tối thiểu hóa side effect + - Không test ghi file, database, hoặc gọi API thật trong unit test. + - Nếu cần test integration, viết riêng ở layer khác (Integration Test). +- Kiểm tra Coverage +- Sử dụng t.Run cho subtests \ No newline at end of file diff --git a/Samples/Cấu hình Air Tom.md b/Samples/Cấu hình Air Tom.md new file mode 100644 index 0000000..e69de29 diff --git a/Templates/Air Tomb - Golang.md b/Templates/Air Tomb - Golang.md new file mode 100644 index 0000000..2df014b --- /dev/null +++ b/Templates/Air Tomb - Golang.md @@ -0,0 +1,103 @@ +File ```.air.toml``` là file cấu hình cho công cụ Air - một công cụ hot-reload dành cho ứng dụng Go. Air giúp các lập trình viên Go phát triển ứng dụng nhanh hơn bằng cách theo dõi các thay đổi trong mã nguồn và tự động biên dịch lại, khởi động lại ứng dụng khi có thay đổi. + +``` +# ----------------------------------------------------- +# Air Template Configuration - Cấu hình mẫu Air +# Công cụ Hot-reload cho ứng dụng Go +# ----------------------------------------------------- + +air.toml +# Thư mục gốc của dự án, mặc định là thư mục hiện tại +root = "." + +# Thư mục chứa dữ liệu test +testdata_dir = "testdata" + +# Thư mục tạm để lưu các file biên dịch +tmp_dir = "tmp" + +# Cấu hình quá trình build +[build] + # Các tham số dòng lệnh được truyền vào file thực thi + args_bin = [] + + # Đường dẫn đến file thực thi sau khi biên dịch + bin = "./tmp/main.exe" + + # Lệnh biên dịch ứng dụng + cmd = "go build -o ./tmp/main.exe ./cmd/server/main.go" + + # Độ trễ (millisecond) trước khi khởi động lại sau khi phát hiện thay đổi + delay = 1000 + + # Các thư mục bị loại trừ khỏi việc theo dõi + exclude_dir = ["assets", "tmp", "vendor", "testdata", "node_modules", ".git"] + + # Các file cụ thể bị loại trừ khỏi việc theo dõi + exclude_file = [".gitignore", ".air.toml", "README.md"] + + # Loại trừ các file theo biểu thức chính quy + exclude_regex = ["_test.go", "\\.DS_Store"] + + # Có bỏ qua theo dõi các file không thay đổi hay không + exclude_unchanged = false + + # Có theo dõi symbolic link hay không + follow_symlink = false + + # Đường dẫn đầy đủ đến file thực thi (nếu cần các tham số đặc biệt) + full_bin = "" + + # Các thư mục cụ thể cần theo dõi + include_dir = [] + + # Chỉ theo dõi các file có phần mở rộng trong danh sách này + include_ext = ["go", "tpl", "tmpl", "html", "css", "js"] + + # Độ trễ trước khi kết thúc tiến trình cũ sau khi tái khởi động + kill_delay = "0s" + + # File log lưu các lỗi build + log = "build-errors.log" + + # Có gửi tín hiệu ngắt đến ứng dụng trước khi kill hay không + send_interrupt = false + + # Có dừng theo dõi khi gặp lỗi build hay không + stop_on_error = true + +# Cấu hình màu sắc cho đầu ra +[color] + # Màu cho thông tin ứng dụng + app = "green" + + # Màu cho thông tin build + build = "yellow" + + # Màu cho thông tin chung + main = "magenta" + + # Màu cho thông tin runner + runner = "cyan" + + # Màu cho thông tin watcher + watcher = "blue" + +# Cấu hình cho log +[log] + # Thời gian (ms) giữa các lần update của file log + time = false + + # Có hiển thị màu trong log hay không + main_only = false + +# Cấu hình cho screen +[screen] + # Có xóa màn hình mỗi khi tái khởi động hay không + clear_on_rebuild = true + + # Có giữ cuộn màn hình hay không + keep_scroll = true + + +``` \ No newline at end of file diff --git a/Templates/Docker Template.md b/Templates/Docker Template.md new file mode 100644 index 0000000..40f5eb0 --- /dev/null +++ b/Templates/Docker Template.md @@ -0,0 +1,99 @@ +``` +docker-compose.yml + +services: +  db: +    image: postgres:15 +    environment: +      POSTGRES_USER: ${DB_USER} +      POSTGRES_PASSWORD: ${DB_PASSWORD} +      POSTGRES_DB: ${DB_NAME} +    volumes: +      - db_data:/var/lib/postgresql/data +      - ./migrations:/docker-entrypoint-initdb.d +    ports: +      - "5432:5432" +    healthcheck: +      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"] +      interval: 5s +      timeout: 5s +      retries: 5 +    deploy: +      resources: +        limits: +          cpus: '0.5' +          memory: 512M +  adminer: +    image: adminer +    restart: always +    ports: +      - "8081:8080" +    depends_on: +      db: +        condition: service_healthy +  app: +    build: . +    environment: +      DB_HOST: db +      DB_USER: ${DB_USER} +      DB_PASSWORD: ${DB_PASSWORD} +      DB_NAME: ${DB_NAME} +      DB_PORT: "5432" +      LOG_LEVEL: "debug" +    ports: +      - "8080:8080" +    depends_on: +      db: +        condition: service_healthy +    deploy: +      resources: +        limits: +          cpus: '1' +          memory: 1G +volumes: +  db_data: +  pgdata_dev: +networks: +  default: +    name: matching_network +    driver: bridge +``` + +``` +Dockerfile +# Build stage +FROM golang:1.23-alpine AS builder +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o matching-app cmd/server/main.go + +# Final image +FROM alpine:3.18 +WORKDIR /app + +# Add non-root user +RUN addgroup -S appgroup && adduser -S appuser -G appgroup + +# Copy binary and resources +COPY --from=builder --chown=appuser:appgroup /app/matching-app . +COPY --from=builder --chown=appuser:appgroup /app/migrations ./migrations +COPY --from=builder --chown=appuser:appgroup /app/configs ./configs + +# Environment variables +ENV APP_PORT=8080 +ENV APP_ENV=production + +# Install wget for healthcheck +RUN apk --no-cache add wget + +# Healthcheck +HEALTHCHECK --interval=30s --timeout=3s \ +  CMD wget --no-verbose --tries=1 --spider http://localhost:${APP_PORT}/health || exit 1 + +EXPOSE ${APP_PORT} +USER appuser +ENTRYPOINT ["/app/matching-app"] +CMD [] +``` \ No newline at end of file diff --git a/Templates/Env.md b/Templates/Env.md new file mode 100644 index 0000000..93a715a --- /dev/null +++ b/Templates/Env.md @@ -0,0 +1,31 @@ +`.env` phù hợp **trong giai đoạn dev/local**, đơn giản và dễ triển khai. +``` +.env +# Database configuration +DB_USER= +DB_PASSWORD= +DB_NAME= + +# App configuration +APP_PORT=8080 +APP_ENV=development +LOG_LEVEL=debug + +# Email settings (SMTP) +SMTP_HOST= +SMTP_PORT=587 +SMTP_USER= +SMTP_PSSWORD= + + +# AWS S3 Configuration +AWS_ACCESS_KEY_ID +AWS_SECRET_ACCESS_KEY= +AWS_REGION= +AWS_S3_BUCKET= + +# Telegram Notification +TELEGRAM_TOKEN= +TELEGRAM_CHAT_ID= + +``` \ No newline at end of file diff --git a/Templates/Git Template.md b/Templates/Git Template.md new file mode 100644 index 0000000..74baa1b --- /dev/null +++ b/Templates/Git Template.md @@ -0,0 +1,94 @@ +``` +.gitignore + +# Các file và thư mục tạm thời của Go +/tmp/ +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.test +*.out +/vendor/ + +# File log +*.log +build-errors.log + +# Thư mục template và các file mẫu +/template/ +template-* +*-template* +example-* +*.example.* + +# Thư mục tạm thời của Air +.air.conf +.air.toml.backup + +# Các file cấu hình và IDE +.idea/ +.vscode/ +*.swp +*.swo +.DS_Store +Thumbs.db + +# Các file binary được tạo ra +/bin/ +/build/ + +# Các file môi trường và cấu hình cụ thể cho môi trường cục bộ +.env +.env.local +.env.*.local +*.local.yaml +*.local.yml +*.local.toml +*.local.json + +# Các thư mục cache +.cache/ +__pycache__/ +node_modules/ +.npm/ + +# Các file và thư mục khác không cần thiết +coverage/ +coverage.txt +profile.out +.coverage + +# Các file backup +*~ +*.bak +*.backup +*.old +*.orig + +``` +## Git Message +``` +.gitmessage +# type: feat | fix | docs | style | refactor | perf | test | chore +# scope: phần của project bị ảnh hưởng (auth, api, db...) +# summary: mô tả ngắn gọn (không viết hoa, không chấm câu) +# body: mô tả thêm (có thể bỏ qua) +# footer: liên kết issue hoặc cảnh báo BREAKING CHANGE +# ~/.gitmessage.txt + +(): + +[Body - mô tả chi tiết] + +[Footer - issue liên quan, breaking change,...] + +``` + +**Commit Scope** +- **Dev Code** → `feat`, `fix` +- **Dev Refactor → `refactor`, `perf`, `style` +- DevOps → `build`, `ci`, `chore` +- **Tester|BA** → `docs`, `test` +- **Leader | Automation** → `revert` \ No newline at end of file diff --git a/Templates/Makefile.md b/Templates/Makefile.md new file mode 100644 index 0000000..c9a9167 --- /dev/null +++ b/Templates/Makefile.md @@ -0,0 +1,65 @@ +``` +Makefile +# --- Gitea & Runner Management --- + +# Định nghĩa các target không phải là file +.PHONY: gitea-up gitea-down gitea-force-up gitea-force-down \ +        gitea-runner-up gitea-runner-down gitea-runner-force-up gitea-runner-force-down + +# Đường dẫn đến file docker-compose.yaml +GITEA_COMPOSE_FILE := ./docker-compose.yaml + +# --- Gitea Management --- +gitea-up: ## Khởi động toàn bộ dịch vụ Gitea (DB, server và runner) +    @echo ">>> Khởi động dịch vụ Gitea..." +    docker-compose -f $(GITEA_COMPOSE_FILE) up -d +    @echo ">>> Đã khởi động dịch vụ Gitea." + +gitea-down: ## Dừng toàn bộ dịch vụ Gitea (DB, server và runner) +    @echo ">>> Dừng dịch vụ Gitea..." +    docker-compose -f $(GITEA_COMPOSE_FILE) down +    @echo ">>> Đã dừng dịch vụ Gitea." + +gitea-force-up: ## Khởi động lại và buộc xây dựng lại các dịch vụ Gitea +    @echo ">>> Force khởi động lại dịch vụ Gitea..." +    docker-compose -f $(GITEA_COMPOSE_FILE) up -d --force-recreate --build +    @echo ">>> Đã force khởi động lại dịch vụ Gitea." + +gitea-force-down: ## Dừng và xóa các container, network và image của Gitea +    @echo ">>> Force dừng và xóa dịch vụ Gitea..." +    docker-compose -f $(GITEA_COMPOSE_FILE) down -v --rmi local +    @echo ">>> Đã force dừng và xóa dịch vụ Gitea." + +# --- Runner Management --- + +gitea-runner-up: ## Chỉ khởi động runner cho Gitea +    @echo ">>> Khởi động Gitea runner..." +    docker-compose -f $(GITEA_COMPOSE_FILE) up -d runner +    @echo ">>> Đã khởi động Gitea runner." + +gitea-runner-down: ## Chỉ dừng runner của Gitea +    @echo ">>> Dừng Gitea runner..." +    docker-compose -f $(GITEA_COMPOSE_FILE) stop runner +    @echo ">>> Đã dừng Gitea runner." + +gitea-runner-force-up: ## Force khởi động lại runner cho Gitea +    @echo ">>> Force khởi động lại Gitea runner..." +    docker-compose up -d --force-recreate --build runner +    @echo ">>> Đã force khởi động lại Gitea runner." + +gitea-runner-force-down: ## Force dừng và xóa runner của Gitea +    @echo ">>> Force dừng và xóa Gitea runner..." +    docker-compose rm -fsv runner +    @echo ">>> Đã force dừng và xóa Gitea runner." + +# --- Help --- + +help: ## Hiển thị hướng dẫn sử dụng các lệnh +    @echo "----------------------------------------" +    @echo "   GITEA & RUNNER MANAGEMENT COMMANDS   " +    @echo "----------------------------------------" +    @echo "Usage: make [target]" +    @echo "" +    @echo "Targets:" +    @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[36m%-20s\033[0m %s\n", $$1, $$2}' +``` \ No newline at end of file diff --git a/Templates/Pipeline Template(Dev).md b/Templates/Pipeline Template(Dev).md new file mode 100644 index 0000000..c9a1f42 --- /dev/null +++ b/Templates/Pipeline Template(Dev).md @@ -0,0 +1,70 @@ +Template cho dev dùng CI +Build - Unit Test - Lint Test - Deploy Local + +``` +for golang: + +name: Go CI for Feature Branch + +on: + push: + branches: + - "feature/**" + +jobs: + build-test: + name: Build & Test + runs-on: ubuntu-latest + + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.21 # Hoặc phiên bản Go bạn dùng + + - name: Install dependencies + run: go mod tidy + + - name: Build + run: go build ./... + + - name: Run unit tests + run: go test -v ./... + + - name: Check formatting + run: go fmt ./... + +``` +``` +for Nodejs +name: Feature Branch CI + +on: + push: + branches: + - 'feature/**' + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint + + - name: Test + run: npm run test + +``` \ No newline at end of file diff --git a/Templates/Pipeline Template(Main).md b/Templates/Pipeline Template(Main).md new file mode 100644 index 0000000..fa8ed93 --- /dev/null +++ b/Templates/Pipeline Template(Main).md @@ -0,0 +1,393 @@ +Build - Test - Security (SCA/SAST) - Staging - Deploy +Example +``` +# File: .gitea/workflows/ci.yml (Phiên bản cải thiện) +name: Go CI Pipeline + +# Step 1: Thêm trigger pull_request +on: + +  push: + +    tags: + +      - 'v*' + +jobs: + +  # ---- Job: Lint Code ---- + +  lint: + +    name: Lint Code + +    runs-on: ubuntu-latest + +    steps: + +      # Step 2: Cập nhật action versions + +      - name: Checkout code + +        uses: actions/checkout@v4 + + + +      # Step 2: Cập nhật action versions + +      - name: Set up Go + +        uses: actions/setup-go@v5 + +        with: + +          go-version: '1.23' # Đặt phiên bản Go của bạn + +          cache-dependency-path: go.sum # Bật cache cho Go modules + + + +      - name: Run golangci-lint + +        uses: golangci/golangci-lint-action@v6 + +        with: + +          version: latest # Hoặc phiên bản cụ thể + +          args: --timeout=5m # Giữ timeout + +          # Gợi ý: Tạo file .golangci.yml trong repo để cấu hình chi tiết, + +          # bao gồm bật các linter bảo mật như 'gosec' để có SAST cơ bản. + +          # cache: true # Cân nhắc bật cache của golangci-lint nếu cần + + + +  # ---- Job: Run Tests ---- + +  test: + +    name: Run Tests + +    runs-on: ubuntu-latest + +    steps: + +      # Step 2: Cập nhật action versions + +      - name: Checkout code + +        uses: actions/checkout@v4 + + + +      # Step 2: Cập nhật action versions + +      - name: Set up Go + +        uses: actions/setup-go@v5 + +        with: + +          go-version: '1.23' + +          cache-dependency-path: go.sum + + + +      # Step 7: Cài đặt tool tạo report JUnit + +      - name: Install go-junit-report + +        run: go install github.com/jstemmer/go-junit-report@latest + + + +      # Step 7: Chạy test, tạo coverage + +      - name: Run Go Test, Coverage + +        run: | + +          # Chạy test với -v để go-junit-report có input, lưu output vào file log + +          go test -v -race -coverprofile=coverage.out ./... | tee test-output.log + +          # Tạo report coverage dạng text (tùy chọn) + +          go tool cover -func=coverage.out + +  # ---- Job: Security Scan (SCA - govulncheck) ---- + +  sca_scan: + +    name: Security Scan (SCA - govulncheck) + +    runs-on: ubuntu-latest + +    steps: + +      # Step 2: Cập nhật action versions + +      - name: Checkout code + +        uses: actions/checkout@v4 + + + +      # Step 2: Cập nhật action versions + +      - name: Set up Go + +        uses: actions/setup-go@v5 + +        with: + +          go-version: '1.23' + +          cache-dependency-path: go.sum + + + +      # Step 5: Thay Trivy bằng govulncheck action + +      - name: Run Go Vulnerability Check (govulncheck) + +        uses: golang/govulncheck-action@v1 + +        # govulncheck sẽ tự động fail job nếu tìm thấy lỗ hổng có thể bị ảnh hưởng + + + +  # ---- Job: Build ---- + +  build: + +    name: Build Application + +    runs-on: ubuntu-latest + +    # Quan trọng: needs phải bao gồm tất cả các job kiểm tra trước đó + +    steps: + +      # Step 2: Cập nhật action versions + +      - name: Checkout code + +        uses: actions/checkout@v4 + + + +      # Step 2: Cập nhật action versions + +      - name: Set up Go + +        uses: actions/setup-go@v5 + +        with: + +          go-version: '1.23' + +          cache-dependency-path: go.sum + + + +      # Step 6: Build với các cờ tối ưu và version info + +      - name: Build Go Application + +        run: | + +          # Lấy thông tin version (ví dụ: tên tag hoặc tên nhánh + SHA ngắn) + +          # Lưu ý: Biến context của Gitea có thể là gitea.* thay vì github.* + +          APP_VERSION="${{ gitea.ref_name }}-${{ format('{0}', gitea.sha) }}" + +          # Thay main.version bằng đường dẫn thực tế đến biến version trong code của bạn + +          go build -v -ldflags="-s -w -X main.version=${APP_VERSION}" -o ./bin/server ./cmd/server + +      # Step 6: Upload artifact binary + +      # Step 2: Cập nhật action versions + +      - name: Upload build artifact + +        uses: actions/upload-artifact@v3 + +        with: + +          name: server-binary # Tên artifact rõ ràng hơn + +          path: ./bin/server # Đường dẫn tới file binary + + + +  docker-build-push: + +    name: Build and Push Docker Image + +    runs-on: ubuntu-latest + +    needs: [build] + +    if: gitea.ref_name == 'master' || startsWith(gitea.ref_name, 'v') + +    steps: + +      - name: Checkout code # Cần checkout để lấy Dockerfile.prod + +        uses: actions/checkout@v4 + + + +      - name: Download build artifact # Tải artifact binary từ job 'build' + +        uses: actions/download-artifact@v3 # Dùng v3 cho Gitea + +        with: + +          name: server-binary # Tên artifact đã upload ở job build + +          path: ./bin # Giải nén vào thư mục ./bin + + + +      - name: Cài Docker CLI + +        run: | + +          apt-get update + +          apt-get install -y docker.io + +          docker version + + + +      - name: Set up Docker Buildx # Công cụ build image nâng cao + +        uses: docker/setup-buildx-action@v3 + + + +      - name: Login to Gitea Container Registry # Đăng nhập vào registry + +        uses: docker/login-action@v3 + +        with: + +          registry: ${{ gitea.server_url }} # Biến context chứa URL Gitea (vd: gitea.tuvanwebsite.com) - Kiểm tra lại biến đúng + +          username: ${{ secrets.REGISTRY_USER }} + +          password: ${{ secrets.REGISTRY_PASSWORD }} + + + +      - name: Build and push Docker image + +        uses: docker/build-push-action@v5 + +        with: + +          context: . # Build context là thư mục gốc + +          file: ./Dockerfile # Chỉ định Dockerfile cho production + +          push: true # Đẩy image lên registry + +          tags: | # Đặt tên và tag cho image + +            ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:${{ gitea.ref_name }} + +            ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:latest + +          # cache-from: type=gha # Bật cache build layer (tùy chọn) + +          # cache-to: type=gha,mode=max + +  # ---- Job: Deploy to VPS ---- + +  deploy: + +    name: Deploy to VPS + +    runs-on: ubuntu-latest + +    if: gitea.ref_name == 'master' || startsWith(gitea.ref_name, 'v') + +    steps: + +      - name: Set image name + +        run: echo "IMAGE_NAME=${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:${{ gitea.ref_name }}" >> $GITEA_ENV + +      - name: Cài Docker CLI + +        run: | + +          apt-get update + +          apt-get install -y docker.io + +          apt-get install -y curl + +          docker version + +      - name: Deploy using Docker commands + +        run: | + +          curl -v https://${{ secrets.REGISTRY_URL }} || echo "Curl failed" + +          echo "Deploying image: ${{ env.IMAGE_NAME }}" + +          # Kéo image mới nhất về VPS host (thông qua runner) + +          docker pull ${{ env.IMAGE_NAME }} + + + +          # Dừng container cũ nếu đang chạy (bỏ qua lỗi nếu chưa có) + +          docker stop my-go-app-container || true + + + +          # Xóa container cũ nếu tồn tại (bỏ qua lỗi nếu chưa có) + +          docker rm my-go-app-container || true + + + +          # Chạy container mới từ image vừa kéo + +          # Quan trọng: Thêm các biến môi trường cần thiết cho ứng dụng (-e) + +          # và đảm bảo nó kết nối đúng network để thấy DB (-network) + +          docker run -d \ + +            --name my-go-app-container \ + +            --network gitea_gitea_network \ + +            --restart always \ + +            -p 8080:8080 \ + +            -e DB_HOST=db \ + +            -e DB_USER=gitea \ + +            -e DB_PASSWORD=gitea \ + +            -e DB_NAME=gitea \ + +            ${{ env.IMAGE_NAME }} # Sử dụng image vừa build/push +``` \ No newline at end of file diff --git a/Templates/Workflow.md b/Templates/Workflow.md new file mode 100644 index 0000000..0be83c6 --- /dev/null +++ b/Templates/Workflow.md @@ -0,0 +1,159 @@ +``` +# File: .gitea/workflows/ci.yml (Phiên bản cải thiện) + +name: Go CI Pipeline +# Step 1: Thêm trigger pull_request +on: +  push: +    tags: +      - 'v*' +jobs: +  # ---- Job: Lint Code ---- +  lint: +    name: Lint Code +    runs-on: ubuntu-latest +    steps: +      - name: Checkout code +        uses: actions/checkout@v4 +      - name: Set up Go +        uses: actions/setup-go@v5 +        with: +          go-version: '1.23' # Đặt phiên bản Go của bạn +          cache-dependency-path: go.sum # Bật cache cho Go modules +      - name: Run golangci-lint +        uses: golangci/golangci-lint-action@v6 +        with: +          version: latest # Hoặc phiên bản cụ thể +          args: --timeout=5m # Giữ timeout +  # ---- Job: Run Tests ---- +  test: +    name: Run Tests +    runs-on: ubuntu-latest +    steps: +      # Step 2: Cập nhật action versions +      - name: Checkout code +        uses: actions/checkout@v4 +      # Step 2: Cập nhật action versions +      - name: Set up Go +        uses: actions/setup-go@v5 +        with: +          go-version: '1.23' +          cache-dependency-path: go.sum + +      # Step 7: Cài đặt tool tạo report JUnit +      - name: Install go-junit-report +        run: go install github.com/jstemmer/go-junit-report@latest + +      # Step 7: Chạy test, tạo coverage +      - name: Run Go Test, Coverage +        run: | +          go test -race -coverprofile=coverage.out ./... | tee test-output.log +  # ---- Job: Security Scan (SCA - govulncheck) ---- + +  sca_scan: +    name: Security Scan (SCA - govulncheck) +    runs-on: ubuntu-latest +    steps: +      - name: Checkout code +        uses: actions/checkout@v4 +      - name: Set up Go +        uses: actions/setup-go@v5 +        with: +          go-version: '1.23' +          cache-dependency-path: go.sum +      - name: Run Go Vulnerability Check (govulncheck) +        uses: golang/govulncheck-action@v1 +  # ---- Job: Build ---- +  build: +    name: Build Application +    runs-on: ubuntu-latest +    needs: [lint,test] +    steps: +      - name: Checkout code +        uses: actions/checkout@v4 +      - name: Set up Go +        uses: actions/setup-go@v5 +        with: +          go-version: '1.23' +          cache-dependency-path: go.sum +      - name: Build Go Application +        run: | +          APP_VERSION="${{ gitea.ref_name }}-${{ format('{0}', gitea.sha) }}" +          go build -v -ldflags="-s -w -X main.version=${APP_VERSION}" -o ./bin/server ./cmd/server +      - name: Upload build artifact +        uses: actions/upload-artifact@v3 +        with: +          name: server-binary # Tên artifact rõ ràng hơn +          path: ./bin/server # Đường dẫn tới file binary +  docker-build-push: +    name: Build and Push Docker Image +    runs-on: ubuntu-latest +    needs: [build] +    if: gitea.ref_name == 'master' || startsWith(gitea.ref_name, 'v') +    steps: +      - name: Checkout code # Cần checkout để lấy Dockerfile.prod +        uses: actions/checkout@v4 +      - name: Download build artifact # Tải artifact binary từ job 'build' +        uses: actions/download-artifact@v3 # Dùng v3 cho Gitea +        with: +          name: server-binary # Tên artifact đã upload ở job build +          path: ./bin # Giải nén vào thư mục ./bin +      - name: Cài Docker CLI +        run: | +          apt-get update +          apt-get install -y docker.io +      - name: Set up Docker Buildx # Công cụ build image nâng cao +        uses: docker/setup-buildx-action@v3 +      - name: Login to Gitea Container Registry # Đăng nhập vào registry +        uses: docker/login-action@v3 +        with: +          registry: ${{ gitea.server_url }} # Biến context chứa URL Gitea (vd: gitea.tuvanwebsite.com) - Kiểm tra lại biến đúng +          username: ${{ secrets.REGISTRY_USER }} +          password: ${{ secrets.REGISTRY_PASSWORD }} +      - name: Build and push Docker image +        uses: docker/build-push-action@v5 +        with: +          context: . # Build context là thư mục gốc +          file: ./Dockerfile # Chỉ định Dockerfile cho production +          push: true # Đẩy image lên registry +          tags: | # Đặt tên và tag cho image +            ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:${{ gitea.ref_name }} +            ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:latest +          # cache-from: type=gha # Bật cache build layer (tùy chọn) +          # cache-to: type=gha,mode=max + +  # ---- Job: Deploy to VPS ---- + +  deploy: +    name: Deploy to VPS +    runs-on: ubuntu-latest +    if: gitea.ref_name == 'master' || startsWith(gitea.ref_name, 'v') +    steps: +      - name: Set image name +        run: echo "IMAGE_NAME=${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}:${{ gitea.ref_name }}" >> $GITEA_ENV +      - name: Cài Docker CLI +        run: | +          apt-get update +          apt-get install -y docker.io +          docker version + +      - name: Deploy using Docker commands +        run: | +          echo "Deploying image: ${{ env.IMAGE_NAME }}" +          # Kéo image mới nhất về VPS host (thông qua runner) +          docker pull ${{ env.IMAGE_NAME }} +          # Dừng container cũ nếu đang chạy (bỏ qua lỗi nếu chưa có) +          docker stop my-go-app-container || true +          # Xóa container cũ nếu tồn tại (bỏ qua lỗi nếu chưa có) +          docker rm my-go-app-container || true +          docker run -d \ +            --name my-go-app-container \ +            --network gitea_gitea_network \ +            --restart always \ +            -p 8080:8080 \ +            -e DB_HOST=db \ +            -e DB_USER=gitea \ +            -e DB_PASSWORD=gitea \ +            -e DB_NAME=gitea \ +            ${{ env.IMAGE_NAME }} # Sử dụng image vừa build/push +``` \ No newline at end of file diff --git a/Tổng quan.md b/Tổng quan.md new file mode 100644 index 0000000..37fff6b --- /dev/null +++ b/Tổng quan.md @@ -0,0 +1,58 @@ +### Tổng quan về dự án + + - Giới thiệu tổng quan về dự án: [Zee] + - Knowledge Base: Knowledge Base Folder + - Tài liệu theo quy trình [[Tài liệu theo Workflow]] + - Tài liệu theo Vai trò [[Tài liệu theo Role]] + - Hướng dẫn cho người mới : Guidelines Folder, Sample Folder + - Mẫu cấu trúc: Template Folder + - Diagram: [[Diagrams CICD]], [[Diagram Image]] + +### Tổng quan về kiến trúc + + - Sử dụng Mô hình DDD (Domain Driven Development) - Customize + - `Resource`: Các Aggregate DDD + - `Transaction`: Các Saga điều phối luồng nghiệp vụ phức tạp + - `Adapter`: Xử lý giao tiếp với các hệ thống bên ngoài + - `Helper`: Các thư viện, tiện ích dùng chung + - `UIUX`: Lớp giao diện người dùng +- Thành phần kiến trúc chi tiết (U-Hierarchy) + - `ubit`: Đơn vị logic nhỏ nhất (hàm, type, hằng số) + - `ubrick`: Tập hợp các `ubit` liên quan + - `ublock`: Thành phần hoạt động độc lập tương đối + - `ubundle`: Tính năng hoàn chỉnh cho người dùng + +### Techstack + + - Frontend: Thiết kế giao diện theo Framework + - Framework: Vue (Nuxtjs), Flutter (Mobile) + - Css Framework: TailwindCss + - Helper Color generation: UL Color Schema + - CMS Framework: ..... + - Database: Postreql, Mongodb, .... +- CI/CD Workflow: + - Git Server: Gitea + - Runner: Gitea Runner + - Workflow Action: Gitea Action + - Server: VPS, Cloud Service(AWS, GCP, Azure) + - Artifact Management: Gitea Packages, Nexus, Docker + - Secret Management: Gitea Secret + - Containerization: Kubernetes, Docker + - Feature Flag: Go Feature Flag, Unleash Selfhosted + - *Logging: Loki + Grafana (Soon)* + - *Monitoring: Grafana(Soon)* + - *Alerting: Telegram(Soon)* + - *Infra as Code: Ansible, OpenTofu (Soon)* +- Backend: + - Ngôn ngữ: Golang, Nodejs + - ORM: https://gorm.io/ + - Web Framework: https://gin-gonic.com/ + - API Document: https://swagger.io/ +### Thư viện ngôn ngữ +- Library Golang [[Thư viện cho Golang]] +- Library Nodejs [[Thư viện cho Nodejs]] +### Thông tin liên hệ & Contact +- Kênh chính: Google Docs +- Kênh Chat: Telegram | Discord +- Lưu trữ dữ liệu: Obsidiant, Google Drive +- Meeting: Discord