<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Christian Holländer</title>
    <description>The latest articles on DEV Community by Christian Holländer (@christian98).</description>
    <link>https://dev.to/christian98</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F345318%2F0d320a2b-dcc5-4bde-8481-80ec0be1d666.JPG</url>
      <title>DEV Community: Christian Holländer</title>
      <link>https://dev.to/christian98</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christian98"/>
    <language>en</language>
    <item>
      <title>MongoDB vs MySQL: A Real-World Performance Showdown Using Disneyland Data</title>
      <dc:creator>Christian Holländer</dc:creator>
      <pubDate>Thu, 25 Sep 2025 11:40:40 +0000</pubDate>
      <link>https://dev.to/christian98/mongodb-vs-mysql-a-real-world-performance-showdown-using-disneyland-data-1i07</link>
      <guid>https://dev.to/christian98/mongodb-vs-mysql-a-real-world-performance-showdown-using-disneyland-data-1i07</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally posted over on my personal website. Maybe you want to check it out &lt;a href="https://christian-hollaender.de/posts/5-mongodb-vs-mysql-a-real-world-performance-showdown-using-disneyland-data" rel="noopener noreferrer"&gt;[HERE]&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;MongoDB vs MySQL head-to-head: We benchmarked both databases with real Disneyland data. MongoDB won writes by 67% and some queries by 98%, but MySQL had surprises too!&lt;/p&gt;




&lt;p&gt;When choosing a database for your next project, performance benchmarks often feel abstract and disconnected from real-world scenarios. That's why our recent university project comparing MongoDB and MySQL using actual Disneyland visitor data provides such valuable insights – we tested both databases against the same complex dataset with realistic use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dataset: Perfect for Database Testing
&lt;/h2&gt;

&lt;p&gt;We used a comprehensive Disneyland Paris dataset that presented real analytical challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wait times&lt;/strong&gt; for 37 attractions (2018-2019)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily attendance&lt;/strong&gt; data (2018-2022)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weather conditions&lt;/strong&gt; (1999-2022)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Park operational schedules&lt;/strong&gt; (2018-2022)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dataset was ideal for performance testing because it required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-frequency writes (weather data every hour, wait times every 15 minutes)&lt;/li&gt;
&lt;li&gt;Complex aggregations across multiple data sources&lt;/li&gt;
&lt;li&gt;Time-series analysis&lt;/li&gt;
&lt;li&gt;JOIN operations between related data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database Setup: Fair Fight Conditions
&lt;/h2&gt;

&lt;p&gt;To ensure a fair comparison, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identical hardware&lt;/strong&gt;: Same server (20GB RAM, 6 CPU cores, HDD storage)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Equivalent indexing&lt;/strong&gt;: Created the same indexes on both systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized schema&lt;/strong&gt;: Normalized data structure for MySQL, embedded documents for MongoDB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same queries&lt;/strong&gt;: Translated identical business logic between SQL and MongoDB aggregation pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Schema Differences
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;MySQL&lt;/strong&gt;: Traditional normalized approach with separate tables for weather descriptions, linked via foreign keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;: Document-based approach with embedded weather objects, eliminating the need for joins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Results: The Numbers Don't Lie
&lt;/h2&gt;

&lt;p&gt;We ran each query 100 times sequentially to get reliable averages. Here are the results:&lt;/p&gt;

&lt;h3&gt;
  
  
  Write Operations (Data Insertion)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;MongoDB Advantage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Weather Data Insert&lt;/td&gt;
&lt;td&gt;56.7ms&lt;/td&gt;
&lt;td&gt;19.6ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;65.4% faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wait Times Insert&lt;/td&gt;
&lt;td&gt;59.2ms&lt;/td&gt;
&lt;td&gt;19.3ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;67.4% faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attendance Insert&lt;/td&gt;
&lt;td&gt;57.2ms&lt;/td&gt;
&lt;td&gt;19.3ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;66.2% faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedule Insert&lt;/td&gt;
&lt;td&gt;57.7ms&lt;/td&gt;
&lt;td&gt;28.4ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50.7% faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: MongoDB consistently outperformed MySQL for write operations, often by more than 2:1 ratios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read Operations (Analytics Queries)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Query Type&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;RQ1&lt;/strong&gt;: Average wait times by attraction&lt;/td&gt;
&lt;td&gt;52.6 seconds&lt;/td&gt;
&lt;td&gt;1.0 seconds&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MongoDB (98.1% faster)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;RQ2&lt;/strong&gt;: Attendance by weather conditions&lt;/td&gt;
&lt;td&gt;413ms&lt;/td&gt;
&lt;td&gt;20.7 seconds&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MySQL (98% faster)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;RQ3&lt;/strong&gt;: Wait times vs weather correlation&lt;/td&gt;
&lt;td&gt;1h 12m 37s&lt;/td&gt;
&lt;td&gt;5ms*&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;RQ4&lt;/strong&gt;: Holiday vs regular attendance&lt;/td&gt;
&lt;td&gt;66.3ms&lt;/td&gt;
&lt;td&gt;58.5ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MongoDB (11.7% faster)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;*MongoDB query completed quickly, MySQL query failed after 4+ hours&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What These Results Actually Mean
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MongoDB's Strengths Revealed
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple Aggregations&lt;/strong&gt;: The 98% performance advantage in RQ1 shows MongoDB's aggregation pipeline excels at straightforward grouping and averaging operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Time-Based Queries&lt;/strong&gt;: RQ3's dramatic difference (MySQL took over an hour, MongoDB completed in milliseconds) demonstrates MongoDB's superiority for complex temporal correlations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write-Heavy Workloads&lt;/strong&gt;: Consistent 50-67% faster write performance makes MongoDB ideal for real-time data ingestion scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  MySQL's Surprising Victory
&lt;/h3&gt;

&lt;p&gt;RQ2 (weather-based attendance analysis) was 98% faster in MySQL. This query required complex temporary table operations and multiple data source correlations – an area where SQL's mature optimization still shines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Why Behind the Performance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MongoDB Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No JOIN overhead&lt;/strong&gt;: Embedded documents eliminate expensive table joins&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized aggregation pipeline&lt;/strong&gt;: Purpose-built for analytical workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible indexing&lt;/strong&gt;: Better suited for document-based queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema flexibility&lt;/strong&gt;: No rigid structure constraints during writes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MySQL Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mature query optimization&lt;/strong&gt;: Decades of SQL optimizer improvements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient temporary operations&lt;/strong&gt;: Better handling of complex intermediate results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory management&lt;/strong&gt;: Superior for certain multi-table operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Application Insights
&lt;/h2&gt;

&lt;p&gt;Based on our findings, choose:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB when you have:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-frequency data ingestion (IoT sensors, real-time analytics)&lt;/li&gt;
&lt;li&gt;Time-series data analysis&lt;/li&gt;
&lt;li&gt;Simple to moderate aggregation needs&lt;/li&gt;
&lt;li&gt;Schema evolution requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MySQL when you have:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex multi-source data correlations&lt;/li&gt;
&lt;li&gt;Heavy use of temporary tables and complex JOINs&lt;/li&gt;
&lt;li&gt;Mature application ecosystems expecting SQL&lt;/li&gt;
&lt;li&gt;Strict consistency requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Unexpected Learning: Context Matters
&lt;/h2&gt;

&lt;p&gt;The most valuable insight wasn't that one database is universally better – it's that &lt;strong&gt;workload characteristics determine the winner&lt;/strong&gt;. MongoDB dominated write operations and simple aggregations by massive margins, while MySQL excelled at complex relational operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Optimization Lessons
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Index Strategy&lt;/strong&gt;: Both databases benefited equally from proper indexing on date fields and frequently queried attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Query Design&lt;/strong&gt;: MongoDB's aggregation pipelines required different thinking than SQL, but often resulted in more maintainable code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hardware Considerations&lt;/strong&gt;: Even on modest hardware (HDD storage), the performance differences were dramatic, suggesting they'd be even more pronounced on modern SSD systems.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bottom Line for Database Selection
&lt;/h2&gt;

&lt;p&gt;Don't choose a database based on hype or familiarity alone. Our Disneyland data analysis proved that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write-heavy applications&lt;/strong&gt;: MongoDB provides substantial advantages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex analytical queries&lt;/strong&gt;: Results vary dramatically by query type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixed workloads&lt;/strong&gt;: Consider using both databases for different use cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 98% performance differences we observed aren't edge cases – they represent real-world scenarios that could mean the difference between a responsive application and one that frustrates users.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This performance analysis was conducted as part of a Modern Database Systems course at TH Köln. The complete benchmark code and query implementations are available &lt;a href="https://gitlab.com/christian98-uni/mds" rel="noopener noreferrer"&gt;here&lt;/a&gt; for those interested in replicating these tests.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>mysql</category>
      <category>mongodb</category>
      <category>performance</category>
    </item>
    <item>
      <title>eBPF vs Sidecar Monitoring: What We Learned Building Both</title>
      <dc:creator>Christian Holländer</dc:creator>
      <pubDate>Sun, 13 Jul 2025 10:25:39 +0000</pubDate>
      <link>https://dev.to/christian98/ebpf-vs-sidecar-monitoring-what-we-learned-building-both-34m4</link>
      <guid>https://dev.to/christian98/ebpf-vs-sidecar-monitoring-what-we-learned-building-both-34m4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally posted over on my personal website. Maybe you want to check it out &lt;a href="https://christian-hollaender.de/posts/3-ebpf-vs-sidecar-monitoring-what-we-learned-building-both" rel="noopener noreferrer"&gt;[HERE]&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;We tried to replace sidecar monitoring with eBPF in Kubernetes. Spoiler: it didn't go as planned. Here's what we learned about hype vs reality in cloud-native monitoring, and when cutting-edge tech isn't always the answer.&lt;/p&gt;




&lt;p&gt;Last semester, my team and I embarked on an ambitious project: comparing eBPF-based monitoring with traditional sidecar proxy monitoring in Kubernetes clusters. What started as academic curiosity turned into a deep dive into kernel programming, developer experience, and the realities of cutting-edge technology adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Promise of eBPF
&lt;/h2&gt;

&lt;p&gt;Extended Berkeley Packet Filter (eBPF) has been making waves in the cloud-native world. The promise is compelling: instead of deploying a sidecar container in every pod to monitor network traffic, you can run a single eBPF program in the kernel that observes everything on the node. It sounds like magic—lower resource overhead, better security visibility, and simplified deployments.&lt;/p&gt;

&lt;p&gt;But is it really better? That's what we set out to discover.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Traditional Approach: Sidecar Proxies
&lt;/h2&gt;

&lt;p&gt;Before diving into eBPF, let's talk about how monitoring typically works today. The sidecar pattern has become the go-to approach for microservice monitoring. Tools like Envoy proxy sit alongside your application in the same pod, intercepting all network traffic and providing rich telemetry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The good parts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Well-understood deployment patterns&lt;/li&gt;
&lt;li&gt;Rich ecosystem of tools and integrations&lt;/li&gt;
&lt;li&gt;Isolated from the host system&lt;/li&gt;
&lt;li&gt;Language and framework agnostic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The not-so-good parts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource overhead multiplied across every pod&lt;/li&gt;
&lt;li&gt;Additional complexity in pod configurations&lt;/li&gt;
&lt;li&gt;Potential single points of failure&lt;/li&gt;
&lt;li&gt;Network latency from additional hops&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Our eBPF Experiment
&lt;/h2&gt;

&lt;p&gt;We decided to build two functionally identical network monitors: one using the traditional sidecar approach and another using eBPF. Our goal was simple—track HTTP request timing and response sizes for services communicating in a Kubernetes cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Reality Check
&lt;/h3&gt;

&lt;p&gt;Here's where things got interesting (read: frustrating). While the sidecar implementation was straightforward, the eBPF version became a lesson in humility.&lt;/p&gt;

&lt;p&gt;We chose Rust with the Aya framework, hoping to avoid the typical C development complexity associated with eBPF. The initial setup was smooth—Aya's templates got us started quickly. But implementing HTTP monitoring? That's where we hit the wall.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Technical Challenges
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Memory Constraints&lt;/strong&gt;: eBPF programs are limited to a 512-byte stack. Try parsing HTTP payloads with that constraint. Every function call needs to be carefully designed to avoid stack overflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verifier&lt;/strong&gt;: eBPF's safety verifier is both a blessing and a curse. It prevents crashes and security issues, but it's incredibly strict about memory access patterns. We spent countless hours fighting "invalid memory access" errors even with proper bounds checking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limited Debugging&lt;/strong&gt;: Forget about your favorite debugger. eBPF debugging involves a lot of &lt;code&gt;bpf_printk()&lt;/code&gt; statements and careful reading of verifier logs. The development experience feels like programming in the 1990s.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ecosystem Maturity&lt;/strong&gt;: While there are excellent eBPF tools like Pixie and Cilium, rolling your own solution requires deep kernel knowledge. The learning curve is steep, and the documentation assumes significant background knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Actually Discovered
&lt;/h2&gt;

&lt;p&gt;After weeks of development, we had to face facts: we couldn't complete our eBPF HTTP monitor in the timeframe. But this "failure" taught us valuable lessons.&lt;/p&gt;

&lt;h3&gt;
  
  
  eBPF Isn't Magic
&lt;/h3&gt;

&lt;p&gt;The hype around eBPF is real, but it's not a silver bullet. It excels at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low-level network analysis&lt;/li&gt;
&lt;li&gt;System-wide visibility&lt;/li&gt;
&lt;li&gt;Performance monitoring&lt;/li&gt;
&lt;li&gt;Security enforcement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But for application-layer monitoring like HTTP request tracing? The traditional approaches are often more practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Developer Experience Gap
&lt;/h3&gt;

&lt;p&gt;Moving from sidecar configuration to eBPF programming shifts the burden from operations teams to developers. This isn't necessarily bad, but it requires different skills. You're essentially doing kernel programming, which most application developers haven't done since their systems programming course.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Choose What
&lt;/h3&gt;

&lt;p&gt;Based on our experience, here's our take:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose eBPF when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need system-wide visibility&lt;/li&gt;
&lt;li&gt;Performance overhead is critical&lt;/li&gt;
&lt;li&gt;You're building infrastructure tools&lt;/li&gt;
&lt;li&gt;Your team has kernel programming expertise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stick with sidecars when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need application-layer insights&lt;/li&gt;
&lt;li&gt;Your team values quick iteration&lt;/li&gt;
&lt;li&gt;You want mature tooling and support&lt;/li&gt;
&lt;li&gt;Operational simplicity matters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;Our experiment confirmed something important: technology choices aren't just about technical capabilities—they're about team capabilities, operational complexity, and long-term maintainability.&lt;/p&gt;

&lt;p&gt;eBPF is incredibly powerful, but with great power comes great complexity. For most teams monitoring microservices, mature solutions like Envoy proxy or ready-made eBPF tools like Pixie offer the best balance of capability and usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prototype early&lt;/strong&gt;: We should have built a minimal eBPF program first to understand the constraints before committing to a complex implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverage existing tools&lt;/strong&gt;: Unless you have specific requirements, using battle-tested solutions like Cilium or Pixie is probably smarter than rolling your own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider the total cost&lt;/strong&gt;: The "cost" of a technology includes development time, debugging complexity, and ongoing maintenance—not just runtime overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Know your use case&lt;/strong&gt;: eBPF shines for infrastructure and low-level monitoring, but application-layer observability might be better served by traditional approaches.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;While our eBPF monitor didn't cross the finish line, the experience was invaluable. We gained deep insights into kernel programming, network monitoring, and the practical challenges of adopting cutting-edge technology.&lt;/p&gt;

&lt;p&gt;eBPF is undoubtedly the future of many aspects of systems programming. But like any powerful technology, it requires careful consideration of when and how to apply it. Sometimes the boring, well-understood solution is exactly what you need.&lt;/p&gt;

&lt;p&gt;For teams considering eBPF for monitoring, my advice is simple: start with existing tools, understand your specific requirements, and be prepared for a steep learning curve if you decide to build custom solutions.&lt;/p&gt;

&lt;p&gt;The future of cloud-native monitoring is exciting, but it's built on a foundation of understanding both the possibilities and the trade-offs of the tools at our disposal.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post is based on research conducted as part of a university project exploring eBPF applications in Kubernetes environments. While our implementation didn't reach completion, the insights gained about technology adoption and developer experience proved invaluable.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to create a shared Prettier configuration</title>
      <dc:creator>Christian Holländer</dc:creator>
      <pubDate>Fri, 14 Oct 2022 13:13:25 +0000</pubDate>
      <link>https://dev.to/christian98/how-to-create-a-shared-prettier-configuration-3284</link>
      <guid>https://dev.to/christian98/how-to-create-a-shared-prettier-configuration-3284</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally posted over on my personal website. Maybe you want to check it out &lt;a href="https://christian-hollaender.de/posts/2-how-to-create-a-shared-prettier-configuration"&gt;[HERE]&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Keeping configs for styling and linting tools consistent across multiple projects can be challenging. Many tools support shared configs, which are created once and used everywhere. This article will discover how to create a shared configuration for prettier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Recently we decided, that we want to have a common styling on how to write our Typescript code. This would make it easier for us to read and understand code others had written or even that we have written ourselves a few months ago. Therefore we agreed on integrating &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt;. An opinionated code formatter.&lt;/p&gt;

&lt;p&gt;When we first adopted prettier on all our dozens of projects we copy/pasted the configuration from one project to the other. As we updated the config to fit our needs we were faced with inconsistent options in our projects. So we needed to figure out, how to change the prettier options globally for all our projects at the same time. Luckily the prettier maintainers got you covered. They already thought of that problem and provide a native way to share the config across multiple projects by creating a separate npm package. (&lt;a href="https://prettier.io/docs/en/configuration.html#sharing-configurations"&gt;Sharing Configurations&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In this guide, I want to show you how we structured our shared config to meet several projects with different prettier plugins, like the phenomenal &lt;a href="https://github.com/tailwindlabs/prettier-plugin-tailwindcss"&gt;Tailwind Prettier plugin&lt;/a&gt;. But also to make it extensible if a project needs some special config options only for this specific project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;First of all, we need to initialize our repository. As I love typescript I wanted that the shared config itself is written in typescript and gets transpiled to javascript through a built-step. I will do this by using Rollup.js, but Webpack should do the trick as well. So let’s get started..&lt;/p&gt;

&lt;p&gt;Installing Typescript should be straightforward by running &lt;code&gt;npm i -D typescript&lt;/code&gt; and creating a &lt;code&gt;tsconfig.json&lt;/code&gt; in the project root. I am using this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ESNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"importHelpers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"experimentalDecorators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"emitDecoratorMetadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowSyntheticDefaultImports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sourceMap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declaration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declarationDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist/types"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declarationMap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resolveJsonModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typeRoots"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/@types"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"es2015"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"es2017"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.ts"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I want to initialize the Rollup.js setup by adding the &lt;code&gt;rollup.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;excludeDependenciesFromBundle&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-exclude-dependencies-from-bundle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-node-resolve&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;commonjs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-commonjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;typescript&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-typescript2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visualizer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-visualizer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// eslint-disable-next-line @typescript-eslint/no-var-requires&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;packageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/index.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inlineDynamicImports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;sourcemap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;excludeDependenciesFromBundle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;commonjs&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;typescript&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;useTsconfigDeclarationDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="nx"&gt;visualizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package-deps.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sunburst&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;gzipSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;brotliSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I will skip the installation of the necessary dependencies, as I think you already know how to do this when you are interested in creating a shared prettier config ;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we are finally ready to actually create the shared config in our &lt;code&gt;src&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prettier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;singleQuote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;bracketSameLine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tabWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.{json,yml,yaml}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;tabWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.{yml,yaml}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;singleQuote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;bracketSpacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last but not least I want to show you a cool little trick to use the just-built config right in this project. When do this by creating a &lt;code&gt;prettier.config.js&lt;/code&gt; file in our project root. In there we put the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('prettier').Options} */&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dist/prettier-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are actually just importing our build module and re-export it so our prettier command can find it. But note: You need to build before you can apply the changes of the shared config to the project because there is a built-step involved!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automatic Package Releases using Semantic-Release</title>
      <dc:creator>Christian Holländer</dc:creator>
      <pubDate>Sat, 24 Sep 2022 21:08:23 +0000</pubDate>
      <link>https://dev.to/christian98/automatic-package-releases-using-semantic-release-8k1</link>
      <guid>https://dev.to/christian98/automatic-package-releases-using-semantic-release-8k1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post was originally posted over on my personal website. Maybe you want to check it out &lt;a href="https://christian-hollaender.de/posts/1-automatic-package-releases-using-semantic-release"&gt;[HERE]&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Writing the release notes and Changelog manually is a time-consuming and complicated task. And then you need to push your new release to your desired Package-registry like NPM or Packagist. Fortunately, there is a better way to do this. Join me in discovering an alternative.&lt;/p&gt;




&lt;p&gt;When you already maintained an open-source package or developed a package at work, you might know how complicated the job of releasing a new version can be. Most of the time the process contains the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scim all Commits, Issues, and PRs to see what changed&lt;/li&gt;
&lt;li&gt;Create a list of the previously collected changes for your Changelog and Release-Notes&lt;/li&gt;
&lt;li&gt;Decide if you want to create a patch, minor or major release (and probably have to ask the author of the changes)&lt;/li&gt;
&lt;li&gt;If your package provides the version to its users, update it&lt;/li&gt;
&lt;li&gt;Add a new Git tag to the repository and let your CI/CD build one last time&lt;/li&gt;
&lt;li&gt;Push the newly built package to the Registry of your liking (don't forget to authenticate 😉)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Fortunately, there is an easy way to automate all of this. It's called CI/CD. Personally, I use Gitlab CI/CD as all my Code is hosted on Gitlab. But Github Actions and other providers should work similarly. So now we need to think about how we can achieve all our tasks in an automated manner. We as developers are lazy people, so writing a bunch of bash scripts all ourselves is not really an option. Luckily there is a tool we can use to help out:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://github.com/semantic-release/semantic-release"&gt;Semantic-Release&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Semantic-Release is a tool that automates most of the hard tasks needed to release a new version of our package. It actually can also release new versions of our application, but that is a bit more difficult. Its plugin system makes it easy and extendable for multiple package managers and steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  So let's get started:
&lt;/h3&gt;

&lt;p&gt;For this example we want to publish a new NPM package as this is the easiest, to begin with.&lt;/p&gt;

&lt;p&gt;First, install the necessary packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; semantic-release @semantic-release/git @semantic-release/gitlab @semantic-release/npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I installed the main package &lt;code&gt;semantic-release&lt;/code&gt; with some plugins that I need for my setup. There is a good list of official and community plugins on the documentation page of the project: &lt;a href="https://semantic-release.gitbook.io/semantic-release/extending/plugins-list"&gt;https://semantic-release.gitbook.io/semantic-release/extending/plugins-list&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also add a script section to your &lt;code&gt;package.json&lt;/code&gt;. For me, it was actually necessary. Otherwise, I could not run the command inside my CI/CD environment. Because it was not in my &lt;code&gt;PATH&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"semantic-release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"semantic-release"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we can run Semantic Release, we need to configure the project so that releasing works. This is especially important if you don't want to push a package into the normal NPM registry, but want to use the GitLab registry as I do.&lt;br&gt;
For this, we have to adjust the "publishConfig" in the &lt;code&gt;package.json&lt;/code&gt;. Enter there the URL of your registry. For me, this is the project-specific URL of the GitLab registry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publishConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@&amp;lt;package-scope&amp;gt;:registry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://gitlab.com/api/v4/projects/&amp;lt;gitlab-project-id&amp;gt;/packages/npm/"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Do not set the &lt;code&gt;private&lt;/code&gt; attribute in your &lt;code&gt;package.json&lt;/code&gt; to true, even though it is an internal/private package. This will prevent Semantic-Release from publishing your package to ANY registry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that, we still need to authenticate against our internal registry. For this, we use the so-called &lt;code&gt;.npmrc&lt;/code&gt; file. In this file, we configure our package scope with a target URL and a personal access token for authentication. I found it easiest to put the scope definition directly into the repo. The token setting must never happen in the repo, otherwise, you expose the token to possibly unauthorized third parties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@&amp;lt;package-scope&amp;gt;:registry=https://gitlab.com/api/v4/projects/&amp;lt;gitlab-project-id&amp;gt;/packages/npm/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can set your personal access token for local development in your &lt;code&gt;~/.npmrc&lt;/code&gt; file. This way you can also authenticate in other projects on your machine and you do not accidentally commit your token to the repo. You can do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//gitlab.com/api/v4/packages/npm/:_authToken=&amp;lt;access-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Yes the syntax with the &lt;code&gt;//&lt;/code&gt; at the beginning is correct. It is rather strange, but this is how it is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As we also need the token in our CI/CD we need to set this inside our pipeline job. I did this like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/"&amp;gt;.npmrc&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "${CI_API_V4_URL#https?}/packages/npm/:_authToken=${CI_JOB_TOKEN}"&amp;gt;&amp;gt;.npmrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I completely overwrite the &lt;code&gt;.npmrc&lt;/code&gt; with variables provided by the CI environment. The nice thing about GitLab is, that it already provides all necessary tokens and URLs. I'll show the complete Job-configuration later on.&lt;/p&gt;

&lt;p&gt;Now that we configured everything for NPM to publish a package, we also need to configure Semantic-Release so that we can trigger the releases correctly. Therefore we can use a variety of file formats. The most popular ones are JSON and Javascript. You can find out more &lt;a href="https://semantic-release.gitbook.io/semantic-release/usage/configuration#configuration-file"&gt;here&lt;/a&gt;. For this demo I chose &lt;code&gt;release.config.js&lt;/code&gt; cause it gives us the most dynamic way to configure Semantic-Release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import("semantic-release").Options } */&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@semantic-release/commit-analyzer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@semantic-release/release-notes-generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@semantic-release/gitlab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@semantic-release/npm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;branches&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+([0-9])?(.{+([0-9]),x}).x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-major&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beta&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;prerelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alpha&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;prerelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Configuring the branches is currently only necessary because we already use the new git naming for our default branch "main". If you are still using "master", you won't need to configure them.&lt;/p&gt;

&lt;p&gt;If you are using TypeScript like me, you can also install &lt;code&gt;@types/semantic-release&lt;/code&gt; and use the shown type doc, to get autocompletion in most IDEs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Add CI job
&lt;/h2&gt;

&lt;p&gt;Last but not least we need to configure our already mentioned CI-Job. This depends on your environment. As I am using Gitlab-CI/CD I can only show how this works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:18.7&lt;/span&gt;
  &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
  &lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/"&amp;gt;.npmrc&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "${CI_API_V4_URL#https?}/packages/npm/:_authToken=${CI_JOB_TOKEN}"&amp;gt;&amp;gt;.npmrc&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm run semantic-release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing you will also need to set is an environment Token called: &lt;code&gt;GITLAB_TOKEN&lt;/code&gt;. This is needed for the Gitlab-plugin and to be able to upload Releases to Gitlab. You can find these in the left menu under &lt;code&gt;Deployments &amp;gt; Releases&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow
&lt;/h3&gt;

&lt;p&gt;To use this automatic release setup, you need to use a special Commit syntax. It is actually quite simple, but you need to memorize all the different keys. Like if you write a commit message like &lt;code&gt;feat: some dope new feature&lt;/code&gt;, Semantic-Release will trigger a minor update of your package. If you use &lt;code&gt;fix: some small bug fix&lt;/code&gt;, it will trigger a patch release. You can also always do a major release by adding &lt;code&gt;BREAKING CHANGE: Description what changes.&lt;/code&gt; to your commit. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat: we added a non backward compatible change

BREAKING CHANGE: Please now use this and that.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This should be it. Now you are all set to automatically release your package with the special Commit-Syntax.&lt;br&gt;
If you want to know more I highly suggest reading through the amazing &lt;a href="https://semantic-release.gitbook.io/semantic-release/"&gt;documentation&lt;/a&gt;. I have already mentioned it here and there throughout this post.&lt;/p&gt;

&lt;p&gt;And now the only thing left is to say thank you for reading!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
