My datasette-screenshots repository generates screenshots of Datasette using my shot-scraper tool, for people who need them for articles or similar.
Jacob Weisz suggested optimizing these images as they were quite big. I want them to be as high quality as possible (I even take them using --retina
mode), but that didn't mean I couldn't use lossless compression on them.
I often use squoosh.app to run a version of Oxipng compiled to WebAssembly in my browser. I decided to figure out how to run that same program in GitHub Actions.
Surprisingly there isn't yet a packaged version of Oxipng for Ubuntu - so I needed another way of installing it.
The project README suggests installing it using cargo install oxipng
.
I used the tmate trick to try that out in a GitHub Actions worker - the cargo
command is available by default but it took over a minute to fetch and compile all of the dependencies.
I didn't want to do this on every run, so I looked into ways to cache the built program. Thankfully the actions/cache
action documents how to use it with Rust.
The full recipe for installing Oxipng in GitHub Actions looks like this:
- name: Cache Oxipng
uses: actions/cache@v3
with:
path: ~/.cargo/
key: ${{ runner.os }}-cargo
- name: Install Oxipng
run: |
which oxipng || cargo install oxipng
The first time the action runs it does a full compile of Oxipng - but on subsequent runs the which oxipng
command succeeds and skips the cargo install
step entirely.
All of the PNGs that I wanted to optimize were in the root of my checkout, so I added this step:
- name: Optimize PNGs
run: |-
oxipng -o 4 -i 0 --strip safe *.png
The -o 4
is the highest recommended level of optimization.
-i 0
causes it to remove interlacing - "Interlacing can add 25-50% to the size of an optimized image" according to the README.
--strip safe
strips out any image metadata that is guaranteed not to affect how the image is rendered.
Oxipng updates the specified images in place, hence the *.png
at the end.
I tested this all in a branch first so that I could see if it was working correctly.
Since my workflow usually pushes any changed files back to the same GitHub repository, I added a check to that step which caused it to only run on pushes to the main
branch:
- name: Commit and push
if: github.ref == 'refs/heads/main'
run: |-
git config user.name "Automated"
...
But I wanted to preview the generated images - so I added this step in the branch to save them to an artifact zip file that I could then inspect:
- name: Artifacts
uses: actions/upload-artifact@v3
with:
name: screenshots
path: "*.png"
Once I got it working, I squash-merged this pull request back into main
.
Oxipng worked really well!
It reduced the size of all three of my screenshots:
This commit shows the difference and lets you compare both images.
Created 2022-05-18T18:45:23-07:00, updated 2022-09-12T14:22:14-07:00 · History · Edit