Over the holiday I decided to teach myself to write Github Actions, and put together an action that builds Snapcraft projects.
For those who haven’t tried it out, Github Actions is Github’s built-in continuous integration and automation system. It was in beta for much of last year before being made generally available in November. It is similar to Travis CI, but allows anyone to provide canned “actions” that can be slotted into a workflow.
Using the action
Here is a trivial workflow that uses my action:
name: "build"
on: # run on pull requests and commits to master
pull_request:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: jhenstridge/snapcraft-build-action@v1
The snapcraft-build-action
action will do the following:
- fix up permissions on the root directory: for some reason it isn’t owned by root in Github’s build image, which trips up the sanity checks in
snap-confine
. - Remove the .deb version of LXD and install the snap version. Configure LXD with
lxd init --auto
- Install the stable version of Snapcraft
- Invoke Snapcraft to build the project using its LXD backend.
This should provide an environment capable of building most (or all?) snaps, including those that depend on build-snaps
. It’s also complex enough that I think the action provides value over including equivalent shell commands in the workflow directly.
Integrating with other actions
The action also provides an output parameter containing the file name of the built snap. This could be used to save the snap as an artifact of the workflow:
...
steps:
- uses: actions/checkout@v2
- uses: jhenstridge/snapcraft-build-action@v1
id: snapcraft
- uses: actions/upload-artifact@v1
with:
name: snap
path: ${{ steps.snapcraft.outputs.snap }}
… or to install the snap in order to test that it actually functions as expected:
...
- run: |
sudo snap install --dangerous ${{ steps.snapcraft.outputs.snap }}
# do something with the snap
Next Steps
I haven’t published the action to the Github marketplace yet. If there’s interest in this kind of thing, I thought it might be better to publish it from a more official location than my personal Github account. I think it would be worth putting together two extra actions to complement the build action:
- a “lint” action that runs
review-tools.snap-review
. This could help developers catch errors before publishing the package. - a “publish” action that publishes a snap to the store. This would follow best practice, by using exported login information provided through a secret, and making sure the login info is deleted before moving on to the next step of the job.
While this overlaps a bit with the build.snapcraft.io service, I think it would be useful for projects that want more control over their CI pipeline. For instance:
- ensure that pull requests don’t break the snap build.
- perform extra testing steps between building the snap and publishing it.
- publish a snap to the stable channel when a release tag is pushed to Github.
- handle projects where the repository contains multiple Snapcraft projects, or the project isn’t located at the root of the repository.