omgkit 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugin/skills/databases/mongodb/SKILL.md +81 -28
- package/plugin/skills/databases/prisma/SKILL.md +87 -32
- package/plugin/skills/databases/redis/SKILL.md +80 -27
- package/plugin/skills/devops/aws/SKILL.md +80 -26
- package/plugin/skills/devops/github-actions/SKILL.md +84 -32
- package/plugin/skills/devops/kubernetes/SKILL.md +94 -32
- package/plugin/skills/devops/performance-profiling/SKILL.md +59 -863
- package/plugin/skills/frameworks/django/SKILL.md +158 -24
- package/plugin/skills/frameworks/express/SKILL.md +153 -33
- package/plugin/skills/frameworks/fastapi/SKILL.md +153 -34
- package/plugin/skills/frameworks/laravel/SKILL.md +146 -33
- package/plugin/skills/frameworks/nestjs/SKILL.md +137 -25
- package/plugin/skills/frameworks/rails/SKILL.md +594 -28
- package/plugin/skills/frameworks/react/SKILL.md +94 -962
- package/plugin/skills/frameworks/spring/SKILL.md +528 -35
- package/plugin/skills/frameworks/vue/SKILL.md +147 -25
- package/plugin/skills/frontend/accessibility/SKILL.md +145 -36
- package/plugin/skills/frontend/frontend-design/SKILL.md +114 -29
- package/plugin/skills/frontend/responsive/SKILL.md +131 -28
- package/plugin/skills/frontend/shadcn-ui/SKILL.md +133 -43
- package/plugin/skills/frontend/tailwindcss/SKILL.md +105 -37
- package/plugin/skills/frontend/threejs/SKILL.md +110 -35
- package/plugin/skills/languages/javascript/SKILL.md +195 -34
- package/plugin/skills/methodology/brainstorming/SKILL.md +98 -30
- package/plugin/skills/methodology/defense-in-depth/SKILL.md +83 -37
- package/plugin/skills/methodology/dispatching-parallel-agents/SKILL.md +92 -31
- package/plugin/skills/methodology/executing-plans/SKILL.md +117 -28
- package/plugin/skills/methodology/finishing-development-branch/SKILL.md +111 -32
- package/plugin/skills/methodology/problem-solving/SKILL.md +65 -311
- package/plugin/skills/methodology/receiving-code-review/SKILL.md +76 -27
- package/plugin/skills/methodology/requesting-code-review/SKILL.md +93 -22
- package/plugin/skills/methodology/root-cause-tracing/SKILL.md +75 -40
- package/plugin/skills/methodology/sequential-thinking/SKILL.md +75 -224
- package/plugin/skills/methodology/systematic-debugging/SKILL.md +81 -35
- package/plugin/skills/methodology/test-driven-development/SKILL.md +120 -26
- package/plugin/skills/methodology/testing-anti-patterns/SKILL.md +88 -35
- package/plugin/skills/methodology/token-optimization/SKILL.md +73 -34
- package/plugin/skills/methodology/verification-before-completion/SKILL.md +128 -28
- package/plugin/skills/methodology/writing-plans/SKILL.md +105 -20
- package/plugin/skills/omega/omega-architecture/SKILL.md +178 -40
- package/plugin/skills/omega/omega-coding/SKILL.md +247 -41
- package/plugin/skills/omega/omega-sprint/SKILL.md +208 -46
- package/plugin/skills/omega/omega-testing/SKILL.md +253 -42
- package/plugin/skills/omega/omega-thinking/SKILL.md +263 -51
- package/plugin/skills/security/better-auth/SKILL.md +83 -34
- package/plugin/skills/security/oauth/SKILL.md +118 -35
- package/plugin/skills/security/owasp/SKILL.md +112 -35
- package/plugin/skills/testing/playwright/SKILL.md +141 -38
- package/plugin/skills/testing/pytest/SKILL.md +137 -38
- package/plugin/skills/testing/vitest/SKILL.md +124 -39
- package/plugin/skills/tools/document-processing/SKILL.md +111 -838
- package/plugin/skills/tools/image-processing/SKILL.md +126 -659
- package/plugin/skills/tools/mcp-development/SKILL.md +85 -758
- package/plugin/skills/tools/media-processing/SKILL.md +118 -735
- package/plugin/stdrules/SKILL_STANDARDS.md +490 -0
package/package.json
CHANGED
|
@@ -1,43 +1,96 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: MongoDB database. Use
|
|
2
|
+
name: Developing with MongoDB
|
|
3
|
+
description: The agent implements MongoDB NoSQL database solutions with document modeling, aggregation pipelines, and Mongoose ODM. Use when building document-based applications, designing schemas, writing aggregations, or implementing NoSQL patterns.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# MongoDB
|
|
6
|
+
# Developing with MongoDB
|
|
7
7
|
|
|
8
|
-
##
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
// Schema with Mongoose
|
|
12
|
+
import mongoose, { Schema, Document } from 'mongoose';
|
|
13
|
+
|
|
14
|
+
interface IUser extends Document {
|
|
15
|
+
email: string;
|
|
16
|
+
profile: { firstName: string; lastName: string };
|
|
17
|
+
createdAt: Date;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const userSchema = new Schema<IUser>({
|
|
21
|
+
email: { type: String, required: true, unique: true, lowercase: true },
|
|
13
22
|
profile: {
|
|
14
|
-
|
|
15
|
-
|
|
23
|
+
firstName: { type: String, required: true },
|
|
24
|
+
lastName: { type: String, required: true },
|
|
16
25
|
},
|
|
17
|
-
|
|
26
|
+
}, { timestamps: true });
|
|
27
|
+
|
|
28
|
+
userSchema.index({ email: 1 });
|
|
29
|
+
export const User = mongoose.model<IUser>('User', userSchema);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
| Feature | Description | Guide |
|
|
35
|
+
|---------|-------------|-------|
|
|
36
|
+
| Document Schema | Type-safe schema design with Mongoose | Embed related data, use references for large collections |
|
|
37
|
+
| CRUD Operations | Create, read, update, delete with type safety | Use `findById`, `findOne`, `updateOne`, `deleteOne` |
|
|
38
|
+
| Aggregation Pipelines | Complex data transformations and analytics | Chain `$match`, `$group`, `$lookup`, `$project` stages |
|
|
39
|
+
| Indexing | Query optimization with proper indexes | Create compound indexes matching query patterns |
|
|
40
|
+
| Transactions | Multi-document ACID operations | Use sessions for operations requiring atomicity |
|
|
41
|
+
| Change Streams | Real-time data change notifications | Watch collections for inserts, updates, deletes |
|
|
42
|
+
|
|
43
|
+
## Common Patterns
|
|
44
|
+
|
|
45
|
+
### Repository Pattern with Pagination
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
async findPaginated(filter: FilterQuery<IUser>, page = 1, limit = 20) {
|
|
49
|
+
const [data, total] = await Promise.all([
|
|
50
|
+
User.find(filter).sort({ createdAt: -1 }).skip((page - 1) * limit).limit(limit),
|
|
51
|
+
User.countDocuments(filter),
|
|
52
|
+
]);
|
|
53
|
+
return { data, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } };
|
|
18
54
|
}
|
|
19
55
|
```
|
|
20
56
|
|
|
21
|
-
|
|
22
|
-
```javascript
|
|
23
|
-
// Find
|
|
24
|
-
db.users.find({ email: /example.com/ });
|
|
57
|
+
### Aggregation Pipeline
|
|
25
58
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{ $match: {
|
|
29
|
-
{ $group: { _id:
|
|
59
|
+
```typescript
|
|
60
|
+
const stats = await Order.aggregate([
|
|
61
|
+
{ $match: { status: 'completed', createdAt: { $gte: startDate } } },
|
|
62
|
+
{ $group: { _id: '$userId', total: { $sum: '$amount' }, count: { $sum: 1 } } },
|
|
63
|
+
{ $sort: { total: -1 } },
|
|
64
|
+
{ $limit: 10 },
|
|
30
65
|
]);
|
|
66
|
+
```
|
|
31
67
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
68
|
+
### Transaction for Order Creation
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const session = await mongoose.startSession();
|
|
72
|
+
try {
|
|
73
|
+
session.startTransaction();
|
|
74
|
+
await Product.updateOne({ _id: productId }, { $inc: { stock: -quantity } }, { session });
|
|
75
|
+
const order = await Order.create([{ userId, items, total }], { session });
|
|
76
|
+
await session.commitTransaction();
|
|
77
|
+
return order[0];
|
|
78
|
+
} catch (error) {
|
|
79
|
+
await session.abortTransaction();
|
|
80
|
+
throw error;
|
|
81
|
+
} finally {
|
|
82
|
+
session.endSession();
|
|
83
|
+
}
|
|
37
84
|
```
|
|
38
85
|
|
|
39
86
|
## Best Practices
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
87
|
+
|
|
88
|
+
| Do | Avoid |
|
|
89
|
+
|----|-------|
|
|
90
|
+
| Design schemas based on query patterns | Embedding large arrays in documents |
|
|
91
|
+
| Create indexes for frequently queried fields | Using `$where` or mapReduce in production |
|
|
92
|
+
| Use `lean()` for read-only queries | Skipping validation on writes |
|
|
93
|
+
| Implement pagination for large datasets | Storing large files directly (use GridFS) |
|
|
94
|
+
| Set connection pool size appropriately | Hardcoding connection strings |
|
|
95
|
+
| Use transactions for multi-document ops | Ignoring index usage in explain plans |
|
|
96
|
+
| Add TTL indexes for expiring data | Creating too many indexes (write overhead) |
|
|
@@ -1,55 +1,110 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Prisma ORM
|
|
2
|
+
name: Developing with Prisma
|
|
3
|
+
description: The agent implements Prisma ORM for type-safe database access with schema design, migrations, and queries. Use when building database layers, designing relational schemas, implementing type-safe queries, or managing database migrations.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Prisma
|
|
6
|
+
# Developing with Prisma
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
7
9
|
|
|
8
|
-
## Schema
|
|
9
10
|
```prisma
|
|
11
|
+
// prisma/schema.prisma
|
|
12
|
+
generator client {
|
|
13
|
+
provider = "prisma-client-js"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
datasource db {
|
|
17
|
+
provider = "postgresql"
|
|
18
|
+
url = env("DATABASE_URL")
|
|
19
|
+
}
|
|
20
|
+
|
|
10
21
|
model User {
|
|
11
22
|
id String @id @default(cuid())
|
|
12
23
|
email String @unique
|
|
13
24
|
posts Post[]
|
|
14
25
|
createdAt DateTime @default(now())
|
|
26
|
+
@@index([email])
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
model Post {
|
|
18
30
|
id String @id @default(cuid())
|
|
19
31
|
title String
|
|
20
|
-
author User @relation(fields: [authorId], references: [id])
|
|
21
32
|
authorId String
|
|
33
|
+
author User @relation(fields: [authorId], references: [id])
|
|
22
34
|
}
|
|
23
35
|
```
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
```bash
|
|
38
|
+
npx prisma migrate dev --name init
|
|
39
|
+
npx prisma generate
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
| Feature | Description | Guide |
|
|
45
|
+
|---------|-------------|-------|
|
|
46
|
+
| Schema Design | Declarative data modeling with relations | Define models, relations, indexes in schema.prisma |
|
|
47
|
+
| Type-Safe Queries | Auto-generated TypeScript types | Use `findMany`, `findUnique`, `create`, `update` |
|
|
48
|
+
| Migrations | Version-controlled schema changes | `prisma migrate dev` for development, `deploy` for production |
|
|
49
|
+
| Relations | One-to-one, one-to-many, many-to-many | Use `include` or `select` to load related data |
|
|
50
|
+
| Transactions | ACID operations across multiple queries | Use `$transaction` for atomic operations |
|
|
51
|
+
| Raw Queries | Execute raw SQL when needed | Use `$queryRaw` for complex queries |
|
|
52
|
+
|
|
53
|
+
## Common Patterns
|
|
54
|
+
|
|
55
|
+
### Repository with Pagination
|
|
56
|
+
|
|
26
57
|
```typescript
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
async function findUsers(page = 1, limit = 20, where?: Prisma.UserWhereInput) {
|
|
59
|
+
const [data, total] = await prisma.$transaction([
|
|
60
|
+
prisma.user.findMany({ where, skip: (page - 1) * limit, take: limit, include: { profile: true } }),
|
|
61
|
+
prisma.user.count({ where }),
|
|
62
|
+
]);
|
|
63
|
+
return { data, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } };
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Interactive Transaction
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
async function createOrder(userId: string, items: { productId: string; qty: number }[]) {
|
|
71
|
+
return prisma.$transaction(async (tx) => {
|
|
72
|
+
let total = 0;
|
|
73
|
+
for (const item of items) {
|
|
74
|
+
const product = await tx.product.update({
|
|
75
|
+
where: { id: item.productId },
|
|
76
|
+
data: { stock: { decrement: item.qty } },
|
|
77
|
+
});
|
|
78
|
+
if (product.stock < 0) throw new Error(`Insufficient stock: ${product.name}`);
|
|
79
|
+
total += product.price * item.qty;
|
|
80
|
+
}
|
|
81
|
+
return tx.order.create({ data: { userId, total, items: { create: items } } });
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Cursor-Based Pagination
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
async function getPaginatedPosts(cursor?: string, take = 20) {
|
|
90
|
+
const posts = await prisma.post.findMany({
|
|
91
|
+
take: take + 1,
|
|
92
|
+
...(cursor && { skip: 1, cursor: { id: cursor } }),
|
|
93
|
+
orderBy: { createdAt: 'desc' },
|
|
94
|
+
});
|
|
95
|
+
const hasMore = posts.length > take;
|
|
96
|
+
return { data: hasMore ? posts.slice(0, -1) : posts, nextCursor: hasMore ? posts[take - 1].id : null };
|
|
97
|
+
}
|
|
49
98
|
```
|
|
50
99
|
|
|
51
100
|
## Best Practices
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
101
|
+
|
|
102
|
+
| Do | Avoid |
|
|
103
|
+
|----|-------|
|
|
104
|
+
| Use `select` to fetch only needed fields | Exposing Prisma Client directly in APIs |
|
|
105
|
+
| Create indexes for frequently queried fields | Skipping migrations in production |
|
|
106
|
+
| Use transactions for multi-table operations | Ignoring N+1 query problems |
|
|
107
|
+
| Run migrations in CI/CD pipelines | Hardcoding connection strings |
|
|
108
|
+
| Use connection pooling in production | Using raw queries unless necessary |
|
|
109
|
+
| Validate input before database operations | Using implicit many-to-many for complex joins |
|
|
110
|
+
| Seed development databases consistently | Ignoring transaction isolation levels |
|
|
@@ -1,41 +1,94 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Redis caching. Use
|
|
2
|
+
name: Developing with Redis
|
|
3
|
+
description: The agent implements Redis caching, data structures, and real-time messaging patterns. Use when implementing caching layers, session storage, rate limiting, pub/sub messaging, or distributed data structures.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Redis
|
|
6
|
+
# Developing with Redis
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Quick Start
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Set with expiry
|
|
13
|
-
await redis.set('user:123', JSON.stringify(user), 'EX', 3600);
|
|
10
|
+
```typescript
|
|
11
|
+
import Redis from 'ioredis';
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
const redis = new Redis({
|
|
14
|
+
host: process.env.REDIS_HOST || 'localhost',
|
|
15
|
+
port: parseInt(process.env.REDIS_PORT || '6379'),
|
|
16
|
+
maxRetriesPerRequest: 3,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Basic caching
|
|
20
|
+
await redis.setex('user:123', 3600, JSON.stringify(userData));
|
|
16
21
|
const cached = await redis.get('user:123');
|
|
17
|
-
if (cached) return JSON.parse(cached);
|
|
18
22
|
```
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
| Feature | Description | Guide |
|
|
27
|
+
|---------|-------------|-------|
|
|
28
|
+
| Caching | High-speed key-value storage with TTL | Use `setex` for auto-expiration, `get` for retrieval |
|
|
29
|
+
| Session Storage | Distributed session management | Store sessions with user ID index for multi-device |
|
|
30
|
+
| Rate Limiting | Request throttling with sliding windows | Use sorted sets or token bucket algorithms |
|
|
31
|
+
| Pub/Sub | Real-time messaging between services | Separate subscriber connections from publishers |
|
|
32
|
+
| Streams | Event sourcing and message queues | Consumer groups for reliable message processing |
|
|
33
|
+
| Data Structures | Lists, sets, sorted sets, hashes | Choose structure based on access patterns |
|
|
34
|
+
|
|
35
|
+
## Common Patterns
|
|
36
|
+
|
|
37
|
+
### Cache-Aside Pattern
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
async function getOrSet<T>(key: string, factory: () => Promise<T>, ttl = 3600): Promise<T> {
|
|
41
|
+
const cached = await redis.get(key);
|
|
42
|
+
if (cached) return JSON.parse(cached);
|
|
43
|
+
|
|
44
|
+
const value = await factory();
|
|
45
|
+
await redis.setex(key, ttl, JSON.stringify(value));
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
27
48
|
```
|
|
28
49
|
|
|
29
|
-
### Rate
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
50
|
+
### Sliding Window Rate Limiter
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
async function checkRateLimit(key: string, limit: number, windowSec: number): Promise<boolean> {
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
const windowStart = now - windowSec * 1000;
|
|
56
|
+
|
|
57
|
+
const pipeline = redis.pipeline();
|
|
58
|
+
pipeline.zremrangebyscore(key, '-inf', windowStart);
|
|
59
|
+
pipeline.zadd(key, now, `${now}:${Math.random()}`);
|
|
60
|
+
pipeline.zcard(key);
|
|
61
|
+
pipeline.expire(key, windowSec);
|
|
62
|
+
|
|
63
|
+
const results = await pipeline.exec();
|
|
64
|
+
const count = results?.[2]?.[1] as number;
|
|
65
|
+
return count <= limit;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Distributed Lock
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
async function acquireLock(key: string, ttlMs = 10000): Promise<string | null> {
|
|
73
|
+
const lockId = crypto.randomUUID();
|
|
74
|
+
const acquired = await redis.set(`lock:${key}`, lockId, 'PX', ttlMs, 'NX');
|
|
75
|
+
return acquired === 'OK' ? lockId : null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function releaseLock(key: string, lockId: string): Promise<boolean> {
|
|
79
|
+
const script = `if redis.call("get",KEYS[1])==ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end`;
|
|
80
|
+
return (await redis.eval(script, 1, `lock:${key}`, lockId)) === 1;
|
|
81
|
+
}
|
|
35
82
|
```
|
|
36
83
|
|
|
37
84
|
## Best Practices
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
85
|
+
|
|
86
|
+
| Do | Avoid |
|
|
87
|
+
|----|-------|
|
|
88
|
+
| Set TTL on all cache keys | Storing objects larger than 100KB |
|
|
89
|
+
| Use pipelines for batch operations | Using `KEYS` command in production |
|
|
90
|
+
| Implement connection pooling | Ignoring memory limits and eviction |
|
|
91
|
+
| Use Lua scripts for atomic operations | Using Redis as primary database |
|
|
92
|
+
| Add key prefixes for namespacing | Blocking on long-running operations |
|
|
93
|
+
| Monitor memory with `INFO memory` | Storing sensitive data unencrypted |
|
|
94
|
+
| Set up Redis Sentinel for HA | Skipping connection error handling |
|
|
@@ -1,51 +1,105 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: AWS
|
|
2
|
+
name: Deploying to AWS
|
|
3
|
+
description: The agent implements AWS cloud solutions with Lambda, S3, DynamoDB, ECS, and CDK infrastructure as code. Use when building serverless functions, deploying containers, managing cloud storage, or defining infrastructure as code.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# AWS
|
|
6
|
+
# Deploying to AWS
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Quick Start
|
|
9
9
|
|
|
10
|
-
### Lambda
|
|
11
10
|
```typescript
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
// Lambda handler
|
|
12
|
+
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
|
14
13
|
|
|
14
|
+
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
|
|
15
|
+
const { id } = event.pathParameters || {};
|
|
15
16
|
return {
|
|
16
17
|
statusCode: 200,
|
|
17
|
-
|
|
18
|
+
headers: { 'Content-Type': 'application/json' },
|
|
19
|
+
body: JSON.stringify({ id, message: 'Success' }),
|
|
18
20
|
};
|
|
19
21
|
};
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
```bash
|
|
25
|
+
# Deploy with CDK
|
|
26
|
+
npx cdk deploy --all
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
| Feature | Description | Guide |
|
|
32
|
+
|---------|-------------|-------|
|
|
33
|
+
| Lambda | Serverless function execution | Use for APIs, event processing, scheduled tasks |
|
|
34
|
+
| S3 | Object storage with presigned URLs | Store files, serve static assets, data lakes |
|
|
35
|
+
| DynamoDB | NoSQL database with single-digit ms latency | Design single-table schemas with GSIs |
|
|
36
|
+
| ECS/Fargate | Container orchestration | Run Docker containers without managing servers |
|
|
37
|
+
| API Gateway | REST and WebSocket API management | Throttling, auth, request validation |
|
|
38
|
+
| CDK | Infrastructure as TypeScript code | Define stacks, manage deployments programmatically |
|
|
39
|
+
|
|
40
|
+
## Common Patterns
|
|
41
|
+
|
|
42
|
+
### S3 Presigned Upload URL
|
|
43
|
+
|
|
23
44
|
```typescript
|
|
24
45
|
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
46
|
+
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
47
|
+
|
|
48
|
+
const s3 = new S3Client({});
|
|
25
49
|
|
|
26
|
-
|
|
50
|
+
async function getUploadUrl(key: string, contentType: string): Promise<string> {
|
|
51
|
+
const command = new PutObjectCommand({ Bucket: process.env.BUCKET!, Key: key, ContentType: contentType });
|
|
52
|
+
return getSignedUrl(s3, command, { expiresIn: 3600 });
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### DynamoDB Single-Table Pattern
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb';
|
|
27
60
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
61
|
+
// pk: USER#123, sk: PROFILE | ORDER#timestamp
|
|
62
|
+
async function getUserWithOrders(userId: string) {
|
|
63
|
+
const result = await docClient.send(new QueryCommand({
|
|
64
|
+
TableName: process.env.TABLE!,
|
|
65
|
+
KeyConditionExpression: 'pk = :pk',
|
|
66
|
+
ExpressionAttributeValues: { ':pk': `USER#${userId}` },
|
|
67
|
+
}));
|
|
68
|
+
return result.Items;
|
|
69
|
+
}
|
|
33
70
|
```
|
|
34
71
|
|
|
35
|
-
###
|
|
72
|
+
### CDK Stack Definition
|
|
73
|
+
|
|
36
74
|
```typescript
|
|
37
|
-
import
|
|
75
|
+
import * as cdk from 'aws-cdk-lib';
|
|
76
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
77
|
+
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
78
|
+
|
|
79
|
+
const table = new dynamodb.Table(this, 'Table', {
|
|
80
|
+
partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING },
|
|
81
|
+
sortKey: { name: 'sk', type: dynamodb.AttributeType.STRING },
|
|
82
|
+
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
|
|
83
|
+
});
|
|
38
84
|
|
|
39
|
-
const
|
|
85
|
+
const fn = new lambda.Function(this, 'Handler', {
|
|
86
|
+
runtime: lambda.Runtime.NODEJS_20_X,
|
|
87
|
+
handler: 'index.handler',
|
|
88
|
+
code: lambda.Code.fromAsset('dist'),
|
|
89
|
+
environment: { TABLE_NAME: table.tableName },
|
|
90
|
+
});
|
|
40
91
|
|
|
41
|
-
|
|
42
|
-
TableName: 'users',
|
|
43
|
-
Item: { id: { S: '123' }, email: { S: 'test@example.com' } },
|
|
44
|
-
}));
|
|
92
|
+
table.grantReadWriteData(fn);
|
|
45
93
|
```
|
|
46
94
|
|
|
47
95
|
## Best Practices
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
|
|
97
|
+
| Do | Avoid |
|
|
98
|
+
|----|-------|
|
|
99
|
+
| Use IAM roles, never access keys in code | Hardcoding credentials or secrets |
|
|
100
|
+
| Enable encryption at rest and in transit | Exposing S3 buckets publicly |
|
|
101
|
+
| Tag resources for cost tracking | Over-provisioning resources |
|
|
102
|
+
| Use environment variables for config | Skipping CloudWatch alarms |
|
|
103
|
+
| Implement least-privilege IAM policies | Using root account for deployments |
|
|
104
|
+
| Enable X-Ray tracing for debugging | Synchronous invocations for long tasks |
|
|
105
|
+
| Use VPC for sensitive workloads | Ignoring backup and disaster recovery |
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: GitHub Actions CI/CD. Use
|
|
2
|
+
name: Automating with GitHub Actions
|
|
3
|
+
description: The agent implements GitHub Actions CI/CD workflows with builds, tests, and deployments. Use when setting up continuous integration, automating deployments, creating reusable actions, or implementing security scanning.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# GitHub Actions
|
|
6
|
+
# Automating with GitHub Actions
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
7
9
|
|
|
8
|
-
## CI Workflow
|
|
9
10
|
```yaml
|
|
11
|
+
# .github/workflows/ci.yml
|
|
10
12
|
name: CI
|
|
11
13
|
|
|
12
14
|
on:
|
|
@@ -16,48 +18,98 @@ on:
|
|
|
16
18
|
branches: [main]
|
|
17
19
|
|
|
18
20
|
jobs:
|
|
19
|
-
|
|
21
|
+
build:
|
|
20
22
|
runs-on: ubuntu-latest
|
|
21
|
-
|
|
22
23
|
steps:
|
|
23
24
|
- uses: actions/checkout@v4
|
|
24
|
-
|
|
25
25
|
- uses: actions/setup-node@v4
|
|
26
26
|
with:
|
|
27
|
-
node-version:
|
|
28
|
-
cache:
|
|
29
|
-
|
|
27
|
+
node-version: 20
|
|
28
|
+
cache: npm
|
|
30
29
|
- run: npm ci
|
|
31
|
-
- run: npm run lint
|
|
32
30
|
- run: npm test
|
|
33
31
|
- run: npm run build
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
##
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
| Feature | Description | Guide |
|
|
37
|
+
|---------|-------------|-------|
|
|
38
|
+
| Workflows | Event-driven automation pipelines | Trigger on push, PR, schedule, or manual dispatch |
|
|
39
|
+
| Jobs | Parallel or sequential task execution | Use `needs` for dependencies, matrix for variations |
|
|
40
|
+
| Actions | Reusable workflow components | Use marketplace actions or create custom composite |
|
|
41
|
+
| Environments | Deployment targets with protection | Configure approvals, secrets, and URLs |
|
|
42
|
+
| Artifacts | Build output persistence | Upload/download between jobs, retention policies |
|
|
43
|
+
| Caching | Dependency caching for speed | Cache npm, pip, gradle directories |
|
|
44
|
+
|
|
45
|
+
## Common Patterns
|
|
46
|
+
|
|
47
|
+
### Matrix Build
|
|
48
|
+
|
|
37
49
|
```yaml
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
jobs:
|
|
51
|
+
test:
|
|
52
|
+
runs-on: ${{ matrix.os }}
|
|
53
|
+
strategy:
|
|
54
|
+
matrix:
|
|
55
|
+
os: [ubuntu-latest, macos-latest]
|
|
56
|
+
node: [18, 20, 22]
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
- uses: actions/setup-node@v4
|
|
60
|
+
with:
|
|
61
|
+
node-version: ${{ matrix.node }}
|
|
62
|
+
- run: npm ci && npm test
|
|
49
63
|
```
|
|
50
64
|
|
|
51
|
-
|
|
65
|
+
### Deployment with Environments
|
|
66
|
+
|
|
52
67
|
```yaml
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
jobs:
|
|
69
|
+
deploy:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
environment:
|
|
72
|
+
name: production
|
|
73
|
+
url: https://example.com
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v4
|
|
76
|
+
- run: npm ci && npm run build
|
|
77
|
+
- name: Deploy
|
|
78
|
+
run: ./deploy.sh
|
|
79
|
+
env:
|
|
80
|
+
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Docker Build and Push
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
jobs:
|
|
87
|
+
docker:
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@v4
|
|
91
|
+
- uses: docker/setup-buildx-action@v3
|
|
92
|
+
- uses: docker/login-action@v3
|
|
93
|
+
with:
|
|
94
|
+
registry: ghcr.io
|
|
95
|
+
username: ${{ github.actor }}
|
|
96
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
97
|
+
- uses: docker/build-push-action@v5
|
|
98
|
+
with:
|
|
99
|
+
push: true
|
|
100
|
+
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
|
|
101
|
+
cache-from: type=gha
|
|
102
|
+
cache-to: type=gha,mode=max
|
|
57
103
|
```
|
|
58
104
|
|
|
59
105
|
## Best Practices
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
106
|
+
|
|
107
|
+
| Do | Avoid |
|
|
108
|
+
|----|-------|
|
|
109
|
+
| Use concurrency groups to cancel stale runs | Hardcoding secrets in workflows |
|
|
110
|
+
| Cache dependencies for faster builds | Skipping security scanning |
|
|
111
|
+
| Use matrix strategies for cross-platform | Using deprecated action versions |
|
|
112
|
+
| Implement environment protection rules | Running unnecessary jobs on PRs |
|
|
113
|
+
| Set timeouts on long-running jobs | Ignoring workflow permissions |
|
|
114
|
+
| Use reusable workflows for common patterns | Self-hosted runners without security review |
|
|
115
|
+
| Upload test artifacts on failure | Skipping concurrency controls |
|