Search code examples
npmyarnpkgfishnpm-run

Why does this fish while loop terminate after a single iteration?


This is a fish function used to upgrade JavaScript packages for a project. Strangely, it terminates after a single iteration with an exit status of 0. Why?

function yarn-upgrade-all --description "Upgrade JavaScript packages"
    yarn outdated | sed '1,/^Package/d;/^Done/d' | awk '{print $1, $4}' | while read -l PACKAGE VERSION
        echo
        set_color brwhite
        echo -n "==>"
        set_color yellow
        echo -n " "$PACKAGE
        set_color brblue
        echo -n " "$VERSION
        set_color brwhite
        echo -n " <=="
        set_color normal
        echo
        echo

        yarn upgrade --latest $PACKAGE
        and yarn run test
        and yarn run build
        and git commit -am "Upgrade to "$PACKAGE" "$VERSION
        or begin
            set_color red
            echo "last command exited with status $status" >&2
            set_color normal
            return 1
        end
    end
end

On the other hand, this second function, which contains only a stub body, runs through all packages piped into the loop.

function yarn-upgrade-all-debug --description "Upgrade JavaScript packages"
    yarn outdated | sed '1,/^Package/d;/^Done/d' | awk '{print $1, $4}' | while read -l PACKAGE VERSION
        echo $PACKAGE $VERSION
    end
end

fish --version

fish, version 3.0.2


Solution

  • The loop terminates after a single iteration because the yarn run invocations in the loop body slurp up the rest of stdin. (Credits to @glenn-jackman.)

    A possible workaround is to redirect stdin to /dev/null for these commands:

            and yarn run test < /dev/null
            and yarn run build < /dev/null
    

    The culprit is run-s from the npm-run-all package, which is invoked by both yarn run commands.

    https://github.com/mysticatea/npm-run-all/issues/166