GoulvenClech

GoulvenClech

Sampo - automate changelogs, versioning, and publishing for Elixir (and multi-ecosystem monorepos)

Hey everyone :waving_hand:

I’m excited to share Sampo, a tool suite to automate changelogs, versioning, and publishing—even for monorepos across multiple package registries. It now supports Elixir (Hex) packages alongside Rust (Crates.io) and JavaScript/TypeScript (npm).

If you’ve ever struggled with keeping changelogs updated, coordinating version bumps across dependent packages, or automating your Hex publishing process, this might interest you!

In a nutshell

Sampo is a CLI tool (for now only available on Cargo, but soon on your favorite OS package manager), a Github Action, and a GitHub App that work together to streamline your release process.

Sampo automatically discovers Elixir (and Rust/Javascript/Typescript) packages in your workspace (including umbrella projects), respects your mix.exs configuration, and calls mix hex.publish under the hood (you still need to have your HEX_API_KEY environment variable or Mix’s auth configured).

Like Hex.pm, Sampo enforces Semantic Versioning (SemVer) to indicate the nature of changes in each release. Versions follow the MAJOR.MINOR.PATCH format with three bump levels: patch — Bug fixes and backwards-compatible changes; minor — New features that are backwards-compatible: major — Breaking changes that are not backwards-compatible.

For example, a user can safely update from version 1.2.3 to 1.2.4 (patch) or 1.3.0 (minor), but should review changes before updating to 2.0.0 (major). Sampo also supports pre-release versions (e.g., 1.2.0-rc.1) as SemVer §9 conventions.

For each change made to your packages, you can use sampo add to create a new changeset file, the CLI will prompt you to select which packages were affected, the type of version bump (patch/minor/major), and a description of the change. You can use Sampo GitHub bot to get reminders on each PR without a changeset.

---
hex/back-end: minor
npm/web-app: patch
---

A helpful description of the change, to be read by your users.

Those changesets are markdown file, inspired by Changesets and Lerna, stored in the .sampo/changesets/ directory. Sampo consumes those changesets to determine version bumps, and update changelogs—a human-readable file listing all changes for each released version, at the root of every package.


# Example

## 0.2.0 — 2024-06-20

### Minor changes

- [abcdefg](link/to/commit) A helpful description of the changes. — Thanks @user!

## 0.1.1 — 2024-05-12

### Patch changes

- [hijklmn](link/to/commit) A brief description of the fix. — Thanks @first-time-contributor for their first contribution!

... previous entries ...

Run sampo release to process all pending changesets, bump package versions, and update changelogs. This can be automated in CI/CD pipelines using Sampo GitHub Action, with a release PR created whenever changesets are detected. As long as the release is not finalized, you can continue to add changesets and re-run the sampo release command. Sampo will update package versions and pending changelogs accordingly.

Finally, run sampo publish to publish updated packages to their respective registries and tag the current versions. This step can also be automated in CI/CD pipelines using Sampo GitHub Action, by merging the release PR, and can also create GitHub Releases and Discussions for each new tag.

Philosophy

Sampo is designed to be an helpful, reliable, and flexible tool that users can trust.

We want to make it easy to get started, with minimal configuration, sensible defaults, and automated workflows. At the same time, we want to provide rich configuration options, and flexible workflows to cover more advanced use cases. Finally, Sampo should be easy to opt in and opt out, with little to none assumptions, conventions to follow, or lock-ins.

It’s fully open-source, and we welcome contributions and feedback from the community! If you give it a try, please let us know what you think, and if we can do anything to improve the Elixir support :slightly_smiling_face:

And leave a star on GitHub if you find it useful!

Most Liked

GoulvenClech

GoulvenClech

Hi everyone :waving_hand:

Since I introduced Sampo here, I’ve written a longer article that goes into the motivations behind the project, the design philosophy, and some ideas for what’s next. I hope you find this interesting!

dimitarvp

dimitarvp

Very timely, I’m recently doing one final pass out evaluating various such tools. Thanks for releasing yours!

Where Next?

Popular in Libraries Top

New
OvermindDL1
Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML...
132 13487 106
New
achempion
Hi, I would like to tell about my initiative to further maintain and develop Waffle project which is the fork of Arc library. The progre...
New
mplatts
With HEEX released we decided to start a components library using Tailwind CSS - check it out here: Petal Components. We also have a boi...
New
mcrumm
If you would like to migrate away from node/npm/webpack while still using sass, the dart_sass package provides a installer and runner for...
New
asiniy
Hey there! I wrote a download elixir package which does exactly what its name about - an easy way to download files. I saw solutions ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
jakub-zawislak
Hi everyone, I’m coming from the Symfony (PHP) framework. I like Phoenix, but it has a one thing that was build much better in the Symfo...
New
Crowdhailer
I have been updating a library that allows you to pipe between functions that use the erlang result tuple convention. Assuming you have...
New
bryanjos
Hi, I wanted share a small library we at Revelry Labs made for rendering react components from the server side. There are instructions fo...
New

Other popular topics Top

freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New

Sub Categories:

We're in Beta

About us Mission Statement