Skip to content

Adding our automation to a snap

Merlijn Sebrechts edited this page Dec 16, 2023 · 18 revisions

Snapcrafters has a bunch of really cool automation. This guide explains how it works and how you can add it to your (Snapcrafters) snap.

General idea

  • snapcraft.yaml explicitly states which architectures it should be built on.
  • snapcraft.yaml has hardcoded versions of the app and upstream dependencies. This is to make our builds more reproducible. That way, we can rebuild a snap without immediately pulling in the latest version of an app. This also makes it very clear what version of an app will be built.
  • sync-version-with-upstream.yml periodically checks if new versions are available. If there are, it updates snapcraft.yaml and commits this directly to the repository. This has to be customized for each snap.
  • release-to-candidate.yaml runs on every commit to the candidate branch.
    • It builds the snap and pushes it to the candidate channel in the Snap Store.
    • It creates a "call for testing" issue asking people to test this version.
    • It runs the snap in a VM and takes two screenshots.
  • promote-to-stable.yml listens to comments in the call for testing issue. It releases the snap to stable if a Snapcrafter writes a command to do so.
  • pull-request.yml runs every time someone creates a PR. In that case, it builds the snap and checks if it passes automated reviews.

The actual common logic for these actions is in our ci repository

How to add it to your snap

Step 1: Create a PR to add automation

Clone your repository, download your clone locally, and start updating your snap.

  1. If your snap always downloads the latest version of the app and its dependencies, you need to update snapcraft.yaml first. Remove the code that gets the latest version, and change it by code that has the version hardcoded. For example, by using the top-level version keyword, and/or by using the source-tag keywords for parts.

  2. Most snaps can simply copy pull-request.yml, release-to-candidate.yaml, and promote-to-stable.yml. These workflows should work for any snap by default.

  3. The next step is to copy and update sync-version-with-upstream.yml. You need to update the update-script part of this workflow. This is a bash script that updates your snapcraft.yaml file to use the latest versions.

    1. The first step in this script is to get the latest version of the application from an online source. This can be GitHub, Gitlab, or any other website. For example:

      • Get the latest non-beta signal-desktop version from a GitHub Release.

        URL="https://api.github.com/repos/signalapp/Signal-Desktop/releases"
        VERSION=$(curl -sL ${URL} |  jq .[].tag_name -r | grep -v beta | sort -r | head -n 1  | tr -d 'v')
      • Get the latest version of dav1d from a GitLab Release:

        VERSION=$(curl -s https://code.videolan.org/api/v4/projects/198/releases/ | jq '.[0].tag_name' -r)
      • Get the latest version from a Git Branch Name:

        VERSION=$(git -c 'versionsort.suffix=-' ls-remote --refs --sort='v:refname' --heads https://git.videolan.org/git/ffmpeg.git | tail --lines=1 | cut --delimiter='/' --fields=3,4)
      • Get the latest version from a Git Tag:

        VERSION=$(git -c 'versionsort.suffix=-' ls-remote --refs --sort='v:refname' --tags https://code.videolan.org/videolan/dav1d.git | tail --lines=1 | cut --delimiter='/' --fields=3)
      • Get the latest version of Discord from their deb repository.

        DEB_API="https://discord.com/api/download?platform=linux&format=deb"
        DEB_URL=$(curl -w "%{url_effective}\n" -I -L -s -S "${DEB_API}" -o /dev/null)
        VERSION=$(echo "${DEB_URL}" | cut -d'/' -f6)
    2. The next step is to update the version in your snapcraft.yaml file. For example:

      • This updates the main version of your snap.

        sed -i 's/^\(version: \).*$/\1'"\"$VERSION\""'/' snap/snapcraft.yaml
      • This updates the source-tag property of the nv-codec-headers part.

        yq -i ".parts.nv-codec-headers.source-tag = \"$VERSION\"" snap/snapcraft.yaml

        Note: using yq is often easier than sed, but it can change some whitespace in your snap.

    If your snapcraft.yaml contains multiple libraries or dependencies with specific version, your script should gather the latest version of each one and update snapcraft.yaml accordingly.

    Some applications require specific versions for their dependencies. In that case, you need to do a little bit more work.

    For example signal-desktop downloads the upstream packages.json and extracts the versions of dependencies from that file.

Step 2: Ask an Administrator for help

There are two things you can't do yourself. Once the PR has been created, tag @merlijn-sebrechts to ask him the following.

  • To rename the main branch to candidate.
  • To add the required secrets needed for automation.