yarnpkg / yarnpkg/berry

[Feature] Portable scripts

Open
#200 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
8.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

  • I'd be willing to implement this feature
  • This feature can already be implemented through a plugin

Describe the user story

As a package developer I have run into issues where run-scripts depend on the system, e.g. most often because of a binary that was globally installed on one system but not another, but also because of environments.

Describe the solution you'd like

I'd like a way to tell a run-script it cannot use any system-provided executable or environment variable, preferably with a whitelist of environment variables to allow, e.g. CI to allow the script to check whether it's running on a dev machine or a CI environment.

Example API:

{
  "scripts": {},
  "scriptsMeta": {
    "onlyLocalCommands": true,
    // alternatively, "env" > "whitelist" to allow for a "blacklist" as well
    "envWhitelist": ["CI"]
  }
}

Describe the drawbacks of your solution

Not allowing system-provided executables means we don't get access to any of the GNU coreutils on Linux, BSD coreutils on BSD/macOS or any other commands available on the system. Script authors would either have to depend on packages like rimraf to provide an rm -rf alternative, or someone would have to provide a more complete tooling.

Note that the someone providing a set of utility commands doesn't have to be yarn. I could install cash-ls to get a basic ls function. We could even end up with @gnu/coreutils and @bsd/coreutils packages, providing access to commands implementing the coreutils with GNU's leniency or BSD's POSIX-compliance.

Describe alternatives you've considered

  • The functionality is, in theory, already available:
    • I could prefix the command with PATH='' to clear the path (once #166 is implemented)

      $ PATH='' which yarn
      bash: which: No such file or directory
      

      This still doesn't stop someone from writing /usr/local/sbin/nginx in the start script though.

    • I could clear the environment by prefixing my commands with env -i:

      $ env -i -P "$PATH" PATH='' bash -c '/usr/bin/env'
      PWD=/Users/bram
      SHLVL=1
      PATH=
      _=/usr/bin/env
      

      I can "whitelist" environment variables by copying them over, e.g. CI=$CI, but that means all checks on the existence of the variable now always trigger, because the variable is always present.

  • Remove the GNU coreutils from my BSD machine and live the BSD lifestyle. Also, buy a macOS device for everyone not on BSD yet.
  • Get everyone to run scripts in my repos via standardised environments like vagrant or docker. Last time I tried this (years ago) I ran into issues because 1) everything needs to happen in the vagrant guest, you can't run scripts locally anymore because any actual binaries are ELF linux binaries and not macOS's mach-o and 2) host<->guest file access was very slow, especially when watching file changes.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No files, tests, or entry points are named. Start by mapping how run-scripts currently receive executables and environment variables, then define the API and its behavior for local commands and an environment whitelist. Done means the behavior is specified and covered for the proposed cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs, typescript
Domain
cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.