[OBSOLETED] The selective-pull scriptlet stage snap workaround

NOTE: This stage snap is now superseded by the selective-checkout stage snap, check out Selective-checkout: Check out the tagged release revision if it isn't promoted to the stable channel for more info regarding the usage.


The problem

Currently, due to the limitation of the automated build infrastructure based on build.snapcraft.io and Launchpad, it’s not possible to ensure that a snap will be built on certain tagged release as a build is only triggered when:

  • Someone pushes to the associated repository(which development tip (a.k.a. HEAD) not necessarily a tagged release)
  • A launchpad import occurs if the repo is set to be importing periodically from an external repository

The workaround

This stage snap features a scriptlet that re-implements the pull step that will only build development snapshots snaps if the latest tagged release has been promoted to the stable channel. This ensures that there’s always a revision of the stable release snap available in the edge channel for the publisher to promote it to the stable channel.

Case: Tagged release published to the stable channel

Case: Tagged release hasn’t published to the stable channel

selective-pull: Last tagged release(1.8.0) hasn't promoted to the stable channel(1.7.0) on the Snap Store, building tagged release instead.
Note: checking out 'v1.8.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 8c20443 release version 1.8.0
selective-pull: Snap version determined to be "1.8.0".

This script is inspired by the snapcrafters adopted snaps workflow, documented in the following forum topic:

Refer the following forum topic for a possible solution proposal to this problem:

Prerequisites

  • Your snap recipe is using the base keyword (i.e. not the legacy snapcraft syntax)
  • Your main component part is using the git SCM.
  • Your release tags must be version sorted and is dot-separated or underline-separated, e.g. 1.2, 1.2.3, v1.2.3, or LIBUSB_3_0_0.
  • The build host must have internet access (for querying snap status on the snap store)
  • Your snap must not be private on the snap store (unlisted is fine)

How to use

  1. Set the adopt-info key with the main component part’s name as the value.

  2. Merge the following part definition:

    parts:
      selective-pull:
        plugin: nil
        build-packages:
        - git
        stage-snaps:
        - selective-pull
        prime:
        - -*
    
  3. Merge the following keys to the main component part:

    parts:
      _part_name_:
        after:
        - selective-pull
        # Either the root source tree with a .git repository
        source: .
        # or an external git repository (the source-depth should be deep enough to have a tagged release)
        source: https://example.com/project/.git
        override-pull: |
          # Replace the `snapcraftctl pull` call with:
          "$SNAPCRAFT_STAGE"/scriptlets/selective-pull
    
          # Do your additional regular stuff
    

The logic

  • The scriptlet will checkout HEAD and build development snapshot snap if the latest tagged release has been promoted to the stable channel
  • The scriptlet will checkout the latest tagged release and build tagged release snap if the latest tagged release hasn’t been promoted to the stable channel (check is based on version-sort)
  • The scriptlet will checkout as-is if a git repository is not found and will set the snap version to unknown

The implementation

Snaps that are using this stage snap


Happy snapcrafting!