Skip to content

Instantly share code, notes, and snippets.

@DavidAnson
Created August 27, 2023 18:58
Show Gist options
  • Save DavidAnson/39b0eed160f7ce481c92e24a651b5d6f to your computer and use it in GitHub Desktop.
Save DavidAnson/39b0eed160f7ce481c92e24a651b5d6f to your computer and use it in GitHub Desktop.

Revisions

  1. DavidAnson created this gist Aug 27, 2023.
    67 changes: 67 additions & 0 deletions notes.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    For historical purposes and possible future reference, here are my notes on why I backed out a change to use `npm-shrinkwrap.json` in `markdownlint-cli2`.

    The basic problem is that npm will include platform-specific packages in `npm-shrinkwrap.json`. Specifically, if one generates `npm-shrinkwrap.json` on Mac, it may include components (like `fsevents`) that are only supported on Mac. Attempts to use a published package with such a `npm-shrinkwrap.json` on a different platform like Linux or Windows fails with `EBADPLATFORM`. This seems (to me, currently) like a fundamental and fatal flaw with the way npm implements `npm-shrinkwrap.json`. And while there are ways npm might address this problem, the current state of things seems unusably broken.

    To make this concrete, the result of running `rm npm-shrinkwrap.json && npm install && npm shrinkwrap` for this project on macOS can be found here: <https://github.com/DavidAnson/markdownlint-cli2/blob/v0.9.0/npm-shrinkwrap.json>. Note that `fsevents` is an optional Mac-only dependency: <https://github.com/DavidAnson/markdownlint-cli2/blob/66b36d1681566451da8d56dcef4bb7a193cdf302/npm-shrinkwrap.json#L1955-L1958>. Including it is not wrong per se, but sets the stage for failure as reproduced via GitHub Codespaces:

    ```bash
    @DavidAnson ➜ /workspaces/temp (main) $ ls
    @DavidAnson ➜ /workspaces/temp (main) $ node --version
    v20.5.1
    @DavidAnson ➜ /workspaces/temp (main) $ npm --version
    9.8.0
    @DavidAnson ➜ /workspaces/temp (main) $ npm install [email protected]
    npm WARN deprecated [email protected]: 0.x is no longer supported. Please upgrade to 4.x or higher.

    added 442 packages in 4s

    9 packages are looking for funding
    run `npm fund` for details
    @DavidAnson ➜ /workspaces/temp (main) $ npm clean-install
    npm ERR! code EBADPLATFORM
    npm ERR! notsup Unsupported platform for [email protected]: wanted {"os":"darwin"} (current: {"os":"linux"})
    npm ERR! notsup Valid os: darwin
    npm ERR! notsup Actual os: linux

    npm ERR! A complete log of this run can be found in: /home/codespace/.npm/_logs/2023-08-27T18_24_58_585Z-debug-0.log
    @DavidAnson ➜ /workspaces/temp (main) $
    ```

    Note that the initial install succeeded, but the subsequent attempt to use "clean-install" failed due to the platform mis-match. This is a basic user scenario and the user is completely blocked at this point.

    Because this is a second-level failure, it is not caught by most reasonable continuous integration configurations which work from the current project directory instead of installing and testing via the packed `.tgz` file. However, attempts to reproduce this failure in CI via `.tgz` were unsuccessful: <https://github.com/DavidAnson/markdownlint-cli2/commit/f9bcd599b3e6dbc8d2ebc631b13e922c5d0df8c0>. From what I can tell, npm install of a local `.tgz` file is handled differently than when that same (identical) file is installed via the package repository.

    While there are some efforts to test the `.tgz` scenario better (for example: <https://github.com/boneskull/midnight-smoker>), better testing does not solve the fundamental problem that `npm-shrinkwrap.json` is a platform-specific file that gets used by npm in a cross-platform manner.

    ---

    Unrelated, but notable: npm installs ALL package dependencies when `npm-shrinkwrap.json` is present - even in a context where it would normally NOT install `devDependencies`. Contrast the 442 packages installed above vs. the 40 when `--omit=dev` is used explicitly:

    ```bash
    @DavidAnson ➜ /workspaces/temp (main) $ npm install [email protected] --omit=dev

    added 40 packages in 1s

    9 packages are looking for funding
    run `npm fund` for details
    @DavidAnson ➜ /workspaces/temp (main) $
    ```

    But the default behavior of a dependency install in this manner is not to include `devDependencies` as seen when installing a version of this package without `npm-shrinkwrap.json`:

    ```bash
    @DavidAnson ➜ /workspaces/temp (main) $ npm install [email protected]

    added 35 packages in 2s

    7 packages are looking for funding
    run `npm fund` for details
    @DavidAnson ➜ /workspaces/temp (main) $
    ```

    ---

    References:

    - Request and discussion: <https://github.com/DavidAnson/markdownlint-cli2/issues/186>
    - Problem and investigation: <https://github.com/DavidAnson/markdownlint-cli2/issues/198>