DevOps-agentti: Dockerfile + docker-compose.yml + README pipeline-vaiheina

DevOps generoi nyt kolme tiedostoa:
- Dockerfile (multi-stage build, python:3.12-slim)
- docker-compose.yml (palvelut, volumet, portit)
- README.md (quick start docker compose up)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 06:41:34 +03:00
parent f1b57a6c53
commit ac698a766e

View File

@@ -1157,7 +1157,7 @@
coder: { name: 'Koodari — System Prompt', model: 'qwen-coder', default: 'Olet kokenut ohjelmistokehittäjä. Kirjoita selkeää, testattavaa koodia ja vastaa aina koodilla.' },
data: { name: 'Data-Agentti — System Prompt', model: 'qwen-coder', default: 'Olet tietokanta-asiantuntija. Vastaat skeemojen suunnittelusta, SQL-kyselyiden optimoinnista ja datamalleista.' },
qa: { name: 'QA — System Prompt', model: 'qwen-coder', default: 'Olet laadunvarmistaja (QA). Kirjoitat testejä, etsit virheitä ja varmistat, että kaikki reunatapaukset on huomioitu.' },
tester: { name: 'DevOps — System Prompt', model: 'qwen-coder', default: 'Olet DevOps-insinööri. Vastaat koodin julkaisuputkista, serveri-infrastruktuurista ja ympäristön suorituskyvystä.' },
tester: { name: 'DevOps — System Prompt', model: 'qwen-coder', default: 'Olet DevOps-insinööri. Kirjoitat Dockerfile- ja docker-compose.yml-tiedostot, README:t ja käynnistysohjeet. Käytä aina multi-stage Docker buildia ja docker compose -orkestrointia.' },
};
const selectedAgents = new Set();
let sharedPrompt = localStorage.getItem('kpn-shared-prompt') || '';
@@ -2208,21 +2208,53 @@ ${Object.entries(generatedFiles).map(([n, c]) => `--- ${n} ---\n${c}`).join('\n\
if (tests) generatedFiles['test_app.py'] = tests;
pipelineStep('qa', 'Testit', 'done', 'test_app.py', tests);
// Vaihe 6: DevOps — käynnistysohjeet
// Vaihe 6: DevOps — Dockerfile
const step6 = step5 + 1;
termLog(`\n<span style="color:#d29922;font-weight:bold">[${step6}] DevOps</span> — käynnistys`);
pipelineStep('tester', 'DevOps', 'active', 'Käynnistysohjeet');
const devopsPrompt = `Write a minimal README.md for this project. Include ONLY:
1. One-line description
2. How to install (pip/uv)
3. How to run
4. How to test
Max 15 lines. No badges, no license, no contributing section.
termLog(`\n<span style="color:#d29922;font-weight:bold">[${step6}] DevOps</span> — Dockerfile`);
pipelineStep('tester', 'Dockerfile', 'active', 'Dockerfile');
const dockerPrompt = `Write a Dockerfile for this project. Use multi-stage build:
- Stage 1 (builder): install dependencies
- Stage 2 (runtime): copy only what's needed, minimal image
Use python:3.12-slim as base. EXPOSE the correct port. CMD to start the app.
Only output the Dockerfile content, nothing else.
Files: ${Object.keys(generatedFiles).join(', ')}
Main app entry: ${Object.keys(generatedFiles).find(f => f.includes('main') || f.includes('app')) || Object.keys(generatedFiles)[0]}`;
const dockerfile = await kpnRun(agentPrompts.tester.model, dockerPrompt, false, 256);
if (dockerfile) generatedFiles['Dockerfile'] = dockerfile;
pipelineStep('tester', 'Dockerfile', 'done', 'Dockerfile', dockerfile);
// Vaihe 7: DevOps — docker-compose.yml
const step7 = step6 + 1;
termLog(`\n<span style="color:#d29922;font-weight:bold">[${step7}] DevOps</span> — docker-compose.yml`);
pipelineStep('tester', 'Compose', 'active', 'docker-compose.yml');
const composePrompt = `Write a docker-compose.yml for this project. Include:
- app service (build from Dockerfile, port mapping, restart: unless-stopped)
- db service if SQLite/PostgreSQL is used (volume for data persistence)
- Named volumes for persistent data
Only output the YAML content, nothing else.
Files: ${Object.keys(generatedFiles).join(', ')}`;
const readme = await kpnRun(agentPrompts.tester.model, devopsPrompt, false, 256);
const compose = await kpnRun(agentPrompts.tester.model, composePrompt, false, 256);
if (compose) generatedFiles['docker-compose.yml'] = compose;
pipelineStep('tester', 'Compose', 'done', 'docker-compose.yml', compose);
// Vaihe 8: DevOps — README
const step8 = step7 + 1;
termLog(`\n<span style="color:#d29922;font-weight:bold">[${step8}] DevOps</span> — README`);
pipelineStep('tester', 'README', 'active', 'README.md');
const readmePrompt = `Write a minimal README.md. Include ONLY:
1. One-line description
2. Quick start: docker compose up
3. Development: how to run without Docker
4. API endpoints (if applicable)
5. How to test
Max 20 lines.
Files: ${Object.keys(generatedFiles).join(', ')}`;
const readme = await kpnRun(agentPrompts.tester.model, readmePrompt, false, 256);
if (readme) generatedFiles['README.md'] = readme;
pipelineStep('tester', 'DevOps', 'done', 'README.md', readme);
pipelineStep('tester', 'README', 'done', 'README.md', readme);
termLog(`\n<span style="color:#a371f7;font-weight:bold">━━━ Pipeline valmis (${Object.keys(generatedFiles).length} tiedostoa) ━━━</span>`);
renderProjectCard(generatedFiles, task);