Snapcraft and snapd/store disagree about channel map

So I’m experimenting with epochs. I released revision 1 (epoch 0) to edge, and then released revision 2 (epoch 1) to edge. Then I decided I wanted revision 1 back on edge. It worked:

$ snapcraft release kyrofa-epoch-example 1 edge
Track    Arch    Channel    Version    Revision    Notes
latest   amd64   stable     -          -           -
                 candidate  -          -           -
                 beta       -          -           -
                 edge       0.1        1           -

Except I still got revision 2 when I tried to install. I found that confusing. Turns out snapcraft and snapd/the store disagree about what is actually released, now. Snapcraft claims it’s revision 1:

$ snapcraft status kyrofa-epoch-example
Track    Arch    Channel    Version    Revision    Notes
latest   amd64   stable     -          -           -
                 candidate  -          -           -
                 beta       -          -           -
                 edge       0.1        1           -

snapd claims it’s revision 2:

$ snap info kyrofa-epoch-example
name:      kyrofa-epoch-example
<snip>
snap-id: YuLmITBJZrUxPi2xej0DVIcf3DslLq7U
channels:
  latest/stable:    –                      
  latest/candidate: –                      
  latest/beta:      –                      
  latest/edge:      0.2 2020-06-08 (2) 4kB -

What’s going on here? I want snapcraft to be right because that’s what I requested, but it’s obviously wrong since I do indeed get revision 2 when installing. Does my use of epochs mean I can no longer “unrelease” like this? I suppose that makes sense if you think hard enough about it (how would you update old epochs otherwise), but makes this feature really scary. I also feel like snapcraft should be doing something different here, in that case.

(cc @sergiusens, @cjp256)

1 Like

The channel map shown by Snapcraft 3.x is what the store returns from the v1 state endpoint when running “status” and from the v1 release endpoint for release which what I suspect you are using. I would be interested to see what the results are when using Snapcraft 4.x where we still use those endpoints for execution but we call the v2 channel-map endpoint for presentation.

At the end of the day Snapcraft just presents what is returned from the store, perhaps releasing should fail or maybe reality for a given device that has already updated been altered and the snap client needs to hint about this, but from your description there is certainly a disconnect here.

I’ve run into a similar situation with epochs (described below) and I think this is unfortunately just endemic to using epochs and rather awkward to work around. This is because the channel-map for a snap with epochs now really is more like “epoch to channel-map map”, where the highest epoch the store has seen is the default channel-map, but you still have channel-maps for other epochs. Snapcraft for example doesn’t seem to really understand epochs when displaying things here and seems to just look at what the most recent release for a channel is, while the store/snapd is showing you the “highest epoch” channel-map that a new client would see upon installing. Also note I did not actually notice a difference between snapcraft 4 output and snapcraft 3 output in this situation FWIW, both of them showed the same channel-map but in my case.

I think that snapcraft status should show, or have an option for showing, the channel-map for the various epochs. Possibly also snap info, but that command’s already very dense so perhaps it’s not useful unless you’re the publisher of the snap as is the case with snapcraft status. That would make it more clear what the state of the snap’s channel-map is for various clients (new ones see the most high epoch, old ones see a specific epoch depending on what epoch they have, etc.). Also some way of seeing what chain of revisions an old client would step through if you have epochs that are mutually compatible like 1* and 2*, etc.

The ideal thing in my mind to solve this situation independent of how it is presented via snap info/snapcraft status would be to somehow “unassociate” a revision with an epoch on the store side, but that obviously is very confusing since the epoch is in the snap blob, but the work-around I used when I hit this is basically that, where I just downloaded the old epoch revision, changed the version number and re-uploaded and re-released.

What happened to me in more detail was:

  1. I had epoch 0 on a channel (revision 100)
  2. I meant to release a new snap with epoch 1 but accidentally uploaded/published it with epoch 0 (revision 101)
  3. I then re-uploaded the prior revision but actually with epoch 1 now (revision 102)

This left some clients in a very confused state:

  • new clients installed from the channel, got epoch 1 from revision 102 (as expected and intended)
  • old clients refreshed, but got the broken epoch 0 snap revision 101 from step 2 (very much not intended)

This was because the most recent revision on the channel with epoch 0 was the broken revision 101, and to fix this I had to download the old revision 100, and re-upload it to the channel with a different version number, so that the most recent revision on the channel with epoch 0 was now revision 102. Then everything worked as expected with old clients on effectively the old epoch and version, and new clients on the new epoch and new, incompatible version.

What I would have liked to do is “unpublish” revision 101 from that channel and that epoch so that old clients never would do the refresh because they wouldn’t see any newer snap revisions on that epoch.