<!-- CANARY: REQ=REQ-DOCS-001; FEATURE="Docs"; ASPECT=Documentation; STATUS=TESTED; OWNER=docs; UPDATED=2026-01-15 --> <h2 id="continuous-integration-for-geode" class="position-relative d-flex align-items-center group"> <span>Continuous Integration for Geode</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="continuous-integration-for-geode" aria-haspopup="dialog" aria-label="Share link: Continuous Integration for Geode"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h2><div id="headingShareModal" class="heading-share-modal" role="dialog" aria-modal="true" aria-labelledby="headingShareTitle" hidden> <div class="hsm-dialog" role="document"> <div class="hsm-header"> <h2 id="headingShareTitle" class="h6 mb-0 fw-bold">Share this section</h2> <button type="button" class="hsm-close" aria-label="Close"> <i class="fa-solid fa-xmark"></i> </button> </div> <div class="hsm-body"> <label for="headingShareInput" class="form-label small text-muted mb-1 text-uppercase fw-bold" style="font-size: 0.7rem; letter-spacing: 0.5px;">Permalink</label> <div class="input-group mb-4 hsm-url-group"> <input id="headingShareInput" type="text" class="form-control font-monospace" readonly aria-readonly="true" style="font-size: 0.85rem;" /> <button class="btn btn-primary hsm-copy" type="button" aria-label="Copy" title="Copy"> <i class="fa-duotone fa-clipboard" aria-hidden="true"></i> </button> </div> <div class="small fw-bold mb-2 text-muted text-uppercase" style="font-size: 0.7rem; letter-spacing: 0.5px;">Share via</div> <div class="hsm-share-grid"> <a id="share-twitter" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-twitter me-2"></i>Twitter </a> <a id="share-linkedin" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-linkedin me-2"></i>LinkedIn </a> <a id="share-facebook" class="btn btn-outline-secondary w-100" target="_blank" rel="noopener noreferrer"> <i class="fa-brands fa-facebook me-2"></i>Facebook </a> </div> </div> </div> </div> <style> .heading-share-modal { position: fixed; inset: 0; display: flex; justify-content: center; align-items: center; background: rgba(0, 0, 0, 0.6); z-index: 1050; padding: 1rem; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); } .heading-share-modal[hidden] { display: none !important; } .hsm-dialog { max-width: 420px; width: 100%; background: var(--bs-body-bg, #fff); color: var(--bs-body-color, #212529); border: 1px solid var(--bs-border-color, rgba(0,0,0,0.1)); border-radius: 1rem; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); overflow: hidden; animation: hsm-fade-in 0.2s ease-out; } @keyframes hsm-fade-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } [data-bs-theme="dark"] .hsm-dialog { background: #1e293b; border-color: rgba(255,255,255,0.1); color: #f8f9fa; } .hsm-header { display: flex; justify-content: space-between; align-items: center; padding: 1rem 1.5rem; border-bottom: 1px solid var(--bs-border-color, rgba(0,0,0,0.1)); background: rgba(0,0,0,0.02); } [data-bs-theme="dark"] .hsm-header { background: rgba(255,255,255,0.02); border-color: rgba(255,255,255,0.1); } .hsm-close { background: transparent; border: none; color: inherit; opacity: 0.5; padding: 0.25rem 0.5rem; border-radius: 0.25rem; font-size: 1.2rem; line-height: 1; transition: opacity 0.2s; } .hsm-close:hover { opacity: 1; } .hsm-body { padding: 1.5rem; } .hsm-url-group { display: flex !important; align-items: stretch; } .hsm-url-group .form-control { flex: 1; min-width: 0; margin: 0; background: var(--bs-secondary-bg, #f8f9fa); border-color: var(--bs-border-color, #dee2e6); border-top-right-radius: 0; border-bottom-right-radius: 0; height: 42px; } .hsm-url-group .btn { flex: 0 0 auto; margin: 0; margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; height: 42px; display: flex; align-items: center; justify-content: center; padding: 0 1.25rem; z-index: 2; } [data-bs-theme="dark"] .hsm-url-group .form-control { background: #0f172a; border-color: #334155; color: #e2e8f0; } .hsm-share-grid { display: flex; flex-direction: column; gap: 0.5rem; } .hsm-share-grid .btn { display: flex; align-items: center; justify-content: center; font-size: 0.9rem; padding: 0.6rem; border-color: var(--bs-border-color); width: 100%; } [data-bs-theme="dark"] .hsm-share-grid .btn { color: #e2e8f0; border-color: #475569; } [data-bs-theme="dark"] .hsm-share-grid .btn:hover { background: #334155; border-color: #cbd5e1; } </style> <script> (function(){ const modal = document.getElementById('headingShareModal'); if(!modal) return; const input = modal.querySelector('#headingShareInput'); const copyBtn = modal.querySelector('.hsm-copy'); const twitter = modal.querySelector('#share-twitter'); const linkedin = modal.querySelector('#share-linkedin'); const facebook = modal.querySelector('#share-facebook'); const closeBtn = modal.querySelector('.hsm-close'); let lastFocus=null; let trapBound=false; function buildUrl(id){ return window.location.origin + window.location.pathname + '#' + id; } function isOpen(){ return !modal.hasAttribute('hidden'); } function hydrate(id){ const url=buildUrl(id); input.value=url; const enc=encodeURIComponent(url); const text=encodeURIComponent(document.title); if(twitter) twitter.href=`https://twitter.com/intent/tweet?url=${enc}&text=${text}`; if(linkedin) linkedin.href=`https://www.linkedin.com/sharing/share-offsite/?url=${enc}`; if(facebook) facebook.href=`https://www.facebook.com/sharer/sharer.php?u=${enc}`; } function openModal(id){ lastFocus=document.activeElement; hydrate(id); if(!isOpen()){ modal.removeAttribute('hidden'); } requestAnimationFrame(()=>{ input.focus(); }); trapFocus(); } function closeModal(){ if(!isOpen()) return; modal.setAttribute('hidden',''); if(lastFocus && typeof lastFocus.focus==='function') lastFocus.focus(); } function copyCurrent(){ try{ navigator.clipboard.writeText(input.value).then(()=>feedback(true),()=>fallback()); } catch(e){ fallback(); } } function fallback(){ input.select(); try{ document.execCommand('copy'); feedback(true);}catch(e){ feedback(false);} } function feedback(ok){ if(!copyBtn) return; const icon=copyBtn.querySelector('i'); if(!icon) return; const prev=copyBtn.getAttribute('data-prev')||icon.className; if(!copyBtn.getAttribute('data-prev')) copyBtn.setAttribute('data-prev',prev); icon.className= ok ? 'fa-duotone fa-clipboard-check':'fa-duotone fa-circle-exclamation'; setTimeout(()=>{ icon.className=prev; },1800); } function handleShareClick(e){ e.preventDefault(); const btn=e.currentTarget; const id=btn.getAttribute('data-share-target'); if(id) openModal(id); } function bindShareButtons(){ document.querySelectorAll('.h-share').forEach(btn=>{ if(!btn.dataset.hShareBound){ btn.addEventListener('click', handleShareClick); btn.dataset.hShareBound='1'; } }); } bindShareButtons(); if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded', bindShareButtons); } else { requestAnimationFrame(bindShareButtons); } document.addEventListener('click', function(e){ const shareBtn=e.target.closest && e.target.closest('.h-share'); if(shareBtn && !shareBtn.dataset.hShareBound){ handleShareClick.call(shareBtn, e); } }, true); document.addEventListener('click', e=>{ if(e.target===modal) closeModal(); if(e.target.closest && e.target.closest('.hsm-close')){ e.preventDefault(); closeModal(); } if(copyBtn && (e.target===copyBtn || (e.target.closest && e.target.closest('.hsm-copy')))) { e.preventDefault(); copyCurrent(); } }); document.addEventListener('keydown', e=>{ if(e.key==='Escape' && isOpen()) closeModal(); }); function trapFocus(){ if(trapBound) return; trapBound=true; modal.addEventListener('keydown', f=>{ if(f.key==='Tab' && isOpen()){ const focusable=[...modal.querySelectorAll('a[href],button,input,textarea,select,[tabindex]:not([tabindex="-1"])')].filter(el=>!el.hasAttribute('disabled')); if(!focusable.length) return; const first=focusable[0]; const last=focusable[focusable.length-1]; if(f.shiftKey && document.activeElement===first){ f.preventDefault(); last.focus(); } else if(!f.shiftKey && document.activeElement===last){ f.preventDefault(); first.focus(); } } }); } if(closeBtn) closeBtn.addEventListener('click', e=>{ e.preventDefault(); closeModal(); }); })(); </script><p>Continuous Integration (CI) is the practice of automatically building, testing, and validating code changes as they&rsquo;re committed to version control. For Geode, CI ensures that every change maintains database correctness, preserves GQL standards compliance, prevents performance regressions, and validates polyglot client compatibility.</p> <h3 id="foundations-of-continuous-integration" class="position-relative d-flex align-items-center group"> <span>Foundations of Continuous Integration</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="foundations-of-continuous-integration" aria-haspopup="dialog" aria-label="Share link: Foundations of Continuous Integration"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><p>Continuous Integration is built on several core principles:</p> <p><strong>Frequent Integration</strong>: Developers integrate code changes multiple times daily, preventing large merge conflicts and integration issues.</p> <p><strong>Automated Building</strong>: Every commit triggers an automated build process that compiles the codebase and identifies compilation errors immediately.</p> <p><strong>Automated Testing</strong>: Comprehensive test suites run automatically, providing rapid feedback on functionality and preventing regressions.</p> <p><strong>Fast Feedback</strong>: Developers receive build and test results within minutes, enabling quick fixes before context switching.</p> <p><strong>Maintain a Single Source Repository</strong>: All code, tests, and configuration reside in version control (Git), ensuring reproducibility.</p> <p>For database systems like Geode, CI is particularly critical because bugs can result in data corruption, lost transactions, or query correctness issues that are difficult to debug in production.</p> <h3 id="geodes-ci-implementation" class="position-relative d-flex align-items-center group"> <span>Geode&amp;rsquo;s CI Implementation</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="geodes-ci-implementation" aria-haspopup="dialog" aria-label="Share link: Geodes CI Implementation"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="repository-structure" class="position-relative d-flex align-items-center group"> <span>Repository Structure</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="repository-structure" aria-haspopup="dialog" aria-label="Share link: Repository Structure"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Geode&rsquo;s monorepo structure enables comprehensive CI across all components:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/home/benji/src/gl/devnw/codepros/geode/ </span></span><span class="line"><span class="cl">├── geode/ # Server (Zig) </span></span><span class="line"><span class="cl">│ ├── src/ </span></span><span class="line"><span class="cl">│ ├── test/ </span></span><span class="line"><span class="cl">│ └── build.zig </span></span><span class="line"><span class="cl">├── geode-client-go/ # Go client </span></span><span class="line"><span class="cl">├── geode-client-python/ # Python client </span></span><span class="line"><span class="cl">├── geode-client-rust/ # Rust client </span></span><span class="line"><span class="cl">├── geode-client-zig/ # Zig client </span></span><span class="line"><span class="cl">├── geode-test-harness/ # Cross-client tests </span></span><span class="line"><span class="cl">└── .github/workflows/ # CI configuration </span></span></code></pre></div><p>This structure allows CI to:</p> <ul> <li>Build all components in a single pipeline</li> <li>Test server changes against all clients</li> <li>Validate cross-client compatibility</li> <li>Ensure end-to-end functionality</li> </ul> <h4 id="build-process" class="position-relative d-flex align-items-center group"> <span>Build Process</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="build-process" aria-haspopup="dialog" aria-label="Share link: Build Process"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Server Build</strong> (Zig):</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># geode/Makefile</span> </span></span><span class="line"><span class="cl">build: </span></span><span class="line"><span class="cl"> zig build -Doptimize<span class="o">=</span>ReleaseSafe </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">test: </span></span><span class="line"><span class="cl"> zig build <span class="nb">test</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl">geodetestlab-comprehensive: </span></span><span class="line"><span class="cl"> zig build <span class="nb">test</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Run comprehensive test suite (1,688 tests)</span> </span></span><span class="line"><span class="cl"> ./zig-out/bin/geodetestlab --comprehensive </span></span></code></pre></div><p><strong>CI Build Configuration</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># .github/workflows/build.yml</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build Geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">main, develop]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">pull_request</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">main]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">build-zig</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build Server (Zig ${{ matrix.zig }})</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">${{ matrix.os }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">matrix</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">os</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">ubuntu-24.04, macos-14]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">zig</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">0.1.0</span><span class="p">]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Setup Zig</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">goto-bus-stop/setup-zig@v2</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l">${{ matrix.zig }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build Geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> zig build -Doptimize=ReleaseSafe </span></span></span><span class="line"><span class="cl"><span class="sd"> ./zig-out/bin/geode --version</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Verify Binary</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> file geode/zig-out/bin/geode </span></span></span><span class="line"><span class="cl"><span class="sd"> ldd geode/zig-out/bin/geode || true</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Upload Binary</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/upload-artifact@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">geode-${{ matrix.os }}-${{ matrix.zig }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">geode/zig-out/bin/geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">retention-days</span><span class="p">:</span><span class="w"> </span><span class="m">7</span><span class="w"> </span></span></span></code></pre></div> <h4 id="automated-testing" class="position-relative d-flex align-items-center group"> <span>Automated Testing</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="automated-testing" aria-haspopup="dialog" aria-label="Share link: Automated Testing"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Geode&rsquo;s CI runs multiple test suites:</p> <p><strong>1. Unit Tests</strong> (Core functionality):</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">unit-tests</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Unit Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-24.04</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">needs</span><span class="p">:</span><span class="w"> </span><span class="l">build-zig</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Setup Zig</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">goto-bus-stop/setup-zig@v2</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="m">0.1.0</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Unit Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> zig build test -Dtest-filter=&#34;*&#34;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Parse Test Results</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Extract test counts </span></span></span><span class="line"><span class="cl"><span class="sd"> echo &#34;Tests run, passed, failed&#34;</span><span class="w"> </span></span></span></code></pre></div><p><strong>2. GeodeTestLab Comprehensive Suite</strong> (1,688 tests):</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run GeodeTestLab</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> make geodetestlab-comprehensive</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check Pass Rate</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Require 97.4% pass rate (1644/1688) </span></span></span><span class="line"><span class="cl"><span class="sd"> python scripts/check-pass-rate.py \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --results geode/test-results.json \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --threshold 0.974</span><span class="w"> </span></span></span></code></pre></div><p><strong>3. GQL Compliance Tests</strong> (ISO/IEC 39075:2024):</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">gql-compliance</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">GQL Compliance</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">needs</span><span class="p">:</span><span class="w"> </span><span class="l">build-zig</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Download Server Binary</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/download-artifact@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Start Geode</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> chmod +x geode </span></span></span><span class="line"><span class="cl"><span class="sd"> ./geode serve --listen 0.0.0.0:3141 &amp; </span></span></span><span class="line"><span class="cl"><span class="sd"> sleep 5</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Conformance Profile Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Must pass profile scope (see conformance profile) </span></span></span><span class="line"><span class="cl"><span class="sd"> python gql/iso-tests/run-suite.py \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --host localhost:3141 \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --strict</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Enforce Conformance Profile</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> if [ $? -ne 0 ]; then </span></span></span><span class="line"><span class="cl"><span class="sd"> echo &#34;GQL conformance profile tests failed - blocking merge&#34; </span></span></span><span class="line"><span class="cl"><span class="sd"> exit 1 </span></span></span><span class="line"><span class="cl"><span class="sd"> fi</span><span class="w"> </span></span></span></code></pre></div><p><strong>4. Client Library Tests</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">client-tests</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Test ${{ matrix.client }} Client</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">needs</span><span class="p">:</span><span class="w"> </span><span class="l">build-zig</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">matrix</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">client</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">go, python, rust, zig]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Download Server</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/download-artifact@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Start Server</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> ./geode serve &amp; </span></span></span><span class="line"><span class="cl"><span class="sd"> sleep 5</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Setup ${{ matrix.client }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">./.github/actions/setup-${{ matrix.client }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode-client-${{ matrix.client }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">make test</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Upload Results</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">always()</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/upload-artifact@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test-results-${{ matrix.client }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">geode-client-${{ matrix.client }}/test-results/</span><span class="w"> </span></span></span></code></pre></div><p><strong>5. Cross-Client Integration Tests</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">integration-tests</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Integration Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">needs</span><span class="p">:</span><span class="w"> </span><span class="l">client-tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Setup Test Harness</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode-test-harness</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">make setup</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run All Client Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> make test-all </span></span></span><span class="line"><span class="cl"><span class="sd"> make test-all-html</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Upload HTML Report</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/upload-artifact@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">integration-report</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">geode-test-harness/reports/</span><span class="w"> </span></span></span></code></pre></div> <h4 id="code-quality-checks" class="position-relative d-flex align-items-center group"> <span>Code Quality Checks</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="code-quality-checks" aria-haspopup="dialog" aria-label="Share link: Code Quality Checks"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Linting and Formatting</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">code-quality</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Code Quality</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-24.04</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check Zig Formatting</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> find geode/src -name &#34;*.zig&#34; | xargs zig fmt --check</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Lint Go Client</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode-client-go</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> go fmt ./... </span></span></span><span class="line"><span class="cl"><span class="sd"> go vet ./... </span></span></span><span class="line"><span class="cl"><span class="sd"> golangci-lint run</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Lint Python Client</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode-client-python</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> black --check . </span></span></span><span class="line"><span class="cl"><span class="sd"> pylint geode_client/ </span></span></span><span class="line"><span class="cl"><span class="sd"> mypy geode_client/</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Lint Rust Client</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">working-directory</span><span class="p">:</span><span class="w"> </span><span class="l">geode-client-rust</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> cargo fmt -- --check </span></span></span><span class="line"><span class="cl"><span class="sd"> cargo clippy -- -D warnings</span><span class="w"> </span></span></span></code></pre></div><p><strong>Static Analysis</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Static Analysis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Memory safety checks </span></span></span><span class="line"><span class="cl"><span class="sd"> zig build -Dcheck </span></span></span><span class="line"><span class="cl"><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Security scanning </span></span></span><span class="line"><span class="cl"><span class="sd"> semgrep --config=auto geode/src/ </span></span></span><span class="line"><span class="cl"><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Dependency audit </span></span></span><span class="line"><span class="cl"><span class="sd"> cd geode-client-go &amp;&amp; go list -m all | nancy sleuth </span></span></span><span class="line"><span class="cl"><span class="sd"> cd geode-client-rust &amp;&amp; cargo audit</span><span class="w"> </span></span></span></code></pre></div><p><strong>CANARY Marker Validation</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Validate CANARY Markers</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Ensure all implementations have CANARY markers </span></span></span><span class="line"><span class="cl"><span class="sd"> python scripts/validate-canary-markers.py \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --dir geode/src \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --require-evidence</span><span class="w"> </span></span></span></code></pre></div> <h3 id="advanced-ci-patterns" class="position-relative d-flex align-items-center group"> <span>Advanced CI Patterns</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="advanced-ci-patterns" aria-haspopup="dialog" aria-label="Share link: Advanced CI Patterns"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="parallel-test-execution" class="position-relative d-flex align-items-center group"> <span>Parallel Test Execution</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="parallel-test-execution" aria-haspopup="dialog" aria-label="Share link: Parallel Test Execution"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Geode parallelizes tests for faster feedback:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">test-parallel</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Parallel Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-24.04</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">fail-fast</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">matrix</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">shard</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">1</span><span class="p">,</span><span class="w"> </span><span class="m">2</span><span class="p">,</span><span class="w"> </span><span class="m">3</span><span class="p">,</span><span class="w"> </span><span class="m">4</span><span class="p">,</span><span class="w"> </span><span class="m">5</span><span class="p">,</span><span class="w"> </span><span class="m">6</span><span class="p">,</span><span class="w"> </span><span class="m">7</span><span class="p">,</span><span class="w"> </span><span class="m">8</span><span class="p">]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Test Shard ${{ matrix.shard }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Split tests into 8 shards </span></span></span><span class="line"><span class="cl"><span class="sd"> zig build test -Dshard=${{ matrix.shard }} -Dtotal-shards=8</span><span class="w"> </span></span></span></code></pre></div><p><strong>Benefits</strong>:</p> <ul> <li>8-minute test suite runs in 1-2 minutes</li> <li>Early failure detection</li> <li>Better resource utilization</li> </ul> <h4 id="incremental-testing" class="position-relative d-flex align-items-center group"> <span>Incremental Testing</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="incremental-testing" aria-haspopup="dialog" aria-label="Share link: Incremental Testing"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Only test affected components:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Detect Changed Files</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">id</span><span class="p">:</span><span class="w"> </span><span class="l">changed</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Get changed files since last commit </span></span></span><span class="line"><span class="cl"><span class="sd"> CHANGED=$(git diff --name-only HEAD~1 HEAD) </span></span></span><span class="line"><span class="cl"><span class="sd"> echo &#34;files=$CHANGED&#34; &gt;&gt; $GITHUB_OUTPUT</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Targeted Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> if echo &#34;${{ steps.changed.outputs.files }}&#34; | grep -q &#34;geode/src/parser&#34;; then </span></span></span><span class="line"><span class="cl"><span class="sd"> # Parser changed - run parser tests </span></span></span><span class="line"><span class="cl"><span class="sd"> zig build test -Dtest-filter=&#34;parser.*&#34; </span></span></span><span class="line"><span class="cl"><span class="sd"> fi </span></span></span><span class="line"><span class="cl"><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> if echo &#34;${{ steps.changed.outputs.files }}&#34; | grep -q &#34;geode-client-python&#34;; then </span></span></span><span class="line"><span class="cl"><span class="sd"> # Python client changed </span></span></span><span class="line"><span class="cl"><span class="sd"> cd geode-client-python &amp;&amp; pytest </span></span></span><span class="line"><span class="cl"><span class="sd"> fi</span><span class="w"> </span></span></span></code></pre></div> <h4 id="dependency-caching" class="position-relative d-flex align-items-center group"> <span>Dependency Caching</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="dependency-caching" aria-haspopup="dialog" aria-label="Share link: Dependency Caching"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Cache dependencies to speed up builds:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Cache Zig Dependencies</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/cache@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> ~/.cache/zig </span></span></span><span class="line"><span class="cl"><span class="sd"> geode/zig-cache </span></span></span><span class="line"><span class="cl"><span class="sd"> geode/zig-out</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ runner.os }}-zig-${{ hashFiles(&#39;**/build.zig.zon&#39;) }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">restore-keys</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> ${{ runner.os }}-zig-</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Cache Go Modules</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/cache@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">~/go/pkg/mod</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ runner.os }}-go-${{ hashFiles(&#39;**/go.sum&#39;) }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Cache Rust Dependencies</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/cache@v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> ~/.cargo/registry </span></span></span><span class="line"><span class="cl"><span class="sd"> ~/.cargo/git </span></span></span><span class="line"><span class="cl"><span class="sd"> geode-client-rust/target</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">${{ runner.os }}-cargo-${{ hashFiles(&#39;**/Cargo.lock&#39;) }}</span><span class="w"> </span></span></span></code></pre></div> <h4 id="test-result-reporting" class="position-relative d-flex align-items-center group"> <span>Test Result Reporting</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="test-result-reporting" aria-haspopup="dialog" aria-label="Share link: Test Result Reporting"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Generate comprehensive test reports:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Generate Test Report</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">always()</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> python scripts/generate-test-report.py \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --input test-results/ \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --output test-report.html \ </span></span></span><span class="line"><span class="cl"><span class="sd"> --format html</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Publish Test Results</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">EnricoMi/publish-unit-test-result-action@v2</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">always()</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">files</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> geode/test-results/**/*.xml </span></span></span><span class="line"><span class="cl"><span class="sd"> geode-client-*/test-results/**/*.xml </span></span></span><span class="line"><span class="cl"><span class="sd"> geode-test-harness/reports/**/*.xml</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Comment PR with Results</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">github.event_name == &#39;pull_request&#39;</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/github-script@v7</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">script</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> const fs = require(&#39;fs&#39;); </span></span></span><span class="line"><span class="cl"><span class="sd"> const report = fs.readFileSync(&#39;test-report.html&#39;, &#39;utf8&#39;); </span></span></span><span class="line"><span class="cl"><span class="sd"> github.rest.issues.createComment({ </span></span></span><span class="line"><span class="cl"><span class="sd"> issue_number: context.issue.number, </span></span></span><span class="line"><span class="cl"><span class="sd"> owner: context.repo.owner, </span></span></span><span class="line"><span class="cl"><span class="sd"> repo: context.repo.repo, </span></span></span><span class="line"><span class="cl"><span class="sd"> body: report </span></span></span><span class="line"><span class="cl"><span class="sd"> });</span><span class="w"> </span></span></span></code></pre></div> <h3 id="ci-best-practices-for-geode" class="position-relative d-flex align-items-center group"> <span>CI Best Practices for Geode</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="ci-best-practices-for-geode" aria-haspopup="dialog" aria-label="Share link: CI Best Practices for Geode"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="1-fail-fast" class="position-relative d-flex align-items-center group"> <span>1. Fail Fast</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="1-fail-fast" aria-haspopup="dialog" aria-label="Share link: 1. Fail Fast"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Prioritize quick checks first:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">jobs</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># Run fast checks first</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">quick-checks</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-24.04</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Lint (30 seconds)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Format Check (20 seconds)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Compile Check (1 minute)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># Run expensive tests only if quick checks pass</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">comprehensive-tests</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">needs</span><span class="p">:</span><span class="w"> </span><span class="l">quick-checks</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Full Test Suite (8 minutes)</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Performance Tests (15 minutes)</span><span class="w"> </span></span></span></code></pre></div> <h4 id="2-keep-ci-fast" class="position-relative d-flex align-items-center group"> <span>2. Keep CI Fast</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="2-keep-ci-fast" aria-haspopup="dialog" aria-label="Share link: 2. Keep CI Fast"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Target: Feedback within 10 minutes</p> <p><strong>Optimization strategies</strong>:</p> <ul> <li>Cache aggressively (builds, dependencies, test data)</li> <li>Parallelize independent tests</li> <li>Use incremental testing</li> <li>Run expensive tests nightly instead of per-commit</li> </ul> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">on</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">main]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">pull_request</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># Fast tests on PR</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">types</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">opened, synchronize]</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># Comprehensive tests nightly</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">cron</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;0 2 * * *&#39;</span><span class="w"> </span></span></span></code></pre></div> <h4 id="3-make-ci-reproducible" class="position-relative d-flex align-items-center group"> <span>3. Make CI Reproducible</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="3-make-ci-reproducible" aria-haspopup="dialog" aria-label="Share link: 3. Make CI Reproducible"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Pin all versions</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">env</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ZIG_VERSION</span><span class="p">:</span><span class="w"> </span><span class="m">0.1.0</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">GO_VERSION</span><span class="p">:</span><span class="w"> </span><span class="m">1.24.0</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">PYTHON_VERSION</span><span class="p">:</span><span class="w"> </span><span class="m">3.11.8</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">RUST_VERSION</span><span class="p">:</span><span class="w"> </span><span class="m">1.70.0</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># Pin action versions</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">CHECKOUT_VERSION</span><span class="p">:</span><span class="w"> </span><span class="l">v4</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">SETUP_GO_VERSION</span><span class="p">:</span><span class="w"> </span><span class="l">v5</span><span class="w"> </span></span></span></code></pre></div><p><strong>Use deterministic builds</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Zig builds are deterministic by default</span> </span></span><span class="line"><span class="cl">zig build -Doptimize<span class="o">=</span>ReleaseSafe </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Go builds with reproducibility</span> </span></span><span class="line"><span class="cl">go build -trimpath -ldflags<span class="o">=</span><span class="s2">&#34;-buildid=&#34;</span> </span></span></code></pre></div> <h4 id="4-test-in-clean-environments" class="position-relative d-flex align-items-center group"> <span>4. Test in Clean Environments</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="4-test-in-clean-environments" aria-haspopup="dialog" aria-label="Share link: 4. Test in Clean Environments"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Avoid environment pollution</strong>:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Tests in Clean Environment</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Each test gets fresh database </span></span></span><span class="line"><span class="cl"><span class="sd"> for test in tests/*; do </span></span></span><span class="line"><span class="cl"><span class="sd"> # Clean state </span></span></span><span class="line"><span class="cl"><span class="sd"> rm -rf /tmp/geode-test-data </span></span></span><span class="line"><span class="cl"><span class="sd"> mkdir -p /tmp/geode-test-data </span></span></span><span class="line"><span class="cl"><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Run isolated </span></span></span><span class="line"><span class="cl"><span class="sd"> GEODE_DATA_DIR=/tmp/geode-test-data $test </span></span></span><span class="line"><span class="cl"><span class="sd"> done</span><span class="w"> </span></span></span></code></pre></div> <h4 id="5-monitor-ci-health" class="position-relative d-flex align-items-center group"> <span>5. Monitor CI Health</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="5-monitor-ci-health" aria-haspopup="dialog" aria-label="Share link: 5. Monitor CI Health"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Track CI metrics:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># scripts/ci-metrics.py</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span> </span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">prometheus_client</span> <span class="kn">import</span> <span class="n">Counter</span><span class="p">,</span> <span class="n">Histogram</span><span class="p">,</span> <span class="n">push_to_gateway</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">ci_duration</span> <span class="o">=</span> <span class="n">Histogram</span><span class="p">(</span><span class="s1">&#39;ci_duration_seconds&#39;</span><span class="p">,</span> <span class="s1">&#39;CI duration&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;job&#39;</span><span class="p">])</span> </span></span><span class="line"><span class="cl"><span class="n">ci_failures</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="s1">&#39;ci_failures_total&#39;</span><span class="p">,</span> <span class="s1">&#39;CI failures&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;job&#39;</span><span class="p">])</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">report_ci_metrics</span><span class="p">(</span><span class="n">job_name</span><span class="p">,</span> <span class="n">duration</span><span class="p">,</span> <span class="n">success</span><span class="p">):</span> </span></span><span class="line"><span class="cl"> <span class="n">ci_duration</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="n">job</span><span class="o">=</span><span class="n">job_name</span><span class="p">)</span><span class="o">.</span><span class="n">observe</span><span class="p">(</span><span class="n">duration</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="ow">not</span> <span class="n">success</span><span class="p">:</span> </span></span><span class="line"><span class="cl"> <span class="n">ci_failures</span><span class="o">.</span><span class="n">labels</span><span class="p">(</span><span class="n">job</span><span class="o">=</span><span class="n">job_name</span><span class="p">)</span><span class="o">.</span><span class="n">inc</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">push_to_gateway</span><span class="p">(</span><span class="s1">&#39;monitoring.geodedb.com:9091&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">job</span><span class="o">=</span><span class="s1">&#39;ci-metrics&#39;</span><span class="p">,</span> </span></span><span class="line"><span class="cl"> <span class="n">registry</span><span class="o">=</span><span class="n">registry</span><span class="p">)</span> </span></span></code></pre></div> <h3 id="debugging-ci-failures" class="position-relative d-flex align-items-center group"> <span>Debugging CI Failures</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="debugging-ci-failures" aria-haspopup="dialog" aria-label="Share link: Debugging CI Failures"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="access-build-logs" class="position-relative d-flex align-items-center group"> <span>Access Build Logs</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="access-build-logs" aria-haspopup="dialog" aria-label="Share link: Access Build Logs"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Download logs from GitHub Actions</span> </span></span><span class="line"><span class="cl">gh run view &lt;run-id&gt; --log </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Or via API</span> </span></span><span class="line"><span class="cl">curl -L <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> -H <span class="s2">&#34;Accept: application/vnd.github+json&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> -H <span class="s2">&#34;Authorization: Bearer </span><span class="nv">$GITHUB_TOKEN</span><span class="s2">&#34;</span> <span class="se">\ </span></span></span><span class="line"><span class="cl"><span class="se"></span> https://api.github.com/repos/devnw/geode/actions/runs/&lt;run-id&gt;/logs </span></span></code></pre></div> <h4 id="reproduce-locally" class="position-relative d-flex align-items-center group"> <span>Reproduce Locally</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="reproduce-locally" aria-haspopup="dialog" aria-label="Share link: Reproduce Locally"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Use act to run GitHub Actions locally:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Install act</span> </span></span><span class="line"><span class="cl">brew install act <span class="c1"># macOS</span> </span></span><span class="line"><span class="cl"><span class="c1"># or</span> </span></span><span class="line"><span class="cl">curl https://raw.githubusercontent.com/nektos/act/master/install.sh <span class="p">|</span> bash </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Run specific job</span> </span></span><span class="line"><span class="cl">act -j unit-tests </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="c1"># Run entire workflow</span> </span></span><span class="line"><span class="cl">act push </span></span></code></pre></div> <h4 id="debug-mode" class="position-relative d-flex align-items-center group"> <span>Debug Mode</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="debug-mode" aria-haspopup="dialog" aria-label="Share link: Debug Mode"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p>Enable debug logging:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Enable Debug Logging</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">runner.debug</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> export GEODE_LOG_LEVEL=debug </span></span></span><span class="line"><span class="cl"><span class="sd"> export GEODE_TRACE=1 </span></span></span><span class="line"><span class="cl"><span class="sd"> zig build test -Dlog-level=debug</span><span class="w"> </span></span></span></code></pre></div><p>Trigger with:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">gh workflow run ci.yml -f <span class="nv">debug</span><span class="o">=</span><span class="nb">true</span> </span></span></code></pre></div> <h4 id="common-ci-issues" class="position-relative d-flex align-items-center group"> <span>Common CI Issues</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="common-ci-issues" aria-haspopup="dialog" aria-label="Share link: Common CI Issues"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><p><strong>Issue 1: Flaky Tests</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># Mark flaky tests with retries</span> </span></span><span class="line"><span class="cl"><span class="nd">@pytest.mark.flaky</span><span class="p">(</span><span class="n">reruns</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">reruns_delay</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">test_concurrent_transactions</span><span class="p">():</span> </span></span><span class="line"><span class="cl"> <span class="c1"># Test that occasionally fails due to timing</span> </span></span><span class="line"><span class="cl"> <span class="k">pass</span> </span></span></code></pre></div><p><strong>Issue 2: Resource Exhaustion</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Clean Up Resources</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">if</span><span class="p">:</span><span class="w"> </span><span class="l">always()</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Stop all Geode processes </span></span></span><span class="line"><span class="cl"><span class="sd"> pkill -9 geode || true </span></span></span><span class="line"><span class="cl"><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Clean temp data </span></span></span><span class="line"><span class="cl"><span class="sd"> rm -rf /tmp/geode-* </span></span></span><span class="line"><span class="cl"><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Free memory </span></span></span><span class="line"><span class="cl"><span class="sd"> sync; echo 3 &gt; /proc/sys/vm/drop_caches || true</span><span class="w"> </span></span></span></code></pre></div><p><strong>Issue 3: Timeout Issues</strong></p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">jobs</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">test</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout-minutes</span><span class="p">:</span><span class="w"> </span><span class="m">30</span><span class="w"> </span><span class="c"># Prevent hanging builds</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Run Tests</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">timeout-minutes</span><span class="p">:</span><span class="w"> </span><span class="m">20</span><span class="w"> </span><span class="c"># Per-step timeout</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l">make test</span><span class="w"> </span></span></span></code></pre></div> <h3 id="ci-security-considerations" class="position-relative d-flex align-items-center group"> <span>CI Security Considerations</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="ci-security-considerations" aria-haspopup="dialog" aria-label="Share link: CI Security Considerations"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3> <h4 id="secret-management" class="position-relative d-flex align-items-center group"> <span>Secret Management</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="secret-management" aria-haspopup="dialog" aria-label="Share link: Secret Management"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Configure Secrets</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">env</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">GEODE_LICENSE_KEY</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.GEODE_LICENSE_KEY }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">AWS_SECRET_KEY</span><span class="p">:</span><span class="w"> </span><span class="l">${{ secrets.AWS_SECRET_KEY }}</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Never echo secrets </span></span></span><span class="line"><span class="cl"><span class="sd"> # Never log secrets </span></span></span><span class="line"><span class="cl"><span class="sd"> # Use secrets only where needed</span><span class="w"> </span></span></span></code></pre></div> <h4 id="dependency-scanning" class="position-relative d-flex align-items-center group"> <span>Dependency Scanning</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="dependency-scanning" aria-haspopup="dialog" aria-label="Share link: Dependency Scanning"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Scan Dependencies</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd"> </span></span></span><span class="line"><span class="cl"><span class="sd"> # Scan for vulnerabilities </span></span></span><span class="line"><span class="cl"><span class="sd"> cd geode-client-go &amp;&amp; govulncheck ./... </span></span></span><span class="line"><span class="cl"><span class="sd"> cd geode-client-rust &amp;&amp; cargo audit </span></span></span><span class="line"><span class="cl"><span class="sd"> cd geode-client-python &amp;&amp; safety check</span><span class="w"> </span></span></span></code></pre></div> <h4 id="code-scanning" class="position-relative d-flex align-items-center group"> <span>Code Scanning</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="code-scanning" aria-haspopup="dialog" aria-label="Share link: Code Scanning"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h4><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">CodeQL Analysis</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">github/codeql-action/analyze@v3</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">languages</span><span class="p">:</span><span class="w"> </span><span class="l">go, python, cpp</span><span class="w"> </span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">queries</span><span class="p">:</span><span class="w"> </span><span class="l">security-and-quality</span><span class="w"> </span></span></span></code></pre></div> <h3 id="related-topics" class="position-relative d-flex align-items-center group"> <span>Related Topics</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="related-topics" aria-haspopup="dialog" aria-label="Share link: Related Topics"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><strong><a href="/tags/ci-cd/" >CI/CD</a> </strong>: Complete CI/CD pipeline</li> <li><strong><a href="/tags/unit-tests/" >Unit Tests</a> </strong>: Unit testing strategies</li> <li><strong><a href="/tags/integration-tests/" >Integration Tests</a> </strong>: Integration testing</li> <li><strong><a href="/tags/deployment/" >Deployment</a> </strong>: Deployment automation</li> <li><strong><a href="/tags/containers/" >Containers</a> </strong>: Container-based CI</li> <li><strong><a href="/tags/cloud/" >Cloud</a> </strong>: Cloud-based CI/CD platforms</li> </ul> <h3 id="further-reading" class="position-relative d-flex align-items-center group"> <span>Further Reading</span> <button type="button" class="h-share btn btn-link p-0 text-decoration-none link-secondary opacity-50 hover-opacity-100 transition-all ms-1" data-share-target="further-reading" aria-haspopup="dialog" aria-label="Share link: Further Reading"> <i class="fa-sharp-duotone fa-solid fa-share-nodes" aria-hidden="true" style="font-size: 0.8em;"></i> <span class="visually-hidden">Share link</span> </button> </h3><ul> <li><strong>CI Best Practices</strong>: <code>/docs/development/ci-best-practices/</code></li> <li><strong>Test Automation Guide</strong>: <code>/docs/development/test-automation/</code></li> <li><strong>GitHub Actions Reference</strong>: <code>/docs/operations/github-actions/</code></li> <li><strong>Build Optimization</strong>: <code>/docs/development/build-optimization/</code></li> <li><strong>Quality Assurance</strong>: <code>/docs/development/quality-assurance/</code></li> </ul>

Related Articles

No articles found with this tag yet.

Back to Home