Skip to content

Save to GitHub cache

Eugene Lazutkin edited this page May 12, 2025 · 3 revisions

save-to-github-cache saves a binary artifact to a Github release according to the platform, architecture, and Node ABI.

Note: this utility was moved from its own project and renamed from save-to-github to save-to-github-cache to avoid a name clash.

How to use

In your package.json (pseudo-code with comments):

{
  // your custom package.json stuff
  // ...
  "scripts": {
    // your scripts go here
    // ...

    // saves an artifact
    "save-to-github": "save-to-github-cache --artifact build/Release/ABC.node",
  }
}

Let's assume that our workflow is like that:

  • Development with multiple commits, tests, rinse, repeat.
  • When we are ready to release we tag using a semantic versioning, e.g., 2.0.1.
  • Now is the good time to build and save artifacts.
  • Then we publish our package on npm, GitHub Packages, or any other repository of your choice.

Let's enable GitHub actions on the project to automate our builds on tagging. Create a file (e.g., build.yml) in .github/workflows folder with the following content:

name: Node.js builds

on:
  push:
    tags:
      - v?[0-9]+.[0-9]+.[0-9]+.[0-9]+
      - v?[0-9]+.[0-9]+.[0-9]+
      - v?[0-9]+.[0-9]+

jobs:
  create-release:
    name: Create release
    runs-on: ubuntu-latest

    steps:
    - name: Create release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        tag_name: ${{github.ref}}
        release_name: Release ${{github.ref}}
        draft: false
        prerelease: false

  build:
    name: Node.js ${{matrix.node-version}} on ${{matrix.os}}
    needs: create-release
    runs-on: ${{matrix.os}}

    strategy:
      matrix:
        os: [windows-latest, macOS-latest, ubuntu-latest]
        node-version: [10, 12, 14]

    steps:
    - uses: actions/checkout@v2
      with:
        submodules: true
    - name: Setup Node.js ${{matrix.node-version}}
      uses: actions/setup-node@v1
      with:
        node-version: ${{matrix.node-version}}
    - name: Get NPM cache directory
      id: npm-cache
      run: |
        echo "::set-output name=dir::$(npm config get cache)"
    - name: Cache node modules
      uses: actions/cache@v2
      with:
        path: ${{steps.npm-cache.outputs.dir}}
        key: ${{runner.os}}-node-${{hashFiles('**/package-lock.json')}}
        restore-keys: |
          ${{runner.os}}-node-
          ${{runner.os}}-
    - name: Install the package and run tests
      env:
        DEVELOPMENT_SKIP_GETTING_ASSET: true
      run: |
        npm ci
        npm run build --if-present
        npm test
    - name: Save to GitHub release
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      run: npm run save-to-github

It will build and save 9 artifacts on all permutations of Windows/MacOS/Ubuntu for Node 10/12/14.

Environment variables

The project doesn't use any user-settable environment variables, but it is meant to be run using a GitHub action. It relies on GitHub action's environment variables for security and information on a repository and a tag.

It is very likely that our package uses install-from-cache too. In this case, it makes sense to set DEVELOPMENT_SKIP_GETTING_ASSET to a non-empty value. This way during the build we are forcing an artifact to be built anew.

Command-line parameters

  • --artifact path — points to a location of the artifact. It is a required parameter.
  • --prefix prefix — provides a prefix for the generated artifact name. Default: ''.
  • --suffix suffix — provides a suffix for the generated artifact name. Default: ''.
  • --format format — (since 1.4.0) provides a list of compression formats used to save an artifact. It can be a comma-separated string of br for brotli, gz for gzip, and/or none for no compression. Example: br,gz,none. Default: br.

Ultimately, the file name has the following format:

`${prefix}${platform}-${arch}-${abi}${suffix}${compression}`

Where:

  • prefix is a user-supplied value (see above).
  • platform is process.platform.
    • Because Linux has different implementations of the C standard library, a special case is made for musl used by distributions like Alpine. Such platforms have a code linux-musl.
  • arch is process.arch.
  • abi is process.versions.modules.
  • suffix is a user-supplied value (see above).
  • compression can be .br (if available on the platform), .gz, or an empty string (since 1.4.0) if no compression was applied.

Example with default values: linux-x64-83.br.

Example

The realistic complex example can be found in uhop/node-re2:

Clone this wiki locally