Skip to content

Commit 8a1ecc0

Browse files
update
1 parent 9e1b74c commit 8a1ecc0

2 files changed

Lines changed: 48 additions & 46 deletions

File tree

.github/workflows/hourly-ai.yml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,28 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- name: Checkout Code
16-
uses: actions/checkout@v3
16+
uses: actions/checkout@v4 # Use V4
1717

1818
- name: Setup Node.js
19-
uses: actions/setup-node@v3
19+
uses: actions/setup-node@v4
2020
with:
21-
node-version: '18'
21+
node-version: '20' # Using a modern node version
2222

2323
- name: Install dependencies
24-
run: npm install firebase-admin @google/generative-ai
24+
run: |
25+
npm init -y
26+
npm install firebase-admin @google/generative-ai
2527
2628
- name: Execute AI Script
2729
env:
2830
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
2931
FIREBASE_SERVICE_ACCOUNT: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
3032
run: node scripts/generate-ai-tip.js
31-
33+
3234
- name: Commit & Push Documentation 📝
3335
run: |
3436
git config --global user.name 'Academy-Writer-Bot'
3537
git config --global user.email 'bot@littleslaw.com'
3638
git add docs/
37-
git commit -m "Auto-updated Documentation for tools" || echo "No changes to commit"
39+
git commit -m "Auto-update wiki: [${{ github.workflow }}]" || echo "No changes to commit"
3840
git push

scripts/generate-ai-tip.js

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,86 +13,86 @@ if (!admin.apps.length) {
1313
const db = admin.firestore();
1414

1515
// 2. AI SETUP
16-
// Ensure your GEMINI_API_KEY secret is correct in GitHub
1716
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
1817

1918
async function run() {
2019
try {
21-
// Use "gemini-1.5-flash" - this is the most current stable identifier
20+
// Using 'gemini-1.5-flash' - adding '-latest' is often more stable in CI
2221
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
2322

24-
// Tool categories and their respective folders
2523
const categories = [
2624
{
27-
folder: 'performance',
28-
tools: ['JMeter', 'NeoLoad', 'LoadRunner', 'k6', 'Locust', 'Gatling'],
29-
topics: 'Correlation, Parameterization, Think Time, Pacing, Throughput, Workload Modeling'
25+
id: 'performance',
26+
tools: ['JMeter', 'NeoLoad', 'LoadRunner', 'k6', 'Locust'],
27+
topics: 'Correlation, Parameterization, Workload Modeling, Pacing'
3028
},
3129
{
32-
folder: 'sre',
33-
tools: ['Kubernetes', 'AKS', 'Azure-Monitor', 'Grafana', 'Datadog', 'Dynatrace', 'AppDynamics'],
34-
topics: 'SLOs, SLIs, Error Budgets, Auto-scaling, Observability, AKS clusters, Circuit Breaking'
30+
id: 'sre',
31+
tools: ['Kubernetes', 'AKS', 'Azure', 'Grafana', 'Datadog', 'Dynatrace'],
32+
topics: 'SLOs, Error Budgets, AKS Scaling, Observability'
3533
},
3634
{
37-
folder: 'devops',
38-
tools: ['GitHub-Actions', 'Jenkins', 'Linux-Performance', 'Docker', 'GitLab-CI', 'Ansible'],
39-
topics: 'Pipelines, CI/CD, Shell Scripting, Kernel Tuning, TCP/IP Optimization, Container Hardening'
35+
id: 'devops',
36+
tools: ['GitHub', 'Jenkins', 'Linux', 'Pipelines', 'Docker'],
37+
topics: 'CI/CD workflows, Bash Scripting, Linux Performance Tuning'
4038
}
4139
];
4240

43-
// Randomly pick a category and then a tool
4441
const selectedCat = categories[Math.floor(Math.random() * categories.length)];
4542
const selectedTool = selectedCat.tools[Math.floor(Math.random() * selectedCat.tools.length)];
4643

4744
const prompt = `
48-
ACT AS: A World-Class Principal Performance Architect & SRE with 30 years of experience.
49-
You are mentoring students at Little's Law Academy.
50-
51-
GOAL: Write a Technical Wiki entry for ${selectedTool} focused on ${selectedCat.topics}.
45+
ACT AS: A Principal Performance Architect & SRE with 30 years of experience.
46+
47+
GOAL: Write a professional Masterclass entry (300 words) about ${selectedTool}.
48+
Focus on these areas: ${selectedCat.topics}.
5249
53-
STRUCTURE (Markdown):
54-
1. # ${selectedTool}: Advanced Architecture Insight
55-
2. THE TRENCHES (Narrative): Start with a "war story". Talk about an emotional moment early in your career involving high-stakes performance failure and the lesson learned.
56-
3. TECHNICAL DEEP DIVE: Explain a specific concept related to ${selectedTool} (e.g. Memory profiling, TCP tuning, or async workloads).
57-
4. PRACTICAL EXAMPLE: Provide a real-world code snippet, CLI command, or configuration snippet (YAML, JMX, or Script).
58-
5. THE VETERAN'S WISDOM: Closing emotional/professional advice for future-proofing an SRE career.
59-
60-
TONE: Professional, sophisticated, inspiring, and strictly technical.
61-
LENGTH: Exactly around 300 words.
50+
FORMAT (Strict Markdown):
51+
1. # ${selectedTool} Architectural Deep Dive
52+
2. ## The Trenches (Story)
53+
Write a 100-word emotional "war story" from the past (e.g., a massive production failure at 3 AM) and how it felt to be the one responsible for the fix.
54+
3. ## Technical Analysis
55+
Explain a highly technical bottleneck involving ${selectedTool}. Use expert terminology (Latency, Throughput, TCP, Heap Analysis).
56+
4. ## Implementation Example
57+
Provide a clear technical example (e.g., a code snippet, a CLI command, or a YAML config).
58+
5. ## Veteran Wisdom
59+
Close with a one-sentence inspiring advice for future Performance Engineers.
60+
61+
WORD COUNT: Ensure the total length is at least 300 words.
6262
`;
6363

6464
const result = await model.generateContent(prompt);
6565
const response = await result.response;
66-
const masterclassMD = response.text();
66+
const text = response.text();
6767

68-
if (!masterclassMD) throw new Error("Response was empty.");
68+
if (!text) throw new Error("AI returned empty content");
6969

70-
// 3. SYNC TO FIREBASE (For the Homepage Banner)
70+
// 3. UPDATE FIREBASE (Real-time Site Banner)
7171
await db.collection('admin_data').doc('hourly_tip').set({
72-
content: masterclassMD,
72+
content: text,
7373
tool: selectedTool,
74-
folder: selectedCat.folder,
74+
category: selectedCat.id,
7575
lastUpdated: new Date().toISOString()
7676
});
7777

78-
// 4. SYNC TO GITHUB (Create Folders & Save MD)
79-
// Correct path for sub-folders inside 'docs'
78+
// 4. UPDATE GITHUB (Permanent categorized Docs)
79+
// Root is 'docs/', Subfolders are 'performance/', 'sre/', 'devops/'
8080
const baseDocsDir = path.join(__dirname, '../docs');
81-
const categoryDir = path.join(baseDocsDir, selectedCat.folder);
81+
const categoryFolder = path.join(baseDocsDir, selectedCat.id);
8282

83-
if (!fs.existsSync(categoryDir)) {
84-
fs.mkdirSync(categoryDir, { recursive: true });
83+
if (!fs.existsSync(categoryFolder)) {
84+
fs.mkdirSync(categoryFolder, { recursive: true });
8585
}
8686

8787
const fileName = `${selectedTool.toLowerCase()}.md`;
88-
const filePath = path.join(categoryDir, fileName);
88+
const filePath = path.join(categoryFolder, fileName);
8989

90-
fs.writeFileSync(filePath, masterclassMD);
90+
fs.writeFileSync(filePath, text);
9191

92-
console.log(`✅ [${selectedCat.folder}] ${selectedTool} Masterclass generated.`);
92+
console.log(`✅ [${selectedCat.id}] Successfully documented ${selectedTool} into /docs/${selectedCat.id}/${fileName}`);
9393

9494
} catch (error) {
95-
console.error("❌ Script Error:", error.message);
95+
console.error("❌ Fatal Error:", error.message);
9696
process.exit(1);
9797
}
9898
}

0 commit comments

Comments
 (0)