Extracting information from sources in snapcraft parts


#1
Change snapcraft version
Initial introduction 2.39
appstream support 2.39
common-id 2.40
setup.py support 2.41
snapcraftctl set-version 2.41
snapcraftctl set-grade 2.41

Some of the values required by the snapcraft.yaml file might be already provided by other metadata sources available in the upstream project.

Instead of duplicating this information, you can declare that a snapcraft part must parse the metadata file from the source, and adopt that parsed information. For example, the following snapcraft.yaml will parse the file called metadata-file and try to extract from it the version, summary and description for the snap.

name: my-snap-name
adopt-info: part-with-metadata

parts:
  part-with-metadata:
    plugin: dump
    parse-info: <metadata-file>

Metadata sources

Appstream

Appstream is a standard for metadata of software components. It can provide the summary, description and icon for the snap, and the desktop files for the apps.

Let’s say we have an upstream project with the following appstream file in sampleapp.metainfo.xml:

<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
  <id>com.example.sampleapp</id>
  <summary>Single-line elevator pitch for your amazing application</summary>
  <description>
    This is applications's description. A paragraph or two to tell the
    most important story about it.
  </description>
  <icon type="local">assets/icon.png</icon>
  <launchable type="desktop-id">
    com.example.sampleapp.desktop
  </launchable>
</component>

Then you can adopt this info into your snapcraft.yaml like this:

name: sampleapp-name
adopt-info: sampleapp

apps:
  sampleapp:
    command: sampleapp
    common-id: com.example.sampleapp

parts:
  sampleapp:
    plugin: dump
    source: http://github.com/example/sampleapp.git
    parse-info: [sampleapp.metainfo.xml]

The resulting snap will take the summary and description from the appstream file and it will use the referred icon and desktop files.

Note that appstream doesn’t use a path to declare the desktop file. It uses a Desktop File ID.

To know which appstream desktop-id corresponds to your app, you must declare the common-id of the app in the snapcraft.yaml. snapcraft will search for a parsed appstream file with the same component id and extract the desktop-id.
Then it will search for the desktop file in the directories usr/local/share and usr/share relative to the part source, following the Desktop File ID rules.

setup.py

If your setup.py uses setuptools, version and description can be extracted from setup.py to be used as the version and description of the resulting snap.

Let’s say we have the following setup.py in the root of a hypothetical git tree http://github.com/example/sampleapp.git that looks like:

import setuptools

setuptools.setup(
    name='hello-world',
    version='1.0',
    author='snapcrafter',
    author_email='snapcraft@lists.snapcraft.io',
    description='A simple hello world in python',
    scripts=['hello']
)

Then you can adopt this info into your snapcraft.yaml like this:

name: sampleapp-name
summary: sampleapp summary
adopt-info: sampleapp

apps:
  sampleapp:
    command: sampleapp

parts:
  sampleapp:
    plugin: python
    source: http://github.com/example/sampleapp.git
    parse-info: [setup.py]

Part scriptlets

Individual parts in your snapcraft.yaml can set the version and grade by using snapcraftctl. All you need to do is select which part to adopt using adopt-info:

# ...
adopt-info: my-part
# ...
parts:
  my-part:
    # ...
    override-pull: |
      snapcraftctl pull
      snapcraftctl set-version "my-version"
      snapcraftctl set-grade "devel"

Snapcraft version scripts
Version script "helpers"
Asking for a transfer of the QXmlEdit from frederickjh/qxmledit to snapcrafters
#2
  • What happens if you include multiple items in the list in a part’s parse-info?
  • Is there a usecase for parse-info that isn’t linked to the snap using adopt-info?
    • if not then why do we have adopt-info at all?
  • Can we adopt the info from multiple parts?
    • if we can have multiple items in parse-info for a single part then surely we should be able to reference the info from multiple parts?

#3

I will reflect the docs with the behavior of in function precedence.

You could be using someone else’s part that suddenly starts using parse-info. This provides a very explicit behavior from day one. Do you think we should relax it? This documentation mostly reflects Extracting existing data from projects to feed into snap.yaml

I think you should move to using the equivalents of the to-be set-version and such if you have a very odd use case or we will be creating a Swiss knife of a beast :slight_smile:


#4

Thanks for the clarifications :slight_smile: That all sounds rather tasty nomnomnom…

No, I think that makes sense now that you’ve blown the cobwebs from my brain :-p


#5

I wonder if it’s possible to adopt the git describe version from the adopt-info specified part’s source repo when the version key is also set with the value git


#6

I think something like that is available or in the work, cc @sergiusens


#7

Can you clarify? In the meantime I will explain what is already there.

version: git

Works, it is just very opinionated on release tags, from the git man page:

Annotated tags are meant for release while lightweight tags are meant
for private or temporary object labels. For this reason, some git
commands for naming objects (like git describe) will ignore lightweight
tags by default.

For this and other reasons we now have snapcraftctl set-version <version> which can be used in any part and can be picked up by Ă dopt-info`.


#8

I would like to use the version: git like version string, but instead of describing the recipe containing repo, make it describe the part’s source repo according to the adopt-info key’s value. The described version is enough for me and I want to avoid calling snapcraftctl set-version <version> when possible.


#9

I’ve encountered a problem that in snapcraft 2.43.1(snap) the snapcraftctl command can’t be called in a script called in a override-pull scriptlet:

Pulling hello 
Cloning into '/root/build_hello-snapcrafters/parts/hello/src'...

...

/root/build_hello-snapcrafters/parts/hello/src/../../../snap/local/utilities/set-snap-version.bash: line 35: snapcraftctl: command not found
Failed to run 'override-pull': Exit code was 127.

This issue isn’t reproduced in build.snapcraft.io, nor it is reproduced in snapcraft 3.0