<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ci-Cd on Daffa Abhipraya</title><link>https://blog.abhipraya.dev/tags/ci-cd/</link><description>Recent content in Ci-Cd on Daffa Abhipraya</description><generator>Hugo</generator><language>en-us</language><copyright>© Daffa Abhipraya</copyright><lastBuildDate>Thu, 09 Apr 2026 00:00:00 +0700</lastBuildDate><atom:link href="https://blog.abhipraya.dev/tags/ci-cd/index.xml" rel="self" type="application/rss+xml"/><item><title>PPL: Quality Gates That Actually Block Bad Code</title><link>https://blog.abhipraya.dev/ppl/part-a/qa/</link><pubDate>Thu, 09 Apr 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-a/qa/</guid><description>&lt;p>Quality tools are useless if they are not enforced. Our project had SonarQube analyzing every commit, schema fuzzing running against our API, and load tests measuring latency, but every single one of them was set to &lt;code>allow_failure: true&lt;/code>. Violations were silently ignored, real bugs slipped through, and nobody noticed because the pipeline was always green. This blog covers how we turned those advisory checks into blocking gates, built automated CI reporting so reviewers could actually see the results, and watched the tools catch a JWT vulnerability, a production crash, and 31 code quality violations that had been accumulating for weeks.&lt;/p></description></item><item><title>PPL: When 91% Test Coverage Means Nothing</title><link>https://blog.abhipraya.dev/ppl/part-a/tdd-and-qa/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-a/tdd-and-qa/</guid><description>&lt;p>We had 91% line coverage and felt good about it. Then we ran mutation testing and scored 0%. Every line of our service layer was executed by tests; almost nothing was actually verified. This is the story of how six advanced testing tools exposed the gap between &amp;ldquo;code was run&amp;rdquo; and &amp;ldquo;code was checked,&amp;rdquo; and what that means for any team relying on coverage as a quality signal.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note:&lt;/strong> Our project is hosted on an internal GitLab instance, so we use the term &lt;strong>MR (Merge Request)&lt;/strong> throughout this blog. If you&amp;rsquo;re coming from GitHub, MRs are the equivalent of &lt;strong>Pull Requests (PRs)&lt;/strong>.&lt;/p></description></item><item><title>PPL: Development Discipline [Sprint 1, Week 3]</title><link>https://blog.abhipraya.dev/ppl/part-b/s1w3-discipline/</link><pubDate>Fri, 13 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-b/s1w3-discipline/</guid><description>&lt;h2 id="what-i-worked-on">
 &lt;a class="anchor" href="#what-i-worked-on" data-anchor="what-i-worked-on" aria-hidden="true">#&lt;/a>
 What I Worked On
&lt;/h2>
&lt;p>Sprint 1 Week 3 was the highest-output week of the project so far. I authored and merged &lt;strong>14 merge requests&lt;/strong> covering full-stack features, CI/CD pipeline improvements, production infrastructure fixes, and data integrity patches.&lt;/p>
&lt;h2 id="mr-summary">
 &lt;a class="anchor" href="#mr-summary" data-anchor="mr-summary" aria-hidden="true">#&lt;/a>
 MR Summary
&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>MR&lt;/th>
 &lt;th>Type&lt;/th>
 &lt;th>Title&lt;/th>
 &lt;th>Date&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>!20&lt;/td>
 &lt;td>feat&lt;/td>
 &lt;td>Layout, navigation &amp;amp; dashboard (full stack)&lt;/td>
 &lt;td>Mar 7&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!47&lt;/td>
 &lt;td>feat&lt;/td>
 &lt;td>Seed production admin and staff users with Nashta emails&lt;/td>
 &lt;td>Mar 7&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!12&lt;/td>
 &lt;td>feat&lt;/td>
 &lt;td>Invoice management (full stack)&lt;/td>
 &lt;td>Mar 8&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!54&lt;/td>
 &lt;td>feat&lt;/td>
 &lt;td>Add Payments link to sidebar navigation&lt;/td>
 &lt;td>Mar 8&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!66&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Rename out-of-order migration timestamps to unblock CI deploy&lt;/td>
 &lt;td>Mar 9&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!67&lt;/td>
 &lt;td>feat&lt;/td>
 &lt;td>Add migration dry-run validation to MR pipelines&lt;/td>
 &lt;td>Mar 9&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!68&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Add missing ENCRYPTION_KEY to deploy env generation&lt;/td>
 &lt;td>Mar 9&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!71&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Add proxy-headers to uvicorn for HTTPS redirect support&lt;/td>
 &lt;td>Mar 10&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!74&lt;/td>
 &lt;td>chore&lt;/td>
 &lt;td>Add Conductor workspace support&lt;/td>
 &lt;td>Mar 11&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!76&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Resolve invoice seeder subquery returning multiple rows&lt;/td>
 &lt;td>Mar 11&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!77&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Deduplicate invoice numbers in seed CSV&lt;/td>
 &lt;td>Mar 11&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!78&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Polish sidebar, header, profile edit, and invoices page consistency&lt;/td>
 &lt;td>Mar 11&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!79&lt;/td>
 &lt;td>fix&lt;/td>
 &lt;td>Remove sidebar header bottom border&lt;/td>
 &lt;td>Mar 11&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>!17&lt;/td>
 &lt;td>feat&lt;/td>
 &lt;td>Client management (full stack, merged by me)&lt;/td>
 &lt;td>Mar 9&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="breakdown-by-category">
 &lt;a class="anchor" href="#breakdown-by-category" data-anchor="breakdown-by-category" aria-hidden="true">#&lt;/a>
 Breakdown by category
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Full-stack features:&lt;/strong> 4 MRs (!20, !12, !54, !17)&lt;/li>
&lt;li>&lt;strong>CI/CD pipeline:&lt;/strong> 3 MRs (!66, !67, !68)&lt;/li>
&lt;li>&lt;strong>Infrastructure:&lt;/strong> 2 MRs (!71, !74)&lt;/li>
&lt;li>&lt;strong>Data integrity:&lt;/strong> 3 MRs (!47, !76, !77)&lt;/li>
&lt;li>&lt;strong>UI polish:&lt;/strong> 2 MRs (!78, !79)&lt;/li>
&lt;/ul>
&lt;h2 id="commit-message-quality">
 &lt;a class="anchor" href="#commit-message-quality" data-anchor="commit-message-quality" aria-hidden="true">#&lt;/a>
 Commit Message Quality
&lt;/h2>
&lt;p>Every commit follows the conventional commits format: &lt;code>type(scope): description&lt;/code>. The scope tells you exactly which app/layer is affected, and the description is specific enough to understand the change without reading the diff.&lt;/p></description></item><item><title>PPL: Building a Production-Safe Migration Pipeline with Automated Rollback</title><link>https://blog.abhipraya.dev/ppl/part-a/data-seeding/</link><pubDate>Thu, 12 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-a/data-seeding/</guid><description>&lt;h2 id="why-database-migrations-need-safety-nets">
 &lt;a class="anchor" href="#why-database-migrations-need-safety-nets" data-anchor="why-database-migrations-need-safety-nets" aria-hidden="true">#&lt;/a>
 Why Database Migrations Need Safety Nets
&lt;/h2>
&lt;p>Imagine this scenario: a developer adds a new column to the invoices table, pushes to &lt;code>main&lt;/code>, and the CI/CD pipeline deploys it to production. Everything looks fine until the next morning, when the team discovers that the migration also dropped a constraint that was silently relied on by another service. Rolling back means manually writing SQL against the production database at 2 AM.&lt;/p></description></item><item><title>PPL: Building an Integrated Tool Ecosystem for a 9-Person University Team</title><link>https://blog.abhipraya.dev/ppl/part-a/teamwork-tools/</link><pubDate>Thu, 12 Mar 2026 00:00:00 +0700</pubDate><guid>https://blog.abhipraya.dev/ppl/part-a/teamwork-tools/</guid><description>&lt;h2 id="why-tooling-is-a-team-problem-not-a-devops-problem">
 &lt;a class="anchor" href="#why-tooling-is-a-team-problem-not-a-devops-problem" data-anchor="why-tooling-is-a-team-problem-not-a-devops-problem" aria-hidden="true">#&lt;/a>
 Why Tooling Is a Team Problem, Not a DevOps Problem
&lt;/h2>
&lt;p>Most university software engineering courses teach you &lt;em>which&lt;/em> tools to use (Git for version control, Jira for tickets, Docker for deployment). What they rarely teach is &lt;strong>how tools interact with each other&lt;/strong>, and what happens when they don&amp;rsquo;t.&lt;/p>
&lt;p>In a professional environment, a single commit can trigger a cascade: CI runs tests, a Slack bot notifies the team, a coverage report lands in SonarQube, and the ticket moves to &amp;ldquo;In Review&amp;rdquo; on the project board. This doesn&amp;rsquo;t happen by accident. Someone has to build that integration layer, and in a university team, that someone is usually whoever cares enough about developer experience to do it.&lt;/p></description></item></channel></rss>