source: Add rules for AI Coding
This commit is contained in:
126
base/.agent/skills/custom-skills/CI-CD/GenerateGitHubActions.md
Normal file
126
base/.agent/skills/custom-skills/CI-CD/GenerateGitHubActions.md
Normal file
@@ -0,0 +1,126 @@
|
||||
---
|
||||
name: GenerateGitHubActions
|
||||
description: Hướng dẫn tạo CI/CD pipeline tự động hóa Build, Test, Docker Build & Deploy bằng GitHub Actions.
|
||||
---
|
||||
|
||||
# GenerateGitHubActions Skill
|
||||
|
||||
Khi user yêu cầu tạo CI/CD Pipelines (ví dụ: GitHub Actions, hoặc tương đương cho GitLab CI / Azure DevOps), bạn cần sinh ra file luồng tự động hóa theo các bước chuẩn sau đây.
|
||||
|
||||
## Mục đích
|
||||
- Tự động hóa quá trình kiểm tra mã nguồn (CI) và triển khai (CD).
|
||||
- Đảm bảo code push lên nhánh `main` luôn hoạt động đúng đắn và sẵn sàng lên production.
|
||||
|
||||
## Hướng dẫn sinh cấu hình (GitHub Actions)
|
||||
|
||||
Tạo file luồng công việc Workflow cho GitHub Actions.
|
||||
|
||||
### 1. Đường dẫn và tên file
|
||||
- **Đường dẫn**: `.github/workflows/ci-cd.yml`
|
||||
- (Hoặc theo định dạng của platform tương ứng: `.gitlab-ci.yml` cho GitLab, `azure-pipelines.yml` cho Azure DevOps).
|
||||
|
||||
### 2. Các bước cấu hình bắt buộc trong file YAML
|
||||
|
||||
Workflow cần trải qua các luồng chính sau (mẫu dưới dây cho GitHub Actions):
|
||||
|
||||
#### Phân đoạn 1: Build & Test (CI)
|
||||
- **Triggers**: Lắng nghe sự kiện `push` hoặc `pull_request` vào nhánh `main`.
|
||||
- **Setup môi trường**:
|
||||
- Checkout mã nguồn (ví dụ dùng `actions/checkout@v4`).
|
||||
- Cài đặt .NET SDK tương ứng với dự án (ví dụ `actions/setup-dotnet@v4` cho .NET 8.0). **Lưu ý: Bật tính năng cache Nuget để tăng tốc độ build.**
|
||||
- **Run Tests**:
|
||||
- Chạy khối lệnh `dotnet restore`, `dotnet build --no-restore`.
|
||||
- Quan trọng nhất: Chạy `dotnet test --no-build --verbosity normal`. (Chỉ khi Test Xanh (Passed) thì các bước sau mới được chạy tiếp).
|
||||
|
||||
#### Phân đoạn 2: Docker Build & Push (Bắt đầu CD)
|
||||
- **Cần điều kiện**: Chỉ chạy khi Job Build & Test thành công (`needs: build`).
|
||||
- **Đăng nhập Container Registry**:
|
||||
- Login vào Docker Hub hoặc Azure Container Registry (ACR) sử dụng System Secrets (ví dụ `DOCKER_USERNAME` và `DOCKER_PASSWORD`).
|
||||
- **Build & Push Image**:
|
||||
- Build Image từ Dockerfile (chú ý chỉ đường dẫn thư mục gốc nơi chứa dự án chính để `docker build` có thể truy cập qua các tầng thư mục Clean Architecture).
|
||||
- Gắn tag cho Image (ví dụ: `latest` hoặc theo Commit SHA/phiên bản).
|
||||
- Push Image lên Registry.
|
||||
|
||||
#### Phân đoạn 3: Deploy to Server (CD - Webhook / SSH)
|
||||
- Dùng thư viện `appleboy/ssh-action` (hoặc tương tự) để SSH vào Server đích.
|
||||
- Yêu cầu server pull file Image mới nhất từ Registry.
|
||||
- **Quan trọng:** Ưu tiên sử dụng `docker compose` để deploy (pull và up) nếu cấu trúc dự án của user có file `docker-compose.yml`, giúp khởi động lại toàn bộ stack (API, DB, Redis...) thay vì chỉ chạy `docker run` độc lập.
|
||||
|
||||
## Mẫu File Mặc Định (`ci-cd.yml`)
|
||||
|
||||
Dưới đây là khung mẫu bạn cần căn cứ để thiết kế khi sinh file cho user:
|
||||
|
||||
```yaml
|
||||
name: CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
cache: true # Bật cache Nuget, lần sau build nhanh gấp đôi
|
||||
cache-dependency-path: '**/packages.lock.json'
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet build --no-restore
|
||||
|
||||
- name: Test
|
||||
run: dotnet test --no-build --verbosity normal
|
||||
|
||||
docker-build-push:
|
||||
needs: build-and-test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ secrets.DOCKER_USERNAME }}/chi-tiet-ten-project-lowercase:latest
|
||||
|
||||
deploy:
|
||||
needs: docker-build-push
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
|
||||
steps:
|
||||
- name: Deploy via SSH
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.SERVER_HOST }}
|
||||
username: ${{ secrets.SERVER_USER }}
|
||||
key: ${{ secrets.SERVER_SSH_KEY }}
|
||||
script: |
|
||||
cd /path/to/your/project/on/server # Trỏ tới thư mục chứa docker-compose.yml
|
||||
docker compose pull # Kéo image mới nhất về (dựa theo file compose)
|
||||
docker compose up -d --build # Khởi động lại các service có sự thay đổi
|
||||
```
|
||||
|
||||
## Lưu ý cho AI Agent
|
||||
- Khi User yêu cầu sinh pipeline, hãy yêu cầu User xác nhận về tên tài khoản Docker Hub, Server Credentials và nhắc họ cấu hình đầy đủ `Secrets` trên GitHub sau khi sinh file.
|
||||
- **Hãy tự động thay thế chuỗi tên project (`chi-tiet-ten-project-lowercase` trong mẫu) bằng tên thật của Project / Repository mà User đang thao tác. Chuyển tất cả về chữ thường (lowercase) khi đặt tên Docker Image để tránh lỗi định dạng của Docker.**
|
||||
- **Nếu user có dùng `docker-compose`, hãy ưu tiên sinh lệnh `docker compose up -d` thay vì `docker run` thuần.**
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: GenerateCQRSFeature
|
||||
description: Hướng dẫn tạo một feature theo chuẩn CQRS sử dụng MediatR (bao gồm Entity, Command/Query, Handler, và Controller).
|
||||
---
|
||||
|
||||
# GenerateCQRSFeature Skill
|
||||
|
||||
Khi user yêu cầu tạo một feature theo luồng **CQRS** với đầu vào bao gồm **Tên Feature** (VD: `Order`) và **Action** (VD: `Create`), bạn **BẮT BUỘC** phải thực hiện các bước sau để sinh ra code và file tương ứng:
|
||||
|
||||
## 1. Đầu ra thư mục và file (Outputs)
|
||||
|
||||
Dựa trên {FeatureName} và {Action}, hãy tạo các file sau (nếu action thuộc loại Read/Get thì đổi 'Commands' thành 'Queries'):
|
||||
|
||||
1. **Domain Entity**
|
||||
- **Đường dẫn**: `Domain/Entities/{FeatureName}.cs`
|
||||
- **Nội dung**: Lớp Entity cơ bản định nghĩa các thuộc tính.
|
||||
|
||||
2. **Command / Query**
|
||||
- **Đường dẫn**: `Application/Features/{FeatureName}s/Commands/{Action}{FeatureName}/{Action}{FeatureName}Command.cs`
|
||||
- **Nội dung**: Input model kế thừa từ `IRequest<TResponse>` của MediatR.
|
||||
|
||||
3. **Command / Query Handler**
|
||||
- **Đường dẫn**: `Application/Features/{FeatureName}s/Commands/{Action}{FeatureName}/{Action}{FeatureName}CommandHandler.cs`
|
||||
- **Nội dung**: Xử lý logic nghiệp vụ, implements `IRequestHandler<{Action}{FeatureName}Command, TResponse>`. Inject Repository hoặc service cần thiết vào đây.
|
||||
|
||||
4. **WebAPI Controller**
|
||||
- **Đường dẫn**: `WebAPI/Controllers/{FeatureName}sController.cs` (Lưu ý thêm số nhiều cho tên Controller nếu cần thiết).
|
||||
- **Nội dung**: REST API endpoints. **Yêu cầu:** Nhận DI `IMediator` qua constructor để điều hướng Request (ví dụ gọi `await _mediator.Send(command)`).
|
||||
|
||||
## 2. Cấu hình Dependency Injection (KHÔNG CẦN LÀM)
|
||||
|
||||
⚠️ **Lưu ý:** Như nguyên tắc thiết lập project, luồng CQRS **KHÔNG CẦN** update file cấu hình Dependency Injection (DI configuration).
|
||||
|
||||
Thư viện MediatR đã tự động quét (Auto-register) tất cả các lớp Handler kế thừa từ `IRequestHandler`, vì thế bạn **TUYỆT ĐỐI BỎ QUA** việc cập nhật các file config DI cho phần Handler này.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: GenerateNTierFeature
|
||||
description: Hướng dẫn tạo một feature theo chuẩn N-Tier (bao gồm Entity, Interface, Service, Controller và cấu hình Dependency Injection).
|
||||
---
|
||||
|
||||
# GenerateNTierFeature Skill
|
||||
|
||||
Khi user yêu cầu tạo một feature theo luồng **N-Tier** với đầu vào là **Tên Feature** (VD: `Category`), bạn **BẮT BUỘC** phải thực hiện các bước sau để sinh ra code và file tương ứng:
|
||||
|
||||
## 1. Đầu ra thư mục và file (Outputs)
|
||||
|
||||
Hãy tạo các file sau với nội dung phù hợp cho {FeatureName}:
|
||||
|
||||
1. **Domain Entity**
|
||||
- **Đường dẫn**: `Domain/Entities/{FeatureName}.cs`
|
||||
- **Nội dung**: Lớp Entity cơ bản định nghĩa các thuộc tính.
|
||||
|
||||
2. **Service Interface**
|
||||
- **Đường dẫn**: `Application/Interfaces/I{FeatureName}Service.cs`
|
||||
- **Nội dung**: Các interface định nghĩa hợp đồng hàm cho {FeatureName}.
|
||||
|
||||
3. **Service Implementation**
|
||||
- **Đường dẫn**: `Application/Services/{FeatureName}Service.cs`
|
||||
- **Nội dung**: Lớp kế thừa từ `I{FeatureName}Service`. **Yêu cầu:** Nhận Dependency Injection (DI) thông qua constructor (ví dụ: `IRepository<{FeatureName}>`).
|
||||
|
||||
4. **WebAPI Controller**
|
||||
- **Đường dẫn**: `WebAPI/Controllers/{FeatureName}sController.cs` (Lưu ý thêm số nhiều cho tên Controller).
|
||||
- **Nội dung**: Lớp Controller. **Yêu cầu:** Phải nhận DI `I{FeatureName}Service` thông qua constructor và định nghĩa các endpoint tương ứng.
|
||||
|
||||
## 2. Cấu hình Dependency Injection (BƯỚC BẮT BUỘC THỰC HIỆN)
|
||||
|
||||
⚠️ **Quan trọng:** Không giống như CQRS với MediatR ở trên, luồng N-Tier **đòi hỏi** bạn phải chèn thủ công service mới tạo vào Container IoC.
|
||||
|
||||
Bạn **BẮT BUỘC** phải sử dụng tool để mở file cấu hình DI của project (có thể là `DependencyInjection.cs` hoặc `ServiceCollectionExtensions.cs` tùy cấu trúc thư mục) và chèn đoạn mã sau vào hàm cấu hình service liên quan:
|
||||
|
||||
```csharp
|
||||
services.AddScoped<I{FeatureName}Service, {FeatureName}Service>();
|
||||
```
|
||||
|
||||
Hãy đảm bảo bạn dùng công cụ sửa file chính xác (`replace_file_content` hoặc `multi_replace_file_content`) để không làm hỏng cú pháp của file DI.
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: GenerateArchitectureTest
|
||||
description: Hướng dẫn tạo Architecture Test sử dụng NetArchTest.Rules để bảo vệ kiến trúc Clean Architecture.
|
||||
---
|
||||
|
||||
# GenerateArchitectureTest Skill
|
||||
|
||||
Khi user yêu cầu kiểm tra hoặc khởi tạo **Architecture Test**, bạn cần sử dụng thư viện `NetArchTest.Rules` để sinh luận kiểm điểm nhằm bảo vệ chặt chẽ cấu trúc "Clean Architecture" của dự án.
|
||||
|
||||
## Mục đích
|
||||
- Ngăn chặn Dev code ẩu, import sai library/module giữa các tầng (layer).
|
||||
- Nếu vi phạm (VD: import Entity Framework vào tầng Domain), bài test này sẽ báo ĐỎ ngay lập tức lúc build code. Bằng chứng thép giúp kiến trúc được bảo vệ tuyệt đối!
|
||||
|
||||
## Hướng dẫn viết Test Rules
|
||||
|
||||
Bạn cần viết các test method (dùng `[Fact]` với xUnit hoặc NUnit) sử dụng Fluent API của `NetArchTest.Rules`. Dưới đây là các luật phổ biến bắt buộc:
|
||||
|
||||
1. **Domain Layer Rules (Luật tầng Domain):**
|
||||
- Domain không được phụ thuộc vào bất cứ thứ gì từ Infrastructure, Application hay WebAPI.
|
||||
```csharp
|
||||
[Fact]
|
||||
public void DomainLayer_ShouldNot_HaveDependencyOn_OtherLayers()
|
||||
{
|
||||
var result = Types.InAssembly(DomainAssembly)
|
||||
.ShouldNot()
|
||||
.HaveDependencyOnAny(
|
||||
"MyNewProjectName.Application",
|
||||
"MyNewProjectName.Infrastructure",
|
||||
"MyNewProjectName.WebAPI"
|
||||
)
|
||||
.GetResult();
|
||||
|
||||
Assert.True(result.IsSuccessful);
|
||||
}
|
||||
```
|
||||
|
||||
2. **Application Layer Rules (Luật tầng Application):**
|
||||
- Application Layer chỉ được phép giao tiếp với Domain, KHÔNG ĐƯỢC có dependency vào `Infrastructure` hoặc `WebAPI`.
|
||||
|
||||
3. **Controller Rules (Luật đặt tên/vị trí API):**
|
||||
- Controller bắt buộc phải kế thừa class BaseAPIController, và có hậu tố là "Controller".
|
||||
- Không được phép truy vấn Database trực tiếp từ Controller (ngăn không cho Inject `DbContext` hay `IRepository` vào Controller, kiểm duyệt dependencies của Constructor).
|
||||
|
||||
4. **Handler Rules (CQRS):**
|
||||
- Các Handler xử lý logic phải implements interface `IRequestHandler` và kết thúc bằng `CommandHandler` hoặc `QueryHandler`. Nó chỉ nằm ở Application Layer.
|
||||
|
||||
## Định dạng file đầu ra
|
||||
- **Đường dẫn:** Chứa trong test project như `tests/MyNewProjectName.ArchitectureTests/`.
|
||||
- **Tên file:** Thường đặt tên theo phạm vi test như `LayerTests.cs`, `DesignConventionTests.cs`, `NamingRulesTests.cs`, v.v.
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: GenerateIntegrationTest
|
||||
description: Hướng dẫn tạo Integration Test (người thật việc thật) sử dụng WebApplicationFactory và Testcontainers.
|
||||
---
|
||||
|
||||
# GenerateIntegrationTest Skill
|
||||
|
||||
Khi user yêu cầu tạo **Integration Test** để kiểm tra API endpoint từ đầu đến cuối, bạn cần sinh ra code theo hướng dẫn sau:
|
||||
|
||||
## Mục đích
|
||||
- Test xem các mảnh ghép lắp vào ghép với nhau có chạy đúng không.
|
||||
- Flow: Client gọi API -> Middleware -> Controller -> CQRS Handler/Service -> Ghi/Đọc Database thật.
|
||||
|
||||
## Hướng dẫn thực hiện
|
||||
1. **Setup WebApplicationFactory:**
|
||||
- Tự động setup `WebApplicationFactory<Program>` (tạo một test server ngay trong RAM của .NET).
|
||||
- Override cấu hình ứng dụng nếu cần thiết (ví dụ thay đổi ConnectionString trỏ sang test container).
|
||||
|
||||
2. **Setup Testcontainers (Real Database):**
|
||||
- Sử dụng thư viện `Testcontainers` (hoặc cấu hình tương tự) để tự động spin up một Docker container chứa Database thật (ví dụ: PostgreSQL, SQL Server).
|
||||
- Đảm bảo database container này được start trước khi chạy test và tự động xóa (dispose) sau khi test xong. Tránh dùng SQLite in-memory vì hay bị lỗi vặt và không tương đương với database production.
|
||||
|
||||
3. **Viết kịch bản Test gọi API (Arrange - Act - Assert):**
|
||||
- Tạo đối tượng `HttpClient` từ `WebApplicationFactory.CreateClient()`.
|
||||
- **Arrange:** Chuẩn bị payload data dạng JSON objects hoặc tạo trước data base records nếu là API GET/PUT/DELETE.
|
||||
- **Act:** Gọi thẳng vào API endpoint tương ứng bằng code. VD: `await client.PostAsJsonAsync("/api/v1/samples", payload);`.
|
||||
- **Assert:** Kiểm tra kết quả trả về:
|
||||
- Check HTTP Status: có phải `200 OK` hay `400 Bad Request` không.
|
||||
- Deserialize response body để check chính xác object.
|
||||
- (Tùy chọn) Query thẳng vào database container xem bản ghi đã được sinh ra/cập nhật thật chưa.
|
||||
|
||||
## Định dạng file đầu ra
|
||||
- **Đường dẫn:** Chứa trong project test tương ứng như `tests/MyNewProjectName.IntegrationTests/Controllers/...`.
|
||||
- **Tên file:** `[ControllerName]Tests.cs` (ví dụ: `OrdersControllerTests.cs`).
|
||||
32
base/.agent/skills/custom-skills/GenerateTest/UnitTest.md
Normal file
32
base/.agent/skills/custom-skills/GenerateTest/UnitTest.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: GenerateUnitTest
|
||||
description: Hướng dẫn tạo Unit Test cô lập (tốc độ cao) sử dụng Mocking (Moq hoặc NSubstitute).
|
||||
---
|
||||
|
||||
# GenerateUnitTest Skill
|
||||
|
||||
Khi user yêu cầu tạo **Unit Test** cho một class/method, bạn cần tuân thủ các nguyên tắc sau để sinh ra code test:
|
||||
|
||||
## Mục đích
|
||||
- Chỉ test duy nhất 1 class/method.
|
||||
- Bỏ qua hoàn toàn Database thật, Redis hay HTTP.
|
||||
- Tốc độ chạy cực nhanh.
|
||||
|
||||
## 1. Với CQRS Handlers hoặc Services
|
||||
- **Nhận diện Dependencies:** Tự động nhận diện các Interface (ví dụ: `IRepository`, `IUnitOfWork`, `ILogger`, `IMediator`) được inject vào constructor.
|
||||
- **Tạo Mock Object:** Sử dụng thư viện Mocking (như `Moq` hoặc `NSubstitute`) để tạo instance giả của các Interface này.
|
||||
- **Kịch bản Test (Arrange - Act - Assert):**
|
||||
- **Arrange:** Cấp data giả (Mock data) cho các hàm của Interface.
|
||||
- **Act:** Gọi hàm thực thi (ví dụ `Handle()` của CQRS hoặc các method của Service).
|
||||
- **Assert:** Kiểm tra kết quả trả về, HOẶC verify xem một method của Mock object có được gọi đúng số lần không (ví dụ kiểm tra xem `_repository.AddAsync()` có được gọi không), HOẶC kiểm tra xem nó có ném ra `ValidationException` khi input sai không.
|
||||
|
||||
## 2. Với Domain Entities
|
||||
- **Mục tiêu:** Kiểm tra các logic kinh doanh, tính toán nội bộ của Entity.
|
||||
- **Kịch bản:**
|
||||
- Khởi tạo Entity với các trạng thái cụ thể.
|
||||
- Gọi method thay đổi trạng thái hoặc tính toán (ví dụ: `Order.CalculateTotal()`).
|
||||
- Kiểm tra xem giá trị biến đổi có đúng với quy tắc nghiệp vụ không (ví dụ: `Total` phải bằng `Price * Quantity`).
|
||||
|
||||
## Định dạng file đầu ra
|
||||
- **Đường dẫn:** Đặt trong project `tests/MyNewProjectName.UnitTests/...` (tương ứng với thư mục gốc của class bị test).
|
||||
- **Tên file:** `[ClassName]Tests.cs` (ví dụ: `CreateOrderCommandHandlerTests.cs`).
|
||||
Reference in New Issue
Block a user