Pipeline CI/CD yang berstatus hijau tidak menjamin infrastruktur berfungsi di level runtime. Sering terjadi container gagal binding ke port, konfigurasi IAM role runtime tertinggal, atau target group ALB menandai task sebagai unhealthy. Smoke testing otomatis pasca-deploy menjadi benteng validasi terakhir untuk memastikan resource berada pada state yang diharapkan.
Mengandalkan server MCP (Model Context Protocol) generik buatan komunitas sering memicu flaky test karena respons teks tidak terstruktur, latensi tinggi, dan ketidakmampuan menangani batas laju API AWS. Transisi ke AWS Agent Toolkit resmi memungkinkan inspeksi state cloud secara deterministik melalui call terstruktur, penanganan error native, serta definisi skema yang konsisten.
Akar Masalah Flaky Test: API Throttling dan Parsing Output Longgar
Flaky test pada verifikasi cloud umumnya bersumber dari dua faktor utama:
- API Throttling (Rate Limiting): Menjalankan serangkaian query status seperti
DescribeServices,DescribeTasks, atauGetFunctionConfigurationsecara paralel memicuThrottlingExceptionatauRequestLimitExceededdari AWS control plane. Tanpa mekanisme retry bertingkat, test runner langsung gagal menghasilkan false positive. - Loose Output Parsing: MCP generik sering mengembalikan dump JSON mentah atau teks semi-terstruktur yang diproses LLM/parser tanpa validasi ketat. Perubahan minor pada metadata API merusak parsing, atau sebaliknya meloloskan payload kosong saat service sebenarnya sedang crash loop.
Solusinya adalah membungkus pemanggilan Agent Toolkit dengan kontrak skema statis (menggunakan Zod) dan strategi exponential backoff with jitter untuk menoleransi throttling API AWS.
Konfigurasi IAM Least-Privilege untuk Agent Inspector
Agent verifikator hanya bertugas membaca state. Jangan pernah memberikan izin wildcard (*) atau aksi mutasi. Gunakan policy IAM read-only yang dibatasi hanya pada resource metadata target deployment.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AgentInspectorReadOnly",
"Effect": "Allow",
"Action": [
"ecs:DescribeServices",
"ecs:DescribeTasks",
"lambda:GetFunctionConfiguration",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTargetHealth"
],
"Resource": "*"
}
]
}Batasi Resource ke ARN environment terkait (misalnya cluster staging atau production) jika format ARN resource AWS tersebut mendukung pembatasan level aksi.
Implementasi Runner: Validasi Skema Zod dan Exponential Backoff
Script berikut mengimplementasikan test runner Node.js/TypeScript untuk memverifikasi kesiapan ECS Service pasca-deploy. Runner memanfaatkan validasi schema Zod pada payload respons Agent Toolkit dan menangani retry otomatis.
import { z } from "zod";
// 1. Skema deterministik untuk verifikasi state ECS Service
const ECSServiceStateSchema = z.object({
services: z.array(
z.object({
serviceName: z.string(),
status: z.literal("ACTIVE"),
desiredCount: z.number(),
runningCount: z.number(),
deployments: z.array(
z.object({
status: z.string(),
rolloutState: z.enum(["COMPLETED", "IN_PROGRESS", "FAILED"]),
})
),
})
).min(1, "Service tidak ditemukan"),
});
type ECSServiceState = z.infer<typeof ECSServiceStateSchema>;
// 2. Helper backoff untuk mitigasi ThrottlingException
async function withRetry<T>(
fn: () => Promise<T>,
retries = 5,
baseDelayMs = 1000
): Promise<T> {
try {
return await fn();
} catch (error: any) {
if (retries <= 0) throw error;
const isThrottled = error.name === "ThrottlingException" || error.$metadata?.httpStatusCode === 429;
const delay = baseDelayMs * Math.pow(2, 5 - retries) + Math.random() * 200;
if (isThrottled) {
console.warn(`Throttled oleh AWS API. Retry dalam ${Math.round(delay)}ms...`);
}
await new Promise((resolve) => setTimeout(resolve, delay));
return withRetry(fn, retries - 1, baseDelayMs);
}
}
// 3. Eksekusi verifikasi state via Agent Toolkit Wrapper
export async function verifyDeployment(toolkitClient: any, cluster: string, service: string) {
const rawOutput = await withRetry(async () => {
return await toolkitClient.execute({
tool: "aws_ecs_describe_services",
parameters: { cluster, services: [service] },
});
});
// Parsing ketat: Gagal langsung jika skema tidak sesuai (eliminasi false positive)
const parsed = ECSServiceStateSchema.safeParse(rawOutput);
if (!parsed.success) {
throw new Error(`Skema state AWS tidak valid: ${JSON.stringify(parsed.error.issues)}`);
}
const targetService = parsed.data.services[0];
const primaryDeployment = targetService.deployments[0];
if (targetService.runningCount < targetService.desiredCount) {
throw new Error(
`Deployment belum sehat: runningCount (${targetService.runningCount}) < desiredCount (${targetService.desiredCount})`
);
}
if (primaryDeployment.rolloutState !== "COMPLETED") {
throw new Error(`Rollout ECS belum selesai. State saat ini: ${primaryDeployment.rolloutState}`);
}
return true;
}Pola Contract Testing di CI Tanpa Live Credentials
Menjalankan live AWS credentials di setiap runner CI memunculkan risiko keamanan credential leakage dan flakiness jaringan eksternal. Gunakan contract testing untuk memverifikasi logika runner terhadap mock payload Agent Toolkit.
import { describe, it, expect, vi } from "vitest";
import { verifyDeployment } from "./smoke-runner";
describe("Contract Test: ECS Verification Runner", () => {
it("harus lolos jika state service ACTIVE dan rollout COMPLETED", async () => {
const mockToolkit = {
execute: vi.fn().mockResolvedValue({
services: [
{
serviceName: "order-service-api",
status: "ACTIVE",
desiredCount: 2,
runningCount: 2,
deployments: [{ status: "PRIMARY", rolloutState: "COMPLETED" }],
},
],
}),
};
const result = await verifyDeployment(mockToolkit, "prod-cluster", "order-service-api");
expect(result).toBe(true);
});
it("harus melempar error saat tool response melanggar skema kontrak", async () => {
const mockToolkit = {
execute: vi.fn().mockResolvedValue({
// Response korup / format tidak sesuai spek AWS toolkit
invalidKey: [],
}),
};
await expect(
verifyDeployment(mockToolkit, "prod-cluster", "order-service-api")
).rejects.toThrow(/Skema state AWS tidak valid/);
});
});Mitigasi Eventual Consistency dan Trade-Off
Infrastruktur AWS bersifat eventually consistent. Saat CloudFormation atau Terraform menandai deployment sukses, routing table atau task status pada target group mungkin butuh 15-45 detik sebelum sepenuhnya stabil.
- Interval Polling: Terapkan polling berkala (misal: 10 detik sekali dengan timeout total 3 menit) alih-alih mengeksekusi smoke test tepat satu detik setelah pipeline deploy selesai.
- Trade-Off Eksekusi Agent: Menggunakan agent berbasis model reasoning penuh menambah latensi dan biaya token. Untuk smoke test deterministik pasca-deploy, gunakan pola Tool Call First: definisikan alur pemanggilan tool AWS secara programatis di runner code, dan batasi peran AI hanya untuk menganalisis payload log jika verifikasi menemukan anomali.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!