Skip to content
Eugene Lazutkin edited this page Jul 15, 2020 · 11 revisions

Reasons

There are bazillions helpers, which help to precompile artifacts and use them later on the user's computer. Unfortunately, they didn't fit my needs:

  • Frequently they are huge projects with a lot of dependencies that take care of many things automatically.
  • I want to avoid the dependency hell.
  • Usually, they require to set up some file hosting with secure uploads and downloads.
    • This is an extra dependency, which I should maintain and pay for.
  • I want to be sure that my users are secure.
    • I cannot review mounds of code on every release.
  • The inherent complexity (dependencies, a file service) makes the whole system too fragile, and prone to security glitches.

That's why I arrogantly decided that I can do better.

  • Both projects are essentially one-file utilities.
    • install-from-cache is less than 200 lines.
    • save-to-github is less than 100 lines.
    • Both files can be easily inspected to make sure there is no funny business or bugs.
  • Both projects have a minimal number of dependencies.
    • install-from-cache has no dependencies.
      • You can literally copy it to your project.
    • save-to-github has 1 (one) dependency.
      • It depends on @actions/github to save an artifact in the proper place.
      • It goes to your developer dependencies and doesn't need to be shipped or installed to end-users.
  • It uses GitHub releases to save and serve files.
    • It is free (at least now).
    • It uses a geographically distributed CDN.
    • It is easy to mirror a release (it is just files!) and mirror it locally.
  • Unobtrusive security is implemented by GitHub Actions.
    • save-to-github is automatically supplied with a secure token, so no need to mess with any settings. It just works.
    • For public repositories, actions are free (as of now). For private ones, the free tier includes 2,000 free minutes per month, which is enough for many projects.
  • Nowadays, when brotli compression is wildly supported and comes included with Node (since version 10) we can use it to reduce sizes of stored artifacts.
    • It irks me that almost nobody does it! Smaller size ⇒ faster downloads! It is especially important for popular packages.
    • save-to-github uploads two versions of an artifact: br and gz. Both using the best compression parameters.
    • If an underlying Node does not support brotli, it is skipped.
      • install-from-cache skips its download.
      • save-to-github does not produce nor upload it.
    • install-from-cache checks a gz version if a br version was not available.

Workflow

My workflow is usually like that:

  • Development:
    • Modify code ⇒ commit ⇒ repeat the cycle.
    • In the background I have automatic tests running on every commit.
  • Release:
    • I make sure that a version is properly bumped and the README is updated.
    • I tag the release:
      • git tag 2.0.1
      • git push --tags
    • I publish it:
      • npm publish

Now I can sit back and relax watching how irate users complaining about bugs in the new release. ;-)

With this project, I have a GitHub action for creating a release, which runs on tagging it. It was a minimally invasive procedure.

What if?

What if something bad happens? A network is down, you generated a wrong unusable artifact, which is linked against wrong libraries?

What if my platform is a relatively exotic one? What if you don't have an artifact for my specific platform, architecture, new Node ABI?

No problem. We can afford a false positive.

The downloaded artifact is checked, and if it doesn't work properly, it is discarded, and a new one is built locally from sources.

So in the worse case, we have 1-2 extra HTTP requests downloading an artifact, unpacking, and checking. Usually, it is much faster than building.

The upside is: we save user's resources, including time, in most cases.

Clone this wiki locally