Skip to content

GitHub Actions

Chris Clark edited this page Aug 20, 2021 · 8 revisions

Test and lint on every push

Should we use pylint?

Release when tag is pushed

Releasing a python project should mean pushing a new version of the project to a PyPI repository (either the PyPI or a private PyPI repository).

In some cases, if you also choose to release a binary executable per OS (say, using pyinstaller), creating a new release would also involve uploading the binaries somewhere.

GitHub Release

First off: python projects usually shouldn't need GitHub Releases. A PyPI repository should be the go-to mechanism distributing python projects. The only reason to create a GitHub Release is to distribute executable binaries if you are creating them.

content-type

All assets included in a GitHub Release must specify a content-type which can be any MIME type. A MIME type is just a short string that helps to indicate what sort of file something is (a zip? a text file? an image?) so that clients might choose how to best deal with this file. In this sense, MIME types are similar to magic numbers.

When downloading a release asset from GitHub, the GitHub documentation suggests setting the Accept header to application/octet-stream (which is the most general content-type that exists).

content-type for an executable binary

Appropriate MIME types for an executable binary might be any of:

  • application/octet-stream: Stuff, could be anything
  • application/x-mach-binary: A MacOS executable binary
  • application/x-executable: A Linux executable binary

Some repositories just set the content-type to application/octet-stream for every asset. This works, but I think it's best to narrow things down as much as possible. Using more specific content types can be really helpful to programs that attempt to discover and download assets.

For example, say you want to programmatically fetch a GitHub Release asset suitable for my MacBook. You might write a script like this:

RepoURL=https://api.github.com/repos/cfclrk/py-demo

Asset=$(curl -s $RepoURL/releases/latest \
            | jq '.assets[]
                  | select(.content_type == "application/x-mach-binary")
                  | .id')

curl -sSL \
     $RepoURL/releases/assets/$Asset \
     -o py-demo

Without being able to filter assets by their content_type, you have to invent additional heuristics like: "does the asset's name contain darwin-amd64 or darwin-x86_64?"