diff --git a/.gitignore b/.gitignore index 7c4d4fc..f14ef6d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /devopsgen /devopsgen.exe *.exe +*.exe~ *.bin # Go diff --git a/docs/web/dist/assets/index-BUMrIfxi.css b/docs/web/dist/assets/index-BUMrIfxi.css new file mode 100644 index 0000000..3788710 --- /dev/null +++ b/docs/web/dist/assets/index-BUMrIfxi.css @@ -0,0 +1 @@ +@import "https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap";:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--ui-bg:#f3ede3;--ui-surface:#fffaf2;--ui-surface-2:#f7f0e6;--ui-text:#332820;--ui-text-soft:#5e4d3f;--ui-muted:#756455;--ui-border:#e2d5c5;--ui-border-strong:#d3c2ad;--ui-accent:#8a5b3d;--ui-accent-strong:#7a4f33;--ui-accent-soft:#efe0cf;--ui-accent-contrast:#fffaf2;--ui-badge-ok-bg:#e4ecd9;--ui-badge-ok-fg:#55683f;--ui-badge-warn-bg:#fbf0d2;--ui-badge-warn-fg:#7a5c17;--ui-badge-err-bg:#f9e2db;--ui-badge-err-fg:#8a4a38;--ui-badge-info-bg:#efe6ec;--ui-badge-info-fg:#6e4a63;--ui-note:#f4ead9;--ui-tip:#edf0e2;--ui-caution:#fbf0d2;--ui-danger:#f9e2db;--ui-code:#2d231c;--ui-code-text:#f8f1e8;--ui-code-bar:#efe2d2;--ui-code-bar-text:#5e3c27;--ui-shadow-color:#4a34261a;--ui-shadow-strong:#4a342629;--ui-radius-sm:6px;--ui-radius:10px;--ui-radius-lg:16px;--font-display:"DM Sans", ui-sans-serif, system-ui, sans-serif;--sl-font:"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--sl-font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*{scrollbar-color:var(--ui-border-strong) var(--ui-bg);box-sizing:border-box}html{scroll-behavior:smooth}body{background:var(--ui-bg);color:var(--ui-text);font-family:var(--sl-font);text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;font-size:1rem;font-weight:400;line-height:1.75}::selection{background:var(--ui-accent-soft);color:var(--ui-accent-strong)}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--ui-bg)}::-webkit-scrollbar-thumb{background:var(--ui-border-strong);border:3px solid var(--ui-bg);border-radius:999px}::-webkit-scrollbar-thumb:hover{background:var(--ui-accent)}:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px}.skip{z-index:99;background:var(--ui-accent);color:var(--ui-accent-contrast);border-radius:var(--ui-radius-sm);font-family:var(--sl-font);padding:8px 16px;font-weight:600;position:absolute;top:0;left:-9999px}.skip:focus{left:8px}.topbar{background:var(--ui-surface);border-bottom:1px solid var(--ui-border);align-items:center;gap:16px;padding:.6rem clamp(1rem,3vw,2rem);display:flex}.brand{color:var(--ui-text);align-items:center;gap:10px;text-decoration:none;display:inline-flex}.brand-mark{border-radius:var(--ui-radius);background:var(--ui-accent-soft);width:2.25rem;height:2.25rem;color:var(--ui-accent-strong);box-shadow:0 2px 8px var(--ui-shadow-color);font-family:var(--font-display);place-items:center;font-size:.95rem;font-weight:700;display:grid}.brand-name{font-family:var(--font-display);letter-spacing:-.015em;font-size:1rem;font-weight:700}.brand-sub{background:var(--ui-accent-soft);color:var(--ui-accent-strong);letter-spacing:.08em;border-radius:999px;padding:.16rem .45rem;font-size:.58rem;font-weight:700}.gh-pill{border:1px solid var(--ui-border);background:var(--ui-surface-2);height:2.25rem;box-shadow:none;color:var(--ui-text-soft);font-family:var(--sl-font);border-radius:8px;align-items:center;gap:.4rem;margin-left:auto;padding:0 1rem;font-size:.8rem;font-weight:600;text-decoration:none;transition:background .15s,border-color .15s;display:inline-flex}.gh-pill:hover{background:var(--ui-accent-soft);border-color:var(--ui-border-strong);color:var(--ui-accent-strong)}.shell{grid-template-columns:210px minmax(0,1fr);align-items:start;gap:clamp(1.5rem,3vw,2.5rem);max-width:1200px;margin:0 auto;padding:1.5rem clamp(1rem,3vw,2rem);display:grid}.sidebar{padding-block:.25rem;position:sticky;top:1.5rem}.side-home{margin-bottom:.4rem}.side-group+.side-group{margin-top:1.25rem}.group-label{color:var(--ui-muted);letter-spacing:.12em;text-transform:uppercase;margin:0 0 .4rem;padding:0 .6rem;font-size:.66rem;font-weight:700}.sidebar ul{margin:0;padding:0;list-style:none}.sidebar a,.side-link{color:var(--ui-text-soft);text-transform:capitalize;border-radius:7px;padding:.4rem .6rem;font-weight:500;line-height:1.35;text-decoration:none;transition:background .15s,color .15s;display:block}.sidebar a:hover,.side-link:hover{background:var(--ui-surface-2);color:var(--ui-text)}.sidebar a.is-active,.side-link.is-active{background:var(--ui-accent-soft);color:var(--ui-accent-strong);box-shadow:inset 3px 0 0 var(--ui-accent);font-weight:600}main{min-width:0}.page-head{margin-bottom:26px}.kicker{background:var(--ui-accent-soft);color:var(--ui-accent-strong);letter-spacing:.12em;text-transform:uppercase;border-radius:999px;margin:0 0 12px;padding:.22rem .7rem;font-size:.66rem;font-weight:700;display:inline-block}.violet{background:var(--ui-badge-info-bg);color:var(--ui-badge-info-fg)}.blue{background:var(--ui-note);color:var(--ui-text-soft)}.pink,.yellow{background:var(--ui-caution);color:var(--ui-badge-warn-fg)}h1{color:var(--ui-text);box-shadow:none;font-family:var(--font-display);letter-spacing:-.03em;overflow-wrap:anywhere;background:0 0;margin:0 0 14px;padding:0;font-size:clamp(1.9rem,3.8vw,2.6rem);font-weight:700;line-height:1.12;display:block}.lede{background:var(--ui-surface);max-width:46rem;color:var(--ui-text-soft);border:1px solid var(--ui-border);border-inline-start:3px solid var(--ui-accent);border-radius:8px;margin-block:0 8px;padding:1rem 1.25rem;font-size:1.02rem;line-height:1.7;display:block}h2{border-bottom:1px solid var(--ui-border);font-family:var(--font-display);letter-spacing:-.025em;align-items:center;gap:.6rem;margin-block:2.5rem 1rem;padding-bottom:.55rem;font-size:clamp(1.25rem,2.3vw,1.45rem);font-weight:600;display:flex}h2:before{content:"";background:var(--ui-accent);border-radius:999px;flex:none;width:.35rem;height:1.1em}h3{font-family:var(--font-display);margin-block:1.75rem .6rem;font-size:1.08rem;font-weight:600}strong{color:var(--ui-accent-strong);font-weight:600}code:not(.code-block code){background:var(--ui-surface-2);color:var(--ui-accent-strong);border:1px solid var(--ui-border);border-radius:var(--ui-radius-sm);font-family:var(--sl-font-mono);-webkit-box-decoration-break:clone;box-decoration-break:clone;padding:.08em .35em;font-size:.88em;font-weight:500}a{color:var(--ui-accent-strong);text-decoration:underline;-webkit-text-decoration-color:var(--ui-border-strong);text-decoration-color:var(--ui-border-strong);text-underline-offset:3px;text-decoration-thickness:1px}a:hover{color:var(--ui-accent);-webkit-text-decoration-color:var(--ui-accent);text-decoration-color:var(--ui-accent);background:0 0}.btn:hover,.gh-pill:hover,.sidebar a:hover,.side-link:hover{background-color:inherit}a.btn:hover{color:var(--ui-accent-contrast);background:var(--ui-accent-strong);text-decoration:none}.hero{background:var(--ui-surface);color:var(--ui-text);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:0 16px 40px var(--ui-shadow-color);grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);align-items:center;gap:clamp(1.5rem,4vw,3rem);margin:.5rem 0 2rem;padding:clamp(1.5rem,4vw,3rem);display:grid;position:relative}.hero-cta{flex-wrap:wrap;gap:.75rem;margin-top:6px;display:flex}.btn{border:1px solid var(--ui-accent);background:var(--ui-accent);color:var(--ui-accent-contrast);box-shadow:0 2px 6px var(--ui-shadow-color);border-radius:9px;padding:.6rem 1.1rem;font-weight:600;text-decoration:none;transition:background .15s,border-color .15s,box-shadow .15s,transform .15s;display:inline-block}.btn:hover{box-shadow:0 6px 16px var(--ui-shadow-strong);transform:translateY(-1px)}.btn-pink{background:var(--ui-surface-2);color:var(--ui-text);border-color:var(--ui-border)}.btn-pink:hover{background:var(--ui-accent-soft);border-color:var(--ui-border-strong);color:var(--ui-accent-strong)}.btn-yellow{background:var(--ui-surface-2);color:var(--ui-text);border-color:var(--ui-border)}.cards{grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1.25rem;display:grid}.card{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius);box-shadow:0 1px 2px var(--ui-shadow-color);color:inherit;padding:1.5rem;text-decoration:none;transition:transform .18s,box-shadow .18s,border-color .18s}.card h3{margin-top:0;font-size:.98rem}.card p,.card li{color:var(--ui-muted);font-size:.9rem;line-height:1.6}.card:hover{border-color:var(--ui-border-strong);box-shadow:0 10px 24px var(--ui-shadow-color);transform:translateY(-2px)}a.card h3{color:var(--ui-accent-strong)}.core .card:hover{border-color:var(--ui-accent)}.shot{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius);box-shadow:0 8px 24px var(--ui-shadow-color);max-width:100%;margin:22px 0;padding:10px}.shot img{border:1px solid var(--ui-border);border-radius:var(--ui-radius-sm);width:100%;height:auto;display:block}.shot figcaption{color:var(--ui-muted);margin-top:10px;font-size:.85rem;font-weight:500}.shot a:hover{color:inherit;background:0 0}.shot-feature{max-width:880px}.screen-strip{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));align-items:start;gap:22px;display:grid}.screen-strip .shot{margin:0 0 12px}.code-block{border:1px solid var(--ui-border);border-radius:var(--ui-radius);background:var(--ui-code);color:var(--ui-code-text);box-shadow:0 10px 30px var(--ui-shadow-color);margin:20px 0;position:relative;overflow:hidden}.code-label{background:var(--ui-code-bar);color:var(--ui-code-bar-text);font-family:var(--sl-font-mono);letter-spacing:.06em;text-transform:uppercase;padding:.45rem .9rem;font-size:.7rem;font-weight:600;position:absolute;top:0;left:0;right:0}.code-block pre{font-family:var(--sl-font-mono);margin:0;padding:2.2rem 18px 16px;font-size:.86rem;line-height:1.6;overflow-x:auto}.code-block code{color:inherit;font-size:inherit;background:0 0;border:0;padding:0}.table-wrap{border:1px solid var(--ui-border);border-radius:var(--ui-radius);background:var(--ui-surface);box-shadow:0 1px 2px var(--ui-shadow-color);margin:18px 0;overflow:auto}table{border-collapse:collapse;width:100%;font-size:.92rem}th,td{text-align:left;vertical-align:top;padding:.65rem .75rem}th{background:var(--ui-surface-2);color:var(--ui-muted);letter-spacing:.06em;text-transform:uppercase;font-size:.7rem;font-weight:700}td{border-top:1px solid var(--ui-border)}tbody tr:nth-child(2n) td{background:var(--ui-surface-2)}td code{white-space:nowrap}.num{font-weight:700}.badge{font-family:var(--sl-font-mono);letter-spacing:.01em;border:0;border-radius:999px;padding:.05rem .5rem;font-size:.74rem;font-weight:600;display:inline-block;transform:none}.badge-ok{background:var(--ui-badge-ok-bg);color:var(--ui-badge-ok-fg)}.badge-warn{background:var(--ui-badge-warn-bg);color:var(--ui-badge-warn-fg)}.badge-err{background:var(--ui-badge-err-bg);color:var(--ui-badge-err-fg)}.badge-info{background:var(--ui-badge-info-bg);color:var(--ui-badge-info-fg)}.kbd{border:1px solid var(--ui-border);background:var(--ui-surface-2);color:var(--ui-text);box-shadow:none;font-family:var(--sl-font-mono);border-radius:5px;padding:.1em .4em;font-size:.84rem;display:inline-block}.callout{background:var(--ui-note);color:var(--ui-text);border:1px solid var(--ui-border);border-inline-start:3px solid var(--ui-accent);border-radius:8px;margin:20px 0;padding:1rem 1.25rem;font-weight:500}.callout p{margin:0}.callout-info,.callout-ok{background:var(--ui-tip)}ul,ol{padding-inline-start:1.5rem}li::marker{color:var(--ui-accent)}.step-list{counter-reset:steps;padding-left:0;list-style:none}.step-list li{counter-increment:steps;margin-top:14px;padding-left:48px;position:relative}.step-list li:before{content:counter(steps);background:var(--ui-accent-soft);width:30px;height:30px;color:var(--ui-accent-strong);box-shadow:none;font-family:var(--font-display);border-radius:999px;place-items:center;font-weight:600;display:grid;position:absolute;top:0;left:0}.flag-name{font-family:var(--sl-font-mono);font-weight:600}.footer{max-width:1200px;color:var(--ui-muted);margin:0 auto;padding:1.5rem clamp(1rem,3vw,2rem) 2.5rem;font-size:.9rem}.footer a{color:var(--ui-accent-strong);text-decoration:underline;-webkit-text-decoration-color:var(--ui-border-strong);text-decoration-color:var(--ui-border-strong)}.footer a:hover{background:var(--ui-accent-soft)}.footer-links{margin-top:6px}.file-tree{font-family:var(--sl-font-mono);white-space:pre;font-size:.9rem;overflow-x:auto}@media (width<=900px){.shell{grid-template-columns:1fr}.sidebar{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius);flex-wrap:wrap;align-items:center;gap:.4rem;padding:.75rem 1rem;display:flex;position:static}.side-group{display:contents;margin:0!important}.sidebar ul{flex-wrap:wrap;gap:.25rem;display:flex}.group-label{margin:0 .2rem}.sidebar a,.side-link{background:var(--ui-surface-2);border-radius:999px;padding:.3rem .7rem}.sidebar a.is-active,.side-link.is-active{box-shadow:none}}@media (width<=720px){.hero{border-radius:var(--ui-radius);box-shadow:0 8px 24px var(--ui-shadow-color);grid-template-columns:1fr;padding:1.5rem}.shot,.code-block{box-shadow:0 4px 16px var(--ui-shadow-color)}th,td{padding:.5rem .55rem}}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:before,:after{transition-duration:.001ms!important;animation-duration:.001ms!important;animation-iteration-count:1!important}} diff --git a/docs/web/dist/assets/index-CVCe6Y9v.css b/docs/web/dist/assets/index-CVCe6Y9v.css deleted file mode 100644 index 58f7954..0000000 --- a/docs/web/dist/assets/index-CVCe6Y9v.css +++ /dev/null @@ -1 +0,0 @@ -:root{--paper:#faf7f0;--ink:#37322b;--outline:#4a443c;--border:3px solid var(--outline);--shadow:6px 6px 0 var(--outline);--shadow-sm:3px 3px 0 var(--outline);--yellow:#f2e3bd;--pink:#f3cfcb;--blue:#c9dced;--lime:#d3e6cf;--purple:#ddcfe9;--red-b:#e8b0a6;--green-b:#b5d9c2;--nav-bg:#3b352e;--nav-ink:#faf3e3;--font:"Segoe UI", "Verdana", "Tahoma", sans-serif;--mono:"Cascadia Code", "Consolas", "JetBrains Mono", monospace}*{box-sizing:border-box}html{scroll-behavior:smooth}body{font-family:var(--font);background:var(--paper);color:var(--ink);-webkit-font-smoothing:antialiased;margin:0;line-height:1.65}body:before{content:"";pointer-events:none;z-index:0;background-image:linear-gradient(#4a443c0d 1px,#0000 1px),linear-gradient(90deg,#4a443c0d 1px,#0000 1px);background-size:32px 32px;position:fixed;inset:0}.skip{background:var(--yellow);border:var(--border);z-index:99;padding:8px 16px;font-weight:700;position:absolute;top:0;left:-9999px}.skip:focus{left:8px}.topbar{z-index:50;background:var(--nav-bg);color:var(--nav-ink);border:var(--border);box-shadow:var(--shadow);flex-wrap:wrap;align-items:center;gap:16px;margin:8px 12px;padding:8px 14px;display:flex;position:sticky;top:8px}.brand{color:var(--nav-ink);letter-spacing:.3px;align-items:center;gap:10px;font-size:1.1rem;font-weight:800;text-decoration:none;display:inline-flex}.brand-mark{background:var(--pink);color:var(--ink);border:2px solid var(--nav-ink);padding:2px 8px;font-weight:800;transform:rotate(-1.5deg)}.brand-sub{background:var(--blue);color:var(--ink);margin-left:8px;padding:1px 6px;font-size:.62rem;transform:rotate(1deg)}.topbar nav ul{flex-wrap:wrap;gap:4px;margin:0;padding:0;list-style:none;display:flex}.nav-link{color:var(--nav-ink);text-transform:uppercase;letter-spacing:.8px;border:2px solid #0000;padding:4px 10px;font-size:.82rem;font-weight:700;text-decoration:none;display:inline-block}.nav-link:hover{background:var(--nav-ink);color:var(--nav-bg);border-color:var(--nav-ink)}.gh-pill{background:var(--yellow);color:var(--ink);border:2px solid var(--nav-ink);box-shadow:2px 2px 0 var(--nav-ink);margin-left:auto;padding:4px 14px;font-weight:800;text-decoration:none}.gh-pill:hover{box-shadow:3px 3px 0 var(--nav-ink);transform:translate(-1px,-1px)}main{z-index:1;max-width:1080px;margin:36px auto;padding:0 20px;position:relative}.page-head{margin-bottom:28px}.kicker{background:var(--lime);border:var(--border);box-shadow:var(--shadow-sm);text-transform:uppercase;letter-spacing:1.6px;margin:0 0 14px;padding:4px 12px;font-size:.75rem;font-weight:800;display:inline-block}.violet{background:var(--purple)}.blue{background:var(--blue)}.pink{background:var(--pink)}.yellow{background:var(--yellow)}h1{letter-spacing:-.5px;text-transform:uppercase;margin:0 0 16px;font-size:clamp(2.1rem,5vw,3.4rem);font-weight:800;line-height:1.08}.lede{background:var(--yellow);border:var(--border);max-width:740px;box-shadow:var(--shadow-sm);padding:12px 16px;font-size:1.12rem;display:inline-block}h2{border-left:10px solid var(--outline);margin:44px 0 14px;padding-left:12px;font-size:1.55rem;font-weight:800}h3{margin:26px 0 10px;font-size:1.12rem;font-weight:800}p,li{font-size:1.02rem}strong{background:var(--lime);padding:0 3px}code{font-family:var(--mono);background:var(--nav-bg);color:var(--nav-ink);padding:2px 6px;font-size:.92em}a{color:var(--ink);text-decoration-thickness:2px;-webkit-text-decoration-color:var(--red-b);text-decoration-color:var(--red-b)}a:hover{background:var(--pink)}.hero{grid-template-columns:1.1fr .9fr;align-items:start;gap:24px;margin-bottom:20px;display:grid}.hero-cta{flex-wrap:wrap;gap:14px;margin-top:8px;display:flex}.btn{text-transform:uppercase;border:var(--border);box-shadow:var(--shadow);background:var(--blue);color:var(--ink);padding:11px 20px;font-size:.95rem;font-weight:800;text-decoration:none;display:inline-block}.btn:hover{box-shadow:8px 8px 0 var(--outline);transform:translate(-2px,-2px)}.btn-pink{background:var(--pink)}.btn-yellow{background:var(--yellow)}.cards{grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px;display:grid}.card{border:var(--border);box-shadow:var(--shadow);background:#fffdf8;padding:18px;position:relative}.card h3{margin-top:0}.card:nth-child(3n+1){background:var(--yellow)}.card:nth-child(3n+2){background:#fffdf8}.card:nth-child(3n){background:var(--blue)}.card:hover{box-shadow:8px 8px 0 var(--outline);transform:translate(-2px,-2px)}.core .card{background:#fffdf8}.core .card:hover{background:var(--lime)}.shot{border:var(--border);box-shadow:var(--shadow);background:#fffdf8;max-width:100%;margin:22px 0;padding:12px}.shot img{border:2px solid var(--outline);width:100%;height:auto;display:block}.shot figcaption{border-top:2px dashed var(--outline);margin-top:10px;padding-top:8px;font-size:.9rem;font-weight:600}.shot a:hover{background:0 0}.shot img:hover{transform:translate(-1px,-1px)}.shot-feature{max-width:860px}.screen-strip{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));align-items:start;gap:22px;display:grid}.screen-strip .shot{margin:0 0 12px}.code-block{background:var(--nav-bg);color:var(--nav-ink);border:var(--border);box-shadow:var(--shadow);margin:18px 0;position:relative}.code-label{background:var(--purple);border:2px solid var(--outline);text-transform:uppercase;letter-spacing:1px;color:var(--ink);padding:2px 10px;font-size:.72rem;font-weight:800;position:absolute;top:-15px;left:12px}.code-block pre{font-family:var(--mono);margin:0;padding:16px 18px;font-size:.88rem;line-height:1.55;overflow-x:auto}.code-block code{color:inherit;background:0 0;padding:0}.table-wrap{border:var(--border);box-shadow:var(--shadow);background:#fffdf8;margin:18px 0;overflow-x:auto}table{border-collapse:collapse;width:100%}th,td{border:2px solid var(--outline);text-align:left;vertical-align:top;padding:10px 12px}th{background:var(--nav-bg);color:var(--nav-ink);text-transform:uppercase;letter-spacing:1px;font-size:.78rem}tbody tr:nth-child(2n) td{background:var(--yellow)}td code{white-space:nowrap}.num{font-size:1.05rem;font-weight:800}.badge{text-transform:uppercase;letter-spacing:.8px;border:2px solid var(--outline);margin-right:6px;padding:3px 10px;font-size:.78rem;font-weight:800;display:inline-block;transform:rotate(-1deg)}.badge-ok{background:var(--green-b);color:var(--ink)}.badge-warn{background:var(--yellow)}.badge-err{background:var(--red-b);color:var(--ink)}.badge-info{background:var(--blue)}.kbd{font-family:var(--mono);border:2px solid var(--outline);box-shadow:2px 2px 0 var(--outline);background:#fffdf8;padding:2px 8px;font-size:.85rem;font-weight:700;display:inline-block}.callout{border:var(--border);box-shadow:var(--shadow-sm);background:var(--pink);margin:22px 0;padding:14px 18px;font-weight:600}.callout-info{background:var(--blue)}.callout-ok{background:var(--lime)}.file-tree{font-family:var(--mono);white-space:pre;font-size:.9rem;overflow-x:auto}.footer{z-index:1;border:var(--border);box-shadow:var(--shadow);background:var(--nav-bg);color:var(--nav-ink);margin:48px 12px 12px;padding:18px 22px;font-size:.9rem;position:relative}.footer a{color:var(--yellow);-webkit-text-decoration-color:var(--yellow);text-decoration-color:var(--yellow)}.footer a:hover{background:var(--yellow);color:var(--ink)}.footer-links{margin-top:6px}ul{padding-left:22px}li+li{margin-top:4px}.step-list{counter-reset:steps;padding-left:0;list-style:none}.step-list li{counter-increment:steps;margin-top:14px;padding-left:52px;position:relative}.step-list li:before{content:counter(steps);background:var(--purple);width:32px;height:32px;color:var(--ink);border:2px solid var(--outline);box-shadow:2px 2px 0 var(--outline);place-items:center;font-weight:800;display:grid;position:absolute;top:-4px;left:0}.flag-name{font-family:var(--mono);font-weight:700}@media (width<=720px){.hero{grid-template-columns:1fr}.topbar{gap:8px}.gh-pill{margin-left:0}main{margin:18px auto}} diff --git a/docs/web/dist/assets/index--kteW9Ru.js b/docs/web/dist/assets/index-ZUvyDOPW.js similarity index 99% rename from docs/web/dist/assets/index--kteW9Ru.js rename to docs/web/dist/assets/index-ZUvyDOPW.js index 3a3ae40..c1e92fd 100644 --- a/docs/web/dist/assets/index--kteW9Ru.js +++ b/docs/web/dist/assets/index-ZUvyDOPW.js @@ -21,4 +21,4 @@ case $? in 3) devopsgen init --force --stack go --registry ghcr --image you/myapp --port 8080 ;; 2) echo "fix your flags" >&2 ;; *) echo "see devopsgen validate output" >&2 ;; -esac`}),(0,d.jsx)(`div`,{className:`callout callout-info`,children:`Codes are part of DevOpsGen's compatibility promise: bumping a major version may add new codes, but existing ones keep their meaning.`})]})}var re=`https://bangkahdev.github.io/DevOpsGen/`,x=[{path:``,component:_,title:`DevOpsGen — DevOps scaffolding for Go & Node.js projects`,description:`DevOpsGen generates production-ready Dockerfiles, GitHub Actions pipelines and Kubernetes manifests for Go and Node.js projects, with safe dry-run plans, automatic backups and config validation.`,keywords:`DevOpsGen, dockerfile generator, github actions generator, kubernetes manifests, go, nodejs, scaffolding, ci cd`,ogImage:`img/init-success.png`},{path:`getting-started`,component:v,title:`Getting Started — DevOpsGen Docs`,description:`Install DevOpsGen via go install or a release binary, then generate a complete Docker, CI and Kubernetes setup for your project with a single command.`,keywords:`DevOpsGen install, go install, quickstart, getting started`,ogImage:`img/init-success.png`},{path:`wizard`,component:y,title:`Interactive Wizard — DevOpsGen Docs`,description:`DevOpsGen launches an interactive TUI wizard that walks through stack detection, ports, container images and Kubernetes options, then writes the generated configuration.`,keywords:`DevOpsGen wizard, tui, bubbletea, interactive`,ogImage:`img/wizard.png`},{path:`init`,component:b,title:`init command — DevOpsGen Docs`,description:`Full reference for devopsgen init flags: stack, app type, CI provider, registry, image, port, Kubernetes ingress, health path, dry-run and force overwrite behaviour.`,keywords:`devopsgen init, flags, dry-run, force, image, ingress`,ogImage:`img/init-success.png`},{path:`detect`,component:ee,title:`detect command — DevOpsGen Docs`,description:`devopsgen detect inspects the current project and reports the programming stack, the files it based its decision on, and candidate application types.`,keywords:`devopsgen detect, stack detection, go.mod, package.json`,ogImage:`img/detect.png`},{path:`validate`,component:te,title:`validate command — DevOpsGen Docs`,description:`devopsgen validate statically checks generated Dockerfiles, GitHub Actions workflows and Kubernetes manifests: FROM digests, action pinning, naming rules, probes and more.`,keywords:`devopsgen validate, dockerfile lint, workflow lint, kubernetes manifest lint`,ogImage:`img/validate.png`},{path:`exit-codes`,component:ne,title:`Exit codes — DevOpsGen Docs`,description:`Every devopsgen command exits with a documented status code: 0 success, 1 general error, 2 invalid configuration, 3 file conflicts, 4 validation failure, 5 ambiguous detection.`,keywords:`devopsgen exit codes, ci integration, pipeline status`,ogImage:`img/invalid-config.png`}];function ie({rel:e,children:t}){return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(`a`,{className:`skip`,href:`#main`,children:`skip to content`}),(0,d.jsxs)(`header`,{className:`topbar`,children:[(0,d.jsxs)(`a`,{className:`brand`,href:e||`./`,children:[(0,d.jsx)(`span`,{className:`brand-mark`,children:`DG`}),(0,d.jsxs)(`span`,{children:[`DevOpsGen`,(0,d.jsx)(`span`,{className:`brand-sub`,children:`DOCS`})]})]}),(0,d.jsx)(`nav`,{"aria-label":`Main navigation`,children:(0,d.jsx)(`ul`,{children:x.filter(e=>e.path!==``).map(t=>(0,d.jsx)(`li`,{children:(0,d.jsx)(`a`,{className:e===``?`nav-link`:`nav-link nav-sub`,href:`${e}${t.path}/`,children:t.path.replace(/-/g,` `)})},t.path))})}),(0,d.jsx)(`a`,{className:`gh-pill`,href:`https://github.com/Bangkahdev/DevOpsGen`,rel:`noopener noreferrer`,target:`_blank`,children:`GitHub`})]}),(0,d.jsx)(`main`,{id:`main`,children:t}),(0,d.jsxs)(`footer`,{className:`footer`,children:[(0,d.jsxs)(`p`,{children:[`DevOpsGen — deterministic DevOps scaffolding for Go & Node.js.`,` `,(0,d.jsx)(`a`,{href:`${e}getting-started/`,children:`Get started`}),` or browse the`,` `,(0,d.jsx)(`a`,{href:`${e}exit-codes/`,children:`exit codes`}),`.`]}),(0,d.jsxs)(`p`,{className:`footer-links`,children:[(0,d.jsx)(`a`,{href:re,children:`canonical site`}),` · `,(0,d.jsx)(`a`,{href:`https://github.com/Bangkahdev/DevOpsGen`,children:`source code`})]})]})]})}var S=x.find(e=>e.path===location.pathname.replace(/\/$/,``).replace(/^.*\//,``))??null,ae=S&&S.path===``?``:`../`,oe=S??x[0];(0,l.createRoot)(document.getElementById(`root`)).render((0,d.jsx)(ie,{rel:ae,children:(0,d.jsx)(oe.component,{rel:ae})})); \ No newline at end of file +esac`}),(0,d.jsx)(`div`,{className:`callout callout-info`,children:`Codes are part of DevOpsGen's compatibility promise: bumping a major version may add new codes, but existing ones keep their meaning.`})]})}var re=`https://bangkahdev.github.io/DevOpsGen/`,x=[{path:``,component:_,title:`DevOpsGen — DevOps scaffolding for Go & Node.js projects`,description:`DevOpsGen generates production-ready Dockerfiles, GitHub Actions pipelines and Kubernetes manifests for Go and Node.js projects, with safe dry-run plans, automatic backups and config validation.`,keywords:`DevOpsGen, dockerfile generator, github actions generator, kubernetes manifests, go, nodejs, scaffolding, ci cd`,ogImage:`img/init-success.png`},{path:`getting-started`,component:v,title:`Getting Started — DevOpsGen Docs`,description:`Install DevOpsGen via go install or a release binary, then generate a complete Docker, CI and Kubernetes setup for your project with a single command.`,keywords:`DevOpsGen install, go install, quickstart, getting started`,ogImage:`img/init-success.png`},{path:`wizard`,component:y,title:`Interactive Wizard — DevOpsGen Docs`,description:`DevOpsGen launches an interactive TUI wizard that walks through stack detection, ports, container images and Kubernetes options, then writes the generated configuration.`,keywords:`DevOpsGen wizard, tui, bubbletea, interactive`,ogImage:`img/wizard.png`},{path:`init`,component:b,title:`init command — DevOpsGen Docs`,description:`Full reference for devopsgen init flags: stack, app type, CI provider, registry, image, port, Kubernetes ingress, health path, dry-run and force overwrite behaviour.`,keywords:`devopsgen init, flags, dry-run, force, image, ingress`,ogImage:`img/init-success.png`},{path:`detect`,component:ee,title:`detect command — DevOpsGen Docs`,description:`devopsgen detect inspects the current project and reports the programming stack, the files it based its decision on, and candidate application types.`,keywords:`devopsgen detect, stack detection, go.mod, package.json`,ogImage:`img/detect.png`},{path:`validate`,component:te,title:`validate command — DevOpsGen Docs`,description:`devopsgen validate statically checks generated Dockerfiles, GitHub Actions workflows and Kubernetes manifests: FROM digests, action pinning, naming rules, probes and more.`,keywords:`devopsgen validate, dockerfile lint, workflow lint, kubernetes manifest lint`,ogImage:`img/validate.png`},{path:`exit-codes`,component:ne,title:`Exit codes — DevOpsGen Docs`,description:`Every devopsgen command exits with a documented status code: 0 success, 1 general error, 2 invalid configuration, 3 file conflicts, 4 validation failure, 5 ambiguous detection.`,keywords:`devopsgen exit codes, ci integration, pipeline status`,ogImage:`img/invalid-config.png`}],ie=[{label:`Overview`,items:[`getting-started`,`wizard`]},{label:`Command reference`,items:[`init`,`detect`,`validate`]},{label:`Operations`,items:[`exit-codes`]}];function S({rel:e,activePath:t,children:n}){return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(`a`,{className:`skip`,href:`#main`,children:`skip to content`}),(0,d.jsxs)(`header`,{className:`topbar`,children:[(0,d.jsxs)(`a`,{className:`brand`,href:e||`./`,children:[(0,d.jsx)(`span`,{className:`brand-mark`,children:`DG`}),(0,d.jsx)(`span`,{className:`brand-name`,children:`DevOpsGen`}),(0,d.jsx)(`span`,{className:`brand-sub`,children:`DOCS`})]}),(0,d.jsx)(`a`,{className:`gh-pill`,href:`https://github.com/Bangkahdev/DevOpsGen`,rel:`noopener noreferrer`,target:`_blank`,children:`GitHub`})]}),(0,d.jsxs)(`div`,{className:`shell`,children:[(0,d.jsxs)(`aside`,{className:`sidebar`,"aria-label":`Documentation navigation`,children:[(0,d.jsx)(`a`,{className:`side-link side-home${t===``?` is-active`:``}`,href:e||`./`,children:`Home`}),ie.map(n=>(0,d.jsxs)(`div`,{className:`side-group`,children:[(0,d.jsx)(`p`,{className:`group-label`,children:n.label}),(0,d.jsx)(`ul`,{children:n.items.map(n=>{let r=x.find(e=>e.path===n);return(0,d.jsx)(`li`,{children:(0,d.jsx)(`a`,{className:`side-link${t===n?` is-active`:``}`,href:`${e}${n}/`,"aria-current":t===n?`page`:void 0,children:r?r.path.replace(/-/g,` `):n})},n)})})]},n.label))]}),(0,d.jsx)(`main`,{id:`main`,children:n})]}),(0,d.jsxs)(`footer`,{className:`footer`,children:[(0,d.jsxs)(`p`,{children:[`DevOpsGen — deterministic DevOps scaffolding for Go & Node.js.`,` `,(0,d.jsx)(`a`,{href:`${e}getting-started/`,children:`Get started`}),` or browse the`,` `,(0,d.jsx)(`a`,{href:`${e}exit-codes/`,children:`exit codes`}),`.`]}),(0,d.jsxs)(`p`,{className:`footer-links`,children:[(0,d.jsx)(`a`,{href:re,children:`canonical site`}),` · `,(0,d.jsx)(`a`,{href:`https://github.com/Bangkahdev/DevOpsGen`,children:`source code`})]})]})]})}var ae=x.find(e=>e.path===location.pathname.replace(/\/$/,``).replace(/^.*\//,``))??null,oe=ae&&ae.path===``?``:`../`,se=ae??x[0];(0,l.createRoot)(document.getElementById(`root`)).render((0,d.jsx)(S,{rel:oe,activePath:ae?ae.path:``,children:(0,d.jsx)(se.component,{rel:oe})})); \ No newline at end of file diff --git a/docs/web/dist/assets/site.css b/docs/web/dist/assets/site.css index 58f7954..3788710 100644 --- a/docs/web/dist/assets/site.css +++ b/docs/web/dist/assets/site.css @@ -1 +1 @@ -:root{--paper:#faf7f0;--ink:#37322b;--outline:#4a443c;--border:3px solid var(--outline);--shadow:6px 6px 0 var(--outline);--shadow-sm:3px 3px 0 var(--outline);--yellow:#f2e3bd;--pink:#f3cfcb;--blue:#c9dced;--lime:#d3e6cf;--purple:#ddcfe9;--red-b:#e8b0a6;--green-b:#b5d9c2;--nav-bg:#3b352e;--nav-ink:#faf3e3;--font:"Segoe UI", "Verdana", "Tahoma", sans-serif;--mono:"Cascadia Code", "Consolas", "JetBrains Mono", monospace}*{box-sizing:border-box}html{scroll-behavior:smooth}body{font-family:var(--font);background:var(--paper);color:var(--ink);-webkit-font-smoothing:antialiased;margin:0;line-height:1.65}body:before{content:"";pointer-events:none;z-index:0;background-image:linear-gradient(#4a443c0d 1px,#0000 1px),linear-gradient(90deg,#4a443c0d 1px,#0000 1px);background-size:32px 32px;position:fixed;inset:0}.skip{background:var(--yellow);border:var(--border);z-index:99;padding:8px 16px;font-weight:700;position:absolute;top:0;left:-9999px}.skip:focus{left:8px}.topbar{z-index:50;background:var(--nav-bg);color:var(--nav-ink);border:var(--border);box-shadow:var(--shadow);flex-wrap:wrap;align-items:center;gap:16px;margin:8px 12px;padding:8px 14px;display:flex;position:sticky;top:8px}.brand{color:var(--nav-ink);letter-spacing:.3px;align-items:center;gap:10px;font-size:1.1rem;font-weight:800;text-decoration:none;display:inline-flex}.brand-mark{background:var(--pink);color:var(--ink);border:2px solid var(--nav-ink);padding:2px 8px;font-weight:800;transform:rotate(-1.5deg)}.brand-sub{background:var(--blue);color:var(--ink);margin-left:8px;padding:1px 6px;font-size:.62rem;transform:rotate(1deg)}.topbar nav ul{flex-wrap:wrap;gap:4px;margin:0;padding:0;list-style:none;display:flex}.nav-link{color:var(--nav-ink);text-transform:uppercase;letter-spacing:.8px;border:2px solid #0000;padding:4px 10px;font-size:.82rem;font-weight:700;text-decoration:none;display:inline-block}.nav-link:hover{background:var(--nav-ink);color:var(--nav-bg);border-color:var(--nav-ink)}.gh-pill{background:var(--yellow);color:var(--ink);border:2px solid var(--nav-ink);box-shadow:2px 2px 0 var(--nav-ink);margin-left:auto;padding:4px 14px;font-weight:800;text-decoration:none}.gh-pill:hover{box-shadow:3px 3px 0 var(--nav-ink);transform:translate(-1px,-1px)}main{z-index:1;max-width:1080px;margin:36px auto;padding:0 20px;position:relative}.page-head{margin-bottom:28px}.kicker{background:var(--lime);border:var(--border);box-shadow:var(--shadow-sm);text-transform:uppercase;letter-spacing:1.6px;margin:0 0 14px;padding:4px 12px;font-size:.75rem;font-weight:800;display:inline-block}.violet{background:var(--purple)}.blue{background:var(--blue)}.pink{background:var(--pink)}.yellow{background:var(--yellow)}h1{letter-spacing:-.5px;text-transform:uppercase;margin:0 0 16px;font-size:clamp(2.1rem,5vw,3.4rem);font-weight:800;line-height:1.08}.lede{background:var(--yellow);border:var(--border);max-width:740px;box-shadow:var(--shadow-sm);padding:12px 16px;font-size:1.12rem;display:inline-block}h2{border-left:10px solid var(--outline);margin:44px 0 14px;padding-left:12px;font-size:1.55rem;font-weight:800}h3{margin:26px 0 10px;font-size:1.12rem;font-weight:800}p,li{font-size:1.02rem}strong{background:var(--lime);padding:0 3px}code{font-family:var(--mono);background:var(--nav-bg);color:var(--nav-ink);padding:2px 6px;font-size:.92em}a{color:var(--ink);text-decoration-thickness:2px;-webkit-text-decoration-color:var(--red-b);text-decoration-color:var(--red-b)}a:hover{background:var(--pink)}.hero{grid-template-columns:1.1fr .9fr;align-items:start;gap:24px;margin-bottom:20px;display:grid}.hero-cta{flex-wrap:wrap;gap:14px;margin-top:8px;display:flex}.btn{text-transform:uppercase;border:var(--border);box-shadow:var(--shadow);background:var(--blue);color:var(--ink);padding:11px 20px;font-size:.95rem;font-weight:800;text-decoration:none;display:inline-block}.btn:hover{box-shadow:8px 8px 0 var(--outline);transform:translate(-2px,-2px)}.btn-pink{background:var(--pink)}.btn-yellow{background:var(--yellow)}.cards{grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px;display:grid}.card{border:var(--border);box-shadow:var(--shadow);background:#fffdf8;padding:18px;position:relative}.card h3{margin-top:0}.card:nth-child(3n+1){background:var(--yellow)}.card:nth-child(3n+2){background:#fffdf8}.card:nth-child(3n){background:var(--blue)}.card:hover{box-shadow:8px 8px 0 var(--outline);transform:translate(-2px,-2px)}.core .card{background:#fffdf8}.core .card:hover{background:var(--lime)}.shot{border:var(--border);box-shadow:var(--shadow);background:#fffdf8;max-width:100%;margin:22px 0;padding:12px}.shot img{border:2px solid var(--outline);width:100%;height:auto;display:block}.shot figcaption{border-top:2px dashed var(--outline);margin-top:10px;padding-top:8px;font-size:.9rem;font-weight:600}.shot a:hover{background:0 0}.shot img:hover{transform:translate(-1px,-1px)}.shot-feature{max-width:860px}.screen-strip{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));align-items:start;gap:22px;display:grid}.screen-strip .shot{margin:0 0 12px}.code-block{background:var(--nav-bg);color:var(--nav-ink);border:var(--border);box-shadow:var(--shadow);margin:18px 0;position:relative}.code-label{background:var(--purple);border:2px solid var(--outline);text-transform:uppercase;letter-spacing:1px;color:var(--ink);padding:2px 10px;font-size:.72rem;font-weight:800;position:absolute;top:-15px;left:12px}.code-block pre{font-family:var(--mono);margin:0;padding:16px 18px;font-size:.88rem;line-height:1.55;overflow-x:auto}.code-block code{color:inherit;background:0 0;padding:0}.table-wrap{border:var(--border);box-shadow:var(--shadow);background:#fffdf8;margin:18px 0;overflow-x:auto}table{border-collapse:collapse;width:100%}th,td{border:2px solid var(--outline);text-align:left;vertical-align:top;padding:10px 12px}th{background:var(--nav-bg);color:var(--nav-ink);text-transform:uppercase;letter-spacing:1px;font-size:.78rem}tbody tr:nth-child(2n) td{background:var(--yellow)}td code{white-space:nowrap}.num{font-size:1.05rem;font-weight:800}.badge{text-transform:uppercase;letter-spacing:.8px;border:2px solid var(--outline);margin-right:6px;padding:3px 10px;font-size:.78rem;font-weight:800;display:inline-block;transform:rotate(-1deg)}.badge-ok{background:var(--green-b);color:var(--ink)}.badge-warn{background:var(--yellow)}.badge-err{background:var(--red-b);color:var(--ink)}.badge-info{background:var(--blue)}.kbd{font-family:var(--mono);border:2px solid var(--outline);box-shadow:2px 2px 0 var(--outline);background:#fffdf8;padding:2px 8px;font-size:.85rem;font-weight:700;display:inline-block}.callout{border:var(--border);box-shadow:var(--shadow-sm);background:var(--pink);margin:22px 0;padding:14px 18px;font-weight:600}.callout-info{background:var(--blue)}.callout-ok{background:var(--lime)}.file-tree{font-family:var(--mono);white-space:pre;font-size:.9rem;overflow-x:auto}.footer{z-index:1;border:var(--border);box-shadow:var(--shadow);background:var(--nav-bg);color:var(--nav-ink);margin:48px 12px 12px;padding:18px 22px;font-size:.9rem;position:relative}.footer a{color:var(--yellow);-webkit-text-decoration-color:var(--yellow);text-decoration-color:var(--yellow)}.footer a:hover{background:var(--yellow);color:var(--ink)}.footer-links{margin-top:6px}ul{padding-left:22px}li+li{margin-top:4px}.step-list{counter-reset:steps;padding-left:0;list-style:none}.step-list li{counter-increment:steps;margin-top:14px;padding-left:52px;position:relative}.step-list li:before{content:counter(steps);background:var(--purple);width:32px;height:32px;color:var(--ink);border:2px solid var(--outline);box-shadow:2px 2px 0 var(--outline);place-items:center;font-weight:800;display:grid;position:absolute;top:-4px;left:0}.flag-name{font-family:var(--mono);font-weight:700}@media (width<=720px){.hero{grid-template-columns:1fr}.topbar{gap:8px}.gh-pill{margin-left:0}main{margin:18px auto}} +@import "https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap";:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--ui-bg:#f3ede3;--ui-surface:#fffaf2;--ui-surface-2:#f7f0e6;--ui-text:#332820;--ui-text-soft:#5e4d3f;--ui-muted:#756455;--ui-border:#e2d5c5;--ui-border-strong:#d3c2ad;--ui-accent:#8a5b3d;--ui-accent-strong:#7a4f33;--ui-accent-soft:#efe0cf;--ui-accent-contrast:#fffaf2;--ui-badge-ok-bg:#e4ecd9;--ui-badge-ok-fg:#55683f;--ui-badge-warn-bg:#fbf0d2;--ui-badge-warn-fg:#7a5c17;--ui-badge-err-bg:#f9e2db;--ui-badge-err-fg:#8a4a38;--ui-badge-info-bg:#efe6ec;--ui-badge-info-fg:#6e4a63;--ui-note:#f4ead9;--ui-tip:#edf0e2;--ui-caution:#fbf0d2;--ui-danger:#f9e2db;--ui-code:#2d231c;--ui-code-text:#f8f1e8;--ui-code-bar:#efe2d2;--ui-code-bar-text:#5e3c27;--ui-shadow-color:#4a34261a;--ui-shadow-strong:#4a342629;--ui-radius-sm:6px;--ui-radius:10px;--ui-radius-lg:16px;--font-display:"DM Sans", ui-sans-serif, system-ui, sans-serif;--sl-font:"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;--sl-font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*{scrollbar-color:var(--ui-border-strong) var(--ui-bg);box-sizing:border-box}html{scroll-behavior:smooth}body{background:var(--ui-bg);color:var(--ui-text);font-family:var(--sl-font);text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;font-size:1rem;font-weight:400;line-height:1.75}::selection{background:var(--ui-accent-soft);color:var(--ui-accent-strong)}::-webkit-scrollbar{width:12px;height:12px}::-webkit-scrollbar-track{background:var(--ui-bg)}::-webkit-scrollbar-thumb{background:var(--ui-border-strong);border:3px solid var(--ui-bg);border-radius:999px}::-webkit-scrollbar-thumb:hover{background:var(--ui-accent)}:focus-visible{outline:2px solid var(--ui-accent);outline-offset:3px}.skip{z-index:99;background:var(--ui-accent);color:var(--ui-accent-contrast);border-radius:var(--ui-radius-sm);font-family:var(--sl-font);padding:8px 16px;font-weight:600;position:absolute;top:0;left:-9999px}.skip:focus{left:8px}.topbar{background:var(--ui-surface);border-bottom:1px solid var(--ui-border);align-items:center;gap:16px;padding:.6rem clamp(1rem,3vw,2rem);display:flex}.brand{color:var(--ui-text);align-items:center;gap:10px;text-decoration:none;display:inline-flex}.brand-mark{border-radius:var(--ui-radius);background:var(--ui-accent-soft);width:2.25rem;height:2.25rem;color:var(--ui-accent-strong);box-shadow:0 2px 8px var(--ui-shadow-color);font-family:var(--font-display);place-items:center;font-size:.95rem;font-weight:700;display:grid}.brand-name{font-family:var(--font-display);letter-spacing:-.015em;font-size:1rem;font-weight:700}.brand-sub{background:var(--ui-accent-soft);color:var(--ui-accent-strong);letter-spacing:.08em;border-radius:999px;padding:.16rem .45rem;font-size:.58rem;font-weight:700}.gh-pill{border:1px solid var(--ui-border);background:var(--ui-surface-2);height:2.25rem;box-shadow:none;color:var(--ui-text-soft);font-family:var(--sl-font);border-radius:8px;align-items:center;gap:.4rem;margin-left:auto;padding:0 1rem;font-size:.8rem;font-weight:600;text-decoration:none;transition:background .15s,border-color .15s;display:inline-flex}.gh-pill:hover{background:var(--ui-accent-soft);border-color:var(--ui-border-strong);color:var(--ui-accent-strong)}.shell{grid-template-columns:210px minmax(0,1fr);align-items:start;gap:clamp(1.5rem,3vw,2.5rem);max-width:1200px;margin:0 auto;padding:1.5rem clamp(1rem,3vw,2rem);display:grid}.sidebar{padding-block:.25rem;position:sticky;top:1.5rem}.side-home{margin-bottom:.4rem}.side-group+.side-group{margin-top:1.25rem}.group-label{color:var(--ui-muted);letter-spacing:.12em;text-transform:uppercase;margin:0 0 .4rem;padding:0 .6rem;font-size:.66rem;font-weight:700}.sidebar ul{margin:0;padding:0;list-style:none}.sidebar a,.side-link{color:var(--ui-text-soft);text-transform:capitalize;border-radius:7px;padding:.4rem .6rem;font-weight:500;line-height:1.35;text-decoration:none;transition:background .15s,color .15s;display:block}.sidebar a:hover,.side-link:hover{background:var(--ui-surface-2);color:var(--ui-text)}.sidebar a.is-active,.side-link.is-active{background:var(--ui-accent-soft);color:var(--ui-accent-strong);box-shadow:inset 3px 0 0 var(--ui-accent);font-weight:600}main{min-width:0}.page-head{margin-bottom:26px}.kicker{background:var(--ui-accent-soft);color:var(--ui-accent-strong);letter-spacing:.12em;text-transform:uppercase;border-radius:999px;margin:0 0 12px;padding:.22rem .7rem;font-size:.66rem;font-weight:700;display:inline-block}.violet{background:var(--ui-badge-info-bg);color:var(--ui-badge-info-fg)}.blue{background:var(--ui-note);color:var(--ui-text-soft)}.pink,.yellow{background:var(--ui-caution);color:var(--ui-badge-warn-fg)}h1{color:var(--ui-text);box-shadow:none;font-family:var(--font-display);letter-spacing:-.03em;overflow-wrap:anywhere;background:0 0;margin:0 0 14px;padding:0;font-size:clamp(1.9rem,3.8vw,2.6rem);font-weight:700;line-height:1.12;display:block}.lede{background:var(--ui-surface);max-width:46rem;color:var(--ui-text-soft);border:1px solid var(--ui-border);border-inline-start:3px solid var(--ui-accent);border-radius:8px;margin-block:0 8px;padding:1rem 1.25rem;font-size:1.02rem;line-height:1.7;display:block}h2{border-bottom:1px solid var(--ui-border);font-family:var(--font-display);letter-spacing:-.025em;align-items:center;gap:.6rem;margin-block:2.5rem 1rem;padding-bottom:.55rem;font-size:clamp(1.25rem,2.3vw,1.45rem);font-weight:600;display:flex}h2:before{content:"";background:var(--ui-accent);border-radius:999px;flex:none;width:.35rem;height:1.1em}h3{font-family:var(--font-display);margin-block:1.75rem .6rem;font-size:1.08rem;font-weight:600}strong{color:var(--ui-accent-strong);font-weight:600}code:not(.code-block code){background:var(--ui-surface-2);color:var(--ui-accent-strong);border:1px solid var(--ui-border);border-radius:var(--ui-radius-sm);font-family:var(--sl-font-mono);-webkit-box-decoration-break:clone;box-decoration-break:clone;padding:.08em .35em;font-size:.88em;font-weight:500}a{color:var(--ui-accent-strong);text-decoration:underline;-webkit-text-decoration-color:var(--ui-border-strong);text-decoration-color:var(--ui-border-strong);text-underline-offset:3px;text-decoration-thickness:1px}a:hover{color:var(--ui-accent);-webkit-text-decoration-color:var(--ui-accent);text-decoration-color:var(--ui-accent);background:0 0}.btn:hover,.gh-pill:hover,.sidebar a:hover,.side-link:hover{background-color:inherit}a.btn:hover{color:var(--ui-accent-contrast);background:var(--ui-accent-strong);text-decoration:none}.hero{background:var(--ui-surface);color:var(--ui-text);border:1px solid var(--ui-border);border-radius:var(--ui-radius-lg);box-shadow:0 16px 40px var(--ui-shadow-color);grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);align-items:center;gap:clamp(1.5rem,4vw,3rem);margin:.5rem 0 2rem;padding:clamp(1.5rem,4vw,3rem);display:grid;position:relative}.hero-cta{flex-wrap:wrap;gap:.75rem;margin-top:6px;display:flex}.btn{border:1px solid var(--ui-accent);background:var(--ui-accent);color:var(--ui-accent-contrast);box-shadow:0 2px 6px var(--ui-shadow-color);border-radius:9px;padding:.6rem 1.1rem;font-weight:600;text-decoration:none;transition:background .15s,border-color .15s,box-shadow .15s,transform .15s;display:inline-block}.btn:hover{box-shadow:0 6px 16px var(--ui-shadow-strong);transform:translateY(-1px)}.btn-pink{background:var(--ui-surface-2);color:var(--ui-text);border-color:var(--ui-border)}.btn-pink:hover{background:var(--ui-accent-soft);border-color:var(--ui-border-strong);color:var(--ui-accent-strong)}.btn-yellow{background:var(--ui-surface-2);color:var(--ui-text);border-color:var(--ui-border)}.cards{grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1.25rem;display:grid}.card{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius);box-shadow:0 1px 2px var(--ui-shadow-color);color:inherit;padding:1.5rem;text-decoration:none;transition:transform .18s,box-shadow .18s,border-color .18s}.card h3{margin-top:0;font-size:.98rem}.card p,.card li{color:var(--ui-muted);font-size:.9rem;line-height:1.6}.card:hover{border-color:var(--ui-border-strong);box-shadow:0 10px 24px var(--ui-shadow-color);transform:translateY(-2px)}a.card h3{color:var(--ui-accent-strong)}.core .card:hover{border-color:var(--ui-accent)}.shot{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius);box-shadow:0 8px 24px var(--ui-shadow-color);max-width:100%;margin:22px 0;padding:10px}.shot img{border:1px solid var(--ui-border);border-radius:var(--ui-radius-sm);width:100%;height:auto;display:block}.shot figcaption{color:var(--ui-muted);margin-top:10px;font-size:.85rem;font-weight:500}.shot a:hover{color:inherit;background:0 0}.shot-feature{max-width:880px}.screen-strip{grid-template-columns:repeat(auto-fit,minmax(300px,1fr));align-items:start;gap:22px;display:grid}.screen-strip .shot{margin:0 0 12px}.code-block{border:1px solid var(--ui-border);border-radius:var(--ui-radius);background:var(--ui-code);color:var(--ui-code-text);box-shadow:0 10px 30px var(--ui-shadow-color);margin:20px 0;position:relative;overflow:hidden}.code-label{background:var(--ui-code-bar);color:var(--ui-code-bar-text);font-family:var(--sl-font-mono);letter-spacing:.06em;text-transform:uppercase;padding:.45rem .9rem;font-size:.7rem;font-weight:600;position:absolute;top:0;left:0;right:0}.code-block pre{font-family:var(--sl-font-mono);margin:0;padding:2.2rem 18px 16px;font-size:.86rem;line-height:1.6;overflow-x:auto}.code-block code{color:inherit;font-size:inherit;background:0 0;border:0;padding:0}.table-wrap{border:1px solid var(--ui-border);border-radius:var(--ui-radius);background:var(--ui-surface);box-shadow:0 1px 2px var(--ui-shadow-color);margin:18px 0;overflow:auto}table{border-collapse:collapse;width:100%;font-size:.92rem}th,td{text-align:left;vertical-align:top;padding:.65rem .75rem}th{background:var(--ui-surface-2);color:var(--ui-muted);letter-spacing:.06em;text-transform:uppercase;font-size:.7rem;font-weight:700}td{border-top:1px solid var(--ui-border)}tbody tr:nth-child(2n) td{background:var(--ui-surface-2)}td code{white-space:nowrap}.num{font-weight:700}.badge{font-family:var(--sl-font-mono);letter-spacing:.01em;border:0;border-radius:999px;padding:.05rem .5rem;font-size:.74rem;font-weight:600;display:inline-block;transform:none}.badge-ok{background:var(--ui-badge-ok-bg);color:var(--ui-badge-ok-fg)}.badge-warn{background:var(--ui-badge-warn-bg);color:var(--ui-badge-warn-fg)}.badge-err{background:var(--ui-badge-err-bg);color:var(--ui-badge-err-fg)}.badge-info{background:var(--ui-badge-info-bg);color:var(--ui-badge-info-fg)}.kbd{border:1px solid var(--ui-border);background:var(--ui-surface-2);color:var(--ui-text);box-shadow:none;font-family:var(--sl-font-mono);border-radius:5px;padding:.1em .4em;font-size:.84rem;display:inline-block}.callout{background:var(--ui-note);color:var(--ui-text);border:1px solid var(--ui-border);border-inline-start:3px solid var(--ui-accent);border-radius:8px;margin:20px 0;padding:1rem 1.25rem;font-weight:500}.callout p{margin:0}.callout-info,.callout-ok{background:var(--ui-tip)}ul,ol{padding-inline-start:1.5rem}li::marker{color:var(--ui-accent)}.step-list{counter-reset:steps;padding-left:0;list-style:none}.step-list li{counter-increment:steps;margin-top:14px;padding-left:48px;position:relative}.step-list li:before{content:counter(steps);background:var(--ui-accent-soft);width:30px;height:30px;color:var(--ui-accent-strong);box-shadow:none;font-family:var(--font-display);border-radius:999px;place-items:center;font-weight:600;display:grid;position:absolute;top:0;left:0}.flag-name{font-family:var(--sl-font-mono);font-weight:600}.footer{max-width:1200px;color:var(--ui-muted);margin:0 auto;padding:1.5rem clamp(1rem,3vw,2rem) 2.5rem;font-size:.9rem}.footer a{color:var(--ui-accent-strong);text-decoration:underline;-webkit-text-decoration-color:var(--ui-border-strong);text-decoration-color:var(--ui-border-strong)}.footer a:hover{background:var(--ui-accent-soft)}.footer-links{margin-top:6px}.file-tree{font-family:var(--sl-font-mono);white-space:pre;font-size:.9rem;overflow-x:auto}@media (width<=900px){.shell{grid-template-columns:1fr}.sidebar{background:var(--ui-surface);border:1px solid var(--ui-border);border-radius:var(--ui-radius);flex-wrap:wrap;align-items:center;gap:.4rem;padding:.75rem 1rem;display:flex;position:static}.side-group{display:contents;margin:0!important}.sidebar ul{flex-wrap:wrap;gap:.25rem;display:flex}.group-label{margin:0 .2rem}.sidebar a,.side-link{background:var(--ui-surface-2);border-radius:999px;padding:.3rem .7rem}.sidebar a.is-active,.side-link.is-active{box-shadow:none}}@media (width<=720px){.hero{border-radius:var(--ui-radius);box-shadow:0 8px 24px var(--ui-shadow-color);grid-template-columns:1fr;padding:1.5rem}.shot,.code-block{box-shadow:0 4px 16px var(--ui-shadow-color)}th,td{padding:.5rem .55rem}}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:before,:after{transition-duration:.001ms!important;animation-duration:.001ms!important;animation-iteration-count:1!important}} diff --git a/docs/web/dist/detect/index.html b/docs/web/dist/detect/index.html index 0773353..3cb7f81 100644 --- a/docs/web/dist/detect/index.html +++ b/docs/web/dist/detect/index.html @@ -21,6 +21,6 @@ -
DGDevOpsGenDOCSGitHub

command reference

devopsgen detect

Inspect the current project and report what DevOpsGen would scaffold for it: the programming stack, the exact files that shaped the decision, and the candidate application types.

devopsgen detect output in a terminal reporting stack go with indicators go.mod
devopsgen detect inside a Go module — chain of evidence straight from the filesystem.

Reading the output

LineMeaning
stack: goThe detected programming stack (go or nodejs).
indicators: go.mod, ...The files that produced evidence — your audit trail for why the stack matched.
app-type candidates: binaryApplication types plausible for this project; the wizard default comes from here too.

How it decides

Detection semantics: DevOpsGen detects in the current working directory, not in --output-dir. Run it from the project you want scanned.
+
DGDevOpsGenDOCSGitHub

command reference

devopsgen detect

Inspect the current project and report what DevOpsGen would scaffold for it: the programming stack, the exact files that shaped the decision, and the candidate application types.

devopsgen detect output in a terminal reporting stack go with indicators go.mod
devopsgen detect inside a Go module — chain of evidence straight from the filesystem.

Reading the output

LineMeaning
stack: goThe detected programming stack (go or nodejs).
indicators: go.mod, ...The files that produced evidence — your audit trail for why the stack matched.
app-type candidates: binaryApplication types plausible for this project; the wizard default comes from here too.

How it decides

Detection semantics: DevOpsGen detects in the current working directory, not in --output-dir. Run it from the project you want scanned.
\ No newline at end of file diff --git a/docs/web/dist/exit-codes/index.html b/docs/web/dist/exit-codes/index.html index a4cb6b7..3f78490 100644 --- a/docs/web/dist/exit-codes/index.html +++ b/docs/web/dist/exit-codes/index.html @@ -21,12 +21,12 @@ -
DGDevOpsGenDOCSGitHub

ci integration

Exit codes

Every DevOpsGen command exits with a stable, documented status code so shells, scripts and CI jobs can branch deterministically — no output parsing required.

CodeClassificationMeaningTypical example
0successEverything requested completed; dry-run plans that resolved cleanly also end here.init created 5 files; --dry-run --force plan is green.
1general errorUnexpected failure — I/O errors, template issues, or a run that failed mid-write and rolled back.Disk full while writing deployment.yaml.
2invalid inputConfiguration failed validation before anything was planned or written.--image BANGKAH/my-app; port -1; Ingress without host.
3conflictTarget files already exist and would be overwritten; nothing was written. Retried with --force.Second init without --force.
4validation failedGenerated documents exist but do not pass static lint rules.Unpinned workflow action in ci.yaml.
5detectionStack detection was ambiguous or found nothing at all.Empty directory without go.mod / package.json.

In practice

devopsgen exiting with code 2 after failing image validation
Exit 2 — config rejected before planning.
devopsgen exiting with code 3 on existing files
Exit 3 — conflict, nothing written.
shell script branching
devopsgen init --stack go --registry ghcr --image you/myapp --port 8080
+
DGDevOpsGenDOCSGitHub

ci integration

Exit codes

Every DevOpsGen command exits with a stable, documented status code so shells, scripts and CI jobs can branch deterministically — no output parsing required.

CodeClassificationMeaningTypical example
0successEverything requested completed; dry-run plans that resolved cleanly also end here.init created 5 files; --dry-run --force plan is green.
1general errorUnexpected failure — I/O errors, template issues, or a run that failed mid-write and rolled back.Disk full while writing deployment.yaml.
2invalid inputConfiguration failed validation before anything was planned or written.--image BANGKAH/my-app; port -1; Ingress without host.
3conflictTarget files already exist and would be overwritten; nothing was written. Retried with --force.Second init without --force.
4validation failedGenerated documents exist but do not pass static lint rules.Unpinned workflow action in ci.yaml.
5detectionStack detection was ambiguous or found nothing at all.Empty directory without go.mod / package.json.

In practice

devopsgen exiting with code 2 after failing image validation
Exit 2 — config rejected before planning.
devopsgen exiting with code 3 on existing files
Exit 3 — conflict, nothing written.
shell script branching
devopsgen init --stack go --registry ghcr --image you/myapp --port 8080
 case $? in
   0) echo "ready" ;;
   3) devopsgen init --force --stack go --registry ghcr --image you/myapp --port 8080 ;;
   2) echo "fix your flags" >&2 ;;
   *) echo "see devopsgen validate output" >&2 ;;
-esac
Codes are part of DevOpsGen's compatibility promise: bumping a major version may add new codes, but existing ones keep their meaning.
+esac
Codes are part of DevOpsGen's compatibility promise: bumping a major version may add new codes, but existing ones keep their meaning.
\ No newline at end of file diff --git a/docs/web/dist/getting-started/index.html b/docs/web/dist/getting-started/index.html index 5b2cb75..24d86da 100644 --- a/docs/web/dist/getting-started/index.html +++ b/docs/web/dist/getting-started/index.html @@ -21,12 +21,12 @@ -
DGDevOpsGenDOCSGitHub

getting started

Zero to CI in one command

Install DevOpsGen, point it at any Go or Node.js project, and get a full Docker + GitHub Actions + Kubernetes baseline in seconds.

Install

go install (go 1.22+)
go install devopsgen.dev/devopsgen@latest

Or grab a prebuilt binary from the project GitHub releases, or build from source:

from source
git clone https://github.com/Bangkahdev/DevOpsGen.git
+
DGDevOpsGenDOCSGitHub

getting started

Zero to CI in one command

Install DevOpsGen, point it at any Go or Node.js project, and get a full Docker + GitHub Actions + Kubernetes baseline in seconds.

Install

go install (go 1.22+)
go install devopsgen.dev/devopsgen@latest

Or grab a prebuilt binary from the project GitHub releases, or build from source:

from source
git clone https://github.com/Bangkahdev/DevOpsGen.git
 cd DevOpsGen
 make build

Two ways to run it

  • Interactive: run devopsgen init in a terminal — the wizard detects your stack and interviews you step by step.
  • Headless: pass every required parameter as flags — the process never waits for stdin, which makes it script- and CI-friendly.

Headless quickstart

inside your project
devopsgen init   --stack go   --ci github-actions   --registry ghcr   --image you/myapp   --port 8080
Terminal capture of devopsgen init completing successfully and reporting five files created
A successful first run — five files created, exit code 0.

Inside a Go project this writes:

what you get
.github/workflows/ci.yaml   # test, vet, build, docker publish
 Kubernetes/deployment.yaml  # non-root, probes, DNS-1053 names
 Kubernetes/service.yaml     # cluster service
 Kubernetes/ingress.yaml     # optional, needs --ingress
-Dockerfile                  # hardened multi-stage build + .dockerignore
Second runs are safe: DevOpsGen refuses to overwrite without --force and exits with code 3 — see the init reference.

Next steps

+Dockerfile # hardened multi-stage build + .dockerignore
Second runs are safe: DevOpsGen refuses to overwrite without --force and exits with code 3 — see the init reference.

Next steps

\ No newline at end of file diff --git a/docs/web/dist/img/detect.png b/docs/web/dist/img/detect.png index f60b80a..59d7ee3 100644 Binary files a/docs/web/dist/img/detect.png and b/docs/web/dist/img/detect.png differ diff --git a/docs/web/dist/img/dry-run-force.png b/docs/web/dist/img/dry-run-force.png index 55ea52b..fa49ac3 100644 Binary files a/docs/web/dist/img/dry-run-force.png and b/docs/web/dist/img/dry-run-force.png differ diff --git a/docs/web/dist/img/dry-run.png b/docs/web/dist/img/dry-run.png index 9a3bd6e..239b232 100644 Binary files a/docs/web/dist/img/dry-run.png and b/docs/web/dist/img/dry-run.png differ diff --git a/docs/web/dist/img/help.png b/docs/web/dist/img/help.png index 9ad0437..6667182 100644 Binary files a/docs/web/dist/img/help.png and b/docs/web/dist/img/help.png differ diff --git a/docs/web/dist/img/init-conflict.png b/docs/web/dist/img/init-conflict.png index 0be48f9..5bc87d0 100644 Binary files a/docs/web/dist/img/init-conflict.png and b/docs/web/dist/img/init-conflict.png differ diff --git a/docs/web/dist/img/init-success.png b/docs/web/dist/img/init-success.png index 0be48f9..4245708 100644 Binary files a/docs/web/dist/img/init-success.png and b/docs/web/dist/img/init-success.png differ diff --git a/docs/web/dist/img/invalid-config.png b/docs/web/dist/img/invalid-config.png index 97795c1..15681aa 100644 Binary files a/docs/web/dist/img/invalid-config.png and b/docs/web/dist/img/invalid-config.png differ diff --git a/docs/web/dist/img/list.png b/docs/web/dist/img/list.png index 2ed629b..2b50989 100644 Binary files a/docs/web/dist/img/list.png and b/docs/web/dist/img/list.png differ diff --git a/docs/web/dist/img/validate.png b/docs/web/dist/img/validate.png index 7f4b32c..ce033c0 100644 Binary files a/docs/web/dist/img/validate.png and b/docs/web/dist/img/validate.png differ diff --git a/docs/web/dist/img/version.png b/docs/web/dist/img/version.png index 355cdf6..e4fc013 100644 Binary files a/docs/web/dist/img/version.png and b/docs/web/dist/img/version.png differ diff --git a/docs/web/dist/index.html b/docs/web/dist/index.html index ecdebf4..7ac1649 100644 --- a/docs/web/dist/index.html +++ b/docs/web/dist/index.html @@ -21,8 +21,8 @@ -
DGDevOpsGenDOCSGitHub

docker · github actions · kubernetes

DevOps scaffolding,
deterministically.

DevOpsGen reads your Go or Node.js project and writes a complete, opinionated DevOps baseline: hardened Dockerfile, GitHub Actions pipeline and ready-to-apply Kubernetes manifests — with dry-run plans, automatic backups and config validation built in.

DevOpsGen interactive wizard running in a Windows terminal, asking for the project stack
The interactive wizard — press Enter to accept smart defaults.

Why DevOpsGen

Deterministic

Same inputs, same bytes — every run. Machine-friendly for code review: a second generation with --force produces bit-identical files.

Safe by default

Existing files are never overwritten without --force. Overwrites get .bak backups, failed runs roll back automatically, and --dry-run prints the full plan first.

Validated output

Built-in validation checks Dockerfile FROM digests, workflow action pinning, Kubernetes naming and health probes before anything ships.

Stack aware

Detects Go and Node.js projects (npm, pnpm, Express, Next.js, Vite, NestJS) from go.mod / package.json and tailors templates accordingly.

Everything a project needs on day one

One init command writes the whole baseline tree. Preview the real terminal output of every command below — all screenshots are live captures, not mockups.

generated in one command
$ devopsgen init --stack go --ci github-actions --registry ghcr --image you/myapp --port 8080
+
DGDevOpsGenDOCSGitHub

docker · github actions · kubernetes

DevOps scaffolding,
deterministically.

DevOpsGen reads your Go or Node.js project and writes a complete, opinionated DevOps baseline: hardened Dockerfile, GitHub Actions pipeline and ready-to-apply Kubernetes manifests — with dry-run plans, automatic backups and config validation built in.

DevOpsGen interactive wizard running in a Windows terminal, asking for the project stack
The interactive wizard — press Enter to accept smart defaults.

Why DevOpsGen

Deterministic

Same inputs, same bytes — every run. Machine-friendly for code review: a second generation with --force produces bit-identical files.

Safe by default

Existing files are never overwritten without --force. Overwrites get .bak backups, failed runs roll back automatically, and --dry-run prints the full plan first.

Validated output

Built-in validation checks Dockerfile FROM digests, workflow action pinning, Kubernetes naming and health probes before anything ships.

Stack aware

Detects Go and Node.js projects (npm, pnpm, Express, Next.js, Vite, NestJS) from go.mod / package.json and tailors templates accordingly.

Everything a project needs on day one

One init command writes the whole baseline tree. Preview the real terminal output of every command below — all screenshots are live captures, not mockups.

generated in one command
$ devopsgen init --stack go --ci github-actions --registry ghcr --image you/myapp --port 8080
 created 5 file(s), replaced 0 file(s) in .
-exit code: 0
Terminal showing a successful DevOpsGen init run creating five files with exit code 0
init — first run creates the complete baseline and exits 0.
Terminal showing DevOpsGen refusing to overwrite five files and exiting with code 3
init on a second run refuses to overwrite files — exit code 3 without --force.
Terminal showing a DevOpsGen dry-run plan listing replace and conflict entries before exiting with code 3
--dry-run prints the exact write plan, unresolved conflicts included.

What gets generated

Template setFilesPurpose
docker (+ .dockerignore)DockerfileHardened image build with non-root user, health check hooks, install/prune commands derived from package manager (npm / pnpm) and lockfile detection.
github-actions.github/workflows/ci.yamlTest/build across Go and Node.js versions, docker build & push, coverage floors, manifest validation.
kubernetesdeployment.yaml, service.yaml, optional ingress.yamlNon-root security context, probes using your health path, RFC 1123-validated names, optional host-based Ingress.

Explore the docs

Command cheatsheet

Terminal showing the full devopsgen help output listing all commands
devopsgen --help — all commands at a glance.
Terminal showing the devopsgen list output with available stacks, app types and registries
devopsgen list — supported stacks, app types and registries.
Terminal showing the devopsgen version output
devopsgen version.
+exit code: 0
Terminal showing a successful DevOpsGen init run creating five files with exit code 0
init — first run creates the complete baseline and exits 0.
Terminal showing DevOpsGen refusing to overwrite five files and exiting with code 3
init on a second run refuses to overwrite files — exit code 3 without --force.
Terminal showing a DevOpsGen dry-run plan listing replace and conflict entries before exiting with code 3
--dry-run prints the exact write plan, unresolved conflicts included.

What gets generated

Template setFilesPurpose
docker (+ .dockerignore)DockerfileHardened image build with non-root user, health check hooks, install/prune commands derived from package manager (npm / pnpm) and lockfile detection.
github-actions.github/workflows/ci.yamlTest/build across Go and Node.js versions, docker build & push, coverage floors, manifest validation.
kubernetesdeployment.yaml, service.yaml, optional ingress.yamlNon-root security context, probes using your health path, RFC 1123-validated names, optional host-based Ingress.

Explore the docs

getting started

Install DevOpsGen via go install or a release binary, then generate a complete Docker, CI and Kubernetes setup for your project with a single command.

wizard

DevOpsGen launches an interactive TUI wizard that walks through stack detection, ports, container images and Kubernetes options, then writes the generated configuration.

init

Full reference for devopsgen init flags: stack, app type, CI provider, registry, image, port, Kubernetes ingress, health path, dry-run and force overwrite behaviour.

detect

devopsgen detect inspects the current project and reports the programming stack, the files it based its decision on, and candidate application types.

validate

devopsgen validate statically checks generated Dockerfiles, GitHub Actions workflows and Kubernetes manifests: FROM digests, action pinning, naming rules, probes and more.

exit codes

Every devopsgen command exits with a documented status code: 0 success, 1 general error, 2 invalid configuration, 3 file conflicts, 4 validation failure, 5 ambiguous detection.

Command cheatsheet

Terminal showing the full devopsgen help output listing all commands
devopsgen --help — all commands at a glance.
Terminal showing the devopsgen list output with available stacks, app types and registries
devopsgen list — supported stacks, app types and registries.
Terminal showing the devopsgen version output
devopsgen version.
\ No newline at end of file diff --git a/docs/web/dist/init/index.html b/docs/web/dist/init/index.html index fd0e19d..3eacce5 100644 --- a/docs/web/dist/init/index.html +++ b/docs/web/dist/init/index.html @@ -21,6 +21,6 @@ -
DGDevOpsGenDOCSGitHub

command reference

devopsgen init

Initialize DevOps configuration. In an interactive terminal with no complete configuration the TUI wizard is launched; when all required parameters are supplied via flags the process runs headless and never waits for stdin.

synopsis
devopsgen init [flags]

Flags

FlagDefaultDescription
--stackauto-detectedProject stack: go or nodejs.
--app-typeauto-detectedApplication type (see devopsgen list).
--cigithub-actionsCI provider.
--registrydockerhubContainer registry: dockerhub or ghcr.
--image—Image repository as namespace/repository — no host and no tag.
--taglatestAdditional image tag alias.
--port—Application port, 1–65535.
--k8strueGenerate Kubernetes manifests.
--ingressoffEnable Kubernetes Ingress (requires --ingress-host).
--ingress-host—Ingress hostname, validated as RFC 1123.
--health-path—HTTP health probe path wired into manifests.
--build-cmd—Build command.
--build-path.Go package path to build inside the container.
--start-cmd—Startup command.
--test-cmd—Test command.
--output-dir.Output directory.
--dry-runoffSimulate without writing anything.
--forceoffOverwrite existing regular files.

Success & conflicts

A clean run writes every template and exits with 0. A second run over an existing project stops before touching anything and exits with 3 until you add --force:

devopsgen init success output with exit code 0
First run: five files created, exit code 0.
devopsgen init conflict error refusing to overwrite files with exit code 3
Re-run without --force: exit code 3, zero files touched.

Preview plans with --dry-run

--dry-run prints the byte-plan: which files would be created, which would be replaced, and which are in conflict. With a conflict present it exits 3; combined with --force a fully green plan exits 0 without writing anything:

devopsgen dry-run plan output showing replace and conflict entries with exit code 3
--dry-run over an existing project: conflict entries, exit code 3.
devopsgen dry-run force plan output where every file would be replaced, exit code 0
--dry-run --force: every file replaced in plan form, exit code 0.

Config validation

Invalid configuration fails fast with 2 before any file is planned — e.g. an image that must be namespace/repository without host or tag, a port outside 1–65535, or an Ingress without a host:

devopsgen init failing config validation on an invalid image with exit code 2
Config errors exit with code 2 and never write files.
Overwrites performed with --force create .bak backups, and any failure mid-run automatically rolls back to the pre-run state.
+
DGDevOpsGenDOCSGitHub

command reference

devopsgen init

Initialize DevOps configuration. In an interactive terminal with no complete configuration the TUI wizard is launched; when all required parameters are supplied via flags the process runs headless and never waits for stdin.

synopsis
devopsgen init [flags]

Flags

FlagDefaultDescription
--stackauto-detectedProject stack: go or nodejs.
--app-typeauto-detectedApplication type (see devopsgen list).
--cigithub-actionsCI provider.
--registrydockerhubContainer registry: dockerhub or ghcr.
--image—Image repository as namespace/repository — no host and no tag.
--taglatestAdditional image tag alias.
--port—Application port, 1–65535.
--k8strueGenerate Kubernetes manifests.
--ingressoffEnable Kubernetes Ingress (requires --ingress-host).
--ingress-host—Ingress hostname, validated as RFC 1123.
--health-path—HTTP health probe path wired into manifests.
--build-cmd—Build command.
--build-path.Go package path to build inside the container.
--start-cmd—Startup command.
--test-cmd—Test command.
--output-dir.Output directory.
--dry-runoffSimulate without writing anything.
--forceoffOverwrite existing regular files.

Success & conflicts

A clean run writes every template and exits with 0. A second run over an existing project stops before touching anything and exits with 3 until you add --force:

devopsgen init success output with exit code 0
First run: five files created, exit code 0.
devopsgen init conflict error refusing to overwrite files with exit code 3
Re-run without --force: exit code 3, zero files touched.

Preview plans with --dry-run

--dry-run prints the byte-plan: which files would be created, which would be replaced, and which are in conflict. With a conflict present it exits 3; combined with --force a fully green plan exits 0 without writing anything:

devopsgen dry-run plan output showing replace and conflict entries with exit code 3
--dry-run over an existing project: conflict entries, exit code 3.
devopsgen dry-run force plan output where every file would be replaced, exit code 0
--dry-run --force: every file replaced in plan form, exit code 0.

Config validation

Invalid configuration fails fast with 2 before any file is planned — e.g. an image that must be namespace/repository without host or tag, a port outside 1–65535, or an Ingress without a host:

devopsgen init failing config validation on an invalid image with exit code 2
Config errors exit with code 2 and never write files.
Overwrites performed with --force create .bak backups, and any failure mid-run automatically rolls back to the pre-run state.
\ No newline at end of file diff --git a/docs/web/dist/validate/index.html b/docs/web/dist/validate/index.html index 0437481..b175770 100644 --- a/docs/web/dist/validate/index.html +++ b/docs/web/dist/validate/index.html @@ -21,7 +21,7 @@ -
DGDevOpsGenDOCSGitHub

command reference

devopsgen validate

Statically lint DevOpsGen output — Dockerfiles, GitHub Actions workflows and Kubernetes manifests — so problems surface on your laptop instead of pipeline number forty.

devopsgen validate passing with the message internal validation passed and exit code 0
Everything checks out — exit code 0.
synopsis
devopsgen validate [flags]          # validate the current project
-devopsgen validate --output-dir ./configs

What it checks

Docker

  • FROM base images are pinned to digest form
  • Required install/prune steps match the package manager
  • Non-root user declared

GitHub Actions

  • Workflow documents carry required structure and names
  • Actions are pinned, config files complete
  • Checkout steps reference valid refs

Kubernetes

  • Resources are DNS 1123/1035 rename-clean
  • Service ↔ Ingress wiring is consistent
  • Probe/health requirements satisfied

Exit behaviour

Combine with devopsgen init in CI: generate, commit, validate, deploy — the exit codes page maps every failure class.

+
DGDevOpsGenDOCSGitHub

command reference

devopsgen validate

Statically lint DevOpsGen output — Dockerfiles, GitHub Actions workflows and Kubernetes manifests — so problems surface on your laptop instead of pipeline number forty.

devopsgen validate passing with the message internal validation passed and exit code 0
Everything checks out — exit code 0.
synopsis
devopsgen validate [flags]          # validate the current project
+devopsgen validate --output-dir ./configs

What it checks

Docker

  • FROM base images are pinned to digest form
  • Required install/prune steps match the package manager
  • Non-root user declared

GitHub Actions

  • Workflow documents carry required structure and names
  • Actions are pinned, config files complete
  • Checkout steps reference valid refs

Kubernetes

  • Resources are DNS 1123/1035 rename-clean
  • Service ↔ Ingress wiring is consistent
  • Probe/health requirements satisfied

Exit behaviour

Combine with devopsgen init in CI: generate, commit, validate, deploy — the exit codes page maps every failure class.

\ No newline at end of file diff --git a/docs/web/dist/wizard/index.html b/docs/web/dist/wizard/index.html index 9c7bb0a..89becab 100644 --- a/docs/web/dist/wizard/index.html +++ b/docs/web/dist/wizard/index.html @@ -21,6 +21,6 @@ -
DGDevOpsGenDOCSGitHub

interactive wizard

The TUI wizard

When you run devopsgen init in a real terminal without a flags-only invocation, a keyboard-driven wizard takes over — Enter accepts the recommended default at every step.

DevOpsGen wizard TUI showing the stack selection list with a highlighted highlighted selection and instructions
Step 1 — stack choice. DevOpsGen pre-selects what its detector recommends.

How the interview flows

A wizard run is fully replayable: the same answers as equivalent flags. To automate the same result, pass the flags headless (init reference).

Keyboard

KeyAction
EnterConfirm current selection / printed default
↑ ↓Move within list choices
typed textFill textual answers (port, image, host)
Ctrl+CAbort the wizard without writing anything

Safety during the run

Everything until the final confirmation is bound to memory only — aborting leaves the project untouched. The write itself follows the same rules as headless mode: never-overwrite-unless---force, backups, and rollback on mid-run failure.

+
DGDevOpsGenDOCSGitHub

interactive wizard

The TUI wizard

When you run devopsgen init in a real terminal without a flags-only invocation, a keyboard-driven wizard takes over — Enter accepts the recommended default at every step.

DevOpsGen wizard TUI showing the stack selection list with a highlighted highlighted selection and instructions
Step 1 — stack choice. DevOpsGen pre-selects what its detector recommends.

How the interview flows

A wizard run is fully replayable: the same answers as equivalent flags. To automate the same result, pass the flags headless (init reference).

Keyboard

KeyAction
EnterConfirm current selection / printed default
↑ ↓Move within list choices
typed textFill textual answers (port, image, host)
Ctrl+CAbort the wizard without writing anything

Safety during the run

Everything until the final confirmation is bound to memory only — aborting leaves the project untouched. The write itself follows the same rules as headless mode: never-overwrite-unless---force, backups, and rollback on mid-run failure.

\ No newline at end of file diff --git a/docs/web/img/detect.png b/docs/web/img/detect.png new file mode 100644 index 0000000..59d7ee3 Binary files /dev/null and b/docs/web/img/detect.png differ diff --git a/docs/web/img/dry-run-force.png b/docs/web/img/dry-run-force.png new file mode 100644 index 0000000..fa49ac3 Binary files /dev/null and b/docs/web/img/dry-run-force.png differ diff --git a/docs/web/img/dry-run.png b/docs/web/img/dry-run.png new file mode 100644 index 0000000..239b232 Binary files /dev/null and b/docs/web/img/dry-run.png differ diff --git a/docs/web/img/help.png b/docs/web/img/help.png new file mode 100644 index 0000000..6667182 Binary files /dev/null and b/docs/web/img/help.png differ diff --git a/docs/web/img/init-conflict.png b/docs/web/img/init-conflict.png new file mode 100644 index 0000000..5bc87d0 Binary files /dev/null and b/docs/web/img/init-conflict.png differ diff --git a/docs/web/img/init-success.png b/docs/web/img/init-success.png new file mode 100644 index 0000000..4245708 Binary files /dev/null and b/docs/web/img/init-success.png differ diff --git a/docs/web/img/invalid-config.png b/docs/web/img/invalid-config.png new file mode 100644 index 0000000..15681aa Binary files /dev/null and b/docs/web/img/invalid-config.png differ diff --git a/docs/web/img/list.png b/docs/web/img/list.png new file mode 100644 index 0000000..2b50989 Binary files /dev/null and b/docs/web/img/list.png differ diff --git a/docs/web/img/validate.png b/docs/web/img/validate.png new file mode 100644 index 0000000..ce033c0 Binary files /dev/null and b/docs/web/img/validate.png differ diff --git a/docs/web/img/version.png b/docs/web/img/version.png new file mode 100644 index 0000000..e4fc013 Binary files /dev/null and b/docs/web/img/version.png differ diff --git a/docs/web/img/wizard.png b/docs/web/img/wizard.png new file mode 100644 index 0000000..8e7944b Binary files /dev/null and b/docs/web/img/wizard.png differ diff --git a/docs/web/public/img/detect.png b/docs/web/public/img/detect.png index f60b80a..59d7ee3 100644 Binary files a/docs/web/public/img/detect.png and b/docs/web/public/img/detect.png differ diff --git a/docs/web/public/img/dry-run-force.png b/docs/web/public/img/dry-run-force.png index 55ea52b..fa49ac3 100644 Binary files a/docs/web/public/img/dry-run-force.png and b/docs/web/public/img/dry-run-force.png differ diff --git a/docs/web/public/img/dry-run.png b/docs/web/public/img/dry-run.png index 9a3bd6e..239b232 100644 Binary files a/docs/web/public/img/dry-run.png and b/docs/web/public/img/dry-run.png differ diff --git a/docs/web/public/img/help.png b/docs/web/public/img/help.png index 9ad0437..6667182 100644 Binary files a/docs/web/public/img/help.png and b/docs/web/public/img/help.png differ diff --git a/docs/web/public/img/init-conflict.png b/docs/web/public/img/init-conflict.png index 0be48f9..5bc87d0 100644 Binary files a/docs/web/public/img/init-conflict.png and b/docs/web/public/img/init-conflict.png differ diff --git a/docs/web/public/img/init-success.png b/docs/web/public/img/init-success.png index 0be48f9..4245708 100644 Binary files a/docs/web/public/img/init-success.png and b/docs/web/public/img/init-success.png differ diff --git a/docs/web/public/img/invalid-config.png b/docs/web/public/img/invalid-config.png index 97795c1..15681aa 100644 Binary files a/docs/web/public/img/invalid-config.png and b/docs/web/public/img/invalid-config.png differ diff --git a/docs/web/public/img/list.png b/docs/web/public/img/list.png index 2ed629b..2b50989 100644 Binary files a/docs/web/public/img/list.png and b/docs/web/public/img/list.png differ diff --git a/docs/web/public/img/validate.png b/docs/web/public/img/validate.png index 7f4b32c..ce033c0 100644 Binary files a/docs/web/public/img/validate.png and b/docs/web/public/img/validate.png differ diff --git a/docs/web/public/img/version.png b/docs/web/public/img/version.png index 355cdf6..e4fc013 100644 Binary files a/docs/web/public/img/version.png and b/docs/web/public/img/version.png differ diff --git a/docs/web/src/components/Layout.jsx b/docs/web/src/components/Layout.jsx index cac643f..e5884ff 100644 --- a/docs/web/src/components/Layout.jsx +++ b/docs/web/src/components/Layout.jsx @@ -1,33 +1,58 @@ import { ROUTES, SITE_URL } from '../routes.jsx'; -export default function Layout({ rel, children }) { +const GROUPS = [ + { label: 'Overview', items: ['getting-started', 'wizard'] }, + { label: 'Command reference', items: ['init', 'detect', 'validate'] }, + { label: 'Operations', items: ['exit-codes'] }, +]; + +export default function Layout({ rel, activePath, children }) { + const homeActive = activePath === ''; return ( <> skip to content
DG - DevOpsGenDOCS + DevOpsGen + DOCS - GitHub
-
{children}
+ +
+ + +
{children}
+
+