[ANN] dune-release-action: Automate your opam package releases with GitHub Actions

Hi everyone :waving_hand:

I’m excited to share a new GitHub Action I’ve been working on: dune-release-action

If you maintain OCaml packages, you know the drill: every release involves a ritual of commands and manual steps. You need to:

  1. Ensure your CHANGES.md is properly formatted
  2. Tag your release
  3. Run dune-release lint + distrib + submit
  4. Create a GitHub release with the correct changelog section
  5. Check the opam-repository’s PR
  6. Oh shit, github token is expired
  7. Create new token without expiration (??)
  8. Retry

For me, was following this guide dune-release.md · GitHub by @anmonteiro, but it typically took around an hour per release.

dune-release-action

dune-release-action automates the entire release workflow in GitHub Actions. Push a git tag, and the action runs dune-release for you with:

  • Handles all the `dune-release` orchestration
  • Validates your changelog format (right tag exists, etc)
  • Creates a GitHub release with proper description (from your changelog section (!!))
  • Submits a PR to opam-repository
name: Release

on:
  push:
    tags:
      - '*'

permissions:
  contents: write
  pull-requests: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: ocaml/setup-ocaml@v3
        with:
          ocaml-compiler: 5.3.0

      - run: opam install dune-release -y

      - uses: davesnx/dune-release-action@v1
        with:
          package-name: 'your-package'
          github-token: ${{ secrets.GH_TOKEN }}

This is very much a one-day half vibe-coded project and it’s hard to test in many use cases, I’m sure there are edge cases and workflows I haven’t considered.

Looking forward to hearing your thoughts!

14 Likes

One thing that excites me about this plugin is that it shifts the generation of release archives over to a mechanized action instead of … running on my laptop! I’ve always been a little nervous about the possibility of release archives being trojaned, since they do not normally correspond directly to git archives. Thanks for releasing it!

3 Likes

A git repo’s integrity is protected by the underlying Merkle tree. This integrity is left behind by relying on archives that have a checksum but no proven connection with the repository - and this is baked into the design of Opam (to keep it independent of git). I like the simplicity of Go’s package management that uses Git as a foundation and accepts the dependency. There is a slight irony here because Opam relies on git for its own data.

2 Likes

At ahrefs we’re thinking about alternative ways distribution and trust could work in opam. One of the experiment we want to push forward a little bit more is RFC: thinking out loud about `signed-by` field to accompany `git:` urls by raphael-proust · Pull Request #6702 · ocaml/opam · GitHub wherein you can specify the source as a git repository address, a tag, and a signature.

It goes further in the "proven connection with the repository” in that it also directly links the release with a private key. It’s proven connection to the repository AND the author (or at the very least a publically verifiable signature of the author).

An interesting thing you could then test for is key changes across releases. A workflow along the lines of:

  • do opam update and opam upgrade
  • get a warning about some package version being signed with a different key than its previous release
  • do some offband sleuthing (check the repo, check for announces on discuss/mailing-list, ask the author on discord/zulip)
  • tell opam whether you accept the new key or not (in which case it fails to update)

We need to add more work into the PR linked above to further the discussion. Don’t hesitate to pitch in with ideas or questions.

3 Likes