<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>mergify — jd:/dev/blog</title><description>Posts tagged &quot;mergify&quot; on jd:/dev/blog.</description><link>https://julien.danjou.info/</link><item><title>GitHub Actions Pricing: The Platform Reality Check</title><link>https://julien.danjou.info/blog/github-actions-isnt-getting-greedy/</link><guid isPermaLink="true">https://julien.danjou.info/blog/github-actions-isnt-getting-greedy/</guid><description>GitHub Actions Pricing: The Platform Reality Check</description><pubDate>Thu, 18 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://resources.github.com/actions/2026-pricing-changes-for-github-actions/&quot;&gt;GitHub just announced pricing changes for GitHub Actions&lt;/a&gt;, and as expected, parts of the CI ecosystem panicked.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/41bef043-9868-48d4-a99c-bd9bf74df245_2582x946.webp&quot; alt=&quot;Screenshot of GitHub Actions pricing changes announcement&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Some people are celebrating the price drop on GitHub-hosted runners. Others are furious that GitHub will start charging for self-hosted runners. And a few businesses are suddenly asking existential questions.&lt;/p&gt;
&lt;p&gt;Since then, &lt;a href=&quot;https://github.com/orgs/community/discussions/182186&quot;&gt;GitHub has paused the self-hosted runner billing change&lt;/a&gt;, acknowledging they moved too fast and didn’t involve the ecosystem enough.&lt;/p&gt;
&lt;p&gt;That doesn’t change the underlying reality. It just delays the conversation.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;GitHub Actions Was Never “Free”&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;GitHub Actions is not just a binary that runs on your machines.&lt;/p&gt;
&lt;p&gt;It’s a platform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;job queuing and scheduling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;runner registration and lifecycle management&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;workflow orchestration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;security, isolation, secrets handling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;reliability at massive scale&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even when you run your own hardware, GitHub is still doing a lot of work on your behalf. That infrastructure has always existed; hosted runners simply subsidized it.&lt;/p&gt;
&lt;p&gt;GitHub explicitly said it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We have real costs in running the Actions control plane.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That’s not new. It’s just now being made explicit.&lt;/p&gt;
&lt;p&gt;Charging a small per-minute platform fee for self-hosted runners isn’t conceptually unfair: it’s GitHub aligning pricing with reality.&lt;/p&gt;
&lt;p&gt;If you believe this is unacceptable, there has always been a clear alternative: run Jenkins, GitLab CI, or any other system where you fully own the control plane.&lt;/p&gt;
&lt;p&gt;But you don’t get GitHub Actions “for free” just because the CPU cycles are yours.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Vendor Lock-In? Yes. And Everyone Chose It.&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Some people are suddenly discovering that GitHub Actions can lead to vendor lock-in.&lt;/p&gt;
&lt;p&gt;That’s… not new.&lt;/p&gt;
&lt;p&gt;GitHub Actions is a GitHub App deeply embedded in the GitHub ecosystem. YAML workflows, permissions, APIs, events. The lock-in was the trade-off for convenience, reliability, and speed of adoption.&lt;/p&gt;
&lt;p&gt;And let’s be honest: most teams are perfectly happy with vendor lock-in (right up until pricing becomes visible). You can’t have a deeply integrated platform &lt;strong&gt;and&lt;/strong&gt; complain when the platform prices itself like one.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/33178faf-02e9-447c-9284-33371515b8c8_1376x864.png&quot; alt=&quot;Illustration of vendor lock-in as a trade-off for platform convenience&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Real Problem: CI Cost Arbitrage&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The real pain isn’t for users. It’s for companies whose business model is essentially:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We’ll run GitHub Actions cheaper than GitHub.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That model was always fragile. If you are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;buying cloud compute from AWS, GCP, or another provider&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;reselling CI minutes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;competing on price against &lt;strong&gt;Microsoft + Azure&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You are not competing on technology. You are competing on &lt;strong&gt;arbitrage&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And arbitrage disappears the moment the platform owner decides to price closer to cost, or decides they don’t want that game played anymore.&lt;/p&gt;
&lt;p&gt;This is not new. This is how platforms work.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;When Self-Hosting Still Makes Sense&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Self-hosted runners absolutely still make sense when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;you are very large&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;you have predictable workloads&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;you already operate infra at scale&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;growth is slow, and margin optimization matters more than velocity&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words, when infrastructure &lt;em&gt;is&lt;/em&gt; your business or a stable internal cost.&lt;/p&gt;
&lt;p&gt;But for growing startups, optimizing CI costs too early is usually a mistake. Time spent shaving a few cents off a CI minute is time not spent shipping product.&lt;/p&gt;
&lt;p&gt;(And yes: &lt;a href=&quot;https://julien.danjou.info/p/why-engineers-shouldnt-decide-your&quot;&gt;this is precisely why engineers should not be the sole decision-makers on infra strategy&lt;/a&gt;.)&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What GitHub’s Pause Actually Signals&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;GitHub’s follow-up message is important:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;They acknowledged real platform costs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;They admitted poor communication&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;They paused to listen, not to abandon the direction&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is not GitHub “giving up.” It’s GitHub realizing that CI/CD has become &lt;strong&gt;critical infrastructure&lt;/strong&gt;, and changes must be introduced with more ecosystem buy-in.&lt;/p&gt;
&lt;p&gt;Hosted runners still get cheaper. Actions is still being positioned as a core execution layer (including for agentic workloads). The platform direction hasn’t changed.&lt;/p&gt;
&lt;p&gt;Only the timeline has.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Takeaway&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;GitHub Actions isn’t “turning evil.” It’s finishing its transition from a feature to a platform.&lt;/p&gt;
&lt;p&gt;If your CI strategy depends on GitHub never charging for orchestration, scheduling, and reliability, that was never a safe assumption.&lt;/p&gt;
&lt;p&gt;And if your business depends on undercutting a hyperscaler on compute, you were always racing the clock.&lt;/p&gt;
&lt;p&gt;For everyone else, this remains mostly good news:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;clearer economics&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;cheaper hosted runners&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;a stronger, more explicit platform contract&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And a reminder that CI/CD is not just about cost. It&apos;s about leverage — whether that&apos;s &lt;a href=&quot;https://julien.danjou.info/blog/the-challenges-of-merge-queues&quot;&gt;merge queues that keep your main branch green&lt;/a&gt; or cheaper runners that let you ship faster.&lt;/p&gt;
</content:encoded><category>devops</category><category>mergify</category></item><item><title>The Day I Got Custom Table Legs</title><link>https://julien.danjou.info/blog/the-day-i-got-custom-table-legs/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-day-i-got-custom-table-legs/</guid><description>What It Taught Me About Support</description><pubDate>Tue, 22 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week, I was with my team at our Mergify &lt;em&gt;on-site&lt;/em&gt; — what we call our &lt;em&gt;MAHOS (Mergify All-Hands On-Site)&lt;/em&gt;. Yes, we’re a fully remote team, so your regular off-site are called on-site for us. 😉&lt;/p&gt;
&lt;p&gt;We talked about the usual: roadmap, strategy, alignment. But then I brought up something a little different. I wanted to explain how we think about customer support at Mergify—not as a checkbox, not as a cost center, but as a way to deliver what I call the &lt;em&gt;&lt;a href=&quot;https://blog.mergify.com/how-we-handle-our-roadmap-for-mergify/&quot;&gt;wow effect&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To make my point, I told them a story. A true one — about a table.&lt;/p&gt;
&lt;p&gt;Two years ago, I had just moved into a new house. My first real garden. I was excited to enjoy it, so I decided to buy a garden table and chairs. After browsing around, I picked &lt;a href=&quot;https://www.lafuma-mobilier.fr/&quot;&gt;Lafuma&lt;/a&gt; — a French brand I’ve liked since I was a kid.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/abbcdd6a-d840-42ed-80cf-7395e6ab1524_645x559.webp&quot; alt=&quot;Lafuma garden table product photo&quot; /&gt;
&lt;em&gt;Fun fact: my very first school backpack in first grade was a Lafuma. Yes, I still remember it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Anyway, the table and chairs arrived. Great delivery. Good packaging. Quality seemed top-notch.&lt;/p&gt;
&lt;p&gt;But something felt… off.&lt;/p&gt;
&lt;p&gt;I sat down, and it wasn’t right. The proportions felt weird. The table was just a little too high, or the chairs too low. So I did what every curious engineer does: I grabbed a tape measure. Compared it to my indoor table. And there it was — the Lafuma table was exactly 2cm too tall. Just enough to make every meal feel slightly awkward.&lt;/p&gt;
&lt;p&gt;So I wrote them a message. Not angry, not demanding. Just a note saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Love the brand, love the product, but this feels like a design oversight.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I didn’t expect a reply.&lt;/p&gt;
&lt;p&gt;One week later, I got a call. It was someone from Lafuma’s support team — a QA engineer.&lt;/p&gt;
&lt;p&gt;He said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I read your message. I’d like to understand exactly what’s wrong.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I explained. He listened. Then, without hesitation, he said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Okay. I’ll send you custom table legs, 2cm shorter. You’ll have them next week.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was stunned.&lt;/p&gt;
&lt;p&gt;“Wait, really? You can do that?”&lt;/p&gt;
&lt;p&gt;“Of course,” he replied. “We have spare legs in the workshop. We’ll just trim and ship them to your size.”&lt;/p&gt;
&lt;p&gt;And that’s exactly what happened. A week later, I swapped out the legs. Perfect fit. Perfect height. Perfect support.&lt;/p&gt;
&lt;p&gt;They didn’t have to do that. I wasn’t going to return the table. I wasn’t even asking for anything. But they did it anyway — because they cared. Because they listened. Because they understood what &lt;em&gt;great&lt;/em&gt; support means.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/52932582-97ff-4eda-93d4-56504d05d4e1_3024x3700.jpeg&quot; alt=&quot;Photo of the Lafuma table with custom-shortened legs installed&quot; /&gt;
&lt;em&gt;New leg size approved by my wife.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s the kind of service we try to deliver at &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Even in B2B, even in software, even at scale — you can still surprise people. (&lt;a href=&quot;https://julien.danjou.info/blog/why-we-still-care-about-quality&quot;&gt;Why we still care about quality&lt;/a&gt; is about the same mindset.) You can still make them feel heard. You can still &lt;em&gt;wow&lt;/em&gt; them. That’s what Amazon did so well for years. And it’s what so many companies forget as they grow.&lt;/p&gt;
&lt;p&gt;But it’s not optional. It’s the difference between a satisfied user and a loyal one. Between a customer and a fan.&lt;/p&gt;
&lt;p&gt;Build the table. And send the legs.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>Why We Still Care About Quality</title><link>https://julien.danjou.info/blog/why-we-still-care-about-quality/</link><guid isPermaLink="true">https://julien.danjou.info/blog/why-we-still-care-about-quality/</guid><description>Quality is slow, hard, and totally worth it</description><pubDate>Tue, 24 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently read &lt;a href=&quot;https://linear.app/blog/why-is-quality-so-rare&quot;&gt;Linear’s excellent blog post on why quality is so rare&lt;/a&gt;, and it resonated deeply with me. Craft, quality, care — these aren’t buzzwords. They’re a way of working, a way of thinking, and frankly, the only way I’ve ever known how to build things.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/d3224e88-3b48-4bbd-ad4c-04f364308e0d_809x394.png&quot; alt=&quot;Screenshot of Linear&apos;s blog post on why quality is so rare&quot; /&gt;
&lt;em&gt;Linear: Why is quality so rare?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For me, it started with &lt;a href=&quot;https://julien.danjou.info/blog/open-source-is-getting-used-to-death&quot;&gt;open source&lt;/a&gt;. When you put your code out in the open, you naturally want to make it good. Maybe even beautiful. I started more than 20 years ago, polishing my Debian packages, making sure they were clean, understandable, and useful. Later I poured that same mindset into building &lt;em&gt;&lt;a href=&quot;https://awesomewm.org&quot;&gt;awesomewm&lt;/a&gt;&lt;/em&gt;, striving to write the best C code I could — because that code was me, visible to anyone curious enough to look.&lt;/p&gt;
&lt;p&gt;Open source taught me that quality is not an accident. It’s a habit. And a commitment.&lt;/p&gt;
&lt;p&gt;Even though &lt;a href=&quot;https://blog.mergify.com/why-mergify-codebase-isnt-open-source-anymore-a-tale-of-growth-change-and-adaptation/&quot;&gt;Mergify is no longer open source&lt;/a&gt;, the ethos never left. We still build like our code is going to be read by thousands, because, well, it is at least read by our folks. Our team ships work we’re proud of. Whether we win a deal or not, it’s common to hear people tell us:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The quality of Mergify stands out.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That never gets old.&lt;/p&gt;
&lt;p&gt;I know I’m not alone in this. Mehdi, my cofounder, and I have been building together for over 15 years. It’s in our DNA: we hate mediocrity. We won’t ship something that we wouldn’t use ourselves — joyfully.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/c6432d0e-0b74-4b90-bbfa-b9f7e4b83516_1376x864.webp&quot; alt=&quot;Illustration of craftsmanship and quality in software engineering&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That said, I’ve also seen the flip side. Back when I worked on &lt;a href=&quot;https://openstack.org&quot;&gt;OpenStack&lt;/a&gt;, a massive open-source project, there was a lot of code… and not always a lot of care. Many contributors came from companies that didn’t value quality — and it showed. Open source can be beautiful, but when it’s driven by quantity instead of pride, it becomes exhausting. I hated that part.&lt;/p&gt;
&lt;p&gt;Quality isn’t just aesthetic. It’s a business strategy. Linear nailed that in their post. When you build something that feels right — fast, polished, thoughtful — users notice. They stay. They tell others. We’ve seen this at Mergify: our growth has been fueled not just by features but by how those features feel to use.&lt;/p&gt;
&lt;p&gt;But quality is more than just a great UI or bug-free code.&lt;/p&gt;
&lt;p&gt;It’s also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A fast, reliable, intuitive product.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clean code that enables long-term agility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thoughtful defaults and edge-case handling.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Being able to say “no” when something adds complexity without enough payoff.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Getting there isn’t easy. You need judgment — to know what’s worth doing and what can wait. That comes with experience and the humility to know you’ll never get everything right. We aim for 80/20, not 100/0. Sometimes that means leaving the last 20% for another day — or maybe never. Not because we don’t care, but because we care about the whole system staying healthy and fast.&lt;/p&gt;
&lt;p&gt;Quality isn’t free. But it pays back. In speed, trust, and joy.&lt;/p&gt;
&lt;p&gt;So yes, it’s a choice. One you make every day.&lt;/p&gt;
&lt;p&gt;You can take the shortcut, or you can make something that lasts.&lt;/p&gt;
&lt;p&gt;We still choose the latter.&lt;/p&gt;
</content:encoded><category>coding</category><category>mergify</category></item><item><title>From Failure to Focus</title><link>https://julien.danjou.info/blog/from-failure-to-focus/</link><guid isPermaLink="true">https://julien.danjou.info/blog/from-failure-to-focus/</guid><description>How CI Insights Was Born</description><pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Startups love to talk about iteration. Failing fast. Learning from mistakes. But when you’re six months into a project that doesn’t ship — not once, but &lt;em&gt;twice&lt;/em&gt; — that mantra starts to feel a bit too real.&lt;/p&gt;
&lt;p&gt;At Mergify, we recently spent almost a year building two separate products around CI/CD. Both had potential. Both looked promising. And both ended up in the graveyard.&lt;/p&gt;
&lt;p&gt;I have written about this in three posts already: &lt;a href=&quot;https://julien.danjou.info/blog/the-100000-mistake&quot;&gt;The $100,000 Mistake&lt;/a&gt;, &lt;a href=&quot;https://julien.danjou.info/blog/when-nobody-wants-your-product&quot;&gt;When Nobody Wants Your Product&lt;/a&gt;, and &lt;a href=&quot;https://julien.danjou.info/blog/when-great-tech-isnt-enough&quot;&gt;When Great Tech Isn&apos;t Enough&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But here’s the thing: that journey was the best thing that could’ve happened to us because it led to &lt;strong&gt;&lt;a href=&quot;https://mergify.com/product/ci-insights&quot;&gt;CI Insights&lt;/a&gt;&lt;/strong&gt;, our newest product, which we’re shipping for real this time.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;When R&amp;amp;D Goes Off-Road&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;If you’ve followed the first parts of this series, you know the backstory. In 2023, after years of growing Mergify’s Merge Queue product, we started exploring new ideas.&lt;/p&gt;
&lt;p&gt;The first was &lt;strong&gt;CI Optimizer&lt;/strong&gt; — a tool to help teams reduce CI/CD costs. But we quickly learned something important: engineers aren’t the ones who care about CI spend. That’s a FinOps conversation. And FinOps teams weren’t our users.&lt;/p&gt;
&lt;p&gt;Then came &lt;strong&gt;CI Issues&lt;/strong&gt;, a project aimed at tracking flaky tests and infrastructure problems. This time we had interest. Teams &lt;em&gt;did&lt;/em&gt; struggle with these problems. But we made the mistake of diving into R&amp;amp;D without doing proper design work. We built a complex system — and it worked — but it was so hard to deploy and operate that we never felt confident letting users in.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/66339157-7d29-4350-b790-71eda725ea58_1376x864.webp&quot; alt=&quot;Illustration of failed product attempts before finding the right design&quot; /&gt;
&lt;em&gt;No design, you said?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So once again, we shelved it.&lt;/p&gt;
&lt;p&gt;Two product attempts, zero releases.&lt;/p&gt;
&lt;p&gt;But what survived both efforts was a deeper understanding of the pain engineers feel every day around CI.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Real Problem: CI Is a Black Box&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Across all our conversations, one theme kept showing up: visibility.&lt;/p&gt;
&lt;p&gt;Teams weren’t desperate to reduce CI costs. They weren’t obsessed with infrastructure failures. But they were all asking the same questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Why is our CI pipeline so slow?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which PRs are consistently the bottleneck?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which tests are flaky?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Where are we wasting time?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nobody had good answers. CI is treated like a utility — flip the switch and hope the light turns on. But when it doesn’t, or when it flickers, most teams don’t have the tools to understand &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We realized what was missing wasn’t a FinOps tool or a smart test tracker — it was &lt;strong&gt;observability&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;CI Insights: The Missing Layer&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;With all the groundwork we’d laid — our CI connectors, our data pipelines, our internal dashboards — we already had most of the pieces. We just needed to reframe the problem.&lt;/p&gt;
&lt;p&gt;So we did.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/dc14e464-b5af-41f0-8d1d-6f1ebbe334f2_2880x1920.png&quot; alt=&quot;Screenshot of the Mergify CI Insights dashboard&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CI Insights&lt;/strong&gt; is the observability layer for your CI.&lt;/p&gt;
&lt;p&gt;It helps teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Spot flaky jobs and tests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Identify long-running or unstable jobs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Understand where their pipeline is slowing them down&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Track trends over time across teams and repos&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s not about cost savings. It’s not about blaming the CI tool. It’s about &lt;em&gt;clarity&lt;/em&gt; — understanding what’s going on, so teams can ship faster and with less frustration.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;This Time, We Built It Right&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We learned from our previous mistakes.&lt;/p&gt;
&lt;p&gt;This time, we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Started with real use cases&lt;/strong&gt; from customers and our own internal needs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Designed first&lt;/strong&gt;, coded second&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Focused on value over complexity&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Shipped it&lt;/strong&gt; to users. Yes. Really.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ve been using CI Insights ourselves for months now. It already helped us catch flaky jobs, detect broken test workflows, and reduce merge queue delays.&lt;/p&gt;
&lt;p&gt;Now, we’re rolling it out to early users — and so far, the feedback has been 🔥.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Bigger Picture&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;CI Insights is more than just a tool. It’s a shift in how we think about CI.&lt;/p&gt;
&lt;p&gt;It’s not just a thing that “runs your tests.” It’s a critical part of your development workflow. And it deserves the same kind of visibility, metrics, and tooling that you already have for production systems.&lt;/p&gt;
&lt;p&gt;We’re building CI Insights to be the &lt;strong&gt;best observability tool for CI&lt;/strong&gt; — because engineers deserve better tools.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What’s Next?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We’re just getting started. The roadmap is full. We’re onboarding users slowly and shaping the product based on real feedback.&lt;/p&gt;
&lt;p&gt;If CI is a black box for your team — if you’re tired of guessing why things are slow — we’d love to hear from you.&lt;/p&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://mergify.com/product/ci-insights&quot;&gt;Request early access&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>Not Just a Job, It’s a Ride</title><link>https://julien.danjou.info/blog/not-just-a-job-its-a-ride/</link><guid isPermaLink="true">https://julien.danjou.info/blog/not-just-a-job-its-a-ride/</guid><description>How we hire at Mergify</description><pubDate>Tue, 15 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hiring is easily one of the hardest jobs I’ve had to do at &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;. Not because there aren’t smart people out there — there are. But because we’re not just hiring for skill. We’re hiring for mindset.&lt;/p&gt;
&lt;p&gt;And let’s be honest: that’s a lot harder to screen for than technical chops.&lt;/p&gt;
&lt;p&gt;When you’re building a startup, every new hire changes the shape of the team. Every person matters. You’re not adding a cog to a big machine — you’re inviting someone on the ride with you, and they’d better be ready for the speed bumps.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What We Actually Look For&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;At Mergify, we look for people who care. Not just about clean code or nice UI — but about the mission. The thing we’re building. The problems we’re solving. If what we’re doing doesn’t excite you, we’re not going to try to sell it to you. We want you to come in already leaning forward.&lt;/p&gt;
&lt;p&gt;We’re looking for people who aren’t title-driven but &lt;strong&gt;outcome-driven&lt;/strong&gt;. People who will get things done even when no ticket has been assigned or clear ownership has been defined yet. That happens a lot.&lt;/p&gt;
&lt;p&gt;You need to bring ideas, not just execute someone else’s. We expect initiative, curiosity, and autonomy.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/957dd9f1-9623-477a-a943-16e35464be07_673x313.png&quot; alt=&quot;Screenshot of Mergify&apos;s vision and mission statement on their website&quot; /&gt;
&lt;em&gt;We provide a good summary of our vision and mission on our website.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Autonomy Isn’t a Buzzword, It’s the Filter&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Here’s a small story that stuck with me.&lt;/p&gt;
&lt;p&gt;We had a candidate once who asked me during the interview, “Who’s in charge of breaking down the project into tickets?”&lt;/p&gt;
&lt;p&gt;I said, “You are.”&lt;/p&gt;
&lt;p&gt;That was enough to scare them off — and that’s OK. At Mergify, you’ll be expected to do exactly that. Define your work, structure your plan, ask questions when you need to — but no one’s going to hand you a Jira board and a user story spec for every task.&lt;/p&gt;
&lt;p&gt;If that makes you nervous, we might not be the right place. If it makes you excited? &lt;a href=&quot;https://careers.mergify.com&quot;&gt;You should talk to us.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Startups Are Messy. That’s the Point.&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;You can’t build a startup with neat little boxes around every role.&lt;/p&gt;
&lt;p&gt;One week, you might be writing code. The next, you’re giving a talk at a meetup. The week after, you’re helping a customer figure out something weird in their CI pipeline.&lt;/p&gt;
&lt;p&gt;We look for people who can jump between lanes without crashing the car. If you need clear job boundaries, startup life will drive you insane. But if you like wearing multiple hats (sometimes in one day), you’ll thrive here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/e5ab8274-c078-4466-aa8b-082e9aae55eb_1376x864.webp&quot; alt=&quot;Illustration of wearing multiple hats at a startup&quot; /&gt;
&lt;em&gt;Wearing multiple hats.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Hiring Mistakes: Yep, We Made Some&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;One of our early missteps? Underestimating how hard remote work can be — for some people.&lt;/p&gt;
&lt;p&gt;We’re fully remote, and we love it. But not everyone is cut out for it. We’ve had brilliant engineers who struggled because they needed more structure, more hand-holding, and more real-time sync. (I wrote about this in &lt;a href=&quot;https://julien.danjou.info/blog/remote-work-great-but-not-perfect&quot;&gt;Remote Work: Great, But Not Perfect&lt;/a&gt;.) And we’ve learned the hard way that great resumes don’t always mean great remote workers.&lt;/p&gt;
&lt;p&gt;Now, we screen harder for that. Autonomy, again, is a big part of the puzzle.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Our Hiring Process (And Why We Meet in Person)&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Our process is pretty standard on the surface:&lt;/p&gt;
&lt;p&gt;👉 A technical test&lt;/p&gt;
&lt;p&gt;👉 A technical interview&lt;/p&gt;
&lt;p&gt;👉 A CEO chat&lt;/p&gt;
&lt;p&gt;👉 An onsite interview&lt;/p&gt;
&lt;p&gt;👉 Reference checks&lt;/p&gt;
&lt;p&gt;We’ve documented the whole thing &lt;a href=&quot;https://careers.mergify.com/hiring-process&quot;&gt;on our website&lt;/a&gt;, so there are no surprises.&lt;/p&gt;
&lt;p&gt;But one thing we insist on: &lt;strong&gt;we meet you in person&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Remote or not, hiring is a human process. A real-life conversation can reveal things that a dozen Zoom calls won’t. We’ve avoided a few bad hires because we took the time to meet face-to-face.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Motivation Over Résumé&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The biggest signal we look for? &lt;strong&gt;Why you want to join.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We try not to overexplain this part publicly, because it’s one of our most effective filters. But let’s just say: if your reason for leaving your current job is “looking for a remote job,” we’ll probably pass.&lt;/p&gt;
&lt;p&gt;We want people who are actively choosing this kind of work, people who are ready for the ambiguity, the responsibility, and, yes, the chaos.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Hiring for Roles You Don’t Know? Brutal.&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;When we hired our first designer, it took us &lt;em&gt;way&lt;/em&gt; longer than it should have. Why? Because we didn’t know how to assess the role.&lt;/p&gt;
&lt;p&gt;If you’ve never done the job yourself, hiring for it is like ordering dinner in a language you don’t speak. You might get lucky, but you probably won’t.&lt;/p&gt;
&lt;p&gt;We’ve learned to spend more time understanding what we actually need before we go looking for someone to do it. Sounds obvious. It’s not.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What’s Hard Now?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Right now, our biggest challenge is finding candidates who combine technical skill with startup DNA.&lt;/p&gt;
&lt;p&gt;We’re looking for people who’ve spent a few years in early-stage companies, who know what it’s like to ship fast, wear multiple hats, and stay sane through ambiguity. Not just smart — adaptable.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;If That’s You…&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Then maybe we should talk. If you’re looking for more than just a job — if you want to build something, shape it, and take pride in it — you might belong here.&lt;/p&gt;
&lt;p&gt;We’re picky, yeah. It slows us down. But we’ve learned the cost of the wrong hire is much higher than waiting for the right one.&lt;/p&gt;
&lt;p&gt;So if you’re ready for the ride, &lt;a href=&quot;https://careers.mergify.com&quot;&gt;we’re hiring&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>When Great Tech Isn’t Enough</title><link>https://julien.danjou.info/blog/when-great-tech-isnt-enough/</link><guid isPermaLink="true">https://julien.danjou.info/blog/when-great-tech-isnt-enough/</guid><description>The Product That Never Shipped</description><pubDate>Wed, 26 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to the third post in our “we-built-something-and-killed-it” series.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://julien.danjou.info/p/the-100000-mistake&quot;&gt;first chapter&lt;/a&gt;, we shared how we started building CI Optimizer—our ambitious attempt to help teams cut down on CI/CD costs.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;https://julien.danjou.info/p/when-nobody-wants-your-product&quot;&gt;second&lt;/a&gt;, we explained why that effort never made it past the runway: while the problem existed, no one really wanted the solution.&lt;/p&gt;
&lt;p&gt;But that wasn’t the end of the story.&lt;/p&gt;
&lt;p&gt;Because just as we were winding down CI Optimizer, something else started to take shape—almost accidentally.&lt;/p&gt;
&lt;h2&gt;From CI Cost to CI Chaos&lt;/h2&gt;
&lt;p&gt;As we were working on CI Optimizer, we had to dig deeper into CI platforms like GitHub Actions or CircleCI. We needed to understand the structure, failures, and performance of CI pipelines to measure their cost.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/59ac52ab-14c5-4f1a-8f0c-686e3d94bc06_1376x864.webp&quot; alt=&quot;Illustration of digging into CI pipeline failures and reliability issues&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And the more we explored, the more something else stood out: teams weren’t just struggling with &lt;strong&gt;CI/CD costs&lt;/strong&gt;—they were struggling with &lt;strong&gt;CI reliability&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;❗Flaky tests.&lt;/p&gt;
&lt;p&gt;❗Unreliable runners.&lt;/p&gt;
&lt;p&gt;❗Timeouts.&lt;/p&gt;
&lt;p&gt;❗Random infra failures.&lt;/p&gt;
&lt;p&gt;And as users of our Merge Queue product kept telling us:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Our workflow is fine—until CI starts acting up.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So we asked ourselves a new question:&lt;/p&gt;
&lt;p&gt;💡 What if we stopped focusing on &lt;strong&gt;how much CI costs&lt;/strong&gt;, and started looking at &lt;strong&gt;how much CI hurts&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;That’s how the idea for our next product—&lt;strong&gt;CI Issues&lt;/strong&gt;—was born.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Pivot: CI Issues&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;CI Issues was meant to do one thing really well:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track, identify, and alert on CI problems before they silently torpedo developer productivity.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We wanted to give teams &lt;strong&gt;insight and visibility&lt;/strong&gt; into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How often their tests flaked&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Whether their CI infrastructure was unreliable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which PRs were impacted&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which workflows deserved attention&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal wasn’t just dashboards. It was &lt;strong&gt;detection and action&lt;/strong&gt;. You’d be able to see patterns, set alerts, and flag recurring issues before developers noticed them.&lt;/p&gt;
&lt;p&gt;And as we started to pitch the concept to engineers, the excitement was real:&lt;/p&gt;
&lt;p&gt;💬 “We have this exact pain.”&lt;/p&gt;
&lt;p&gt;💬 “We’ve built half of this internally.”&lt;/p&gt;
&lt;p&gt;💬 “Please let us know when it’s ready.”&lt;/p&gt;
&lt;p&gt;We felt like we were onto something.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The R&amp;amp;D Rabbit Hole&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;So we jumped in headfirst. We already had code collecting and analyzing CI data, so we started adapting it for CI Issues.&lt;/p&gt;
&lt;p&gt;We ran the system internally, refined metrics, tested detection logic, built a first UI. And then we iterated. And iterated. And iterated again.&lt;/p&gt;
&lt;p&gt;But something was off.&lt;/p&gt;
&lt;p&gt;Every time we looked at what we had, the same thought came back:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“This is good… but it’s not a product.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It was barely working for us internally. Even we had trouble using it.&lt;/p&gt;
&lt;p&gt;It was noisy. It was complex. It was fragile. It wasn’t obvious how to deploy or operate it at scale.&lt;/p&gt;
&lt;p&gt;We had built &lt;strong&gt;tech&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But we hadn’t designed a &lt;strong&gt;product&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/65407c22-58d2-4faf-a612-5fa983ebabfd_1376x864.webp&quot; alt=&quot;Illustration of building tech without product design&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Realization That Stopped Us&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;After almost a year of work, we paused and took a step back. And it hit us:&lt;/p&gt;
&lt;p&gt;We had made the &lt;strong&gt;same mistake&lt;/strong&gt; again—but in a different way.&lt;/p&gt;
&lt;p&gt;With CI Optimizer, we had &lt;strong&gt;no market&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;With CI Issues, we had &lt;strong&gt;no design&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This time, it wasn’t the problem that was flawed—it was our approach.&lt;/p&gt;
&lt;p&gt;We had focused on research, experimentation, pipelines, metrics, code—but we hadn’t put the same energy into figuring out &lt;strong&gt;how the product should be used&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;How would teams onboard?&lt;/p&gt;
&lt;p&gt;How would they configure it?&lt;/p&gt;
&lt;p&gt;How would they act on the data?&lt;/p&gt;
&lt;p&gt;What does success look like for them?&lt;/p&gt;
&lt;p&gt;The longer we waited to answer those questions, the more we realized:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💣 “If we ship this now, we’ll be building another tool that’s hard to use, hard to maintain, and ultimately, unadopted.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So we made the call—again.&lt;/p&gt;
&lt;p&gt;We stopped.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What We Learned (This Time)&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This second failure didn’t sting the same way as the first.&lt;/p&gt;
&lt;p&gt;In fact, it felt like a necessary part of the journey.&lt;/p&gt;
&lt;p&gt;Here’s what we learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Validation isn’t enough—you need design.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even if users want a solution, they won’t use a product that’s hard to operate or understand.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Great tech doesn’t mean great UX.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CI Issues worked, technically—but without thoughtful design, it was dead in the water.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You need both clarity and empathy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Clarity on what you’re solving, and empathy for how your users will experience it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;What’s Next?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The story doesn’t end here.&lt;/p&gt;
&lt;p&gt;CI Issues gave us a powerful insight into how fragile and painful the CI experience can be—and how underserved engineers still are when things go wrong.&lt;/p&gt;
&lt;p&gt;So we took everything we learned from CI Optimizer and CI Issues, and went back to the drawing board—with a new vision, new design principles, and a better understanding of how to build the right thing the right way.&lt;/p&gt;
&lt;p&gt;Stay tuned for the final post in the series: &lt;strong&gt;what we built next, and how it’s going to change how developers deal with CI failures.&lt;/strong&gt;&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>When Nobody Wants Your Product</title><link>https://julien.danjou.info/blog/when-nobody-wants-your-product/</link><guid isPermaLink="true">https://julien.danjou.info/blog/when-nobody-wants-your-product/</guid><description>The Moment We Realized CI Optimizer Was Doomed</description><pubDate>Tue, 04 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the first part of this series, we introduced &lt;em&gt;CI Optimizer&lt;/em&gt;, a product we were convinced would help engineering teams reduce their CI/CD costs. Given the economic downturn in 2023, we saw budgets tightening, companies folding, and engineering teams being forced to justify every dollar they spent.&lt;/p&gt;
&lt;p&gt;If you missed the first part, &lt;a href=&quot;https://julien.danjou.info/blog/the-100000-mistake&quot;&gt;read it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It seemed like the perfect time to launch a tool that would bring cost visibility and optimization to CI/CD workflows.&lt;/p&gt;
&lt;p&gt;We started building immediately, setting up a landing page and a waitlist, and running early customer interviews. Our approach was clear:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Build the product.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Talk to potential users.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Iterate based on feedback.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But as we reached out to customers, one thing became clear:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 Nobody really cared about optimizing CI/CD costs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was the moment we realized we were building something that might never find an audience.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/735a74df-429a-4df9-9aa5-9115ff00c989_1376x864.webp&quot; alt=&quot;Illustration of building a product nobody wants&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Trying to Sell the Product Before It Existed&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;I strongly believe that you should be selling a product before it even exists. If you can’t generate demand when it’s just an idea, chances are you won’t generate demand once it’s built.&lt;/p&gt;
&lt;p&gt;So, as we were writing the first lines of code, we also launched:&lt;/p&gt;
&lt;p&gt;✅ A &lt;strong&gt;marketing campaign&lt;/strong&gt; to build awareness.&lt;/p&gt;
&lt;p&gt;✅ A &lt;strong&gt;landing page&lt;/strong&gt; with a waitlist.&lt;/p&gt;
&lt;p&gt;✅ &lt;strong&gt;Customer outreach&lt;/strong&gt; to gauge interest.&lt;/p&gt;
&lt;p&gt;Our goal was to &lt;strong&gt;validate demand early&lt;/strong&gt;—before we wasted months building something nobody wanted.&lt;/p&gt;
&lt;p&gt;But things didn’t go as expected.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The First Red Flag: Engineers Didn’t Care&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;As we started &lt;strong&gt;talking to users&lt;/strong&gt;, the first warning sign was that &lt;strong&gt;engineers were simply not interested&lt;/strong&gt; in optimizing their CI/CD costs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💬 &lt;strong&gt;“Sure, spending less money is nice, but it’s not a priority.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;“We’ve never been asked to reduce our CI/CD spend.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;“CI is just a necessary cost of doing business.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was surprising. We expected companies to be actively looking for &lt;strong&gt;ways to cut costs&lt;/strong&gt;, but instead, we found:&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Engineers weren’t incentivized to optimize costs.&lt;/strong&gt; Most of them were measured by &lt;strong&gt;features delivered&lt;/strong&gt; and &lt;strong&gt;bugs fixed&lt;/strong&gt;, not by how much they spent on infrastructure.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Budgets were tight, but existing expenses weren’t scrutinized.&lt;/strong&gt; Many teams were cutting &lt;strong&gt;new&lt;/strong&gt; expenditures, but &lt;strong&gt;existing CI/CD costs were just accepted&lt;/strong&gt; as part of doing business.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;It wasn’t an engineering problem—it was a finance problem.&lt;/strong&gt; Even when engineers acknowledged CI/CD spending was high, they said, &lt;strong&gt;“This isn’t my job to fix.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In short:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🚨 &lt;strong&gt;We had built a solution for a problem our audience didn’t care about.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But we weren’t ready to give up yet.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Second Red Flag: Talking to the Wrong People&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Since engineering teams didn’t seem to care, we were often &lt;strong&gt;redirected to FinOps teams&lt;/strong&gt;—the financial teams responsible for tracking cloud spend.&lt;/p&gt;
&lt;p&gt;So we thought, &lt;strong&gt;“Great! Maybe this is our actual target audience.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We started talking to FinOps teams, and here’s what we discovered:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💬 &lt;strong&gt;“We don’t need another tool—we just need a report in a spreadsheet.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;“Can you just give us an API so we can generate cost breakdowns?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;“We don’t want to ‘optimize’ CI/CD automatically. We just need visibility.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💬 &lt;strong&gt;“If we were to buy your product, we’d need more than reporting. We want automatic cost optimization.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here’s where we ran into &lt;strong&gt;our second major issue&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;🚨 &lt;strong&gt;We were not equipped to build a product for FinOps teams.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We understood &lt;strong&gt;engineers&lt;/strong&gt;. We had deep experience with &lt;strong&gt;CI/CD workflows&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But we knew &lt;strong&gt;nothing&lt;/strong&gt; about selling to FinOps.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Selling to FinOps teams is a completely different game.&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;They care about &lt;strong&gt;budgets, forecasting, and high-level cost reporting&lt;/strong&gt;, not about &lt;strong&gt;how CI/CD actually works.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even worse:&lt;/p&gt;
&lt;p&gt;❌ &lt;strong&gt;The product we had in mind was too technical for FinOps teams.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;❌ &lt;strong&gt;The version they needed was much more complex and would take a year to build.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;❌ &lt;strong&gt;We would be competing against massive cloud cost monitoring tools, not other DevOps tools.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At this point, we had two choices:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Keep building a product for engineers who didn’t care.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Completely pivot to a new audience we didn’t understand.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Neither option looked good.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Hard Decision: Killing the Product&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;By the six-month mark, we had spent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;🕚 &lt;strong&gt;Hundreds of hours&lt;/strong&gt; building a proof-of-concept.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;📞 &lt;strong&gt;Countless customer calls&lt;/strong&gt; trying to validate the idea.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;💬 &lt;strong&gt;Weeks refining our messaging&lt;/strong&gt; to see if we could spark interest.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But deep down, we knew the truth:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;❌ &lt;strong&gt;Engineers wouldn’t pay for cost optimization.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ &lt;strong&gt;FinOps teams needed something completely different.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ &lt;strong&gt;There was no clear path forward.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And so, after &lt;strong&gt;six months of work&lt;/strong&gt;, we made the hardest decision a product team can make:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We killed the project.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/69edf6e0-23d2-4c40-aebd-25e4463167ca_1376x864.png&quot; alt=&quot;Illustration of killing a product that has no market fit&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Instead of pushing forward with a product that had no market, we &lt;strong&gt;pivoted to something else&lt;/strong&gt;—which I’ll reveal in the final part of this series.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Even though we ultimately abandoned &lt;em&gt;CI Optimizer&lt;/em&gt;, the experience taught us some &lt;strong&gt;critical lessons&lt;/strong&gt; about building new products:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Talk to Customers Before Writing Code&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We should have validated demand &lt;strong&gt;before&lt;/strong&gt; starting development. Building first and testing later is a &lt;strong&gt;risky&lt;/strong&gt; approach. Fortunately we mitigated this by talking while building.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Engineers Don’t Always Care About Cost Savings&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Developers are focused on &lt;strong&gt;shipping code&lt;/strong&gt;, not &lt;strong&gt;cutting costs&lt;/strong&gt;. If a product &lt;strong&gt;doesn’t directly impact their work&lt;/strong&gt;, they won’t engage with it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Just Because a Problem Exists Doesn’t Mean It Needs a Product&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Companies do spend too much on CI/CD, but that doesn’t mean they’re looking for a tool to fix it. Some problems are simply &lt;strong&gt;not painful enough&lt;/strong&gt; to justify a new product.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Selling to Finance Teams is a Whole Different Game&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;FinOps teams think differently from engineers. If your product doesn’t fit into their &lt;strong&gt;existing finance workflows&lt;/strong&gt;, they won’t use it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Know When to Walk Away&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One of the hardest skills in startups is knowing &lt;strong&gt;when to cut your losses&lt;/strong&gt;. We could have wasted another 6–12 months building something nobody wanted. Instead, we chose to &lt;strong&gt;fail fast and pivot.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What’s Next?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Even though &lt;strong&gt;CI Optimizer never launched&lt;/strong&gt;, it wasn’t a wasted effort.&lt;/p&gt;
&lt;p&gt;In fact, the insights we gained from this failure led us to build &lt;strong&gt;something even better.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;Part 3&lt;/strong&gt;, I’ll reveal how we took everything we learned from this failure and &lt;strong&gt;pivoted to a product that actually resonated with engineers&lt;/strong&gt;—and how that decision changed the trajectory of Mergify.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>The $100,000 Mistake</title><link>https://julien.danjou.info/blog/the-100000-mistake/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-100000-mistake/</guid><description>How We Spent 6 Months Building a CI Tool Nobody Asked For</description><pubDate>Tue, 18 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;&lt;strong&gt;A Journey into Startup Reality&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Not every startup success story begins with a garage, two co-founders, and an overnight explosion of users. And not every failure is a dramatic, fiery crash. Some of the most valuable lessons happen in the quieter moments—when you’ve built something, spent months refining it, and then realized you were &lt;strong&gt;solving the wrong problem&lt;/strong&gt; all along.&lt;/p&gt;
&lt;p&gt;This is the story of &lt;strong&gt;CI Optimizer&lt;/strong&gt;, a product we believed would transform the way companies managed their CI/CD costs. We spent &lt;strong&gt;six months&lt;/strong&gt; designing, building, and testing it—only to ultimately &lt;strong&gt;kill it before launch&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Why? Because we made &lt;strong&gt;one fundamental mistake&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This three-part series is not just about the technical challenges of optimizing CI/CD or the intricacies of pricing cloud infrastructure. It’s about &lt;strong&gt;the hard reality of building a product, talking to customers, and realizing you missed the mark.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you’re an entrepreneur, a product builder, or just someone fascinated by the messy, unpredictable world of startups, this series is for you.&lt;/p&gt;
&lt;p&gt;Let’s start at the beginning.&lt;/p&gt;
&lt;h2&gt;How It Started&lt;/h2&gt;
&lt;p&gt;At the end of 2022, &lt;strong&gt;Mergify was on a roll.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We had spent the past year growing steadily, tripling our revenue, refining our &lt;strong&gt;&lt;a href=&quot;https://mergify.com/product/merge-queue&quot;&gt;Merge Queue&lt;/a&gt;&lt;/strong&gt; &lt;a href=&quot;https://mergify.com/product/merge-queue&quot;&gt;product&lt;/a&gt;, and deepening our place in the DevOps ecosystem. Our customers were engaged, our product-market fit felt strong, and our team fired on all cylinders.&lt;/p&gt;
&lt;p&gt;But as the year drew to a close, something in the air felt different.&lt;/p&gt;
&lt;p&gt;Conversations with prospects were shifting. Instead of discussing new features and scaling up their usage, they were hesitant. Startups—our core audience—were tightening their budgets. Investors were slowing down. &lt;strong&gt;Some of our customers simply disappeared.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, it was the crypto companies. Then, real estate tech. One by one, they went silent—not because they didn’t love our product, but because their businesses were collapsing. &lt;a href=&quot;https://en.wikipedia.org/wiki/2022_stock_market_decline&quot;&gt;The market was crashing&lt;/a&gt;. &lt;a href=&quot;https://news.crunchbase.com/venture/north-american-startup-funding-q4-2022/&quot;&gt;Funding was drying up.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/56767aca-7503-4d8a-921e-183a8e0621f4_1037x871.webp&quot; alt=&quot;Chart showing the 2022 startup market crash and funding decline&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The message became clear:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“We love Merge Queue, but our budget is frozen.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We knew we couldn’t just sit back and hope the market would bounce back. We needed to adapt. That’s how startups survive.&lt;/p&gt;
&lt;p&gt;And that’s when we had what we thought was a &lt;strong&gt;brilliant idea&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Birth of CI Optimizer&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;One undeniable truth about software engineering is that &lt;strong&gt;CI/CD is expensive&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Every build, every test, every deployment—it all costs money.&lt;/p&gt;
&lt;p&gt;At scale, those costs grow exponentially, often without teams fully understanding where their budget is going. Developers push a change, run a full test suite, and move on. But in the background, &lt;strong&gt;cloud bills are racking up&lt;/strong&gt;, and finance teams are left wondering where all that money is going.&lt;/p&gt;
&lt;p&gt;So we thought:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“What if we built a tool that gave teams complete visibility into their CI/CD costs? What if we could identify waste, eliminate unnecessary builds, and optimize pipelines automatically?” What if we could help companies save money on their CI without slowing them down?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It sounded like a no-brainer. &lt;strong&gt;We’d build a smart system that could analyze CI/CD usage and recommend cost-saving adjustments—maybe even automate them.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is something we could even use ourselves to save on our CI/CD bills.&lt;/p&gt;
&lt;p&gt;This wasn’t just an idea—we were convinced we had struck gold.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/c6bf28a5-95f8-420f-ab2b-477fee75984d_1376x864.webp&quot; alt=&quot;Illustration of building a CI/CD cost optimization tool&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Building the Future of CI/CD Cost Optimization&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;By early 2023, we had begun prototyping.&lt;/p&gt;
&lt;p&gt;The first step? Connecting to GitHub Actions. GitHub, like many CI/CD providers, is well known for not providing a good report on cost analysis (still true as of today). Since GitHub is where all of our customers are, this made sense.&lt;/p&gt;
&lt;p&gt;We needed to pull in detailed CI/CD usage data and break down the cost per minute of every build. Our system would scan pipelines, report metrics, identify inefficiencies, and provide actionable insights—like which jobs were wasting the most money.&lt;/p&gt;
&lt;p&gt;It felt like a natural extension of what I had worked on years earlier at Datadog, where I had pushed for replacing CPU seconds with dollar values in profiling tools. The goal was simple: &lt;strong&gt;make CI/CD costs tangible, trackable, and optimizable.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We saw an opportunity to build something that would fit neatly into engineering workflows. The logic was airtight:&lt;/p&gt;
&lt;p&gt;✅ Developers hate waiting for builds.&lt;/p&gt;
&lt;p&gt;✅ Developers need to get more budget.&lt;/p&gt;
&lt;p&gt;✅ We could solve both problems at once.&lt;/p&gt;
&lt;p&gt;Or so we thought.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What We Hoped to Prove&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Our &lt;strong&gt;plan for early 2023&lt;/strong&gt; was straightforward:&lt;/p&gt;
&lt;p&gt;1️⃣ Build an MVP that could &lt;strong&gt;accurately measure CI/CD costs&lt;/strong&gt; at a granular level.&lt;/p&gt;
&lt;p&gt;2️⃣ Talk to &lt;strong&gt;real users&lt;/strong&gt; and validate whether CI/CD engineers cared about cost optimization.&lt;/p&gt;
&lt;p&gt;3️⃣ Launch a &lt;strong&gt;first version of CI Optimizer&lt;/strong&gt; and start onboarding teams.&lt;/p&gt;
&lt;p&gt;We expected engineers to tell us:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“This is amazing! We’ve been waiting for something like this!”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But that’s not what happened.&lt;/p&gt;
&lt;p&gt;Instead, we hit an unexpected roadblock that completely changed the course of the project. (Read what happened next in &lt;a href=&quot;https://julien.danjou.info/blog/when-nobody-wants-your-product&quot;&gt;When Nobody Wants Your Product&lt;/a&gt;.)&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>SaaS Pricing is Hard</title><link>https://julien.danjou.info/blog/saas-pricing-is-hard/</link><guid isPermaLink="true">https://julien.danjou.info/blog/saas-pricing-is-hard/</guid><description>Our Journey at Mergify</description><pubDate>Tue, 04 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Pricing is one of the hardest things to get right in SaaS. If you’re a startup founder, especially in B2B, you’ve likely wrestled with pricing questions:&lt;/p&gt;
&lt;p&gt;💰 &lt;strong&gt;How much should I charge?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;📊 &lt;strong&gt;What pricing model makes sense?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;⚖️ &lt;strong&gt;How do I ensure fairness while maximizing revenue?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;, we’ve spent years experimenting, iterating, and learning the hard way. Here’s a breakdown of our journey—and what we’d do differently if we had to start over.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;How We Picked Our First Pricing Model&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;When we first launched Mergify, we had no idea what the right pricing model should be. So, like many startups, we &lt;strong&gt;copied GitHub&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We charged &lt;strong&gt;per user, based on the size of the entire organization.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This meant that if a company had 200 engineers, they had to pay for all 200 engineers—even if only 20 or 30 of them actually used Mergify.&lt;/p&gt;
&lt;p&gt;For small companies (e.g., 20–30 engineers), this wasn’t a big deal. They usually had one team using Mergify across all their repos. But as we grew and larger companies came in, things got tricky.&lt;/p&gt;
&lt;p&gt;🛑 &lt;strong&gt;Larger companies had multiple teams, and only some teams used Mergify.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💰 &lt;strong&gt;They didn’t want to pay for everyone—just for the engineers who actually needed it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We needed to change.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/52ea4806-fcf2-43cc-b5e2-cd505bc8d0f2_1376x864.webp&quot; alt=&quot;Illustration of SaaS pricing evolution from per-organization to per-collaborator model&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Counting Users the “Right” Way&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;To address this, we moved to a new model:&lt;/p&gt;
&lt;p&gt;✅ Instead of charging per &lt;strong&gt;organization&lt;/strong&gt;, we charged per &lt;strong&gt;collaborator&lt;/strong&gt;—engineers who had &lt;strong&gt;write access&lt;/strong&gt; to a repository where Mergify was active.&lt;/p&gt;
&lt;p&gt;This felt fairer. A company with 100 engineers could now pay only for the repositories where Mergify was used, rather than for the entire org.&lt;/p&gt;
&lt;p&gt;At the same time, we &lt;strong&gt;doubled our price per user&lt;/strong&gt;. Why?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Customers were already seeing the value, and price wasn’t their biggest concern.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The new model lowered the user count for most companies, so we had to balance revenue.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;strong&gt;The Math: Why This Worked&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For a company with &lt;strong&gt;100 engineers&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Old model:&lt;/strong&gt; $2 per user × 100 users = $200/month&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New model:&lt;/strong&gt; $4 per user × 50 repo contributors = $200/month&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For many customers, their bill stayed roughly the same. But they were &lt;strong&gt;happier&lt;/strong&gt; because they felt they were paying for what they actually used.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Fairness is Everything&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;But the journey didn’t stop there.&lt;/p&gt;
&lt;p&gt;Larger organizations often &lt;strong&gt;gave write access to all engineers by default&lt;/strong&gt;, even if only a subset was actually making commits. That meant some companies were being charged for engineers who weren’t actively contributing.&lt;/p&gt;
&lt;p&gt;So we introduced another iteration:&lt;/p&gt;
&lt;p&gt;✅ &lt;strong&gt;Charging per “active user”—engineers who actually made commits.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This approach, inspired by &lt;strong&gt;&lt;a href=&quot;https://slack.com/help/articles/23546798305171-FAQ--Updates-to-Slack%E2%80%99s-active-user-calculation&quot;&gt;Slack’s active user model&lt;/a&gt;&lt;/strong&gt;, made more sense. Now, companies only paid for users who actively used Mergify.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/8295f69d-866e-46b3-907b-b23eaa9b0c94_1376x864.png&quot; alt=&quot;Illustration of active user pricing model for SaaS billing&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;The Math: Why This Worked (Again)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For a company with &lt;strong&gt;100 engineers&lt;/strong&gt;, where only &lt;strong&gt;40 engineers actively pushed commits&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Previous model:&lt;/strong&gt; $4 per user × 100 write-access users = &lt;strong&gt;$400/month&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;New model:&lt;/strong&gt; $8 per user × 40 active users = &lt;strong&gt;$320/month&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, the price per user increased, but total spending often decreased or stayed the same. More importantly, it felt &lt;strong&gt;fairer&lt;/strong&gt; to customers.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;The Real Takeaway: Fairness &amp;gt; Exact Pricing Models&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;What we’ve learned is that most customers don’t scrutinize &lt;strong&gt;how much they pay&lt;/strong&gt;—but they deeply care about &lt;strong&gt;why they are paying it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;Customers want fairness more than they want cheap pricing.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;They don’t want to pay for people who never use the product.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;They want transparency in billing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, no matter how much we refine our pricing, &lt;strong&gt;some customers will always question it&lt;/strong&gt;. That’s fine. What matters is that we keep the discussion focused on value—not just pricing mechanics.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Advice for SaaS Startups Navigating Pricing&lt;/strong&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Don’t get stuck in the weeds of perfect pricing.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Focus on maximizing total revenue, not obsessing over per-user logic.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Price increases aren’t scary if you frame them well.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every time we changed how we counted users, we also raised prices—and it worked fine. You can always grandfather happy customers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;People care more about fairness than numbers.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If customers understand &lt;strong&gt;why&lt;/strong&gt; they’re paying what they’re paying, they’re much less likely to complain.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Pricing is a constant &lt;strong&gt;work in progress&lt;/strong&gt;. We’ll probably keep refining it at Mergify as we grow. But the core lesson is this: &lt;strong&gt;be transparent, focus on fairness, and anchor pricing to the value your product delivers.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you want more on how we think about pricing, I wrote about &lt;a href=&quot;https://julien.danjou.info/blog/saas-and-work-based-pricing&quot;&gt;why we&apos;re sticking with seat-based pricing over work-based models&lt;/a&gt; and the broader &lt;a href=&quot;https://julien.danjou.info/blog/solving-build-vs-buy&quot;&gt;build vs buy dilemma&lt;/a&gt; from the customer&apos;s perspective.&lt;/p&gt;
</content:encoded><category>saas</category><category>mergify</category></item><item><title>Why We Left Heroku</title><link>https://julien.danjou.info/blog/why-we-left-heroku/</link><guid isPermaLink="true">https://julien.danjou.info/blog/why-we-left-heroku/</guid><description>A Tale of Contracts, Challenges, and Change</description><pubDate>Tue, 28 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In January 2023, everything was smooth sailing for Mergify. Our infrastructure was humming along on Heroku, a platform we had trusted for over three years. Heroku was once the go-to choice for startups—simple, reliable, and developer-friendly. We were happy customers, growing steadily and paying our invoices month-to-month.&lt;/p&gt;
&lt;p&gt;Then things started to change.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Start of a Rocky Relationship&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In early 2023, Heroku reached out with an enticing offer: transition from month-to-month billing to an annual Heroku Enterprise contract. The deal included significant discounts on everything—dynos (containers), databases, and add-ons—in exchange for a one-year commitment to a certain number of resources.&lt;/p&gt;
&lt;p&gt;We were told we’d be allowed to overuse our resources up to 30% during the year without being bothered—with the understanding that if we grew beyond that, the contract would be adjusted fairly in the next cycle.&lt;/p&gt;
&lt;p&gt;It sounded like a win-win.&lt;/p&gt;
&lt;p&gt;We signed the contract and carried on. For the first year, everything was fine. By the end of 2023, we had indeed surpassed the 30% growth threshold, but Heroku didn’t reach out. The contract auto-renewed, and we moved into 2024 with no issues.&lt;/p&gt;
&lt;p&gt;That was until the automated emails started arriving.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/3299f3cc-673a-415f-b374-6f61fe6201a0_1456x816.webp&quot; alt=&quot;Illustration of automated emails arriving from Heroku about contract changes&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;A Series of Surprises&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In May 2024, we received an &lt;strong&gt;automated&lt;/strong&gt; email from Heroku. It informed us that the discounts on our containers were being rescinded, effective immediately. Naturally, we contacted Heroku’s support team to understand how that would affect our current contract and were redirected to a new account executive to clarify.&lt;/p&gt;
&lt;p&gt;Their explanation was straightforward: we had doubled our usage, and they wanted us to pay the difference for the current contract term—for the next 9 months.&lt;/p&gt;
&lt;p&gt;While this was unexpected, we decided to comply. We signed an amendment to the contract and paid the outstanding amount. We chalked it up to a policy change, and, as Heroku has been fair so far, we decided to move on.&lt;/p&gt;
&lt;p&gt;But then, in October 2024, another email arrived. This time, Heroku announced that discounts on add-ons, such as PostgreSQL databases and Redis, would also be removed. Once again, we reached out to their team for clarification.&lt;/p&gt;
&lt;p&gt;This conversation, however, was &lt;em&gt;very&lt;/em&gt; different.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/080a6562-068e-43c0-9e8f-61fa6e083f97_1166x1548.png&quot; alt=&quot;Screenshot of the automated Heroku email rescinding add-on discounts&quot; /&gt;
&lt;em&gt;The Heroku automated email we received&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;When Contracts Don’t Matter&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Our current account executive explained that the discounted add-ons we had purchased as part of our original enterprise agreement were no longer “fair” for Heroku.&lt;/p&gt;
&lt;p&gt;Indeed, two years before, our previous account executive offered us a 60% discount on the listed price, which was a power move to make us commit for a whole year to the platform. A practice that worked: we committed to Heroku, and the account executive won a “top deal France SMB” award at Heroku.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/c0c592fa-006d-43e0-9fd3-f0a7448dfb35_1456x816.png&quot; alt=&quot;Illustration of the account executive winning a top deal award for the original Heroku contract&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But now, Heroku wanted us to pay the full price for these services, even though our contract explicitly stated otherwise.&lt;/p&gt;
&lt;p&gt;We reminded them of the terms we agreed to in the contract, but their response was, essentially, “it’s not fair for us anymore.”&lt;/p&gt;
&lt;p&gt;I spent a lot of time trying to understand how getting a few thousand euros more from a loyal startup would impact Salesforce P&amp;amp;L, or how bullying us into paying money we didn’t owe would help our account executive gain respect from their boss, with no luck.&lt;/p&gt;
&lt;p&gt;Despite their efforts to pressure us to pay more, we held firm. A contract is a contract, and we weren’t going to be oppressed into paying for something that wasn’t part of the original agreement.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/1f12cf3e-e8fc-447b-9884-58f90c92808e_1456x816.png&quot; alt=&quot;Illustration of standing firm against unfair contract pressure from a vendor&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, at this point, it was clear that Heroku was no longer a reliable partner for us. Their lack of stability, constant policy changes, and disregard for contractual terms made it impossible to trust them with our infrastructure.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Move Away from Heroku&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;By late 2024, we made the decision to move Mergify’s infrastructure to Google Cloud Platform (GCP). Migrating a live product is never easy, but it was the right choice. Heroku, once the pioneer of developer-friendly hosting, had stagnated. The platform’s lack of innovation, combined with its increasingly unpredictable business practices, made it clear that it was time to leave.&lt;/p&gt;
&lt;p&gt;GCP offered the flexibility, scalability, and reliability we needed to grow. The migration was a success, and while it wasn&apos;t a move we originally planned for, it&apos;s one we&apos;re glad we made. Google helped us a lot in moving to their platform, which made the whole process smooth — and it gave us a chance to rethink our entire CI/CD stack, including how we handle &lt;a href=&quot;https://julien.danjou.info/blog/the-challenges-of-merge-queues&quot;&gt;merge queue challenges&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Reflections on Heroku&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Despite the rocky ending, it’s important to acknowledge Heroku’s role in our journey. The platform played a significant part in our early success, providing the simplicity and ease of use that helped us focus on building our product. For small apps and early-stage startups, Heroku can still be a good choice.&lt;/p&gt;
&lt;p&gt;But over time, Heroku failed to evolve. As the tech industry moved forward, Heroku seemed to stand still. Features stagnated, the platform became less relevant, and dealing with them as a customer grew increasingly frustrating. In 2025, it’s hard to recommend Heroku as a reliable choice for scaling companies.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/243ebb5b-c23b-4ace-b314-d44da9537c5d_1456x816.webp&quot; alt=&quot;Illustration of migrating infrastructure from Heroku to Google Cloud Platform&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Advice for Other Startups&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Our experience with Heroku taught us some valuable lessons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Beware of Contracts with Large Companies:&lt;/strong&gt; Big corporations can change their terms, policies, or priorities on a whim. Make sure you fully understand the risks before signing long-term agreements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stand Your Ground:&lt;/strong&gt; If a vendor tries to pressure you into unfair terms, don’t be afraid to push back. Contracts exist for a reason. Be ready to jump and save your ass.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Choose Platforms That Grow with You:&lt;/strong&gt; Heroku was perfect for us in the beginning, but as our needs grew, it became clear that we needed a more robust and innovative platform.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For startups navigating similar challenges, remember that your infrastructure choices are critical. Hosting platforms should be partners in your growth, not obstacles.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Leaving Heroku wasn’t an easy decision, but it was the right one for Mergify. We’ve learned a lot from this experience, and we’re excited about what’s ahead with our new infrastructure.&lt;/p&gt;
&lt;p&gt;If you’re a startup considering Heroku—or debating whether to stay or move on—ask yourself this: is your hosting platform helping you scale or holding you back? At the end of the day, it’s all about finding a partner you can trust to grow with you.&lt;/p&gt;
</content:encoded><category>devops</category><category>mergify</category></item><item><title>Reflecting on 2024</title><link>https://julien.danjou.info/blog/reflecting-on-2024/</link><guid isPermaLink="true">https://julien.danjou.info/blog/reflecting-on-2024/</guid><description>A Year of Growth, Change, and Learning at Mergify</description><pubDate>Tue, 07 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As 2025 begins, I’m taking a moment to reflect on an eventful 2024—a year of evolution, challenges, and new beginnings for me and &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;. Building a bootstrapped company comes with its own unique highs and lows, and 2024 was no exception. Here’s what the past year taught me and how it has shaped the future of Mergify.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Keeping Mergify Thriving in a Changing Market&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Surviving and thriving as a bootstrap startup is always worth celebrating, especially in a niche like ours. In 2024, we doubled down on what makes Mergify special: our &lt;strong&gt;&lt;a href=&quot;https://mergify.com/product/merge-queue&quot;&gt;Merge Queue&lt;/a&gt;&lt;/strong&gt; product, which remains the best in the market for helping engineering teams manage pull request workflows.&lt;/p&gt;
&lt;p&gt;That said, we also recognized our limitations. While we’ve always been proud of our technology, we realized this year that &lt;strong&gt;having great tech isn’t enough&lt;/strong&gt;. For years, Mergify was more of a tech-driven company than a product-focused one. This year, we worked hard to change that, shifting our mindset to prioritize product design, usability, and scalability.&lt;/p&gt;
&lt;p&gt;The advancement of competitors, such as GitHub, forced us to rethink our strategy. We’ve been evolving in a niche for years, and it’s now time for us to expand our vision beyond what we’ve been doing so far.&lt;/p&gt;
&lt;p&gt;2024 also brought some tough lessons about the realities of the market. We initially decided to double down on marketing in late 2022, deploying our efforts during all of 2023. However, after the startup market crash of late 2022, we spent much of 2023 navigating a challenging environment where companies were hesitant to adopt new tools. As that trend continued into early 2024, we ultimately decided to &lt;strong&gt;scale back our marketing efforts&lt;/strong&gt; and rethink how we approach growth.&lt;/p&gt;
&lt;p&gt;The truth is that marketing alone can’t solve every problem—especially in a niche like ours. Instead, we’re focusing on building the best products possible and letting our work speak for itself. This approach has already started to pay off, and we’re more confident than ever in Mergify’s future.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;A Shift Toward Product and Design&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Consequently, one of the pivotal moments in 2024 was hiring a &lt;strong&gt;designer&lt;/strong&gt;—a first for Mergify. This move sparked a transformation in how we approached our product. It wasn’t just about solving technical challenges anymore; it was about creating an experience developers love.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/db1e31b2-b1ec-4bfa-8995-c64030ac9ac2_1378x953.png&quot; alt=&quot;Screenshot of the new Mergify dashboard design&quot; /&gt;
&lt;em&gt;New Mergify design&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This new focus led to a complete redesign of our branding and dashboard, making it easier than ever for teams to onboard and use Mergify. It also paved the way for &lt;strong&gt;new products&lt;/strong&gt; like &lt;strong&gt;&lt;a href=&quot;https://mergify.com/product/merge-protections&quot;&gt;Merge Protections&lt;/a&gt;&lt;/strong&gt;, a tool for managing repository freezes and policies. This was the first product we built with a product-driven mindset from the ground up, and it’s already gaining traction with customers.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Back to Founder Mode&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In 2024, I found myself returning to what is now called “&lt;a href=&quot;https://paulgraham.com/foundermode.html&quot;&gt;founder mode&lt;/a&gt;.” For the first time in years, I rolled up my sleeves and dove back into &lt;strong&gt;coding and product development&lt;/strong&gt;. Writing Python again, designing architecture, new workflows, and collaborating directly with the team reminded me of the early days of Mergify—and how much I enjoy building things.&lt;/p&gt;
&lt;p&gt;This hands-on approach was fueled in part by the rise of &lt;strong&gt;AI tools&lt;/strong&gt;, which have &lt;a href=&quot;https://julien.danjou.info/blog/connecting-the-dots-with-ai&quot;&gt;transformed how we work&lt;/a&gt;. From speeding up R&amp;amp;D to enhancing productivity, AI has helped us stay agile and efficient as we tackle big challenges in CI/CD.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Doubling Down on R&amp;amp;D&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Speaking of challenges, &lt;strong&gt;research and development&lt;/strong&gt; was a major focus for us in 2024. We spent a lot of time exploring how to solve some of the toughest problems in CI/CD, like &lt;strong&gt;flaky tests, CI failures, and observability issues&lt;/strong&gt;. These pain points resonate deeply with our customers, and we’re excited to bring solutions to market in 2025.&lt;/p&gt;
&lt;p&gt;Our work so far has been a team effort, but it’s also required stepping outside our comfort zone. We’ve been engaging more directly with developers, learning from their frustrations and workflows, and using those insights to shape our next big product.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;On a Personal Note&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Outside of Mergify, 2024 was a year of rediscovery for me. I started writing again, leaning on tools like GPT to help me produce regular content and share my thoughts with a wider audience. Writing has always been a way for me to reflect, and having the discipline to do it consistently has been rewarding.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/3d683497-9731-4495-aa15-f08f944bde7f_2959x3945.jpeg&quot; alt=&quot;Photo taken by Julien&apos;s kids learning photography&quot; /&gt;
&lt;em&gt;I’m also trying to teach my kids to take photographs&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I also continued my work as a &lt;strong&gt;business angel&lt;/strong&gt;, supporting other startups and sharing what I’ve learned from building Mergify. While balancing this with my responsibilities at Mergify can be challenging, it’s incredibly fulfilling to help others navigate the ups and downs of entrepreneurship.&lt;/p&gt;
&lt;p&gt;I continued publishing episodes of &lt;a href=&quot;https://nomdunpipeline.com/&quot;&gt;Nom d’un Pipeline !&lt;/a&gt;, my French CI/CD-themed podcast. This has been a tremendous way to meet new people and learn stuff. I really enjoy the exercise of podcasting, and I’m looking for an excuse to start a new one this year.&lt;/p&gt;
&lt;p&gt;I also recorded several episodes as a guest, &lt;a href=&quot;https://www.ifttd.io/episodes/ci-cd&quot;&gt;one in French in IFTTD&lt;/a&gt;, &lt;a href=&quot;https://www.iot-valley.fr/podcast/37-les-perspectives-sur-lavenir-de-la-tech-avec-julien-danjou&quot;&gt;another one in French and in Toulouse on the future of tech&lt;/a&gt;, &lt;a href=&quot;https://podcasts.apple.com/fr/podcast/14-julien-danjou-mergify/id1691308698?i=1000644808297&quot;&gt;another one in French on The Cloud Screener&lt;/a&gt;, &lt;a href=&quot;https://www.pythonshow.com/p/36-serious-python-with-julien-danjou&quot;&gt;one on The Python Show&lt;/a&gt;, and, finally, &lt;a href=&quot;https://www.youtube.com/watch?v=Fd2iQD7Rfug&quot;&gt;one with saas.group&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Looking Ahead to 2025&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;As I look to the year ahead, I’m more excited than ever about what’s next for Mergify. We’re working on &lt;strong&gt;new products&lt;/strong&gt; that tackle critical pain points in CI/CD, and we’re committed to helping developers ship faster and with less friction. At the same time, we’re staying true to our roots as a bootstrap startup—focused, agile, and always learning.&lt;/p&gt;
&lt;p&gt;2024 was a year of growth in every sense of the word. It challenged us to think differently, to embrace new ideas, and to keep pushing forward. As we enter 2025, I’m grateful for the lessons we’ve learned, the customers we serve, and the incredible team that makes it all possible.&lt;/p&gt;
&lt;p&gt;Here’s to another year of building, learning, and growing.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>Aligning Project Management with Company&apos;s Values</title><link>https://julien.danjou.info/blog/aligning-project-management-with/</link><guid isPermaLink="true">https://julien.danjou.info/blog/aligning-project-management-with/</guid><description>Aligning Project Management with Company&apos;s Values</description><pubDate>Tue, 10 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When Mehdi and I co-founded Mergify, we didn’t just set out to create a great product—we wanted to build a company that reflected our values. Part of that journey has been rethinking project management, a task informed by years of working in organizations where “Agile” had become synonymous with bureaucracy. What started as a flexible, team-oriented methodology often felt bogged down by rituals that added complexity without delivering real results.&lt;/p&gt;
&lt;p&gt;Over the past year, we’ve refined our project management approach at Mergify, shaping it to fit not only the needs of our team but also our belief in simplicity, ownership, and autonomy. Here’s the story of how we got there—and why building a workflow that aligns with your values matters as much as the work itself.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;My Journey Through Agile Overload&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;When I look back at my experiences with Agile in various organizations, one story sticks out. Early in my career, I joined a team at &lt;a href=&quot;https://redhat.com&quot;&gt;Red Hat&lt;/a&gt;, one of the most functional, productive groups I’ve ever worked with. We didn’t rely on heavy Scrum processes; instead, we used a lightweight Kanban board and had stand-ups over &lt;a href=&quot;https://en.wikipedia.org/wiki/IRC&quot;&gt;IRC&lt;/a&gt;. It wasn’t fancy, but it worked. We focused on the work, not the process.&lt;/p&gt;
&lt;p&gt;Contrast that with some other teams I observed. One team, with over 20 members, struggled to maintain a sense of ownership. The &lt;a href=&quot;https://www.theguardian.com/technology/2018/apr/24/the-two-pizza-rule-and-the-secret-of-amazons-success&quot;&gt;two-pizza rule&lt;/a&gt;, famously touted by Jeff Bezos, couldn’t have been more relevant here: a team too big to share two pizzas is often too big to stay effective. Communication is complicated, and the sense of ownership disappears.&lt;/p&gt;
&lt;p&gt;Yet management decided to unify everyone under a single Scrum process, complete with daily stand-ups, sprints, retrospectives, and poker planning.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/4c8fc2f7-0ba1-4d1f-8bd8-35af6390654e_1376x864.webp&quot; alt=&quot;Illustration of a large team struggling under heavy Scrum processes&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That did not fix the problem of the 20-person team. Even my high-functioning team began to falter under the weight of unnecessary rituals.&lt;/p&gt;
&lt;p&gt;It was a powerful lesson: the process isn’t inherently good or bad but must serve the people doing the work.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Starting Mergify with a Blank Slate&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;When we started Mergify, we wanted to avoid the traps of over-engineering our processes. We began with almost no structure—just Slack messages and quick syncs to stay aligned. As the team grew, we added a daily stand-up. For a remote-first company, these short, synchronous check-ins were critical for maintaining a shared understanding, even as most of our work remained asynchronous.&lt;/p&gt;
&lt;p&gt;Instead of following Agile dogma, we opted for a Kanban approach. Tasks moved naturally across the board with minimal friction. We didn’t bother with two-week sprints or strict velocity tracking; we let the workflow dictate the process.&lt;/p&gt;
&lt;p&gt;And it worked; for a while.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Why Lightweight Isn’t Always Enough&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Over time, cracks began to appear. One issue was ownership: who was responsible for creating cards on the Kanban board? Engineers who weren’t involved in defining tasks felt disconnected from the problem, treating the cards as instructions rather than opportunities to solve meaningful challenges. The person creating the card and the person doing the work weren’t always on the same page.&lt;/p&gt;
&lt;p&gt;Another challenge was the endless backlog without a clear sense of what we were building or why; tasks accumulated, and the act of moving cards felt less like progress and more like treading water. The team craved a greater sense of accomplishment—a way to see their impact beyond the daily grind.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Evolving to a Project-Driven Workflow&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;To address these issues, we introduced a project-driven layer to our workflow. Projects became our new organizing principle: scoped pieces of work that could be completed in two to four weeks. Each project was defined by three key elements: a &lt;strong&gt;brief&lt;/strong&gt;, a &lt;strong&gt;lead&lt;/strong&gt;, and a &lt;strong&gt;deadline&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;1. &lt;strong&gt;The Brief&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;The brief outlined the problem, the goals, and the context for the project. It provided enough structure to guide the engineer while leaving room for creativity. Engineers weren’t just implementers—they were collaborators, shaping the solution as they worked.&lt;/p&gt;
&lt;p&gt;2. &lt;strong&gt;The Lead&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;Every project had a designated lead who was responsible for tracking progress and ensuring the work stayed on course. This wasn’t about assigning blame; it was about having a clear point of contact who could raise blockers, answer questions, and coordinate efforts.&lt;/p&gt;
&lt;p&gt;3. &lt;strong&gt;The Deadline&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;Deadlines were less about pressure and more about focus. They encouraged engineers to make trade-offs, prioritize effectively, and avoid over-engineering. If something couldn’t be completed within the timeframe, we adjusted the scope or deferred less critical elements.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/ad9c358b-c1d4-4e07-ba08-e11ebf84bd06_1376x864.webp&quot; alt=&quot;Illustration of project-driven workflow with briefs, leads, and deadlines&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What We Gained&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The shift to project-driven work transformed how we operated. It gave engineers a sense of ownership and allowed us to ship faster, avoiding the dreaded “tunnel effect” where nothing tangible gets delivered for months. It also helped us align our priorities, ensuring that every project contributed meaningfully to our goals.&lt;/p&gt;
&lt;p&gt;This system wasn’t just about productivity but about creating a culture where engineers felt empowered and connected to their work. It reinforced our belief that processes should serve people, not the other way around.&lt;/p&gt;
&lt;p&gt;A few people I talked about our system thought it resembled the &lt;a href=&quot;https://basecamp.com/shapeup&quot;&gt;Shape Up&lt;/a&gt; methodology from Basecamp. I think it does have similarities, except that we’re a small company, meaning we don’t have enough teams to model it exactly yet. But that’s definitely a methodology that resonates with us.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/dea4170d-6f82-4e9f-9d0d-523c0ac8f4e5_2000x729.png&quot; alt=&quot;Diagram of the Shape Up methodology from Basecamp&quot; /&gt;
&lt;em&gt;The Shape Up methodology&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Looking back, the changes we made weren’t just about fixing problems—they were about staying true to our values. At Mergify, we believe in autonomy, ownership, and simplicity, and our workflow reflects those principles.&lt;/p&gt;
&lt;p&gt;If you’re struggling with your own project management processes, ask yourself: do they serve your team’s needs, or are they just there because “that’s how it’s done”? (I wrote about a related frustration in &lt;a href=&quot;https://julien.danjou.info/blog/the-problem-with-okrs-isnt-okrs&quot;&gt;The Problem with OKRs Isn’t OKRs&lt;/a&gt;.) The best workflows aren’t the most popular—they’re the ones that align with your culture and empower your people to do their best work.&lt;/p&gt;
&lt;p&gt;At Mergify, we’re proud of the system we’ve built, and we’re excited to keep evolving it as we grow.&lt;/p&gt;
</content:encoded><category>management</category><category>mergify</category></item><item><title>SaaS and Work-based Pricing</title><link>https://julien.danjou.info/blog/saas-and-work-based-pricing/</link><guid isPermaLink="true">https://julien.danjou.info/blog/saas-and-work-based-pricing/</guid><description>Is this the future?</description><pubDate>Tue, 19 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Despite the rising popularity of work-based pricing in SaaS, Mergify is sticking with seat-based pricing—for now. Here’s why we believe it’s the right choice for our product and our customers, and their ability to budget with confidence&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Work-Based Pricing Trend&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Following the latest SaaS pricing trends is tempting, especially when they align so well with a powerful concept: customers pay in proportion to the value they receive. In recent months, “work-based” pricing has gained traction across the industry, especially in AI-driven applications where you pay per task completed. It’s a straightforward exchange: resolve a customer’s problem and receive $1.&lt;/p&gt;
&lt;p&gt;Simple, clear, and highly attractive.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/bde84986-3269-430e-a397-d7970e372fbd_1376x864.webp&quot; alt=&quot;Illustration of work-based pricing in SaaS&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When we first considered revisiting Mergify’s pricing for next year, work-based pricing seemed like a model worth exploring. Imagine a setup where every task accomplished by Mergify correlated directly to the value we delivered to our customers. More value equals more payment, a transparent exchange that clients find easy to understand. But, as we dove deeper, we realized that the nature of Mergify’s work doesn’t fit so neatly into this model.&lt;/p&gt;
&lt;p&gt;And that might be true for your SaaS as well.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Value Clarity of Work-Based Pricing&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Work-based pricing makes perfect sense for certain SaaS products. Consider the AI-driven customer support solutions rolling out recently, like &lt;a href=&quot;https://www.salesforce.com/agentforce/pricing/&quot;&gt;Salesforce’s $2-per-conversation approach&lt;/a&gt; or &lt;a href=&quot;https://www.intercom.com/help/en/articles/8205718-fin-ai-agent-resolutions&quot;&gt;Intercom’s Finn and its 0.99$ per resolved conversation&lt;/a&gt;. The pricing here is inherently appealing because it aligns precisely with the customer’s perception of value: for every problem resolved, they see a clear, direct benefit to their end users, who leave satisfied and engaged.&lt;/p&gt;
&lt;p&gt;This clarity makes it easy for a customer to decide—they’re paying to solve a specific pain point for their users, and each solved interaction has a measurable outcome. The more conversations are solved, the more they pay; it feels like a no-brainer.&lt;/p&gt;
&lt;p&gt;Customers see exactly where their money is going, and it scales beautifully alongside their growth: the more users they have, the more problems they have, and the more value you can provide. But also: the more users they have, the more money they have, so they’re happy with giving you a part of it. Everything can grow at the same rate, from the customer’s business size to the value your SaaS provides.&lt;/p&gt;
&lt;p&gt;This reminds me of the early days of cloud computing when Amazon Web Services introduced usage-based billing. The more your business grew, the more infrastructure you used, and the higher the bill. It made perfect sense, and that was one of the reasons for its success and early adoption by startups.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/8928f8ae-0c2c-4992-8a82-0c7739b205be_1376x864.png&quot; alt=&quot;Illustration of usage-based billing scaling with business growth&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Why Work-Based Pricing Doesn’t Always Fit&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;At Mergify, we aimed to find the same direct correlation between our value and our pricing model. However, our reality is different: the value we provide is primarily to software engineers who use Mergify to streamline their CI/CD workflows. It’s an incredibly powerful tool, but it doesn’t impact our customers’ end-users in an obvious way. This makes work-based pricing challenging because we’re one step removed from the end-user experience — and, therefore, from the business.&lt;/p&gt;
&lt;p&gt;We brainstormed possible approaches. Perhaps we could charge per pull request made by developers. After all, that’s a major part of what Mergify automates and where it provides value. But we immediately saw a problem: this model could encourage the wrong behavior. If every pull request carries a charge, teams might try to reduce the number of pull requests to save on costs, potentially compromising code quality. As engineers ourselves, we value clean, &lt;a href=&quot;https://en.wikipedia.org/wiki/Atomic_commit&quot;&gt;atomic commits&lt;/a&gt; and easy reviews. A per-pull-request charge could discourage these practices, creating friction between the optimal workflow and our pricing model.&lt;/p&gt;
&lt;p&gt;Another challenge with work-based pricing is the difficulty it presents for customers when predicting their usage. Most organizations set budgets a year in advance, and it’s nearly impossible for a team to accurately estimate the number of pull requests or jobs they’ll need in a year. This unpredictability makes budgeting stressful and challenging, especially for engineers seeking approval for software expenses. With seat-based pricing, customers know their costs upfront, which aligns much better with annual budget planning.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/37914459-6600-46b0-a064-bd6144fb49fe_1376x864.png&quot; alt=&quot;Illustration of the challenges of per-unit pricing for developer tools&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We also considered a per-job charge based on CI (Continuous Integration) runs, but this quickly ran into similar issues. Running a high volume of CI jobs often results in better software quality. Charging per job could lead to reduced testing—a problematic incentive in an industry where quality matters deeply. CI providers charge per job because of the required computing power, but in Mergify’s case, we don’t incur comparable costs. So, a per-job charge wouldn’t reflect our real costs and could end up discouraging best practices.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Challenge of Finding the Right Fit&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In a perfect world, we’d find a model where Mergify’s pricing scaled directly with the customer’s perceived value. However, we found that our usage patterns, like many SaaS, do not align with the benefits of the work-based approach. To truly capture the value Mergify provides, we realize that seat-based pricing continues to be our best option, at least for now.&lt;/p&gt;
&lt;p&gt;By charging per user (seat), we avoid influencing developer behavior, allowing them to use Mergify to improve their workflow without second-guessing how often they use it. We also want to avoid the stress of unpredictable costs. Seat-based pricing allows our clients to budget accurately and avoid unexpected expenses, aligning our pricing model with their planning cycles and offering peace of mind. As we continue to build Mergify, our goal remains to be the trusted tool in the hands of developers.&lt;/p&gt;
&lt;p&gt;Right now, that means a seat-based model, which keeps our focus where it belongs—on supporting teams to do their best work, no strings attached.&lt;/p&gt;
&lt;p&gt;This decision wasn&apos;t easy, and we might revisit it in the future. Pricing is a delicate balance between the customer&apos;s experience, the product&apos;s value, and the company&apos;s needs. I wrote more about &lt;a href=&quot;https://julien.danjou.info/blog/saas-pricing-is-hard&quot;&gt;our full pricing journey at Mergify&lt;/a&gt; — from copying GitHub&apos;s model to active user billing.&lt;/p&gt;
</content:encoded><category>saas</category><category>mergify</category></item><item><title>The Engineer’s Dilemma: What We Did Right at Mergify</title><link>https://julien.danjou.info/blog/the-engineers-dilemma-what-we-did/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-engineers-dilemma-what-we-did/</guid><description>A classic mistake that many tech founders make.</description><pubDate>Tue, 05 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the early days of Mergify, the journey Mehdi and I embarked on wasn’t unique. In fact, it’s a tale as old as time for engineer founders: a couple of smart engineers, passionate about technology, with an exciting vision to revolutionize their space. We had everything we needed—or so we thought: the knowledge, the technical expertise, and the drive to build something incredible.&lt;/p&gt;
&lt;p&gt;This is where the story of Mergify begins, but what often happens next is a classic mistake that many tech founders make. They build a beautiful, feature-packed product that doesn’t solve a real problem—or even worse, it solves a problem no one has. This is the hard lesson that too many engineers learn too late, and it could have easily been us.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/21e071bd-e668-4aa6-a22d-3c96ff16fa8a_2000x1256.jpeg&quot; alt=&quot;Illustration of engineer founders building a startup together&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But we managed to steer our ship in a different direction, and looking back, there are key things we did right. Let me take you through that journey.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Temptation of the Tech&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;For any engineer, there’s nothing more fun than building. The thrill of creating a new feature, optimizing your product, or pushing out updates can become intoxicating. Mehdi and I felt this pull strongly when we started Mergify. We had big ideas, a packed roadmap, and technical solutions that we were eager to implement.&lt;/p&gt;
&lt;p&gt;But here’s the thing: technology, while critical, is only a part of building a successful SaaS business. We could have easily fallen into the trap of focusing solely on the tech and neglecting the most important piece of the puzzle: the customer.&lt;/p&gt;
&lt;p&gt;We both had to confront the reality that building an amazing product wasn’t enough. If we didn’t speak to our customers, understand their pain points, and really get to the heart of their problems, we were going to fail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is where so many engineer-founded startups stumble.&lt;/strong&gt; They fall in love with their technology rather than falling in love with solving the customer’s problem. Luckily, we managed to recognize this early on.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Engineers Need to Talk to People&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Talking to customers doesn’t come naturally to most engineers—it didn’t for us either—but it was a necessary step. While it’s tempting to stay behind your keyboard, tweaking code or adding features, the real magic happens when you step out and listen to what your customers are saying. What do they struggle with? What would make their lives easier? What’s keeping them up at night?&lt;/p&gt;
&lt;p&gt;I remember one story about two bright engineers who reached out to me on LinkedIn, seeking advice. We decided to meet at a bar. They had spent three years working on a fantastic piece of technology but hadn’t seen any traction. Why? because they hadn’t built it with a customer in mind. The tech was solid, but it didn’t solve any real problem. They hadn’t spent time talking to users, and so the product existed in a vacuum.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You&apos;ve got to start with the customer experience and work backwards to the technology&lt;/em&gt; — Steve Jobs (1997)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With Mergify, we knew that if we were going to build something with a lasting impact, we needed to constantly engage with our community and understand their problems. It wasn’t enough to have a great piece of technology—we had to have a great solution to a real problem.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Shifting Roles for Success&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;One of the smartest things Mehdi and I did early on was divide our roles clearly. We knew that if both of us were deep in the tech, Mergify would never succeed. So, while Mehdi stayed focused on building the product, I took on the role of sales, marketing, and customer interaction.&lt;/p&gt;
&lt;p&gt;For an engineer, stepping into these roles can be uncomfortable at first. Sales? Marketing? Communication? These aren’t things they teach you in computer science class. But it was a necessary shift and one that paid off.&lt;/p&gt;
&lt;p&gt;I drew from my experience selling self-published books. I knew that just because you write something doesn’t mean people will read it. You have to market it, spread the word, and get it into the hands of people who need it. The same principle applied to Mergify. We couldn’t just build features and expect users to come flocking. We had to sell it, promote it, and make it known. This is still something we need to do to this day.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;The Hard Truth&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The truth is, you can have the best technology in the world, but if you don’t have customers, it’s worthless.&lt;/p&gt;
&lt;p&gt;I remember another encounter at a wedding, where the bride&apos;s father introduced me to his nephew—a tech entrepreneur. The moment I heard him describe his startup, I already knew what was wrong. “You’re not selling anything, are you?” I asked. The bride’s father looked at me, astonished by the boldness of my assumption. And sure enough, he wasn’t. He and his co-founder, both engineers, had spent their time adding features instead of learning how to sell their product. He admitted that I was not the first to tell them it was one recipe for a disaster.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/0680ef2e-f6d0-48f5-ae52-ed0422a8e382_2000x1256.jpeg&quot; alt=&quot;Illustration of engineers who built great tech but forgot to sell it&quot; /&gt;&lt;/p&gt;
&lt;p&gt;At Mergify, we avoided that trap. We recognized early on that while the tech needed to be solid, the success of our business depended on our ability to market and sell it.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;What We Did Right&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;So, what did we do right at Mergify? We talked to our customers, really talked to them. We asked questions, learned about their challenges, and made sure we were solving their pain points. We didn’t fall in love with our technology; we fell in love with the problem. And most importantly, we divided and conquered. Mehdi stayed on the tech while I trained myself in the art of sales, marketing, and product management.&lt;/p&gt;
&lt;p&gt;These steps weren’t easy, requiring us to step outside our comfort zones, but they made all the difference. Five years later, Mergify isn’t just a successful SaaS company because we built great tech — it’s successful because we solved real problems for real people. (For a different angle on the same lesson, read &lt;a href=&quot;https://julien.danjou.info/blog/tech-is-the-easy-part&quot;&gt;Tech Is the Easy Part&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;And that’s the real lesson for any engineer founder: focus on the problem, not the tech, and you’ll go far.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>There&apos;s (almost) no GitLab</title><link>https://julien.danjou.info/blog/theres-almost-no-gitlab/</link><guid isPermaLink="true">https://julien.danjou.info/blog/theres-almost-no-gitlab/</guid><description>A word on a French bias.</description><pubDate>Tue, 29 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Do you guys support GitLab? Is there any way this can work with GitLab? Does this support merge requests?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No, we don’t.&lt;/p&gt;
&lt;p&gt;As I spent hours screening software engineer candidates those last weeks, I repeatedly answered the same question: where’s Mergify support for GitLab?&lt;/p&gt;
&lt;p&gt;To put things into perspective, we mostly hire in the French market, and I think it deserves some context.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/029f09ae-ee03-4204-bc15-24a420f099f2_1376x864.webp&quot; alt=&quot;Illustration of the French bias toward self-hosted GitLab over GitHub&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Culture Bias&lt;/h2&gt;
&lt;p&gt;I’ve known software engineers for more than 20 years in the country of the baguette, and something is pretty clear. We have amazing engineers, but they suck at understanding what ROI means. Most people have no conception of the value of time, and for most average French engineers, it’s OK to spend time on anything as long as it avoids spending money (or requesting a budget).&lt;/p&gt;
&lt;p&gt;It’s not even a frugality thing; it really is just the inability to compute a basic return on investment and put a price on an hour of work.&lt;/p&gt;
&lt;p&gt;In the context of software forges, that means something: French companies, from startups to scaleups, are heavily biased towards deploying GitLab Community Edition because it’s free. They would do this over a cheap hosting bare metal server. You can find such hosting for around $20/month.&lt;/p&gt;
&lt;p&gt;At this price, the average French software engineer will not buy a GitHub license. They’d call that a rip-off.&lt;/p&gt;
&lt;p&gt;I’ve heard it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/670182a1-7e8a-4579-8241-7a869b24e9e1_1375x720.jpeg&quot; alt=&quot;Fire at OVH datacenter in Strasbourg, March 2021&quot; /&gt;
&lt;em&gt;Fire at OVH datacenter in Strasbourg, March 2021&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you don’t factor in the time it takes to spin up and maintain the GitLab instance or the impact of having &lt;a href=&quot;https://www.reuters.com/article/world/millions-of-websites-offline-after-fire-at-french-cloud-services-firm-idUSKBN2B20NT/&quot;&gt;your server on fire&lt;/a&gt;, then, indeed, a price of $20/month is unbeatable.&lt;/p&gt;
&lt;p&gt;I remember asking one young French engineer in a startup about their GitLab instance and how they would maintain it and manage its security compliance. The answer was straightforward:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We just run `apt upgrade` every night so we’re sure we’ve every security deployment installed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;YMMV.&lt;/p&gt;
&lt;h2&gt;The Market Share&lt;/h2&gt;
&lt;p&gt;In April 2024, the Mergify team spent a few days at Devoxx France, the country&apos;s largest developer conference with nearly 5,000 attendees. We talked to dozens of engineers, and roughly 50% of them were using GitLab at work. Some large teams were moving away from GitLab to GitHub, but for a large majority, we were weirdos for not supporting GitLab. Their view of the market share is biased toward the French market, where GitLab might indeed have a large usage, which might not tend to generate large revenue, though. Remember that the Community Edition of GitLab is &lt;em&gt;free&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/ff991deb-3cd5-484c-be03-511a6ddf6833_3079x1800.webp&quot; alt=&quot;Mergify team at their booth at Devoxx France 2024&quot; /&gt;
&lt;em&gt;Mergify’s team at Devoxx France 2024&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If we compare &lt;a href=&quot;https://telanganatoday.com/githubs-annual-revenue-run-rate-hits-2-billion-driven-by-copilot-nadella&quot;&gt;GitHub’s $2 billion revenue&lt;/a&gt; to &lt;a href=&quot;https://about.gitlab.com/press/releases/2024-03-04-gitlab-reports-fourth-quarter-and-full-fiscal-year-2024-financial-results/&quot;&gt;GitLab’s $579 million revenue&lt;/a&gt; for 2024, this is a 1:4 ratio, which is already pretty huge. Sure, revenue is not usage, but considering that GitHub has Microsoft behind it and &lt;a href=&quot;https://www.spiceworks.com/tech/tech-general/news/gitlab-explores-sale-datadog-google-potential-buyers/&quot;&gt;GitLab is reportedly looking for a buyer&lt;/a&gt;, the future looks way brighter for GitHub — something I explored in more depth in &lt;a href=&quot;https://julien.danjou.info/blog/is-github-the-future-or-becoming&quot;&gt;Is GitHub the Future?&lt;/a&gt;. And I&apos;m not even talking about the fact that the vast majority of open-source projects use GitHub.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/fc24de53-43e4-46af-8e71-c3047d4d4bae_576x811.png&quot; alt=&quot;Screenshot of a LinkedIn comment misunderstanding GitHub vs GitLab market dynamics&quot; /&gt;
&lt;em&gt;No Gauthier, I don’t think that this is how it works.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;(&lt;a href=&quot;https://www.linkedin.com/feed/update/urn:li:activity:7254503750344622080/?commentUrn=urn%3Ali%3Acomment%3A(activity%3A7254503750344622080%2C7254531496810541056)&amp;amp;dashCommentUrn=urn%3Ali%3Afsd_comment%3A(7254531496810541056%2Curn%3Ali%3Aactivity%3A7254503750344622080)&amp;amp;dashReplyUrn=urn%3Ali%3Afsd_comment%3A(7255100415971659776%2Curn%3Ali%3Aactivity%3A7254503750344622080)&amp;amp;replyUrn=urn%3Ali%3Acomment%3A(activity%3A7254503750344622080%2C7255100415971659776)&quot;&gt;LinkedIn post&lt;/a&gt;)&lt;/p&gt;
&lt;h2&gt;Innovation&lt;/h2&gt;
&lt;p&gt;Now that I’ve set the scenery, I feel it’s safe to answer about GitLab support for Mergify. The main reasons why Mergify’s Merge Queue is not looking for GitLab support anytime soon are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Innovation happens on GitHub nowadays. Ten years ago, GitHub was behind on certain topics (hello CI), but they are now way ahead of the competition. GitHub is the place where most open-source is built and where you need to be if you’re building new products;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Most teams using GitLab CE have no intention to buy any software;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The market share of GitLab is small and probably shrinking.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve nothing against GitLab, and their software might be pretty good. All we know is that they’re outsiders, while a lot of the tech market in Europe seems to think that betting on GitLab is the best go-to-market strategy.&lt;/p&gt;
&lt;p&gt;I beg to differ.&lt;/p&gt;
</content:encoded><category>mergify</category><category>devops</category></item><item><title>What&apos;s going on with Dependabot?</title><link>https://julien.danjou.info/blog/whats-going-on-with-dependabot/</link><guid isPermaLink="true">https://julien.danjou.info/blog/whats-going-on-with-dependabot/</guid><description>We&apos;re moving away from it and I&apos;m not sure why it started to suck.</description><pubDate>Tue, 15 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I loved Dependabot. I’ve used it since Grey Baker started it in 2017. I’ve seen it grow from a one-person shop to being acquired by GitHub in 2019. It’s been a fantastic tool that created more than 5,000 pull requests on Mergify repositories. I remember the excitement of finally having a tool that would bring all the new fancy features and bug fixes of my dependencies to my project in a snap.&lt;/p&gt;
&lt;p&gt;Dependabot allowed us to fix a lot of security updates introduced by dependencies, and to be aware of anything new being released in the libraries we use.&lt;/p&gt;
&lt;p&gt;But today, we kicked Dependabot out. Dependabot let us down.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/0ee45b61-3086-492a-8caa-6348ae3405ad_2000x1256.jpeg&quot; alt=&quot;Illustration of frustration with Dependabot&apos;s declining reliability&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Security You Said?&lt;/h2&gt;
&lt;p&gt;The move to acquire Dependabot from GitHub was smart. It was one of the key features that started their security roadmap with the acquisition of Semmle and their CodeQL engine the same year. GitHub has become all about security over the last few years, which makes sense considering the cybersecurity segment&apos;s hyper-growth over the last and upcoming years.&lt;/p&gt;
&lt;p&gt;However, as Dependabot matured under GitHub, cracks started to show in what was once a flawless experience. The tool that was supposed to streamline security and updates became a source of frustration.&lt;/p&gt;
&lt;p&gt;It has major design flaws that GitHub does not seem to care about.&lt;/p&gt;
&lt;p&gt;First, Dependabot can fail silently. That happened to us multiple times a year when Dependabot would just stop working and create pull requests to update our packages. You’d think that debugging such an issue would be possible by going into the Dependabot tab of your repository, but no. The log for this is actually hidden in &lt;em&gt;Insight → Dependency graph → Dependabot.&lt;/em&gt; A strange and unintuitive location for such crucial information.&lt;/p&gt;
&lt;p&gt;Once you find your log, you can then read it and debug it yourself.&lt;/p&gt;
&lt;p&gt;That’s a major problem because there’s nothing warning you that Dependabot is broken. We are used to updating our packages regularly, so we’d know, but there’s nothing preventing your dependencies and security updates from getting stale for months without you noticing. Terrible experience.&lt;/p&gt;
&lt;h2&gt;Always Lagging Behind&lt;/h2&gt;
&lt;p&gt;We’re a Python shop. We leverage &lt;em&gt;poetry&lt;/em&gt; to manage our dependencies, and we use the latest Python version in our containers.&lt;/p&gt;
&lt;p&gt;As a Python shop, staying on the latest version helps us ensure security, performance, and compatibility. So we update it as soon as we can, usually a few days after it’s released.&lt;/p&gt;
&lt;p&gt;And then Dependabot is broken.&lt;/p&gt;
&lt;p&gt;And you have to wait weeks for GitHub to fix the problem.&lt;/p&gt;
&lt;p&gt;The last few times, we had to update ourselves Dependabot itself, &lt;a href=&quot;https://github.com/dependabot/dependabot-core/pull/10470&quot;&gt;as shown here&lt;/a&gt; or even &lt;a href=&quot;https://github.com/dependabot/dependabot-core/pull/10622&quot;&gt;here&lt;/a&gt;. We’re basically doing GitHub’s job for free, maintaining the Dependabot database ourselves for all their customers.&lt;/p&gt;
&lt;p&gt;We contacted GitHub support about this already, and they did not care at all. Their laconic answer was, “Wait for it to be updated.”&lt;/p&gt;
&lt;p&gt;Sure, thank you. We’re the ones doing the updates.&lt;/p&gt;
&lt;p&gt;I get it—maybe Fortune 500 companies don’t care about the latest Python micro releases. But for startups like ours? It’s a big deal.&lt;/p&gt;
&lt;p&gt;So today, we got rid of Dependabot and replaced it with &lt;a href=&quot;https://docs.renovatebot.com/&quot;&gt;Renovate&lt;/a&gt;. It seems better maintained and supports a larger package ecosystem than Dependabot. So far, it has simplified our workflow and is not broken on a simple Python micro update. 🤞&lt;/p&gt;
&lt;p&gt;We&apos;re also adding support for Renovate in &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt; Merge Protections, as we have done for Dependabot in the past. That will ensure you can write advanced rules for &lt;a href=&quot;https://julien.danjou.info/blog/automating-github-workflows&quot;&gt;automating your GitHub workflows&lt;/a&gt;, including automatically merging your dependency update. 🦾 Let me know if you’re interested in trying it out!&lt;/p&gt;
</content:encoded><category>devops</category><category>mergify</category></item><item><title>Why You Need Product Engineers</title><link>https://julien.danjou.info/blog/why-you-need-product-engineers/</link><guid isPermaLink="true">https://julien.danjou.info/blog/why-you-need-product-engineers/</guid><description>And not software engineers</description><pubDate>Tue, 01 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A couple of weeks ago, I attended our quarterly MAHOS (&lt;em&gt;Mergify All Hands On-Site&lt;/em&gt;)—an event where we gather the whole &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt; team together for a week—and gave a small speech about &lt;em&gt;product engineers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/7feac5ff-7567-46db-b3e8-361202fe8ea2_3799x2622.jpeg&quot; alt=&quot;Mergify team group photo, September 2024&quot; /&gt;
&lt;em&gt;Mergify’s team, Sept. 2024&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I was unsure if I coined the term &lt;em&gt;product engineer&lt;/em&gt; at that time or if it already existed. After Googling, I found that I was not the only one who realized that we no longer need &lt;em&gt;software engineers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When we started our venture a few years ago and decided to hire engineers, we naturally looked for software engineers. We found great engineers. They learned a ton of stuff working with us over the last couple of years and became very efficient at producing code. Awesome. I wrote last month about how to become &lt;a href=&quot;https://julien.danjou.info/p/how-to-be-a-great-software-engineer&quot;&gt;a great software engineer&lt;/a&gt;, and while I hold to this, the next step in your career, if you want to work in a product-oriented startup, is to become a &lt;em&gt;product engineer&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;What is a Product Engineer?&lt;/h2&gt;
&lt;p&gt;Is that just a software engineer building a product? Yes! But that is not what a software engineer does by default. Let me tell you an anecdote.&lt;/p&gt;
&lt;p&gt;Last month, with my product owner hat on, I wrote a user story explaining one of the changes we needed to make in Mergify: feature X is enabled by default in the product, which is annoying because most users do need it. We need to 1. allow the users to enable or disable it and 2. make it disabled by default.&lt;/p&gt;
&lt;p&gt;One of our software engineers picks the ticket and implements a solution. Here’s what they do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The feature X can be enabled or disabled;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The feature X is disabled by default;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;An error message warns the user constantly that feature X is currently disabled and that they need to enable it to have it work. There’s a giant red banner to warn users that feature X is disabled—until the user has enabled the feature.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When I see that, I’m really confused. The code is great, and the ticket is indeed implemented, but the last part is terrible from a user experience perspective. It forces the user to enable feature X to get rid of the warning, meaning we get back to a point where users have to enable feature X by default, even if they don’t need it, just because they’re confused.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/0432e3c6-7445-494c-b333-84b6d35c3e2e_519x167.png&quot; alt=&quot;Example of bad product design with a warning banner forcing users to enable a feature&quot; /&gt;
&lt;em&gt;Bad product design.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That is great &lt;em&gt;software engineering&lt;/em&gt; work but terrible &lt;em&gt;product engineering&lt;/em&gt; work. In no case did the engineer put themself in the user&apos;s shoes or try to understand why we needed that change.&lt;/p&gt;
&lt;p&gt;This is where a &lt;em&gt;product engineer&lt;/em&gt; must shine. They need to understand the value and the reason behind the code they write, taking into account the product, its roadmap, its priorities, etc. It requires the ability to do trade-offs by being pragmatic. They need to be obsessed with the customer and understand their problem. In a startup, you need to ship fast, meaning, again, doing trade-offs and being efficient and practical. They need to be detail-oriented, have a sense of ownership, and be on the look to create terrific experiences.&lt;/p&gt;
&lt;p&gt;Writing software has never been so easy. With AI on the rise, writing actual code will have less and less value.&lt;/p&gt;
&lt;p&gt;The core value of building software is going to be whatever AI is not yet able to do, which is &lt;em&gt;&lt;strong&gt;empathy&lt;/strong&gt;&lt;/em&gt;—connecting with and learning from other human beings’ needs.&lt;/p&gt;
&lt;h2&gt;How to Transform Engineers in Product Gurus&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/98343348-3763-4d8c-9bfd-68b936fc004c_2160x1215.png&quot; alt=&quot;Indeed job listing for product engineer showing misguided advice&quot; /&gt;
&lt;em&gt;Do not follow Indeed’s advice, for sure.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Based on the description I wrote above, we implemented some changes and made good progress overall. The improvements we made were due to simple changes we made to the organization.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Connect engineers with customers.&lt;/strong&gt; Doing support directly with customers, joining a demo call, spending time in a booth during an event, and talking to prospects. All those activities where engineering can interact with prospects and customers are very valuable;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explain the why, not the how.&lt;/strong&gt; As a product owner, you must explain why changes are being made and not how they should be made. The more context you feed into your user stories, the easier for an engineer is to make the right decision when building a feature or fixing a problem. It’s especially important when, as a product manager, you have a technical background and you could be tempted to dictate a solution.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are many software engineers out there, but not many product engineers. We’ll be on the lookout for that when hiring in the future. And if you want to join a product-oriented startup in the future, make sure you change your mindset to not just writing code. 😉&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>How To Test Your API Integration</title><link>https://julien.danjou.info/blog/how-to-test-with-an-api/</link><guid isPermaLink="true">https://julien.danjou.info/blog/how-to-test-with-an-api/</guid><description>The Three Rules That Should Govern Your Testing</description><pubDate>Tue, 24 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As I was publishing last week&apos;s post on whether &lt;a href=&quot;https://julien.danjou.info/p/is-github-the-future-or-becoming&quot;&gt;GitHub is becoming obsolete or the future of development platforms&lt;/a&gt;, they decided to trigger &lt;a href=&quot;https://blog.mergify.com/post-mortem-of-incident-2024-09-17/&quot;&gt;a two-hour interruption on Mergify in retaliation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Just kidding. I am sure they did not do that on purpose.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/0f8eda71-7106-45e0-8d33-e0530cd77668_1536x720.jpeg&quot; alt=&quot;Illustration of API integration testing challenges&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.mergify.com/post-mortem-of-incident-2024-09-17/&quot;&gt;Read my post-mortem&lt;/a&gt; if you want the whole story. The summary is that they broke their API for several hours until people started to complain, and they finally rolled back their change. Bringing down our service in the meantime.&lt;/p&gt;
&lt;p&gt;That event forces me to talk about APIs this week.&lt;/p&gt;
&lt;h2&gt;API Definitions Are Just Definitions&lt;/h2&gt;
&lt;p&gt;I won’t go into the definition of an API per se; it’d be boring. You can Google it if you need to.&lt;/p&gt;
&lt;p&gt;The real question is what &lt;em&gt;having&lt;/em&gt; an API &lt;em&gt;means&lt;/em&gt;. Offering an API to your users means authorizing them to interact with your service. This implies many rules, such as the data model of your API, the behavior of your API, the rules of usage, etc. Some can be encoded in a computer-readable machine; others cannot. Engineers like to talk about contracts, and I think it’s an almost good analogy.&lt;/p&gt;
&lt;p&gt;To describe this contract, you need multiple specifications.&lt;/p&gt;
&lt;p&gt;Developers have been ecstatic over &lt;a href=&quot;https://swagger.io/specification/&quot;&gt;OpenAPI&lt;/a&gt; over the last decade as a go-to media for describing their API. I want here to emphasize how little this documents your API. It illustrates the data model used but does not encode much of the behavior the system might exhibit.&lt;/p&gt;
&lt;p&gt;Hey, I can confirm that GitHub did not break its OpenAPI schema when it broke its API last week. Formidable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/8d49cdca-7d99-4c42-a00f-c772ceea9087_2500x714.svg&quot; alt=&quot;Diagram showing the gap between OpenAPI schema and actual API behavior&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, based on the assumption that OpenAPI is enough, many engineers mock their API consumption based on that part of the contract and think they’re done.&lt;/p&gt;
&lt;p&gt;In that situation, the minimum you should do is validate that your mocking follows the OpenAPI schema you’re using. Even that is not enough because sometimes the schema changes—and sometimes it’s just not respected.&lt;/p&gt;
&lt;p&gt;Let’s take GitHub again as an example. Their API is so legacy that the &lt;a href=&quot;https://json-schema.org/blog/posts/github-case-study&quot;&gt;JSON schemas were crafted manually&lt;/a&gt; — and there might still be, I don’t know. It’s fine; it’s better than nothing, and it’s not obvious to change a legacy API that’s been there for 15 years.&lt;/p&gt;
&lt;p&gt;We know first-hand that their system does not always respect the GitHub API JSON Schema.&lt;/p&gt;
&lt;h2&gt;APIs Have Side-effects&lt;/h2&gt;
&lt;p&gt;Again, this approach is entirely based on the data model and is insufficient and of little value.&lt;/p&gt;
&lt;p&gt;Most of an API&apos;s value is in the behavior it triggers. Unless your API is a basic CRUD and does storage only, it will have side effects that might or might not be visible through the API.&lt;/p&gt;
&lt;p&gt;For example, creating an asynchronous job on any REST API will return nothing except a unique identifier, which can be used later to identify the work. You might receive the data via a webhook or have to poll the API to get the job’s status. This kind of behavior cannot be documented in OpenAPI as it’s not part of the data model; there’s nothing to tell you to expect a webhook.&lt;/p&gt;
&lt;h2&gt;API Invisible Parts&lt;/h2&gt;
&lt;p&gt;Now, let’s discuss all the invisible parts of running an API. There are many. The first that come to mind are RBAC, quota, and rate limits. Most APIs have to implement those items, and they also have a direct impact on the API behavior and access.&lt;/p&gt;
&lt;p&gt;Those features will massively impact the quality and quantity of API use. Again, they are pretty hard to test in a black box. There’s no way you can easily mock a full RBAC implementation or real-life rate limits.&lt;/p&gt;
&lt;h2&gt;Testing the Hard Way&lt;/h2&gt;
&lt;p&gt;Having consumed many different APIs for the last five years on Mergify, and especially GitHub’s one that we know by heart, gave us a few ideas on how you can or cannot test.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number one: do not mock. Record your tests.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We leverage &lt;a href=&quot;https://vcrpy.readthedocs.io/en/latest/usage.html&quot;&gt;vcrpy&lt;/a&gt; in Python to do that: the idea is to run your test in a &lt;em&gt;record mode&lt;/em&gt; where real HTTP requests are done against a service. Once the recording is done, you can replay the test when running it locally or in the CI.&lt;/p&gt;
&lt;p&gt;If any of your code tries to make a different HTTP call, the test will fail, and you will have to re-record it. This ensures that no change is made to the application without being noticed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/ca786a70-ec3e-43f4-93dd-86c8ab02b27a_942x111.png&quot; alt=&quot;Screenshot of vcrpy test recording detecting a changed HTTP call&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now, that does prevent your application from being broken, but that does not prevent the API from breaking your app. The only way to do this is to regularly re-record all the tests and see if they break.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So, rule number two: re-record your tests regularly — every day if possible.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For example, we have a test that plays with GitHub pull request labels. When re-recording a test a few months ago, we noticed that if it failed. It turned out that GitHub changed its API to become case-sensitive overnight (that was not in the OpenAPI schema!).&lt;/p&gt;
&lt;p&gt;In that case, we preferred to ask GitHub to fix their API rather than fix our code, but hey, &lt;em&gt;your mileage may vary&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule number three: be ready to fix the code.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;No amount of testing will cover all the edge cases. For example, requests quota or rate limit might be hit in real scenarios but not in testing, meaning you’ll have to handle those specific cases without being able to test. It’s fine — you can actually mock part of the responses here.&lt;/p&gt;
&lt;p&gt;For this, we leverage &lt;a href=&quot;https://sentry.io&quot;&gt;Sentry&lt;/a&gt; to obtain evidence of the problem, replicate it in a test, and fix it. No amount of testing can fix all scenarios, so having a way to &lt;em&gt;hotfix&lt;/em&gt; your code is a must.&lt;/p&gt;
&lt;p&gt;In the end, mixing API test recording for safety and error tracking for fast action is the best combination we’ve seen for dealing with external systems.&lt;/p&gt;
&lt;p&gt;If we map those rules to last week&apos;s incident, rule number three helped to fix the issue quickly, while rule number one would have technically caught it, and rule number two would have done so in less than 24 hours. Even if it turned out in our case that reality kicked in before testing.&lt;/p&gt;
&lt;p&gt;So use that. And retry mechanisms.&lt;/p&gt;
&lt;p&gt;I guess that’ll be for another post.&lt;/p&gt;
</content:encoded><category>coding</category><category>mergify</category></item><item><title>Is GitHub the Future or Becoming Obsolete?</title><link>https://julien.danjou.info/blog/is-github-the-future-or-becoming/</link><guid isPermaLink="true">https://julien.danjou.info/blog/is-github-the-future-or-becoming/</guid><description>Is GitHub the Future or Becoming Obsolete?</description><pubDate>Tue, 17 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over the last few months, I stumbled upon a few articles on GitHub&apos;s history and future. I find those quite interesting. &lt;a href=&quot;https://graphite.dev/blog/github-monopoly-on-code-hosting?ref=blog.gitbutler.com&quot;&gt;Greg Foster gives a quick history of the rise of GitHub over the years&lt;/a&gt;, while Scott Chacon, one of GitHub’s co-founder, &lt;a href=&quot;https://blog.gitbutler.com/why-github-actually-won/&quot;&gt;retraces the history of GitHub from the inside&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The story is great, and I’ll leave it to you to read those posts if you want to learn more. I was alive at that time; I saw and lived it all. I started using Git in 2005, and I’m the 2644th of the 100 million GitHub users—I joined GitHub in 2008 when it was still in beta.&lt;/p&gt;
&lt;p&gt;It’s definitely true that Git won, and especially GitHub. I’ll probably have to write about GitLab at some point (&lt;a href=&quot;https://julien.danjou.info/blog/theres-almost-no-gitlab&quot;&gt;I eventually did&lt;/a&gt;) — but you won’t read any ranting here today. As Scott Chacon writes, GitHub had a taste and perfect timing and soon gained traction from the open-source community.&lt;/p&gt;
&lt;p&gt;Ok, great, so GitHub wins. Where do we go now?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/2a67ca8f-23bc-40da-bf28-f18b10b0be60_2000x1000.jpeg&quot; alt=&quot;Illustration of GitHub&apos;s dominance in code hosting&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Microsoft&lt;/h2&gt;
&lt;p&gt;I believe that GitHub&apos;s growth was already on track before Microsoft bought it in 2018, but that move still changed everything. At that time, GitHub still lacked major features, such as a CI/CD system, and had a hard time being compared to GitLab. The following year that changed, and GitHub Actions started (thanks, Azure) and shook everything up.&lt;/p&gt;
&lt;p&gt;If you read opinions about GitHub vs. GitLab, CodeCommit, Azure DevOps, or any other platform, you’ll mostly see engineers comparing user-visible features. And sure, this has value, and that might be your main criteria to pick one or the other if you’re a small team with full power over their choice.&lt;/p&gt;
&lt;p&gt;However, this is not what GitHub and Microsoft are after anymore. Take a look at the &lt;a href=&quot;https://github.com/github/roadmap&quot;&gt;roadmap&lt;/a&gt; of the last few years, and you’ll see a pattern: &lt;em&gt;enterprise&lt;/em&gt;. Pushing code, creating pull requests, and any part of software engineers&apos; day-to-day activities have been covered for the last 15 years.&lt;/p&gt;
&lt;p&gt;They designed it, the industry adopted it, and GitHub has nothing in its roadmap to change that paradigm. They’re building on the momentum they raised.&lt;/p&gt;
&lt;p&gt;Security, Copilot (AI), and compliance are items that the largest corporation needs to embrace a platform such as GitHub. This is only the beginning: this year, the GitHub sales organization underwent a reorganization to look more like Microsoft&apos;s sales organization. I suspect GitHub is now able to leverage even more Microsoft resources to push its platform to large corporations—which definitely makes sense. The link between GitHub and Azure is tightening, both technically and commercially.&lt;/p&gt;
&lt;p&gt;For the best and the worst.&lt;/p&gt;
&lt;h2&gt;Relevance&lt;/h2&gt;
&lt;p&gt;How is GitHub still relevant if it does not innovate on developer workflow? &lt;a href=&quot;https://www.mistys-internet.website/blog/blog/2024/07/12/github-is-starting-to-feel-like-legacy-software/&quot;&gt;Is it becoming legacy software&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;There is certainly a disjunction between what developers and corporations expect, and at this point, if you look at the ratio between features, compliance, and price, there&apos;s no better alternative than GitHub. I don’t think this is going to change anytime soon.&lt;/p&gt;
&lt;p&gt;For open-source projects, there might be alternatives, but if you’re pragmatic (and lazy), GitHub is the pick. There have been a number of projects trying to escape GitHub over the years, such as when Microsoft acquired it. The latter is still seen as an enemy of open source by some folks (I suspect this is PTSD caused by the &lt;a href=&quot;https://www.zdnet.com/article/ballmer-i-may-have-called-linux-a-cancer-but-now-i-love-it/&quot;&gt;Balmer&lt;/a&gt; era). More recently, another exodus was triggered by the announcement of Copilot and the fear that the training was done on free software. However, at this stage, it’s like emptying an ocean with a spoon, and the impact does not compensate for larger projects moving to GitHub (e.g., &lt;a href=&quot;https://peps.python.org/pep-0512/&quot;&gt;Python&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/3051d896-9814-41f5-9866-20a74692b5d0_1200x630.jpeg&quot; alt=&quot;Steve Ballmer portrait&quot; /&gt;
&lt;em&gt;Steve Ballmer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On the other hand, GitHub is attracting more competitors. It has grown to a point where many startups want to disrupt it: one can look at &lt;a href=&quot;https://radicle.xyz/&quot;&gt;Radicle&lt;/a&gt; and its decentralized approach, &lt;a href=&quot;https://pierre.co/&quot;&gt;Pierre&lt;/a&gt; and its modern design, &lt;a href=&quot;https://www.diversion.dev/&quot;&gt;Diversion&lt;/a&gt; with its game-centric approach, or &lt;a href=&quot;https://www.palmier.io/&quot;&gt;Palmier,&lt;/a&gt; who’s building a new kind of repository.&lt;/p&gt;
&lt;p&gt;They might succeed, but the road is going to be long to get massive adoption — and migration.&lt;/p&gt;
&lt;p&gt;There’s nothing replacing GitHub in the short term. We better deal with it.&lt;/p&gt;
</content:encoded><category>devops</category><category>mergify</category></item><item><title>Staying Competitive</title><link>https://julien.danjou.info/blog/staying-competitive/</link><guid isPermaLink="true">https://julien.danjou.info/blog/staying-competitive/</guid><description>How to fight (back) big corporations</description><pubDate>Tue, 10 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Starting a company is always a challenge. You start small, and you might have to fight competitors that are way larger than you. They could crush you.&lt;/p&gt;
&lt;p&gt;However, being small does not mean that you will necessarily lose against large companies.&lt;/p&gt;
&lt;p&gt;Last week, I was wandering through a forum where I regularly hang out with other SaaS founders. We share founders’ issues, anything from how to run ad campaigns to how to fire people (sigh).&lt;/p&gt;
&lt;p&gt;That day, one of the participants asked a question about staying competitive when large companies enter your market. They were facing a few challenges, the main one being that a multi-billion corporation was adding features to its product that would poach on their turf.&lt;/p&gt;
&lt;p&gt;That resonated with me. Mergify went through the same hassle when &lt;a href=&quot;https://julien.danjou.info/blog/the-challenges-of-merge-queues&quot;&gt;GitHub launched its own merge queue features&lt;/a&gt; last year.&lt;/p&gt;
&lt;p&gt;Being in this position is extremely risky. There are many horror stories out there of startups being killed by larger competitors. You’d just have to watch the latest OpenAI DevDay announcements over the last few months to see how many startups they would instantly disrupt with the announcement of a single feature (marketplace, custom GPTs, etc.).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/cf70dc33-1f44-41b7-aa8d-84ba67f62c1a_1516x416.png&quot; alt=&quot;Apple iOS 18 announcement threatening to disrupt smaller competitors&quot; /&gt;
&lt;em&gt;Is Apple going to kill a bunch of companies with iOS18?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now, that being said, being the underdog is not necessarily a bad thing and can turn out to be a strength. When survival is at stake, the smallest dog can become the more fierce one.&lt;/p&gt;
&lt;h2&gt;80/20&lt;/h2&gt;
&lt;p&gt;In 1668, Jean de La Fontaine wrote a famous fable, &lt;em&gt;Le Lièvre et la Tortue&lt;/em&gt;. If you never heard of it, the TL;DR is: a confident hare mocks a slow tortoise and challenges her to a race. The hare, overconfident, takes a nap mid-race while the tortoise steadily continues and wins. The fable teaches the lesson that persistence and diligence can triumph over arrogance and haste.&lt;/p&gt;
&lt;p&gt;There are multiple choices to do in this situation, but my feeling is that most large companies will implement the “20% features that do 80% of the job.” It makes sense to them economically. With little effort, they can enter the market and grasp a large amount of the share using their moat, branding, marketing, and existing customers.&lt;/p&gt;
&lt;p&gt;They can leverage their vast resources and existing ecosystems to quickly dominate this space. However, they often leave gaps in niche or specialized needs because building the remaining 80% of features to cover every specific use case requires more effort and may not align with their broader goals.&lt;/p&gt;
&lt;p&gt;Unfortunately, if you were also targeting the same 20% feature, this can hurt your business. You’ll stop seeing new customers and will lose existing ones as they remove the one-too-many vendor from their list.&lt;/p&gt;
&lt;p&gt;However, there is a chance for you to stay ahead of the game. Like the hare in the tale, large companies will just take a gigantic nap once they’re done with what they expect to be enough. This is where you can shine.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/2508d33f-3137-40ba-ac04-efd71bb84318_1580x1180.png&quot; alt=&quot;Illustration of the 80/20 rule applied to feature coverage and market share&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A small company that builds beyond the basic 20% and focuses on solving complex or specialized problems can appeal to customers who require more tailored solutions, thus capturing a large share of a more focused market. While large companies serve the general market, small players can dominate specialized verticals. By implementing, e.g., 40% of the features for a particular scope, you could address 97% of the market, thus appearing as an expert and leader in your area.&lt;/p&gt;
&lt;h2&gt;Vertical&lt;/h2&gt;
&lt;p&gt;Another play that I like is to target different verticals. If you design presentation software and suddenly PowerPoint enters the market, it’s going to be pretty hard to win over the long run. Microsoft will win because they’re known (the “&lt;em&gt;nobody gets fired for buying IBM&lt;/em&gt;” rule), and they can reach out to millions of customers — you can’t.&lt;/p&gt;
&lt;p&gt;However, if you pivot to becoming the presentation software specialized in building convincing, AI-generated, prospect-centered sales decks automatically, then you can win an entire part of the broader market.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/a437ebee-cfed-4dee-9528-f75711e49af2_2000x1000.jpeg&quot; alt=&quot;Illustration of targeting vertical markets to compete against large corporations&quot; /&gt;&lt;/p&gt;
&lt;p&gt;For sure, the initial market might be narrower, but by being focused, it’ll be easier to win it. As you’re winning it, you can expand into adjacent markets and grab more share of the global offering.&lt;/p&gt;
&lt;h2&gt;Strategy&lt;/h2&gt;
&lt;p&gt;For both strategies — expanding beyond the 80/20 or addressing a particular, the key to discovering which approach might suit you better is to talk to your existing customers. They are the ones having the answer to the questions “Is there a usage pattern they rely on?” or “Are they working in the same industry?”. Focusing on customer experience or specializing in integrations that large corporations won’t do is only identifiable if you speak to your users.&lt;/p&gt;
&lt;p&gt;Small companies have the agility and execution speed that large companies lack, making them the best innovators.&lt;/p&gt;
&lt;p&gt;I guess that’s my message to anyone out there being attacked by large corporations. Don’t throw the towel too soon. There might be different plays for you to continue growing and fighting back against the Goliath.&lt;/p&gt;
&lt;p&gt;In the end, it’s not just about size. It’s about understanding where you can uniquely provide value and delivering that value better and faster than anyone else.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>Reflecting on the Journey of &quot;Nom d&apos;un Pipeline !&quot;</title><link>https://julien.danjou.info/blog/reflecting-on-the-journey-of-nom/</link><guid isPermaLink="true">https://julien.danjou.info/blog/reflecting-on-the-journey-of-nom/</guid><description>A Podcast About CI/CD for the French Tech Scene</description><pubDate>Tue, 30 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&quot;&lt;a href=&quot;https://nomdunpipeline.com&quot;&gt;Nom d&apos;un Pipeline !&lt;/a&gt;&quot; (translation for English readers: &quot;What a Pipeline!&quot;) has been an incredible journey, filled with learning, growth, and connecting with some of the brightest minds in the French tech scene. As a French-based startup for over five years, with most of our customers and audience in the US, we noticed a significant gap in the knowledge and maturity around CI/CD among French engineering teams. This realization motivated us to create a platform to elevate the understanding and practices of CI/CD in our home country, leading to the birth of &quot;Nom d&apos;un Pipeline !&quot;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/37d5f1f1-3eb9-4cae-984c-ba4f49a99615_1323x1323.png&quot; alt=&quot;Nom d&apos;un Pipeline podcast logo&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;The Birth of an Idea&lt;/h2&gt;
&lt;p&gt;Starting a podcast was a new adventure for me. With the help of Mergify’s marketing team, we built everything from the ground up and began reaching out to potential guests. We aimed to find the right candidates and teams to feature in our 45-minute episodes, sharing their journeys and insights around continuous integration, continuous deployment, and quality assurance.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/60f0e810-d2cf-4180-b93a-b71e84f49613_1536x768.webp&quot; alt=&quot;Nom d&apos;un Pipeline podcast banner&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Highlights from Season 1&lt;/h2&gt;
&lt;p&gt;All episodes were amazing, and the content we built was really valuable. I think several episodes stood out for their depth and impact:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nomdunpipeline.com/episode/definir-identifier-et-tester-pour-performer&quot;&gt;Mathieu Leroux-Huet&lt;/a&gt; discussed performance, offering valuable insights into optimizing systems for better efficiency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nomdunpipeline.com/episode/ep-10-faire-des-economies-avec-ses-propres-runners&quot;&gt;Cyril Rohr&lt;/a&gt; from RunsOn shared how improving GitHub Actions runner can significantly enhance CI workflows speed and cost.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nomdunpipeline.com/episode/ep-6-vers-des-pipelines-ci-cd-imposes-et-standardises-avec-olivier-pillaud-tirard-de-manomano&quot;&gt;Olivier Pillaud-Tirard&lt;/a&gt; from ManoMano detailed how they have improved their CI over the last couple of years, providing a roadmap for other teams to follow.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These episodes were not only informative but also showcased the diverse approaches and innovations happening within the French tech community.&lt;/p&gt;
&lt;h2&gt;Overcoming Challenges&lt;/h2&gt;
&lt;p&gt;Producing a podcast comes with its own set of challenges. One of the biggest hurdles we faced was recording remotely. There were times when technical issues disrupted the recordings, but we managed to overcome these obstacles with perseverance and technical adjustments. While I would love to record in a studio, living in Toulouse makes it challenging since none of my guests are local. Despite these difficulties, the remote setup has allowed us to connect with a broader range of guests.&lt;/p&gt;
&lt;h2&gt;Positive Feedback and Growing Momentum&lt;/h2&gt;
&lt;p&gt;The feedback we&apos;ve received has been overwhelmingly positive. Listeners appreciate the insights and real-world experiences shared by our guests. Knowing that the show provides value and helps the French tech scene advance in CI/CD practices is incredibly rewarding. Recently, we passed the 2,000 views/listens mark, indicating growing momentum after just eight months. This milestone is a testament to the show&apos;s impact and the increasing interest in CI/CD topics.&lt;/p&gt;
&lt;h2&gt;Personal and Professional Growth&lt;/h2&gt;
&lt;p&gt;On a personal level, hosting &quot;Nom d&apos;un Pipeline !&quot; has been a delightful experience. I discovered that I genuinely enjoy talking to people and learning about their teams and tech stacks. It&apos;s been an eye-opening journey that has enriched my understanding of CI/CD and connected me with some brilliant minds in the industry.&lt;/p&gt;
&lt;h2&gt;Acknowledging Our Guests&lt;/h2&gt;
&lt;p&gt;I want to extend my heartfelt thanks to all our guests for their confidence and for sharing their journeys: Clément, Sofiyan, Romaric, Aurélien, Frédéric, Olivier, Dan, Thomas, Mathieu, Cyril and François.&lt;/p&gt;
&lt;p&gt;Your contributions have been invaluable in making this podcast a success.&lt;/p&gt;
&lt;h2&gt;Looking Ahead to Season 2&lt;/h2&gt;
&lt;p&gt;As we wrap up the first season, we are already gearing up for season 2, set to launch in September. We are excited to bring new hosts from major French companies like Doctolib and Alan, promising even more insightful content and engaging discussions. While we don&apos;t have specific plans for season 2 yet, we are committed to continuing our mission of educating and inspiring the French tech community about CI/CD.&lt;/p&gt;
&lt;p&gt;&quot;Nom d&apos;un Pipeline !&quot; has been an extraordinary journey, and I&apos;m proud of what we&apos;ve accomplished so far. We hope that this podcast continues to serve as a valuable resource for the French tech scene, helping teams to improve their continuous integration, testing, continuous deployment, and overall development workflows — including tackling tough topics like &lt;a href=&quot;https://julien.danjou.info/blog/the-challenges-of-merge-queues&quot;&gt;the challenges of merge queues&lt;/a&gt;. Stay tuned for more exciting episodes and insights in the upcoming season!&lt;/p&gt;
&lt;p&gt;If you understand French, don’t forget to subscribe to the podcast &lt;a href=&quot;https://www.nomdunpipeline.com/&quot;&gt;on your favorite podcast platform&lt;/a&gt; or on &lt;a href=&quot;https://www.youtube.com/@NomdunPipeline&quot;&gt;YouTube&lt;/a&gt;!&lt;/p&gt;
</content:encoded><category>mergify</category><category>devops</category></item><item><title>The Challenges of Merge Queues</title><link>https://julien.danjou.info/blog/the-challenges-of-merge-queues/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-challenges-of-merge-queues/</guid><description>Why They’re Hard and Why We’re Simplifying Them</description><pubDate>Tue, 23 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Merge queues are a tough concept to grasp, and over the last five years at &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;, we&apos;ve spent countless hours educating developers about their importance and utility. We&apos;ve published numerous blog posts, written extensive documentation, and even gone to conferences to teach software engineers what a merge queue is. This process of spreading awareness has been a rewarding yet challenging endeavor.&lt;/p&gt;
&lt;p&gt;One of our developers, Charly Laurent, gave an insightful talk on the subject, highlighting how merge queues can revolutionize CI/CD processes. You can check out his talk here:&lt;/p&gt;
&lt;h2&gt;Understanding Merge Queues&lt;/h2&gt;
&lt;p&gt;Merge queues are not an obvious choice for most teams, and they often require a shift in the balance between safety and speed of delivery. Deploying a merge queue means prioritizing quality over quantity, which is not an easy decision for many development teams, who might be pressured to ship fast.&lt;/p&gt;
&lt;p&gt;For example, without a merge queue, teams often merge untested code. This is due to outdated test runs, meaning that they are deploying code that might not work. Without a merge queue, there is no way to prevent merging pull requests with outdated tests and breaking the CI for everyone — which is exactly why you should &lt;a href=&quot;https://julien.danjou.info/blog/stop-merging-your-pull-request-manually&quot;&gt;stop merging your pull requests manually&lt;/a&gt; in the first place. One of our customers faced this exact issue, which meant they needed the equivalent of a full-time engineer dedicated to tracking issues in the main branch that broke the CI.&lt;/p&gt;
&lt;p&gt;Most platform engineers find the concept of moving the post-merge tests to pre-merge tests challenging.&lt;/p&gt;
&lt;h2&gt;The Trade-offs&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://vercel.com/blog/deploy-safely-on-vercel-without-merge-queues&quot;&gt;This blog post from Vercel&lt;/a&gt; captures this common misunderstanding and the trade-off around merge queues and their CI costs and latency:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Despite the majority of commits being safe to merge after the local CI checks complete on their pull request, the merge queue will incur running the cost of running the CI again every time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While this is true, the problem here lies in the word &quot;majority.&quot; The definition of &quot;majority&quot; can vary significantly across teams. If a minority of pull requests break the main branch after merging, it can cause considerable downtime and require substantial effort from CI engineers to restore stability. We&apos;ve seen teams come to Mergify with a 30% failure rate on their &lt;code&gt;main&lt;/code&gt; branch. While a merge queue won&apos;t magically improve the failure rate, it ensures that it doesn&apos;t worsen, even if it means a small decrease in merge speed. That ensures that the effort invested in improving the CI is not wasted the day after.&lt;/p&gt;
&lt;p&gt;Another perspective from Vercel states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With merge queues, changes from developers depend on changes from other developers even if they are unrelated to each other, and this makes it hard to scale monorepo merge times with more developers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This concern is valid for merge queues that don&apos;t support monorepo and queue parallelization. However, most modern merge queues (GitHub&apos;s own being an exception) do allow for optimization in these scenarios.&lt;/p&gt;
&lt;p&gt;Vercel’s blog post concludes with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With this workflow in place, the merge queue can be safely removed because checks will still always be run before users ever see the deployment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This reflects the workflow of many teams that don&apos;t use a merge queue: merge, run tests on &lt;code&gt;main&lt;/code&gt;, then deploy. However, this approach doesn&apos;t solve the issue of merging something that breaks the main branch. During the downtime, teams have to identify the culprit, revert changes, and ensure everything works, causing delays and frustration. Bad developer experience ensues.&lt;/p&gt;
&lt;p&gt;Teams like &lt;a href=&quot;https://www.uber.com/blog/research/keeping-master-green-at-scale/&quot;&gt;Uber recognized this problem six years ago&lt;/a&gt; and started building their merge queues. Similarly, in OpenStack, we had a system supporting multiple repositories with &lt;a href=&quot;https://zuul-ci.org/&quot;&gt;Zuul&lt;/a&gt; over ten years ago.&lt;/p&gt;
&lt;h2&gt;Build New Solutions&lt;/h2&gt;
&lt;p&gt;Considering the merge queue adoption issues, we&apos;ve spent the last few months reworking our merge queue system to simplify deployment and enhance user experience. We know for a fact that developers appreciate the reliability it brings to CI processes, but we also observe the difficulty of discovering and integrating the system. By deploying a merge queue, teams can eliminate the need for a &quot;check that main works before deployment&quot; step because this is done before the actual merge.&lt;/p&gt;
&lt;p&gt;One notable example is a team that previously needed a full-time engineer to manage CI issues due to frequent breaks in the &lt;code&gt;main&lt;/code&gt; branch. After adopting Mergify&apos;s merge queue, they drastically reduced these disruptions, allowing their engineers to focus on more productive tasks.&lt;/p&gt;
&lt;h2&gt;The Road Ahead&lt;/h2&gt;
&lt;p&gt;Merge queues are not without their challenges, and the trade-offs between safety and speed are not always apparent. However, we believe in their potential to transform development workflows. We&apos;re on the verge of redefining the merge queue concept at Mergify, and we think it has far greater potential than what has been realized over the past decade. I’ll be happy to write about that soon and share what we’ve built.&lt;/p&gt;
</content:encoded><category>mergify</category><category>devops</category></item><item><title>Navigating SQL Migrations with Confidence: Introducing sql-compare</title><link>https://julien.danjou.info/blog/navigating-sql-migrations-with-confidence/</link><guid isPermaLink="true">https://julien.danjou.info/blog/navigating-sql-migrations-with-confidence/</guid><description>Delivering SQL schema change at scale.</description><pubDate>Tue, 16 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As long as I can remember, SQL has been a cornerstone of my engineering journey. My early days at university were filled with monotonous Oracle-based SQL courses, which I found uninspiring. Knowing I would likely never use Oracle, I shifted my focus to &lt;a href=&quot;https://mysql.com&quot;&gt;MySQL&lt;/a&gt;. Over time, I discovered the limitations of MySQL and was introduced to &lt;a href=&quot;https://www.postgresql.org/&quot;&gt;PostgreSQL&lt;/a&gt;, thanks to &lt;a href=&quot;https://tapoueh.org/about/&quot;&gt;Dimitri&lt;/a&gt;. I even organized a few meetups in Paris and encouraged Dimitri to publish &quot;&lt;a href=&quot;https://theartofpostgresql.com/&quot;&gt;The Art of PostgreSQL&lt;/a&gt;,&quot; arguably the best book on SQL (&lt;a href=&quot;https://julien.danjou.info/blog/the-art-of-postgresql-is-out&quot;&gt;I reviewed it here&lt;/a&gt;). Eventually, I embraced PostgreSQL wholeheartedly.&lt;/p&gt;
&lt;p&gt;SQL databases are a timeless technology that continues to evolve. From &lt;a href=&quot;https://www.timescale.com/&quot;&gt;Timescale&lt;/a&gt; to &lt;a href=&quot;https://github.com/pgvector/pgvector&quot;&gt;pgvector&lt;/a&gt;, new advancements are continually emerging. However, one persistent challenge has been managing database migrations. Modifying your data model is crucial for evolving your application, but it’s often a daunting task. At Mergify, like many companies, we’ve faced this challenge head-on.&lt;/p&gt;
&lt;p&gt;We&apos;ve tried various solutions, from custom Python scripts to using &lt;a href=&quot;https://github.com/djrobstep/migra&quot;&gt;migra&lt;/a&gt;, an open-source project that is unfortunately no longer maintained. Each solution had its drawbacks, leading us to a crossroads where we had to decide on our next move.&lt;/p&gt;
&lt;h2&gt;The Initial Struggle&lt;/h2&gt;
&lt;p&gt;At &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;, PostgreSQL is the backbone of our data handling, from managing the state of GitHub objects to maintaining our event log. From the beginning, we’ve interacted with the database exclusively using an ORM, choosing &lt;a href=&quot;https://www.sqlalchemy.org/&quot;&gt;SQLAlchemy&lt;/a&gt; for its maturity, framework agnosticism, and support for asynchronous I/O since version 2.0.0.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/81ae39c3-f945-42cc-80c0-99ade9f0bc9f_1456x816.webp&quot; alt=&quot;Illustration of SQL database migration workflow&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Given our frequent production deployments, a robust CI/CD pipeline is essential to handle database evolution smoothly. Every schema modification must be rigorously tested and automatically applied to the production database, adhering to the principles outlined in Martin Fowler&apos;s &quot;&lt;a href=&quot;https://martinfowler.com/articles/evodb.html&quot;&gt;Evolutionary Database Design.&lt;/a&gt;&quot; Version-controlling each database artifact and scripting every change as a migration are critical steps in this process.&lt;/p&gt;
&lt;p&gt;We chose &lt;a href=&quot;https://alembic.sqlalchemy.org/&quot;&gt;Alembic&lt;/a&gt; to manage our database migrations. Maintained by the SQLAlchemy team, Alembic is a command-line tool that can automatically create migration scripts from your SQLAlchemy models. Each script is version-controlled alongside your source code. Alembic applies these migrations to the database, recording the revision number in the &lt;code&gt;alembic_version&lt;/code&gt; table to ensure only new migrations are applied subsequently. This command is typically executed in the continuous delivery pipeline to keep the production database up-to-date.&lt;/p&gt;
&lt;h2&gt;A Naive Beginning&lt;/h2&gt;
&lt;p&gt;Our initial approach to testing migration scripts was straightforward: create two databases—one using SQLAlchemy models and the other using only the migration scripts—and ensure they have identical schemas. This involved:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Creating PostgreSQL servers using Docker:&lt;/strong&gt; On a new server, create two empty databases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generating schemas:&lt;/strong&gt; Use the first database to create artifacts with SQLAlchemy models, and use Alembic to run migration scripts on the second database.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Comparing schemas:&lt;/strong&gt; Dump each database schema into SQL files using &lt;code&gt;pg_dump&lt;/code&gt; and compare them using Python’s &lt;code&gt;filecmp&lt;/code&gt; and &lt;code&gt;difflib&lt;/code&gt; builtin libraries.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s an example command to dump a database schema into an SQL file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pg_dump \
    --dbname=postgresql://user:password@host:port/database \
    --schema-only \
    --exclude-table=alembic_version \
    --format=p \
    --encoding=UTF8 \
    --file /path/to/dump.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To compare the files:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;assert filecmp.cmp(schema_dump_creation_path, schema_dump_migration_path, shallow=False)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the test fails, use &lt;code&gt;difflib&lt;/code&gt; to display the differences:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def filediff(path1: pathlib.Path, path2: pathlib.Path) -&amp;gt; str:
    with path1.open() as f1, path2.open() as f2:
        diff = difflib.unified_diff(
            f1.readlines(),
            f2.readlines(),
            path1.name,
            path2.name,
        )
        return &quot;Database dump differences: \n&quot; + &quot;&quot;.join(diff)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While effective, this test had limitations, such as sensitivity to column order. PostgreSQL doesn’t easily allow changing column positions, necessitating consistent column order in models and production databases.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/f7a3603f-e06b-45d7-97c4-99f9bbb3da76_1456x816.png&quot; alt=&quot;Illustration of comparing database schemas side by side&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;The Complexity Grows&lt;/h2&gt;
&lt;p&gt;As our models grew more complex, our naive test struggled to keep up. Consider the following example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Base:
    updated_at: orm.Mapped[datetime.datetime] = orm.mapped_column(
        sqlalchemy.DateTime(timezone=True),
        server_default=sqlalchemy.func.now(),
    )

class User(Base):
    id: orm.Mapped[int] = orm.mapped_column(
        sqlalchemy.BigInteger,
        primary_key=True,
    )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this setup, the &lt;code&gt;updated_at&lt;/code&gt; column is added to every child model, such as &lt;code&gt;User&lt;/code&gt;. Adding a new column to &lt;code&gt;User&lt;/code&gt;, like &lt;code&gt;name&lt;/code&gt;, would misalign the order, causing schema mismatches.&lt;/p&gt;
&lt;p&gt;To address this, we needed to compare schemas while ignoring column order. We explored various tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Alembic&lt;/strong&gt;: Can compare schemas to generate migration scripts but misses some differences.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Migra&lt;/strong&gt;: An unmaintained tool that compares database schemas effectively.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SQL dumps&lt;/strong&gt;: The most reliable format but challenging to parse and compare directly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Building the Solution: sql-compare&lt;/h2&gt;
&lt;p&gt;It was clear that our current solutions were insufficient. We needed a hero to rescue us from the perils of SQL migration management, so we developed &lt;strong&gt;&lt;a href=&quot;https://github.com/Mergifyio/sql-compare&quot;&gt;sql-compare&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;sql-compare is a Python library that uses &lt;a href=&quot;https://pypi.org/project/sqlparse/&quot;&gt;sqlparse&lt;/a&gt; to parse SQL files and compare schemas, ignoring irrelevant differences like comments, whitespace, and column order. This new tool became an integral part of our workflow, catching migration issues that other tools might miss.&lt;/p&gt;
&lt;p&gt;The main challenge was filtering and grouping tokens by column definition before sorting them. Despite these complexities, sql-compare emerged victorious, enabling us to ensure seamless migrations and maintain schema integrity.&lt;/p&gt;
&lt;h2&gt;The Journey Forward&lt;/h2&gt;
&lt;p&gt;We’ve open-sourced sql-compare to help others facing similar challenges. You can try it by running &lt;code&gt;pip install sql-compare&lt;/code&gt;. We plan to enhance sql-compare, such as creating functions to retrieve all schema differences for better test results. If you have suggestions or want to contribute, feel free to submit issues or pull requests on our GitHub repository.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Managing database migrations is a complex but essential task for evolving applications. With sql-compare, we found our solution, ensuring seamless migrations, maintaining schema integrity, and continuing to deliver high-quality software. Our journey through the challenges of SQL migrations has taught us valuable lessons, and with sql-compare, we’re better equipped to face the future.&lt;/p&gt;
</content:encoded><category>coding</category><category>mergify</category></item><item><title>The Biggest Mistake We Made Building Mergify: Navigating the Hiring Minefield</title><link>https://julien.danjou.info/blog/the-biggest-mistake-we-made-building-a43/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-biggest-mistake-we-made-building-a43/</guid><description>Possibly the hardest part of the job.</description><pubDate>Tue, 02 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This is part 2 of the &quot;Biggest Mistakes&quot; series. Read part 1: &lt;a href=&quot;https://julien.danjou.info/blog/the-biggest-mistake-we-made-building&quot;&gt;Navigating the Payment System Nightmare&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Building a successful startup is a journey filled with unexpected challenges, and hiring the right people is undoubtedly one of the most daunting tasks. As a tech engineer with no HR background, I’ve faced numerous hiring pitfalls that have taught me invaluable lessons. Reflecting on our journey at &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;, it&apos;s clear that navigating the complexities of hiring has been one of the biggest challenges we&apos;ve encountered. Here’s what we’ve learned.&lt;/p&gt;
&lt;h2&gt;Who to Hire: The Temptation of Cheap Labor&lt;/h2&gt;
&lt;p&gt;When you’re a startup with limited resources, it’s tempting to hire interns or apprentices, especially when they come at a low or even zero cost, thanks to government sponsorships. In France, this is an attractive option many startups pursue, and we were no different. Initially, we hired interns and apprentices, believing that this would provide us with much-needed help without straining our budget.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/1eeb04a8-72d7-4d76-b1d7-1ff056e39f80_1536x768.png&quot; alt=&quot;Illustration of the temptation of hiring interns and cheap labor at a startup&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, we quickly realized that while interns can be a valuable addition, they often lack the expertise we needed to tackle complex tasks. As founders, we required skilled assistance, not just extra hands for minor tasks. The overhead of breaking down projects into manageable tasks and guiding interns through them often resulted in a net loss of productivity. While we did encounter some exceptional interns who became valuable team members, the general rule is that relying on almost-free resources like interns is unlikely to provide the expertise needed in the early days of your startup.&lt;/p&gt;
&lt;h2&gt;How to Hire: The Challenge of Assessing Candidates&lt;/h2&gt;
&lt;p&gt;Hiring is more than just finding someone with the right skills; it’s about finding the right fit for your team and company culture. Despite the plethora of online resources on evaluating candidates, the reality of assessing someone over a Zoom call in just a few hours is incredibly challenging.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&apos;ve had both terrific and terrible hires, and in each case, we believed they were a perfect fit at the time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After conducting hundreds of interviews and hiring more than a dozen people, we’ve learned one golden rule: if you have any doubts about a candidate, don’t hire them. It’s better to wait for the right person than to rush and hire someone who might not fit well with your team.&lt;/p&gt;
&lt;h2&gt;Finding Candidates: The Perils of Recruitment&lt;/h2&gt;
&lt;p&gt;The search for talent is a constant struggle. In France, we experimented with various solutions, from Welcome to the Jungle (a nightmare) to &lt;a href=&quot;https://talent.io&quot;&gt;talent.io&lt;/a&gt; (effective). We also engaged a few headhunting firms, which unfortunately turned out to be a costly mistake. These firms often sent us unsuitable candidates and still kept their fees. The legal obligations in France favor the headhunters, not the employers, making it a risky and expensive endeavor.&lt;/p&gt;
&lt;p&gt;For example, we had a candidate that we hired and then paid the fees to the headhunting firm. The employee would stop their trial period and leave. That meant the headhunting firm should send new candidates our way to replace the one that left during the trial period. However, there was no incentive for them to do so as they’d been paid already. Therefore, they didn’t care. We found our candidate in a different manner, meaning the fee was then lost for us. Considering that fees can be 10–20% of the employee&apos;s yearly salary, that’s a large amount of money to throw out the window.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/df7cb53f-1b32-4f33-9622-ca8767df181e_1536x768.webp&quot; alt=&quot;Illustration of the challenges of finding talent through headhunters and recruitment&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Networking and recommendations remain some of the best ways to find talent, but they don’t scale well and often have timing issues; you’d find the right candidate, but they’re not available, or a friend would knock at the door, and you’d not have any budget to hire them.&lt;/p&gt;
&lt;p&gt;Additionally, we realized that marketing our company effectively during hiring talks is crucial. Initially, our pitch didn’t resonate, and most candidates would ignore us. By improving our presentation and emphasizing our company culture and values, we started attracting genuinely interested candidates.&lt;/p&gt;
&lt;p&gt;After years, we discovered that you want to &lt;em&gt;polarize&lt;/em&gt; your candidate early in the process and during their employment to ensure they get 100 % onboard with your venture. Depending on your founder profile, that might be something you do naturally. As tech founders, we were not particularly good at that, but we learned our way through.&lt;/p&gt;
&lt;h2&gt;The Remote Work Dilemma&lt;/h2&gt;
&lt;p&gt;Building a remote team has advantages, like accessing a broader talent pool, but it also comes with significant challenges. At Mergify, we embraced remote work and &lt;a href=&quot;https://blog.mergify.com/embracing-remote-work-how-we-built-mergify-as-a-successful-asynchronous-company/&quot;&gt;wrote extensively about our experience&lt;/a&gt;. Remote work works well with senior staff, but junior employees often struggle without in-person guidance. Sharing the company vision and brainstorming ideas are also more effective in person, which is why we regularly organize in-person meetings.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/2aad7a8b-4718-4807-9bc0-48c702dd110d_1536x768.png&quot; alt=&quot;Illustration of remote work challenges and team building&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Regular team-building events, video calls, and asynchronous communication help bridge the gap, but they can’t completely replace the spontaneous interactions that foster innovation. Remote work is great for finding talent, but in-person connections remain essential for a cohesive and innovative team environment.&lt;/p&gt;
&lt;p&gt;I would not consider remote work a mistake, but we underestimated its impact on the company.&lt;/p&gt;
&lt;h2&gt;Lessons Learned and Rules Established&lt;/h2&gt;
&lt;p&gt;From our hiring mistakes, we’ve developed a few key rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Avoid hiring remote junior staff if you are working remotely. They need more guidance and in-person interaction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Leverage in-person connections for innovation. Remote work makes this challenging, especially for junior staff.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Share a lot of context to drive innovation and execution. Overcommunicate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be cautious of headhunters and their fees. Consider delaying payment until the trial period ends.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Avoid working with multiple headhunting firms to avoid finding your candidate with one when you have already paid the other.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Learn to pitch your company effectively. Highlight your values and culture to attract the right candidates.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you have any doubts about a candidate, don’t hire them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Don’t hire interns and trainees until you have enough senior staff to mentor them. Consider them a small cost, not a huge win.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Navigating the hiring process is complex and fraught with potential pitfalls, but by learning from our mistakes and establishing clear rules, we&apos;ve been able to build a stronger, more effective team.&lt;/p&gt;
&lt;p&gt;If you’re building a startup, remember that the right hires can make all the difference, and taking the time to find them is well worth the effort.&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>The Biggest Mistake We Made Building Mergify: Navigating the Payment System Nightmare</title><link>https://julien.danjou.info/blog/the-biggest-mistake-we-made-building/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-biggest-mistake-we-made-building/</guid><description>Navigating the Pitfalls of Payment Processing: Lessons Learned from Integrating Stripe, GitHub Marketplace, and Paddle</description><pubDate>Tue, 11 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In 2018, we embarked on an exciting journey with &lt;a href=&quot;https://mergify.com&quot;&gt;Mergify&lt;/a&gt;, our brainchild aimed at simplifying GitHub pull request workflows. One of the first crucial decisions we faced was choosing a payment processor. &lt;a href=&quot;https://stripe.com&quot;&gt;Stripe&lt;/a&gt;, with its developer-centric approach, seemed like the perfect fit. Within a few days, I had mastered the Stripe API and built the foundational billing system for Mergify. For a while, everything ran smoothly as we scaled our user base. However, we soon encountered a significant roadblock: handling VAT in Europe.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/350e34cf-0664-400b-a8ff-880cc58f2776_1500x1000.jpeg&quot; alt=&quot;Illustration of navigating payment system challenges&quot; /&gt;&lt;/p&gt;
&lt;p&gt;European VAT is notoriously complex, with countless edge cases that can quickly become a nightmare for any business. Invoicing internationally from France presented additional challenges, leading us to the conclusion that outsourcing our invoicing would be the best course of action.&lt;/p&gt;
&lt;h2&gt;The GitHub Marketplace Misstep&lt;/h2&gt;
&lt;p&gt;In 2019, the &lt;a href=&quot;https://github.com/marketplace&quot;&gt;GitHub Marketplace&lt;/a&gt; appeared to be an attractive solution. It promised to streamline invoicing while exposing Mergify to a broader audience. Although GitHub took a 15% cut (later reduced to 5%), we were not focused on optimizing margins at that stage.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/87f22244-5403-401f-b6b6-07e2bd2c2ad9_3000x1610.webp&quot; alt=&quot;Screenshot of the GitHub Marketplace&quot; /&gt;
&lt;em&gt;GitHub Marketplace&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;However, this decision turned out to be a colossal mistake.&lt;/p&gt;
&lt;p&gt;Issues with payments began to surface almost immediately. Problems with GitHub’s payment system meant we often had to ask customers to contact GitHub support, creating a frustrating experience for them. Our inability to manage payments directly, such as retrying failed transactions, was a significant drawback. It became evident that while the GitHub Marketplace was a great tool for acquiring new customers, it was far from ideal for handling payments.&lt;/p&gt;
&lt;p&gt;As a glaring example, if a GitHub customer switched from credit card billing to invoice, they would lose access to all marketplace apps, including Mergify. This could abruptly cut off our service, leading to dissatisfied customers and lost revenue. By 2020, we decided to completely transition away from the GitHub Marketplace for payments, migrating our customers back to Stripe. This move eliminated the invoicing problems caused by GitHub and allowed us to regain control over our billing process.&lt;/p&gt;
&lt;h2&gt;The Paddle Predicament&lt;/h2&gt;
&lt;p&gt;Despite our move back to Stripe, the VAT issue remained unresolved. In our quest for a better solution, we discovered &lt;a href=&quot;https://www.paddle.com/&quot;&gt;Paddle&lt;/a&gt;, a platform that promised to handle VAT by becoming the merchant of record for our transactions. We quickly integrated Paddle into our system, hopeful it would be the solution we needed. Unfortunately, this decision soon proved to be another costly mistake.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/20387ab7-572e-41a4-b9f8-1122f386de90_1186x779.png&quot; alt=&quot;Screenshot of the Paddle payment platform&quot; /&gt;
&lt;em&gt;Paddle&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Paddle&apos;s API was far less sophisticated than Stripe’s, and we found ourselves grappling with numerous limitations and workarounds to integrate our billing system. The added complexity and subpar user experience led us to conclude that Paddle was not the right fit for Mergify.&lt;/p&gt;
&lt;h2&gt;The Turning Point: Handling VAT Ourselves&lt;/h2&gt;
&lt;p&gt;Realizing that there was no perfect third-party solution, we decided to tackle the VAT problem head-on. In 2020, we took the plunge and developed our own VAT handling system using Stripe and Python. We detailed this process in a &lt;a href=&quot;https://blog.mergify.com/handling-european-vat-with-stripe/&quot;&gt;blog post&lt;/a&gt; sharing our approach and challenges.&lt;/p&gt;
&lt;p&gt;Fortunately, Stripe was also working on solving the VAT issue. By the end of 2021, they released their &lt;a href=&quot;https://stripe.com/en-fr/tax&quot;&gt;comprehensive tax product&lt;/a&gt;, simplifying VAT and other tax processes. This allowed us to finally switch fully to Stripe, discarding our custom code in favor of their robust solution.&lt;/p&gt;
&lt;h2&gt;Lessons Learned&lt;/h2&gt;
&lt;p&gt;The most significant lesson from our journey is that payment processing is not a mere detail—it’s an integral part of the user experience. Even now, I spend several hours each month resolving payment issues, from credit card problems to ensuring invoices are correctly fed into various supplier systems. While automation can handle many aspects, the unique methods and systems of each customer often require personalized solutions.&lt;/p&gt;
&lt;p&gt;Our experience underscores the importance of keeping things simple on your side and minimizing friction for your customers. Ensuring a smooth and reliable payment process is crucial for maintaining customer satisfaction and loyalty.&lt;/p&gt;
&lt;p&gt;In hindsight, we should have approached the payment system with the same rigor and attention to detail as the rest of our product.&lt;/p&gt;
&lt;p&gt;It&apos;s a lesson we learned the hard way, but one that has ultimately strengthened Mergify and our commitment to providing the best possible service for our users.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is part 1 of the &quot;Biggest Mistakes&quot; series. Read part 2: &lt;a href=&quot;https://julien.danjou.info/blog/the-biggest-mistake-we-made-building-a43&quot;&gt;Navigating the Hiring Minefield&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>startup</category><category>mergify</category></item><item><title>Sponsoring Conferences</title><link>https://julien.danjou.info/blog/sponsoring-conferences/</link><guid isPermaLink="true">https://julien.danjou.info/blog/sponsoring-conferences/</guid><description>Our experience at Mergify with conference sponsoring.</description><pubDate>Thu, 06 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week, &lt;a href=&quot;https://julien.danjou.info/p/attending-conferences&quot;&gt;I wrote about my experience attending conferences&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Over the last year, we&apos;ve tried to expose Mergify at conferences to reach out to developers. We’ve done various conferences in Europe and the US—the largest being &lt;a href=&quot;https://qconsf.com/&quot;&gt;QCon San Francisco&lt;/a&gt; 2023 and &lt;a href=&quot;https://www.devoxx.fr/&quot;&gt;Devoxx France&lt;/a&gt; 2024. We sponsored those events and ran booths for several days all day long to talk to engineers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/images/blog/b4e4296f-966f-43cc-b434-4b6668db7706_1572x1893.webp&quot; alt=&quot;Mergify booth at QCon San Francisco 2023&quot; /&gt;
&lt;em&gt;Mergify booth at QCon San Francisco 2023&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The pattern we’ve seen has been interesting. First, QCon San Francisco was the smallest it’s been over the last few years, as far as I can tell. While 1,400 people were expected, counting the number of people seated in the keynote session revealed less than half of that were present. We talked to tens of engineers without great success. It turns out that trying to sell your tool for an early startup like Mergify is not efficient at all in such a place. Companies tend to do that when they are way larger to raise brand awareness and penetrate the market more efficiently.&lt;/p&gt;
&lt;p&gt;At our stage, this was a lot of money spent for barely any gain.&lt;/p&gt;
&lt;p&gt;As Mehdi, my cofounder and CTO says, “no great engineer will go to a conference to find the next tool they’ll need.” Indeed, I don’t believe any good engineer should wait 6 months for the next conference they will attend to find a product to their technical problems.&lt;/p&gt;
&lt;p&gt;Doing market education, as we tried, over a booth, is utopian. Here’s the typical dialogue that would happen:&lt;/p&gt;
&lt;p&gt;– &lt;em&gt;Engineer attending the conference:&lt;/em&gt; “Hi! What does Mergify do?”&lt;br /&gt;
– &lt;em&gt;Mergify staff:&lt;/em&gt; “We offer merge queues for your GitHub repository. Do you know about them?”&lt;br /&gt;
– &lt;em&gt;Engineer attending the conference trying not to lose face:&lt;/em&gt; “Yeah, for sure!”&lt;br /&gt;
– &lt;em&gt;Mergify staff:&lt;/em&gt; “Do you use one in your team?”&lt;br /&gt;
– &lt;em&gt;Engineer:&lt;/em&gt; “No, we don’t need one.”&lt;br /&gt;
– &lt;em&gt;Mergify:&lt;/em&gt; &quot;How so? You&apos;re happy merging outdated PR or running a lot of CI on every PR?&quot;&lt;br /&gt;
– &lt;em&gt;Engineer:&lt;/em&gt; &quot;We… don&apos;t… well… err… what are we talking about exactly?…&quot;&lt;/p&gt;
&lt;p&gt;The truth is, 95% of the engineers we talked to have no clue what a merge queue is. Actually, 80% of them don’t know anything about Git besides the basics (i.e., commit and push), and chatting for 10 minutes over a booth is not a good place to educate them.&lt;/p&gt;
&lt;p&gt;Speaking at conferences is a way better strategy, as the advent of the Developer Evangelist role has demonstrated over the last years. If well executed, it’s cheaper and can have a far better outcome than sponsoring an event.&lt;/p&gt;
&lt;p&gt;You could imagine that sponsoring an event buys you a ticket to speak, but it’s not the case by default. Some conferences allow you to buy speaking time in special, dedicated rooms, for example, but you usually don’t get any special treatment over the regular CfP.&lt;/p&gt;
&lt;p&gt;I really need to talk about that CfP game.&lt;/p&gt;
</content:encoded><category>talks</category><category>mergify</category></item><item><title>One year of Mergify</title><link>https://julien.danjou.info/blog/one-year-of-mergify/</link><guid isPermaLink="true">https://julien.danjou.info/blog/one-year-of-mergify/</guid><description>It has been close to a year now that I&apos;ve incorporated my new company, Mergify. I&apos;ve been busy, and I barely wrote anything about it so far.</description><pubDate>Thu, 12 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It has been close to a year now that I&apos;ve incorporated my new company, &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt;. I&apos;ve been busy, and I barely wrote anything about it so far. Now is an excellent time to take a break and reflect a bit on what happened during those last 12 months.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/export-mergify-logo-title-horizontal.png&quot; alt=&quot;Mergify logo&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;What problem does Mergify solve?&lt;/h2&gt;
&lt;p&gt;Mergify is a powerful automation engine for GitHub pull requests. It allows you to automate everything — and especially merging. You write rules, and it handles the rest.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/Screenshot-2020-03-10-at-11.27.23.png&quot; alt=&quot;Example of rule matching returned in GitHub checks&quot; /&gt;&lt;/p&gt;
&lt;p&gt;For example, let&apos;s say you want your pull request to be merged, e.g., once your CI passes and the pull request has been approved. You just write such a rule, and our engine merges the pull request as soon as it&apos;s ready.&lt;/p&gt;
&lt;p&gt;We also deal with more advanced use cases. For instance, we provide &lt;a href=&quot;https://doc.mergify.io/merge-action.html#strict-merge&quot;&gt;a merge queue&lt;/a&gt; so your pull requests are merged serially and tested by your CI one after another — avoiding any regression in your code.&lt;/p&gt;
&lt;p&gt;Our goal is to make pull request management and automation easy. You can use your bot to trigger a rebase of your pull requests, or a backport to a different branch, just with a single comment.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/Screenshot-2020-03-10-at-11.21.37.png&quot; alt=&quot;Some people like to make bots talk to each other.&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;A New Adventure&lt;/h2&gt;
&lt;p&gt;Mergify is the first company that I ever started. I did run some personal businesses before, created non-profit organizations, built FOSS projects — but I never created a company from scratch, even less with an associate.&lt;/p&gt;
&lt;p&gt;Indeed, I&apos;ve chosen to build the company with my old friend &lt;a href=&quot;https://sileht.net/&quot;&gt;Mehdi&lt;/a&gt;. We&apos;ve known each others for 7 years now, and have worked together all that time on different open-source projects. Having worked with each other for so long has probably been a critical factor in the success of our venture so far.&lt;/p&gt;
&lt;p&gt;I had little experience sharing the founding seats with someone, and tons of reading seemed to indicate that it would be a tough ride. Picking the right business partner(s) can be a hard task. Luckily, after working so much time together, Mehdi and I both know our strengths and weaknesses well enough to be able to circumvent them. 😅&lt;/p&gt;
&lt;p&gt;On the other hand, we both have similar backgrounds as software engineers. That does not help to cover all the hats you need to wear when building a company. Over time, we found arrangements to cover most of those equally between us.&lt;/p&gt;
&lt;p&gt;We don&apos;t have any magical advice to give on this. As in every relationship, communication is the key, and the #1 factor of success.&lt;/p&gt;
&lt;h2&gt;Getting Users&lt;/h2&gt;
&lt;p&gt;I don&apos;t know if we got lucky, but we got users and customers pretty early. We used a few cooperative projects as guinea pigs first, and they were brave enough to try our service and give us feedback. No repository has been harmed during this first phase!&lt;/p&gt;
&lt;p&gt;Then, as soon as we managed to get our application on the &lt;a href=&quot;https://github.com/marketplace/mergify&quot;&gt;GitHub Marketplace&lt;/a&gt;, we saw a steady number of users coming to us.&lt;/p&gt;
&lt;p&gt;This has been fantastic as it allowed us to get feedback rapidly. We set up a form asking users for feedback after they used Mergify for a couple of weeks. What we hear is that users were happy, that the documentation was confusing and that some features were buggy or missing. We planned all of those ideas as our future work in our roadmap, using &lt;a href=&quot;https://medium.com/mergify/how-we-handle-our-roadmap-for-mergify-7e813e24508e&quot;&gt;the principles we described a few months ago&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/fit/c/152/152/1*8I-HPL0bfoIzGied-dzOvA.png&quot; alt=&quot;If you&apos;re curious, you can read this article.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We tried various strategies to get new users, but so far, organic growth has been our #1 way of onboarding new users. Like many small startups out there, we&apos;re not that good at marketing and executing strategies.&lt;/p&gt;
&lt;p&gt;We provide our service for free for open-source projects We are now powering many organizations, such as Mozilla, Amazon Web Services, Ceph and Fedora.&lt;/p&gt;
&lt;h2&gt;Working with GitHub&lt;/h2&gt;
&lt;p&gt;Working with GitHub has been… complicated. When you build an application for a marketplace, your business is entirely dependent on the platform you develop for — both in terms of features and quality of service.&lt;/p&gt;
&lt;p&gt;In our case, we hit quite many bugs with GitHub. Their support has mostly been fast to answer, but some significant issues are still opened months later. The truth is that the GitHub API could deserve more love and care from GitHub. For example, their GraphQL API is a work in progress for years and miss out many essential features.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/Screenshot-2020-03-05-at-16.38.55.png&quot; alt=&quot;GitHub service status is not always green.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We dealt and still deal with all those issues. It obviously impacts our operations and decreases our overall velocity. We regularly have to find new ways to sidestep GitHub limitations.&lt;/p&gt;
&lt;p&gt;You have no idea how we wished for GitHub to be open-source. The idea of not having access to their code and understand how it works is so frustrating that we publish our &lt;a href=&quot;https://github.com/mergifyio/mergify-engine&quot;&gt;engine&lt;/a&gt; as an open-source project. That allows all of our users to see how it works and even propose enhancements.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/Screenshot-2020-03-11-at-10.39.12.png&quot; alt=&quot;Screenshot of the Mergify open-source engine repository on GitHub&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Automate all the way&lt;/h2&gt;
&lt;p&gt;We&apos;re a tiny startup, and we decided to bootstrap our company. We never took any funding. From the beginning, it has been clear to us that we had to think and act like we had no resources. We&apos;re built around a scarcity mindset. Every decision we make is based on the assumption that we basically are very limited in terms of money and time.&lt;/p&gt;
&lt;p&gt;We basically act like any wrong choice we do could (virtually) kill the company. We only do what is essential, we ship fast, and we automate everything.&lt;/p&gt;
&lt;p&gt;For example, we have built our whole operation about CI/CD systems, and pushing any new fix or feature in production is done in a matter of &lt;em&gt;minutes&lt;/em&gt;. It&apos;s not uncommon for us to push a fix from our phone, just by reviewing some code or editing a file.&lt;/p&gt;
&lt;h2&gt;Growth&lt;/h2&gt;
&lt;p&gt;We&apos;re extremely happy with our steady growth and more users using our service. We now manage close to 30k repositories and merge 15k pull requests per month for our users.&lt;/p&gt;
&lt;p&gt;That&apos;s a lot of mouse clicks saved!&lt;/p&gt;
&lt;p&gt;If you want to try &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; yourself, it&apos;s a single click log-in using your GitHub account. Check it out!&lt;/p&gt;
</content:encoded><category>mergify</category></item><item><title>Python Logging with Datadog</title><link>https://julien.danjou.info/blog/python-logging-with-datadog/</link><guid isPermaLink="true">https://julien.danjou.info/blog/python-logging-with-datadog/</guid><description>At Mergify, we generate a pretty large amount of logs. Every time an event is received from GitHub for a particular pull request, our engine computes a new state for it.</description><pubDate>Mon, 03 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt;, we generate a pretty large amount of logs. Every time an event is received from GitHub for a particular pull request, our engine computes a new state for it. Doing so, it logs some informational statements about what it&apos;s doing — and any error that might happen.&lt;/p&gt;
&lt;p&gt;This information is precious to us. Without proper logging, it&apos;d be utterly impossible for us to debug any issue. As we needed to store and index our logs somewhere, we picked Datadog as our log storage provider.&lt;/p&gt;
&lt;p&gt;Datadog offers real-time indexing of our logs. The ability to search our records that fast is compelling as we&apos;re able to retrieve log about a GitHub repository or a pull request with a single click.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/01/Screenshot-2020-01-06-at-17.23.58.png&quot; alt=&quot;Our custom Datadog log facets&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To achieve this result, we had to inject our Python application logs into Datadog. To set up the Python logging mechanism, we rely on &lt;a href=&quot;https://github.com/jd/daiquiri&quot;&gt;&lt;em&gt;daiquiri&lt;/em&gt;&lt;/a&gt;, a fantastic library I maintained for several years now. &lt;em&gt;Daiquiri&lt;/em&gt; leverages the regular Python &lt;code&gt;logging&lt;/code&gt; module, making its a no-brainer to set up and offering a few extra features.&lt;/p&gt;
&lt;p&gt;We recently added native support for the Datadog agent in &lt;em&gt;daiquiri&lt;/em&gt;, making it even more straightforward to log from your Python application.&lt;/p&gt;
&lt;h2&gt;Enabling log on the Datadog agent&lt;/h2&gt;
&lt;p&gt;Datadog has &lt;a href=&quot;https://docs.datadoghq.com/agent/logs/?tab=tailexistingfiles&quot;&gt;extensive documentation on how to configure its agent&lt;/a&gt;. This can be summarized to adding &lt;code&gt;logs_enabled: true&lt;/code&gt; in your agent configuration. Simple as that.&lt;/p&gt;
&lt;p&gt;You then need to create a new source for the agent. The easiest way to connect your application and the Datadog agent is using the TCP socket. Your application will write logs directly to the Datadog agent, which will forward the entries to Datadog backend.&lt;/p&gt;
&lt;p&gt;Create a configuration file in &lt;code&gt;conf.d/python.d/conf.yaml&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;h2&gt;Setting up &lt;code&gt;daiquiri&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Once this is done, you need to configure your Python application to log to the TCP socket configured in the agent above.&lt;/p&gt;
&lt;p&gt;The Datadog agent expects logs in JSON format being sent, which is what &lt;em&gt;daiquiri&lt;/em&gt; does for you. Using JSON allows to embed any extra fields to leverage fast search and indexing. As &lt;em&gt;daiquiri&lt;/em&gt; provides native handling for extra fields, you&apos;ll be able to send those extra fields without trouble.&lt;/p&gt;
&lt;p&gt;First, list &lt;em&gt;daiquiri&lt;/em&gt; in your application dependency. Then, set up logging in your application this way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import daiquiri

daiquiri.setup(
  outputs=[
    daiquiri.output.Datadog(),
  ],
  level=logging.INFO,
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This configuration logs to the default TCP destination &lt;code&gt;localhost:10518&lt;/code&gt; — though you can pass the &lt;code&gt;host&lt;/code&gt; and &lt;code&gt;port&lt;/code&gt; argument to change that. You can customize the outputs as you wish by checking out &lt;a href=&quot;https://daiquiri.readthedocs.io/en/latest/&quot;&gt;daiquiri documentation&lt;/a&gt;. For example, you could also include logging to &lt;code&gt;stdout&lt;/code&gt; by adding &lt;code&gt;daiquiri.output.Stream(sys.stdout)&lt;/code&gt; in the output list.&lt;/p&gt;
&lt;h2&gt;Using &lt;code&gt;extra&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;When using &lt;em&gt;daiquiri&lt;/em&gt;, you&apos;re free to use &lt;code&gt;logging.getLogger&lt;/code&gt; to get your regular logging object. However, by using the alternative &lt;code&gt;daiquiri.getLogger&lt;/code&gt; function, you&apos;re enabling the native use of extra arguments — which is quite handy. That means you can pass any arbitrary key/value to your log call, and see it up being embedded in your log data — up to Datadog.&lt;/p&gt;
&lt;p&gt;Here&apos;s an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import daiquiri

[…]

log = daiquiri.getLogger(__name__)
log.info(&quot;User did something important&quot;, user=user, request_id=request_id)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The extra keyword argument passed to &lt;code&gt;log.info&lt;/code&gt; will be directly shown as attributes in Datadog logs:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/01/Screenshot-2020-01-06-at-18.22.04.png&quot; alt=&quot;One of the log line of our Mergify engine&quot; /&gt;&lt;/p&gt;
&lt;p&gt;All those attributes can then be used to search or to display custom views. This is really powerful to monitor and debug any kind of service.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/01/Screenshot-2020-01-06-at-18.39.05.png&quot; alt=&quot;Screenshot of Datadog log explorer showing custom attributes for search and display&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;A log object per object&lt;/h2&gt;
&lt;p&gt;When passing &lt;em&gt;extra&lt;/em&gt; arguments, it is easy to make mistakes and forget some. This especially can happen when your application wants to log information for a particular object.&lt;/p&gt;
&lt;p&gt;The best pattern to avoid this is to create a custom log object per object:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import daiquiri

class MyObject:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.log = daiquiri.getLogger(&quot;MyObject&quot;, x=self.x, y=self.y)

    def do_something(self):
        try:
            self.call_this()
        except Exception:
            self.log.error(&quot;Something bad happened&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By using the &lt;code&gt;self.log&lt;/code&gt; object as defined above, there&apos;s no way for your application to miss some extra fields for an object. All your logs will look in the same style and will end up being indexed correctly in Datadog.&lt;/p&gt;
&lt;h2&gt;Log Design&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;extra&lt;/em&gt; arguments from the Python loggers are often dismissed, and many developers stick to logging strings with various information included inside. Having a proper explanation string, plus a few extra key/value pairs that are parsable by machines and humans, is a better way to do logging. Leveraging engines such as Datadog allow to store and query those logs in a snap.&lt;/p&gt;
&lt;p&gt;This is way more efficient than trying to parse and grep strings yourselves!&lt;/p&gt;
</content:encoded><category>python</category><category>mergify</category><category>monitoring</category></item><item><title>Dependencies Handling in Python</title><link>https://julien.danjou.info/blog/dependencies-handling-in-python-automatic-update/</link><guid isPermaLink="true">https://julien.danjou.info/blog/dependencies-handling-in-python-automatic-update/</guid><description>Dependencies are a nightmare. Here&apos;s how to handle them properly in Python with pipenv, poetry, Dependabot, and Mergify for fully automatic updates.</description><pubDate>Mon, 02 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Dependencies are a nightmare for many people. &lt;a href=&quot;https://thenewstack.io/to-reduce-tech-debt-eliminate-dependencies-and-refactoring/&quot;&gt;Some even argue they are technical debt&lt;/a&gt;. Managing the list of the libraries of your software is a horrible experience. Updating them — automatically? — sounds like a delirium.&lt;/p&gt;
&lt;p&gt;Stick with me here as I am going to help you get a better grasp on something that you cannot, in practice, get rid of — unless you&apos;re incredibly rich and talented and can live without the code of others.&lt;/p&gt;
&lt;p&gt;First, we need to be clear of something about dependencies: there are two types of them. &lt;a href=&quot;https://caremad.io/posts/2013/07/setup-vs-requirement/&quot;&gt;Donald Stuff wrote better than I would about the subject&lt;/a&gt; years ago. To make it simple, one can say that they are two types of code packages depending on  external code: applications and libraries.&lt;/p&gt;
&lt;h3&gt;Libraries Dependencies&lt;/h3&gt;
&lt;p&gt;Python libraries should specify their dependencies in a generic way. A library should not require &lt;code&gt;requests 2.1.5&lt;/code&gt;: it does not make sense. If every library out there needs a different version of &lt;code&gt;requests&lt;/code&gt;, they can&apos;t be used at the same time.&lt;/p&gt;
&lt;p&gt;Libraries need to declare dependencies based on ranges of version numbers. Requiring &lt;code&gt;requests&amp;gt;=2&lt;/code&gt; is correct. Requiring &lt;code&gt;requests&amp;gt;=1,&amp;lt;2&lt;/code&gt; is also correct if you know that &lt;code&gt;requests 2.x&lt;/code&gt; does not work with the library. The problem that your version range specification is solving is the &lt;strong&gt;API compatibility issue&lt;/strong&gt; between your code and your dependencies — &lt;em&gt;nothing else&lt;/em&gt;. That&apos;s a good reason for libraries to use &lt;a href=&quot;https://semver.org/&quot;&gt;Semantic Versioning&lt;/a&gt; whenever possible.&lt;/p&gt;
&lt;p&gt;Therefore, dependencies should be written in &lt;code&gt;setup.py&lt;/code&gt; as something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from setuptools import setup

setup(
    name=&quot;MyLibrary&quot;,
    version=&quot;1.0&quot;,
    install_requires=[
        &quot;requests&quot;,
    ],
    # ...
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way, it is easy for any application to use the library and co-exist with others.&lt;/p&gt;
&lt;h3&gt;Applications Dependencies&lt;/h3&gt;
&lt;p&gt;An application is just a particular case of libraries. They are not intended to be reused (imported) by other libraries of applications — though nothing would prevent it in practice.&lt;/p&gt;
&lt;p&gt;In the end, that means that you should specify the dependencies the same way that you would do for a library in the application&apos;s &lt;code&gt;setup.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The main difference is that an application is usually &lt;em&gt;deployed&lt;/em&gt; in production to provide its service. Deployments need to be reproducible. For that, you can&apos;t solely rely on &lt;code&gt;setup.py&lt;/code&gt;: the requested range of the dependencies are too broad. You&apos;re at the mercy of random version changes at any time when re-deploying your application.&lt;/p&gt;
&lt;p&gt;You, therefore, need a different version management mechanism to handle deployment than just &lt;code&gt;setup.py&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;pipenv&lt;/em&gt; has &lt;a href=&quot;https://docs.pipenv.org/en/latest/advanced/#pipfile-vs-setuppy&quot;&gt;an excellent section recapping this&lt;/a&gt; in its documentation. It splits dependency types into &lt;em&gt;abstract&lt;/em&gt; and &lt;em&gt;concrete&lt;/em&gt; dependencies: &lt;em&gt;abstract&lt;/em&gt; dependencies are based on ranges (e.g., libraries) whereas &lt;em&gt;concrete&lt;/em&gt; dependencies are specified with precise versions (e.g., application deployments) — as we&apos;ve just seen here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Handling Deployment&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;requirements.txt&lt;/code&gt; file has been used to solve application deployment reproducibility for a long time now. Its format is usually something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;requests==3.1.5
foobar==2.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each library sees itself specified to the micro version. That makes sure each of your deployment is going to install the same version of your dependency. Using a &lt;code&gt;requirements.txt&lt;/code&gt; is a simple solution and a first step toward reproducible deployment. However, it&apos;s not &lt;em&gt;enough&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Indeed, while you can specify which version of &lt;code&gt;requests&lt;/code&gt; you want, if &lt;code&gt;requests&lt;/code&gt; depends on &lt;code&gt;urllib3&lt;/code&gt;, that could make &lt;code&gt;pip&lt;/code&gt; install &lt;code&gt;urllib 2.1&lt;/code&gt; or &lt;code&gt;urllib 2.2&lt;/code&gt;. You can&apos;t know which one will be installed, which does not make your deployment 100% reproducible.&lt;/p&gt;
&lt;p&gt;Of course, you &lt;em&gt;could&lt;/em&gt; duplicate all &lt;code&gt;requests&lt;/code&gt; dependencies yourself in your &lt;code&gt;requirements.txt&lt;/code&gt;, but that would be &lt;strong&gt;madness&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/image.png&quot; alt=&quot;An application dependency tree can be quite deep and complex sometimes.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are various hacks available to fix this limitation, but the real saviors here are &lt;a href=&quot;https://github.com/pypa/pipenv&quot;&gt;&lt;em&gt;pipenv&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;https://poetry.eustace.io/&quot;&gt;&lt;em&gt;poetry&lt;/em&gt;&lt;/a&gt;. The way they solve it is similar to many package managers in other programming languages. They generate a &lt;em&gt;lock file&lt;/em&gt; that contains the list of all installed dependencies (and their own dependencies, etc.) with their version numbers. That makes sure the deployment is 100% reproducible.&lt;/p&gt;
&lt;p&gt;Check out their documentation on how to set up and use them!&lt;/p&gt;
&lt;h3&gt;Handling Dependencies Updates&lt;/h3&gt;
&lt;p&gt;Now that you have your &lt;em&gt;lock file&lt;/em&gt; that makes sure your deployment is reproducible in a snap, you&apos;ve another problem. How do you make sure that your dependencies are up-to-date? There is a real security concern about this, but also bug fixes and optimizations that you might miss by staying behind.&lt;/p&gt;
&lt;p&gt;If your project is hosted on &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt;, &lt;a href=&quot;https://dependabot.com/&quot;&gt;Dependabot&lt;/a&gt; is an excellent solution to solve this issue. Enabling this application on your repository creates automatically pull requests whenever a new version of the library listed in your lock file is available. For example, if you&apos;ve deployed your application with &lt;code&gt;redis 3.3.6&lt;/code&gt;, Dependabot will create a pull request updating to &lt;code&gt;redis 3.3.7&lt;/code&gt; as soon as it gets released. Furthermore, Dependabot supports &lt;code&gt;requirements.txt&lt;/code&gt;, &lt;em&gt;pipenv&lt;/em&gt;, and &lt;em&gt;poetry&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/Screenshot-2019-08-14-at-17.57.47.png&quot; alt=&quot;Dependabot updating jinja2 for you&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Automatic Deployment Update&lt;/h2&gt;
&lt;p&gt;You&apos;re almost there. You have a bot that is letting you know that a new version of a library your project needs is available.&lt;/p&gt;
&lt;p&gt;Once the pull request is created, your continuous integration system is going to kick in, deploy your project, and runs the test. If everything works fine, your pull request is ready to be merged. But are &lt;em&gt;you&lt;/em&gt; really needed in this process?&lt;/p&gt;
&lt;p&gt;Unless you have a particular and personal aversion on specific version numbers —&quot;Gosh I hate versions that end with a 3. It&apos;s always bad luck.&quot;— or unless you have zero automated testing, you, human, is useless. This merge can be fully automatic.&lt;/p&gt;
&lt;p&gt;This is where &lt;a href=&quot;https://mergify.io&quot;&gt;&lt;em&gt;Mergify&lt;/em&gt;&lt;/a&gt; comes into play. Mergify is a GitHub application allowing to define precise rules about how to merge your pull requests. Here&apos;s a rule that I use in every project:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pull_requests_rules:
  - name: automatic merge from dependabot
    conditions:
      - author~=^dependabot(|-preview)\[bot\]$
      - label!=work-in-progress
      - &quot;status-success=ci/circleci: pep8&quot;
      - &quot;status-success=ci/circleci: py37&quot;
    actions:
      merge:
        method: merge
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/Screenshot-2019-08-14-at-18.38.25.png&quot; alt=&quot;Mergify reports when the rule fully matches&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As soon as your continuous integration system passes, Mergify merges the pull request for you.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/Screenshot-2019-08-14-at-18.38.37.png&quot; alt=&quot;Screenshot of Mergify automatically merging a Dependabot pull request&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can then automatically trigger your deployment hooks to update your production deployment and get the new library version installed right away. This leaves your application always up-to-date with newer libraries and not lagging behind several years of releases.&lt;/p&gt;
&lt;p&gt;If anything goes wrong, you&apos;re still able to revert the commit from Dependabot — which you can also automate if you wish with a Mergify rule.&lt;/p&gt;
&lt;h2&gt;Beyond&lt;/h2&gt;
&lt;p&gt;This is to me the state of the art of dependency management lifecycle right now. And while this applies exceptionally well to Python, it can be applied to many other languages that use a similar pattern — such as Node and &lt;em&gt;npm&lt;/em&gt;.&lt;/p&gt;
</content:encoded><category>python</category><category>mergify</category><category>github</category></item><item><title>More GitHub workflow automation</title><link>https://julien.danjou.info/blog/automating-github-workflows/</link><guid isPermaLink="true">https://julien.danjou.info/blog/automating-github-workflows/</guid><description>The more you use computers, the more you see the potentials for automating everything. Who doesn&apos;t love that?</description><pubDate>Tue, 16 Oct 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The more you use computers, the more you see the potentials for automating everything. Who doesn&apos;t love that? By building &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; those last months, we&apos;ve decided it was time bring more automation to the development workflow.&lt;/p&gt;
&lt;p&gt;Mergify&apos;s first version was a &lt;em&gt;minimal viable product&lt;/em&gt; around automating the merge of pull requests. As &lt;a href=&quot;https://julien.danjou.info/blog/stop-merging-your-pull-request-manually&quot;&gt;I wrote a few months ago&lt;/a&gt;, we wanted to automate the merge of pull requests when it was ready to be merged. For most projects, this is easy and consists of a simple rule: &quot;it must be approved by a developer and pass the CI&quot;.&lt;/p&gt;
&lt;h2&gt;Evolving on Feedback&lt;/h2&gt;
&lt;p&gt;For the first few months, we received a lot of feedback from our users. They were enthusiastic about the product but were frustrated by a couple of things.&lt;/p&gt;
&lt;p&gt;First, Mergify would mess up with branch protections. We thought that people wanted the GitHub UI to match their rules. As I&apos;ll explain later, it turns out to be only partially true, and we found a workaround.&lt;/p&gt;
&lt;p&gt;Then, Mergify&apos;s abilities were capped by some of the limitations of the GitHub workflow and API. For example, GitHub would only allow rules per branch, whereas our users wanted to have rules applied based on a lot of different criteria.&lt;/p&gt;
&lt;h2&gt;Building the Next Engine&lt;/h2&gt;
&lt;p&gt;We rolled up our sleeves and started to build that new engine. The first thing was to get rid of the GitHub branch protection feature altogether and leveraging the Checks API to render something useful to the users in the UI. You can now have a complete overview of the rules that will be applied to your pull requests in the UI, making it easy to understand what&apos;s happening.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/10/1_6XA_yUbEHkgBs86cn31yOw.png&quot; alt=&quot;Screenshot of Mergify Checks API showing rule overview in the GitHub UI&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Then, we wrote a new matching engine that would allow matching any pull requests based on any of its attributes. You can now automate your workflow with a finer-grained configuration.&lt;/p&gt;
&lt;h2&gt;What Does It Look Like?&lt;/h2&gt;
&lt;p&gt;Here&apos;s a simple rule you could write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pull_request_rules:
  - name: automatic merge on approval and CI pass
    conditions:
     - &quot;#approved-reviews-by&amp;gt;=1&quot;
     - status-success=continuous-integration/travis-ci/pr
     - label!=work-in-progress
    actions:
      merge:
        method: merge
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that, any pull request that has been approved by a collaborator, passes the Travis CI job and does not have the label &lt;code&gt;work-in-progress&lt;/code&gt; will be automatically merged by Mergify.&lt;/p&gt;
&lt;p&gt;You could use even more &lt;a href=&quot;https://docs.mergify.io/actions/&quot;&gt;actions&lt;/a&gt; to backport this pull request to another branch, close the pull request or add/remove labels. We&apos;re starting to see users building amazing workflow with that engine!&lt;/p&gt;
&lt;p&gt;We&apos;re thrilled by this new version we launched this week and glad we&apos;re getting amazing feedback (again) from our users.&lt;/p&gt;
&lt;p&gt;When you give it a try, drop me a note and let me know what you think about it!&lt;/p&gt;
</content:encoded><category>mergify</category><category>github</category></item><item><title>How I stopped merging broken code</title><link>https://julien.danjou.info/blog/how-i-stopped-merging-broken-code/</link><guid isPermaLink="true">https://julien.danjou.info/blog/how-i-stopped-merging-broken-code/</guid><description>It&apos;s been a while since I moved all my projects to GitHub. It&apos;s convenient to host Git projects, and the collaboration workflow is smooth.</description><pubDate>Tue, 03 Jul 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It&apos;s been a while since I moved all my projects to &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt;. It&apos;s convenient to host Git projects, and the collaboration workflow is smooth.&lt;/p&gt;
&lt;p&gt;I love pull requests to merge code. I review them, I send them, I merge them. The fact that you can plug them into a continuous integration system is great and makes sure that you don&apos;t merge code that will break your software. I usually have &lt;a href=&quot;https://travis-ci.com&quot;&gt;Travis-CI&lt;/a&gt; setup and running my unit tests and code style check.&lt;/p&gt;
&lt;p&gt;The problem with the GitHub workflow is that it allows merging untested code.&lt;/p&gt;
&lt;p&gt;What?&lt;/p&gt;
&lt;p&gt;Yes, it does. If you think that your pull requests, all green decorated, are ready to be merged, you&apos;re wrong.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/07/Screen-Shot-2018-06-20-at-17.12.11.png&quot; alt=&quot;This might not be as good as you think&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You see, pull requests on GitHub are marked as valid as soon as the continuous integration system passes and indicates that everything is valid. However, if the target branch (let&apos;s say, &lt;code&gt;master&lt;/code&gt;) is updated while the pull request is opened, nothing forces to retest that pull request with this new &lt;code&gt;master&lt;/code&gt; branch. You think that the code in this pull request works while that might have become false.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/07/new-master-pr-ci-pass.png&quot; alt=&quot;Master moved, the pull request is not up to date though it&apos;s still marked as passing integration.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So it might be that what went into your &lt;code&gt;master&lt;/code&gt; branch now breaks this not-yet-merged pull request. You&apos;ve no clue. You&apos;ll trust GitHub and press that green merge button, and you&apos;ll break your software. For whatever reason, it&apos;s possible that the test will break.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/07/merge-ci-fail.png&quot; alt=&quot;If the pull request has not been updated with the latest version of its target branch, it might break your integration.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The good news is that&apos;s something that&apos;s solvable with the &lt;em&gt;strict workflow&lt;/em&gt; that &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; provides. There&apos;s a nice explanation and example in Mergify&apos;s blog post &lt;em&gt;&lt;a href=&quot;https://medium.com/@mergifyio/you-are-merging-untested-code-1b9f1a10d533&quot;&gt;You are merging untested code&lt;/a&gt;&lt;/em&gt; that I advise you to read. What Mergify provides here is a way to serialize the merge of pull requests while making sure that they are always updated with the latest version of their target branch. It makes sure that there&apos;s no way to merge broken code.&lt;/p&gt;
&lt;p&gt;That&apos;s a workflow I&apos;ve now adopted and automatized on all my repositories, and we&apos;ve been using such a workflow for &lt;a href=&quot;https://gnocchi.xyz&quot;&gt;Gnocchi&lt;/a&gt; for more than a year, with great success. Once you start using it, it becomes impossible to go back!&lt;/p&gt;
</content:encoded><category>mergify</category></item><item><title>Stop merging your pull requests manually</title><link>https://julien.danjou.info/blog/stop-merging-your-pull-request-manually/</link><guid isPermaLink="true">https://julien.danjou.info/blog/stop-merging-your-pull-request-manually/</guid><description>If there&apos;s something that I hate, it&apos;s doing things manually when I know I could automate them. Am I alone in this situation? I doubt so.  Nevertheless, every day, they are thousands of developers usi</description><pubDate>Wed, 20 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If there&apos;s something that I hate, it&apos;s doing things manually when I know I could automate them. Am I alone in this situation? I doubt so.&lt;/p&gt;
&lt;p&gt;Nevertheless, every day, they are thousands of developers using &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; that are doing the same thing over and over again: they click on this button:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/06/Screen-Shot-2018-06-19-at-18.12.39.png&quot; alt=&quot;Screen-Shot-2018-06-19-at-18.12.39&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This does not make any sense.&lt;/p&gt;
&lt;p&gt;Don&apos;t get me wrong. It makes sense to merge pull requests. It just does not make sense that someone has to push this damn button every time.&lt;/p&gt;
&lt;p&gt;It does not make any sense because every development team in the world has a known list of pre-requisite before they merge a pull request. Those requirements are almost always the same, and it&apos;s something along those lines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the test suite passing?&lt;/li&gt;
&lt;li&gt;Is the documentation up to date?&lt;/li&gt;
&lt;li&gt;Does this follow our code style guideline?&lt;/li&gt;
&lt;li&gt;Have N developers reviewed this?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As this list gets longer, the merging process becomes more error-prone. &quot;Oops, John just clicked on the merge button while there were not enough developer that reviewed the patch.&quot; Rings a bell?&lt;/p&gt;
&lt;p&gt;In my team, we&apos;re like every team out there. We know what our criteria to merge some code into our repository are. That&apos;s why we set up a continuous integration system that runs our test suite each time somebody creates a pull request. We also require the code to be reviewed by 2 members of the team before it&apos;s approbated.&lt;/p&gt;
&lt;p&gt;When those conditions are all set, I want the code to be merged.&lt;/p&gt;
&lt;p&gt;Without clicking a single button.&lt;/p&gt;
&lt;p&gt;That&apos;s exactly how &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; started.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/06/github-branching-1.png&quot; alt=&quot;github-branching-1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; is a service that pushes that merge button for you. You define rules in the &lt;code&gt;.mergify.yml&lt;/code&gt; file of your repository, and when the rules are satisfied, Mergify merges the pull request.&lt;/p&gt;
&lt;p&gt;No need to press any button.&lt;/p&gt;
&lt;p&gt;Take a random pull request, like this one:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/06/Screen-Shot-2018-06-20-at-17.12.11.png&quot; alt=&quot;Screen-Shot-2018-06-20-at-17.12.11&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This comes from a small project that does not have a lot of continuous integration services set up, just Travis. In this pull request, everything&apos;s green: one of the owners reviewed the code, and the tests are passing. Therefore, the code should be already merged: but it&apos;s there, hanging, chilling, waiting for someone to push that merge button. Someday.&lt;/p&gt;
&lt;p&gt;With &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; enabled, you&apos;d just have to put this &lt;code&gt;.mergify.yml&lt;/code&gt; a the root of the repository:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rules:
  default:
    protection:
      required_status_checks:
        contexts:
          - continuous-integration/travis-ci
      required_pull_request_reviews:
        required_approving_review_count: 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With such a configuration, &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; enables the desired restrictions, i.e., Travis passes, and at least one project member reviewed the code. As soon as those conditions are positive, the pull request is automatically merged.&lt;/p&gt;
&lt;p&gt;We built &lt;a href=&quot;https://mergify.io&quot;&gt;Mergify&lt;/a&gt; as a &lt;strong&gt;free service for open-source projects&lt;/strong&gt;. The &lt;a href=&quot;https://github.com/mergifyio/mergify-engine&quot;&gt;engine powering the service&lt;/a&gt; is also open-source.&lt;/p&gt;
&lt;p&gt;Now go &lt;a href=&quot;https://mergify.io&quot;&gt;check it out&lt;/a&gt; and stop letting those pull requests hang out one second more. Merge them!&lt;/p&gt;
&lt;p&gt;If you have any question, feel free to ask us or write a comment below! And stay tuned — as Mergify offers a few other features that I can&apos;t wait to talk about!&lt;/p&gt;
</content:encoded><category>mergify</category></item><item><title>A safe GitHub workflow with Pastamaker</title><link>https://julien.danjou.info/blog/pastamaker/</link><guid isPermaLink="true">https://julien.danjou.info/blog/pastamaker/</guid><description>When the Gnocchi project decided to move to GitHub, we developers had to move from a Gerrit based workflow to a GitHub pull-request one.</description><pubDate>Fri, 15 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When the &lt;a href=&quot;https://gnocchi.xyz&quot;&gt;Gnocchi&lt;/a&gt; project decided to move to &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt;, we developers had to move from a Gerrit based workflow to a GitHub pull-request one.&lt;/p&gt;
&lt;p&gt;This has been challenging in some ways. We were satisfied with the workflow we had using Gerrit and &lt;a href=&quot;https://docs.openstack.org/infra/zuul/&quot;&gt;Zuul&lt;/a&gt; for testing so we decided to adapt GitHub to our requirements.&lt;/p&gt;
&lt;p&gt;We know that Zuul now supports GitHub. However, that implies having your own testing infrastructure, something we can&apos;t afford. Instead, we rely on &lt;a href=&quot;http://travis-ci.org&quot;&gt;Travis&lt;/a&gt;, like most open-source projects hosted on GitHub.&lt;/p&gt;
&lt;h2&gt;The workflow&lt;/h2&gt;
&lt;p&gt;The workflow we wanted to have was the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A contributor creates a pull-request on GitHub.&lt;/li&gt;
&lt;li&gt;The pull-request is tested by Travis.&lt;/li&gt;
&lt;li&gt;The pull-request is reviewed by approved projects members.&lt;/li&gt;
&lt;li&gt;If the tests pass and two reviewers have approved the pull-request, then it&lt;br /&gt;
can be merged.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This sounds simple, but it is actually not &lt;em&gt;that&lt;/em&gt; simple.&lt;/p&gt;
&lt;p&gt;First, when Travis tests the pull-request, it checks what has been sent by the contributor. If the contributor created a pull-request on top of an outdated version of the base branch, that&apos;s what will be tested by Travis during the initial pull-request creation.&lt;/p&gt;
&lt;p&gt;Even if the pull-request has been created using the tip of the base branch, as time passes, the base branch will progress. However, the pull-request created by your contributor will not get those new commits – unless rebased manually.&lt;/p&gt;
&lt;p&gt;That means the Travis tests result is now outdated invalid. Still, GitHub and Travis will both show you that this pull-request passed all tests – yes it &lt;em&gt;did&lt;/em&gt; but with an old base branch from a while back!&lt;/p&gt;
&lt;p&gt;If you added new tests in the meantime in your base branch, it&apos;s possible that this pull-request does not work anymore. Pressing the &lt;em&gt;merge&lt;/em&gt; button might just break your project!&lt;/p&gt;
&lt;p&gt;To help with that problem, GitHub recently added a button that allows you to &lt;em&gt;base branch into the pull-request&lt;/em&gt;. That allows, in one click, to get the pull-requested updated with the base branch (e.g., &lt;em&gt;master&lt;/em&gt;) and retested by Travis.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/github-update-pr-button.png&quot; alt=&quot;github-update-pr-button&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Still, this means that if you have ten pull-requests, you need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Merge base branch into PR#1&lt;/li&gt;
&lt;li&gt;Wait for Travis to pass&lt;/li&gt;
&lt;li&gt;Wait for two reviewers to approve&lt;/li&gt;
&lt;li&gt;Merge PR#1&lt;/li&gt;
&lt;li&gt;All other nine pull-requests are not out of date. You need to do start back at operation 1. for each pull-request.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is very tedious to do manually, especially when your projects has tons of pull-requests.&lt;/p&gt;
&lt;p&gt;This is why &lt;a href=&quot;http://blog.sileht.net&quot;&gt;Mehdi Abaakouk&lt;/a&gt; created &lt;a href=&quot;http://github.com/sileht/pastamaker&quot;&gt;Pastamaker&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Pastamaker to the rescue&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/sileht/pastamaker&quot;&gt;Pastamaker&lt;/a&gt; is a small Web application that implements the described workflow. Once connected to your GitHub project, it will set the proper permissions to protect it for accidental manual merge and force the workflow above to be followed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/pastamaker-pr-1.png&quot; alt=&quot;pastamaker-pr-1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Pastamaker listens for GitHub and Travis events to track the state of each pull-request. If it detects that a pull-request has been approved by two reviewers and that the initial Travis test run passed, it will merge the base branch if needed in it, wait for Travis to pass again, and then finally merge it.&lt;/p&gt;
&lt;p&gt;If multiple pull-requests are approved at the same time and are candidates for a merge, it will order them, update once at a time, wait for Travis results and merge them if they pass. It essentially automates the workflow described above.&lt;/p&gt;
&lt;p&gt;Pastamaker exposes its data via a simple dashboard, which allows seeing all the pull-requests for your project in a snap.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/pastamaker.png&quot; alt=&quot;pastamaker&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Pastamaker offers a lot of tiny other details that make the developers lives easier, such as posting the job result with direct links to the jobs logs in the pull-request – so you&apos;re informed as soon as they pass or fail and can fix them right away!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/sileht/pastamaker&quot;&gt;Pastamaker&lt;/a&gt; is obviously open-source, and we would love to see you give it a try!&lt;/p&gt;
</content:encoded><category>mergify</category><category>github</category></item></channel></rss>