Some Tips to Release Binaries

Published:
3 minute read

There are several things to consider when releasing a binary. Here are some tips that I found useful.

Best Practices

  1. Releases are tied to tags, not branches.
  2. Versioning - Use Semantic Versioning!
  3. Security - Sign the binaries and verify the signatures.
  4. Changelog - Keep a CHANGELOG.md file.
  5. License - Include a LICENSE file.
  6. Documentation - Include a README.md file including how to install and use the binary.
  7. CI/CD - Automate the build, test, and the release process.

Consider Signing the Binary

Signing the binary is a good practice to ensure the integrity and authenticity of the binary. You can use GPG on Linux:

# If you don't already have a GPG key, generate one:
$ gpg --full-generate-key
# Choose RSA and a key size (e.g., 4096).
# Set an expiration date (or none for permanent).
# Enter your name and email (match your GitHub email).

Then, export the public key:

$ gpg --armor --export YOUR_EMAIL > public.key
# This will create a file named public.key.

After that, sign the binary:

$ gpg --detach-sign --armor app-linux-x86_64.tar.gz
# a file named app-linux-x86_64.tar.gz.asc will be created.

gpg --detach-sign --armor app-windows-x64.zip
# a file named app-windows-x64.zip.asc will be created.

Then, you can upload the binaries and their signatures to GitHub releases.

  • app-linux-x86_64.tar.gz
  • app-linux-x86_64.tar.gz.asc
  • app-windows-x64.zip
  • app-windows-x64.zip.asc

Then, users can verify the binaries using the public key:

$ gpg --import public.key
$ gpg --verify app-linux-x86_64.tar.gz.asc app-linux-x86_64.tar.gz
$ gpg --verify app-windows-x64.zip.asc app-windows-x64.zip
# output should be sth like: "Good signature from YOUR_NAME <YOUR_EMAIL>"

Automating the Release Process with GitHub Actions

Add a GitHub Action workflow (.github/workflows/release.yml).

name: Release Binaries

on:
  push:
    tags:
      - 'v*'  # Triggers on versioned tags like v1.0.0

jobs:
  build:
    runs-on: $
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up build environment
        run: echo "Setting up..."

      - name: Build
        run: |
          # Replace with your build commands
          echo "Building binary for $"

      - name: Upload binaries
        uses: actions/upload-artifact@v3
        with:
          name: app-$
          path: path/to/binary

  release:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v3
        with:
          path: ./artifacts

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: ./artifacts/**
          tag_name: $

Automating the Signing in GitHub Actions

You can automate the signing process using GitHub Actions. Here is an example workflow:

- name: Import GPG Key
  run: |
    echo "$GPG_PRIVATE_KEY" | gpg --batch --import
    echo "trusted-key $(gpg --list-keys --with-colons | grep pub | cut -d: -f5)" >> ~/.gnupg/gpg.conf

- name: Sign Binary
  run: gpg --detach-sign --armor myapp-linux-x86_64.tar.gz

Alternative to GPG

If you’re distributing via containers or want an alternative to GPG, you can use Sigstore Cosign.

Code Signing for Windows

I haven’t done this myself, but you can sign the Windows binaries using SignTool.