@musashishao/agent-kit 1.8.2 → 1.9.1
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/.agent/agents/ai-architect.md +39 -0
- package/.agent/agents/ai-asset-factory.md +700 -0
- package/.agent/agents/ai-audio-factory.md +503 -0
- package/.agent/agents/cloud-engineer.md +39 -0
- package/.agent/agents/game-developer.md +190 -89
- package/.agent/agents/marketing-specialist.md +41 -0
- package/.agent/agents/orchestrator.md +113 -3
- package/.agent/agents/penetration-tester.md +15 -1
- package/.agent/agents/project-planner.md +67 -0
- package/.agent/agents/unity-mobile-master.md +949 -0
- package/.agent/mcp/config/registry.json +65 -51
- package/.agent/mcp/servers/notebooklm/README.md +114 -0
- package/.agent/mcp/servers/notebooklm/package.json +35 -0
- package/.agent/mcp/servers/notebooklm/src/auth/chrome.ts +225 -0
- package/.agent/mcp/servers/notebooklm/src/auth/index.ts +1 -0
- package/.agent/mcp/servers/notebooklm/src/index.ts +516 -0
- package/.agent/mcp/servers/notebooklm/src/services/index.ts +3 -0
- package/.agent/mcp/servers/notebooklm/src/services/library.ts +217 -0
- package/.agent/mcp/servers/notebooklm/src/services/notebooklm.ts +380 -0
- package/.agent/mcp/servers/notebooklm/tsconfig.json +15 -0
- package/.agent/mcp-gateway/README.md +169 -20
- package/.agent/mcp-gateway/package.json +22 -7
- package/.agent/mcp-gateway/src/auth/index.ts +55 -0
- package/.agent/mcp-gateway/src/auth/middleware.ts +242 -0
- package/.agent/mcp-gateway/src/auth/oauth.ts +462 -0
- package/.agent/mcp-gateway/src/auth/scopes.ts +227 -0
- package/.agent/mcp-gateway/src/index.ts +252 -105
- package/.agent/mcp-gateway/src/observability/index.ts +5 -0
- package/.agent/mcp-gateway/src/observability/otel.ts +405 -0
- package/.agent/mcp-gateway/src/transports/index.ts +5 -0
- package/.agent/mcp-gateway/src/transports/streamableHttp.ts +235 -0
- package/.agent/rules/CODEX.md +115 -2
- package/.agent/rules/CODE_RULES.md +73 -0
- package/.agent/rules/GEMINI.md +26 -1
- package/.agent/rules/MEMORY_STATE.md +110 -0
- package/.agent/rules/REFERENCE.md +40 -58
- package/.agent/rules/REF_SKILLS.md +116 -0
- package/.agent/rules/REF_WORKFLOWS.md +81 -0
- package/.agent/scripts/ak_cli.py +106 -5
- package/.agent/scripts/memory_manager.py +48 -9
- package/.agent/skills/3d-web-experience/SKILL.md +386 -0
- package/.agent/skills/DEPENDENCIES.md +54 -0
- package/.agent/skills/ab-test-setup/SKILL.md +77 -0
- package/.agent/skills/active-directory-attacks/SKILL.md +59 -0
- package/.agent/skills/agent-evaluation/SKILL.md +430 -0
- package/.agent/skills/agent-memory-systems/SKILL.md +426 -0
- package/.agent/skills/agent-tool-builder/SKILL.md +139 -0
- package/.agent/skills/ai-agents-architect/SKILL.md +115 -0
- package/.agent/skills/ai-product/SKILL.md +86 -0
- package/.agent/skills/ai-wrapper-product/SKILL.md +90 -0
- package/.agent/skills/analytics-tracking/SKILL.md +88 -0
- package/.agent/skills/anti-hallucination/SKILL.md +295 -0
- package/.agent/skills/anti-hallucination/scripts/check_hallucination.py +299 -0
- package/.agent/skills/api-fuzzing-bug-bounty/SKILL.md +66 -0
- package/.agent/skills/app-store-optimization/SKILL.md +66 -0
- package/.agent/skills/autonomous-agent-patterns/SKILL.md +414 -0
- package/.agent/skills/aws-penetration-testing/SKILL.md +50 -0
- package/.agent/skills/aws-serverless/SKILL.md +327 -0
- package/.agent/skills/azure-functions/SKILL.md +340 -0
- package/.agent/skills/bifurcation-analysis/SKILL.md +56 -0
- package/.agent/skills/brainstorming/SKILL.md +80 -6
- package/.agent/skills/broken-authentication/SKILL.md +53 -0
- package/.agent/skills/browser-automation/SKILL.md +408 -0
- package/.agent/skills/browser-extension-builder/SKILL.md +422 -0
- package/.agent/skills/bullmq-specialist/SKILL.md +424 -0
- package/.agent/skills/bun-development/SKILL.md +386 -0
- package/.agent/skills/burp-suite-testing/SKILL.md +60 -0
- package/.agent/skills/clerk-auth/SKILL.md +432 -0
- package/.agent/skills/cloud-penetration-testing/SKILL.md +51 -0
- package/.agent/skills/copywriting/SKILL.md +66 -0
- package/.agent/skills/crewai/SKILL.md +470 -0
- package/.agent/skills/decision-memory/SKILL.md +317 -0
- package/.agent/skills/discord-bot-architect/SKILL.md +447 -0
- package/.agent/skills/email-sequence/SKILL.md +73 -0
- package/.agent/skills/emergence-detector/SKILL.md +230 -0
- package/.agent/skills/emergence-detector/scripts/check_emergence.py +265 -0
- package/.agent/skills/ethical-hacking-methodology/SKILL.md +67 -0
- package/.agent/skills/explained-qa/SKILL.md +142 -0
- package/.agent/skills/explained-qa/game-terminology.md +214 -0
- package/.agent/skills/firebase/SKILL.md +377 -0
- package/.agent/skills/game-development/ai-dialogue-engine/SKILL.md +442 -0
- package/.agent/skills/game-development/ai-graphics-generator/SKILL.md +463 -0
- package/.agent/skills/game-development/ai-playtest-framework/SKILL.md +570 -0
- package/.agent/skills/game-development/camera-systems/SKILL.md +607 -0
- package/.agent/skills/game-development/card-battle-engine/SKILL.md +618 -0
- package/.agent/skills/game-development/character-controller-3d/SKILL.md +908 -0
- package/.agent/skills/game-development/cloud-save-sync/SKILL.md +527 -0
- package/.agent/skills/game-development/combat-system/SKILL.md +748 -0
- package/.agent/skills/game-development/compliance-rating/SKILL.md +277 -0
- package/.agent/skills/game-development/crossplatform-build/SKILL.md +386 -0
- package/.agent/skills/game-development/cultivation-progression/SKILL.md +520 -0
- package/.agent/skills/game-development/data-driven-balance/SKILL.md +535 -0
- package/.agent/skills/game-development/game-analytics-integrator/SKILL.md +410 -0
- package/.agent/skills/game-development/game-audio-advanced/SKILL.md +646 -0
- package/.agent/skills/game-development/game-economy-designer/SKILL.md +375 -0
- package/.agent/skills/game-development/game-marketing/SKILL.md +85 -0
- package/.agent/skills/game-development/game-state-manager/SKILL.md +883 -0
- package/.agent/skills/game-development/godot-expert/SKILL.md +462 -0
- package/.agent/skills/game-development/hybrid-game-spec/SKILL.md +220 -0
- package/.agent/skills/game-development/inventory-quest/SKILL.md +747 -0
- package/.agent/skills/game-development/liveops/SKILL.md +308 -0
- package/.agent/skills/game-development/localization/SKILL.md +286 -0
- package/.agent/skills/game-development/mobile-input-patterns/SKILL.md +343 -0
- package/.agent/skills/game-development/monetization-strategy/SKILL.md +94 -0
- package/.agent/skills/game-development/multiplayer-master/SKILL.md +727 -0
- package/.agent/skills/game-development/narrative-branching/SKILL.md +593 -0
- package/.agent/skills/game-development/npc-ai-integration/SKILL.md +110 -0
- package/.agent/skills/game-development/procedural-generation/SKILL.md +168 -0
- package/.agent/skills/game-development/procedural-level-ai/SKILL.md +367 -0
- package/.agent/skills/game-development/prototyping-rapid/SKILL.md +205 -0
- package/.agent/skills/game-development/spec-ecosystem/SKILL.md +155 -0
- package/.agent/skills/game-development/spec-ecosystem/decision-log-format.md +129 -0
- package/.agent/skills/game-development/spec-ecosystem/templates/PLAN-template.md +178 -0
- package/.agent/skills/game-development/spec-ecosystem/templates/SPEC-template.md +110 -0
- package/.agent/skills/game-development/spec-ecosystem/templates/TASKS-template.md +156 -0
- package/.agent/skills/game-development/survival-systems/SKILL.md +493 -0
- package/.agent/skills/game-development/testing-qa/SKILL.md +270 -0
- package/.agent/skills/game-development/unity-integration/SKILL.md +358 -0
- package/.agent/skills/game-development/unity-mobile-optimization/SKILL.md +271 -0
- package/.agent/skills/game-development/webgpu-shading/SKILL.md +209 -0
- package/.agent/skills/gcp-cloud-run/SKILL.md +358 -0
- package/.agent/skills/graphql/SKILL.md +492 -0
- package/.agent/skills/idor-testing/SKILL.md +64 -0
- package/.agent/skills/inngest/SKILL.md +128 -0
- package/.agent/skills/intent-capture/SKILL.md +65 -0
- package/.agent/skills/langfuse/SKILL.md +415 -0
- package/.agent/skills/langgraph/SKILL.md +360 -0
- package/.agent/skills/launch-strategy/SKILL.md +68 -0
- package/.agent/skills/linux-privilege-escalation/SKILL.md +62 -0
- package/.agent/skills/llm-app-patterns/SKILL.md +367 -0
- package/.agent/skills/marketing-ideas/SKILL.md +66 -0
- package/.agent/skills/mcp-composition/SKILL.md +362 -0
- package/.agent/skills/mcp-observability/SKILL.md +323 -0
- package/.agent/skills/mcp-security/SKILL.md +314 -0
- package/.agent/skills/metasploit-framework/SKILL.md +60 -0
- package/.agent/skills/micro-saas-launcher/SKILL.md +93 -0
- package/.agent/skills/neon-postgres/SKILL.md +339 -0
- package/.agent/skills/paid-ads/SKILL.md +64 -0
- package/.agent/skills/supabase-integration/SKILL.md +411 -0
- package/.agent/skills/trust-spectrum/SKILL.md +291 -0
- package/.agent/skills/vibe-coding-guard/SKILL.md +328 -0
- package/.agent/templates/AGENTS.game.md +63 -0
- package/.agent/templates/docs/WORKFLOW_GUIDE.en.md +100 -0
- package/.agent/templates/docs/WORKFLOW_GUIDE.vi.md +100 -0
- package/.agent/workflows/ai-agent.md +38 -0
- package/.agent/workflows/autofix.md +1 -0
- package/.agent/workflows/brainstorm.md +1 -0
- package/.agent/workflows/context.md +1 -0
- package/.agent/workflows/create.md +39 -8
- package/.agent/workflows/dashboard.md +1 -0
- package/.agent/workflows/debug.md +14 -0
- package/.agent/workflows/deploy.md +14 -0
- package/.agent/workflows/enhance.md +44 -0
- package/.agent/workflows/gamekit-init.md +177 -0
- package/.agent/workflows/gamekit-launch.md +338 -0
- package/.agent/workflows/gamekit-plan.md +204 -0
- package/.agent/workflows/gamekit-qa.md +153 -0
- package/.agent/workflows/gamekit-spec.md +243 -0
- package/.agent/workflows/gamekit-tasks.md +208 -0
- package/.agent/workflows/marketing.md +39 -0
- package/.agent/workflows/next.md +1 -0
- package/.agent/workflows/orchestrate.md +12 -0
- package/.agent/workflows/pentest.md +39 -0
- package/.agent/workflows/plan.md +42 -0
- package/.agent/workflows/preview.md +1 -0
- package/.agent/workflows/quality.md +1 -0
- package/.agent/workflows/saas.md +38 -0
- package/.agent/workflows/spec.md +42 -0
- package/.agent/workflows/status.md +1 -0
- package/.agent/workflows/test.md +14 -0
- package/.agent/workflows/ui-ux-pro-max.md +1 -0
- package/README.md +4 -4
- package/bin/cli.js +411 -111
- package/package.json +1 -2
- package/docs/AI_DATA_INFRASTRUCTURE.md +0 -288
- package/docs/CHANGELOG_AI_INFRA.md +0 -111
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gcp-cloud-run
|
|
3
|
+
description: "Google Cloud Run and Cloud Functions patterns. Covers containerized deployments, Cloud Functions Gen2, Firestore, Pub/Sub, and Terraform/Pulumi IaC."
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ☁️ GCP Cloud Run
|
|
8
|
+
|
|
9
|
+
You are a Google Cloud expert who has deployed production applications on Cloud Run and Cloud Functions. You understand the container-based model, scaling behavior, and GCP service integrations.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## When to Use This Skill
|
|
14
|
+
|
|
15
|
+
- Deploying containerized apps with Cloud Run
|
|
16
|
+
- Event-driven processing with Cloud Functions Gen2
|
|
17
|
+
- Firestore/Bigtable data modeling
|
|
18
|
+
- Pub/Sub message queues
|
|
19
|
+
- Cloud Build CI/CD pipelines
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Capabilities
|
|
24
|
+
|
|
25
|
+
- `cloud-run`
|
|
26
|
+
- `cloud-functions`
|
|
27
|
+
- `firestore`
|
|
28
|
+
- `pub-sub`
|
|
29
|
+
- `cloud-build`
|
|
30
|
+
- `artifact-registry`
|
|
31
|
+
- `cloud-tasks`
|
|
32
|
+
- `cloud-scheduler`
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 1. Cloud Run Patterns
|
|
37
|
+
|
|
38
|
+
### Dockerfile for Cloud Run
|
|
39
|
+
|
|
40
|
+
```dockerfile
|
|
41
|
+
# Dockerfile
|
|
42
|
+
FROM node:20-slim AS builder
|
|
43
|
+
|
|
44
|
+
WORKDIR /app
|
|
45
|
+
COPY package*.json ./
|
|
46
|
+
RUN npm ci --only=production
|
|
47
|
+
|
|
48
|
+
COPY . .
|
|
49
|
+
RUN npm run build
|
|
50
|
+
|
|
51
|
+
# Production image
|
|
52
|
+
FROM node:20-slim
|
|
53
|
+
|
|
54
|
+
ENV NODE_ENV=production
|
|
55
|
+
WORKDIR /app
|
|
56
|
+
|
|
57
|
+
COPY --from=builder /app/dist ./dist
|
|
58
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
59
|
+
COPY package*.json ./
|
|
60
|
+
|
|
61
|
+
# Cloud Run uses PORT env var
|
|
62
|
+
EXPOSE 8080
|
|
63
|
+
CMD ["node", "dist/server.js"]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Node.js Server
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
// server.js
|
|
70
|
+
const express = require('express');
|
|
71
|
+
const { Firestore } = require('@google-cloud/firestore');
|
|
72
|
+
|
|
73
|
+
const app = express();
|
|
74
|
+
app.use(express.json());
|
|
75
|
+
|
|
76
|
+
// Initialize outside request handler
|
|
77
|
+
const firestore = new Firestore();
|
|
78
|
+
const collection = firestore.collection('users');
|
|
79
|
+
|
|
80
|
+
app.get('/users/:id', async (req, res) => {
|
|
81
|
+
try {
|
|
82
|
+
const doc = await collection.doc(req.params.id).get();
|
|
83
|
+
|
|
84
|
+
if (!doc.exists) {
|
|
85
|
+
return res.status(404).json({ error: 'User not found' });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
res.json({ id: doc.id, ...doc.data() });
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error('Error:', error);
|
|
91
|
+
res.status(500).json({ error: error.message });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
app.post('/users', async (req, res) => {
|
|
96
|
+
try {
|
|
97
|
+
const docRef = await collection.add(req.body);
|
|
98
|
+
res.status(201).json({ id: docRef.id });
|
|
99
|
+
} catch (error) {
|
|
100
|
+
res.status(500).json({ error: error.message });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Cloud Run provides PORT
|
|
105
|
+
const PORT = process.env.PORT || 8080;
|
|
106
|
+
app.listen(PORT, () => {
|
|
107
|
+
console.log(`Server running on port ${PORT}`);
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Deploy Command
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Build and push
|
|
115
|
+
gcloud builds submit --tag gcr.io/$PROJECT_ID/my-service
|
|
116
|
+
|
|
117
|
+
# Deploy
|
|
118
|
+
gcloud run deploy my-service \
|
|
119
|
+
--image gcr.io/$PROJECT_ID/my-service \
|
|
120
|
+
--platform managed \
|
|
121
|
+
--region us-central1 \
|
|
122
|
+
--allow-unauthenticated \
|
|
123
|
+
--min-instances 1 \
|
|
124
|
+
--max-instances 100 \
|
|
125
|
+
--memory 512Mi \
|
|
126
|
+
--cpu 1 \
|
|
127
|
+
--set-env-vars "NODE_ENV=production"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 2. Cloud Functions Gen2 Pattern
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// index.js
|
|
136
|
+
const functions = require('@google-cloud/functions-framework');
|
|
137
|
+
const { Firestore } = require('@google-cloud/firestore');
|
|
138
|
+
|
|
139
|
+
const firestore = new Firestore();
|
|
140
|
+
|
|
141
|
+
// HTTP function
|
|
142
|
+
functions.http('helloHttp', async (req, res) => {
|
|
143
|
+
const name = req.query.name || req.body.name || 'World';
|
|
144
|
+
res.json({ message: `Hello, ${name}!` });
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Cloud Event function (Pub/Sub)
|
|
148
|
+
functions.cloudEvent('helloPubSub', async (cloudEvent) => {
|
|
149
|
+
const message = Buffer.from(cloudEvent.data.message.data, 'base64').toString();
|
|
150
|
+
console.log(`Received message: ${message}`);
|
|
151
|
+
|
|
152
|
+
// Process message
|
|
153
|
+
await firestore.collection('messages').add({
|
|
154
|
+
content: message,
|
|
155
|
+
timestamp: new Date()
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Firestore trigger
|
|
160
|
+
functions.cloudEvent('onUserCreate', async (event) => {
|
|
161
|
+
const document = event.data;
|
|
162
|
+
console.log('New user created:', document);
|
|
163
|
+
|
|
164
|
+
// Send welcome email
|
|
165
|
+
await sendWelcomeEmail(document.email);
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Deploy Cloud Function
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
gcloud functions deploy my-function \
|
|
173
|
+
--gen2 \
|
|
174
|
+
--runtime nodejs20 \
|
|
175
|
+
--trigger-http \
|
|
176
|
+
--allow-unauthenticated \
|
|
177
|
+
--region us-central1 \
|
|
178
|
+
--entry-point helloHttp
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 3. Pub/Sub Pattern
|
|
184
|
+
|
|
185
|
+
### Publisher
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
const { PubSub } = require('@google-cloud/pubsub');
|
|
189
|
+
const pubsub = new PubSub();
|
|
190
|
+
|
|
191
|
+
async function publishMessage(topicName, data) {
|
|
192
|
+
const topic = pubsub.topic(topicName);
|
|
193
|
+
|
|
194
|
+
const messageBuffer = Buffer.from(JSON.stringify(data));
|
|
195
|
+
|
|
196
|
+
const messageId = await topic.publish(messageBuffer, {
|
|
197
|
+
// Ordering key for ordered delivery
|
|
198
|
+
orderingKey: data.userId
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
console.log(`Message ${messageId} published.`);
|
|
202
|
+
return messageId;
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Subscriber (Push to Cloud Run)
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
// Pub/Sub push endpoint in Cloud Run
|
|
210
|
+
app.post('/pubsub/push', async (req, res) => {
|
|
211
|
+
try {
|
|
212
|
+
// Verify Pub/Sub token if configured
|
|
213
|
+
const token = req.query.token;
|
|
214
|
+
if (token !== process.env.PUBSUB_VERIFICATION_TOKEN) {
|
|
215
|
+
return res.status(403).send('Forbidden');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const message = JSON.parse(
|
|
219
|
+
Buffer.from(req.body.message.data, 'base64').toString()
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
await processMessage(message);
|
|
223
|
+
|
|
224
|
+
// Acknowledge by returning 2xx
|
|
225
|
+
res.status(200).send('OK');
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.error('Error processing message:', error);
|
|
228
|
+
// Return 5xx to retry
|
|
229
|
+
res.status(500).send('Error');
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 4. Firestore Patterns
|
|
237
|
+
|
|
238
|
+
### Single Document Pattern
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
// Get with caching
|
|
242
|
+
async function getUser(userId) {
|
|
243
|
+
const cacheKey = `user:${userId}`;
|
|
244
|
+
|
|
245
|
+
// Check cache
|
|
246
|
+
const cached = await cache.get(cacheKey);
|
|
247
|
+
if (cached) return cached;
|
|
248
|
+
|
|
249
|
+
// Fetch from Firestore
|
|
250
|
+
const doc = await firestore.collection('users').doc(userId).get();
|
|
251
|
+
|
|
252
|
+
if (!doc.exists) return null;
|
|
253
|
+
|
|
254
|
+
const user = { id: doc.id, ...doc.data() };
|
|
255
|
+
|
|
256
|
+
// Cache for 5 minutes
|
|
257
|
+
await cache.set(cacheKey, user, 300);
|
|
258
|
+
|
|
259
|
+
return user;
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Batch Operations
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
// Batch write for better performance
|
|
267
|
+
async function createUsers(users) {
|
|
268
|
+
const batch = firestore.batch();
|
|
269
|
+
|
|
270
|
+
users.forEach(user => {
|
|
271
|
+
const ref = firestore.collection('users').doc();
|
|
272
|
+
batch.set(ref, {
|
|
273
|
+
...user,
|
|
274
|
+
createdAt: Firestore.FieldValue.serverTimestamp()
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
await batch.commit();
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 5. Cloud Build CI/CD
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
# cloudbuild.yaml
|
|
288
|
+
steps:
|
|
289
|
+
# Run tests
|
|
290
|
+
- name: 'node:20'
|
|
291
|
+
entrypoint: 'npm'
|
|
292
|
+
args: ['ci']
|
|
293
|
+
|
|
294
|
+
- name: 'node:20'
|
|
295
|
+
entrypoint: 'npm'
|
|
296
|
+
args: ['test']
|
|
297
|
+
|
|
298
|
+
# Build container
|
|
299
|
+
- name: 'gcr.io/cloud-builders/docker'
|
|
300
|
+
args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA', '.']
|
|
301
|
+
|
|
302
|
+
# Push to registry
|
|
303
|
+
- name: 'gcr.io/cloud-builders/docker'
|
|
304
|
+
args: ['push', 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA']
|
|
305
|
+
|
|
306
|
+
# Deploy to Cloud Run
|
|
307
|
+
- name: 'gcr.io/cloud-builders/gcloud'
|
|
308
|
+
args:
|
|
309
|
+
- 'run'
|
|
310
|
+
- 'deploy'
|
|
311
|
+
- 'my-service'
|
|
312
|
+
- '--image=gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA'
|
|
313
|
+
- '--region=us-central1'
|
|
314
|
+
- '--platform=managed'
|
|
315
|
+
|
|
316
|
+
images:
|
|
317
|
+
- 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA'
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 6. Anti-Patterns
|
|
323
|
+
|
|
324
|
+
### ❌ No Min Instances
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
# WRONG: Cold start on every request after idle
|
|
328
|
+
gcloud run deploy --min-instances 0
|
|
329
|
+
|
|
330
|
+
# CORRECT: Keep warm for latency-sensitive apps
|
|
331
|
+
gcloud run deploy --min-instances 1
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### ❌ Global State Mutation
|
|
335
|
+
|
|
336
|
+
```javascript
|
|
337
|
+
// WRONG: Global state across requests
|
|
338
|
+
let requestCount = 0;
|
|
339
|
+
|
|
340
|
+
app.get('/', (req, res) => {
|
|
341
|
+
requestCount++; // Unreliable across instances!
|
|
342
|
+
res.json({ count: requestCount });
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// CORRECT: Use external storage
|
|
346
|
+
app.get('/', async (req, res) => {
|
|
347
|
+
const count = await redis.incr('request_count');
|
|
348
|
+
res.json({ count });
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Related Skills
|
|
355
|
+
|
|
356
|
+
- `aws-serverless` - Compare with AWS
|
|
357
|
+
- `azure-functions` - Compare with Azure
|
|
358
|
+
- `docker-expert` - Container optimization
|