Skip to content

Commit 77a39b8

Browse files
Sarah Dayanclaude
andcommitted
refactor: replace shelljs with execa
shelljs is outdated (last release 2022) and has sync-heavy patterns. execa is the modern standard for shell command execution with better error handling and cross-platform support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f28e7bb commit 77a39b8

3 files changed

Lines changed: 131 additions & 46 deletions

File tree

packages/shipjs-lib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@
4444
"deepmerge": "^4.2.2",
4545
"parse-github-url": "1.0.2",
4646
"semver": "7.7.1",
47-
"shelljs": "0.8.5"
47+
"execa": "^9.6.1"
4848
}
4949
}
Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,56 @@
1-
import shell from 'shelljs';
1+
import { execaCommandSync } from 'execa';
22

33
export default function exec(
44
command,
55
{ dir = '.', ignoreError = false, silent = false } = {}
66
) {
7-
const result = shell.exec(command, { silent, cwd: dir });
8-
if (result.code === 0) {
9-
return result;
10-
}
11-
if (ignoreError) {
12-
return {
13-
toString: () => '',
14-
code: result.code,
15-
};
7+
try {
8+
const result = execaCommandSync(command, {
9+
cwd: dir,
10+
shell: true,
11+
reject: false,
12+
});
13+
14+
if (result.exitCode === 0) {
15+
return {
16+
code: 0,
17+
stdout: result.stdout,
18+
stderr: result.stderr,
19+
toString: () => result.stdout,
20+
};
21+
}
22+
23+
if (ignoreError) {
24+
return {
25+
code: result.exitCode,
26+
stdout: result.stdout,
27+
stderr: result.stderr,
28+
toString: () => '',
29+
};
30+
}
31+
32+
throw new Error(
33+
JSON.stringify(
34+
{
35+
message: `Exit code is ${result.exitCode}`,
36+
command,
37+
result: {
38+
code: result.exitCode,
39+
stdout: result.stdout,
40+
stderr: result.stderr,
41+
},
42+
},
43+
null,
44+
2
45+
)
46+
);
47+
} catch (error) {
48+
if (ignoreError) {
49+
return {
50+
code: 1,
51+
toString: () => '',
52+
};
53+
}
54+
throw error;
1655
}
17-
throw new Error(
18-
JSON.stringify(
19-
{
20-
message: `Exit code is ${result.code}`,
21-
command,
22-
result,
23-
},
24-
null,
25-
2
26-
)
27-
);
2856
}

yarn.lock

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,11 @@
14531453
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
14541454
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
14551455

1456+
"@sec-ant/readable-stream@^0.4.1":
1457+
version "0.4.1"
1458+
resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c"
1459+
integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==
1460+
14561461
"@sigstore/bundle@^2.3.2":
14571462
version "2.3.2"
14581463
resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-2.3.2.tgz#ad4dbb95d665405fd4a7a02c8a073dbd01e4e95e"
@@ -1509,6 +1514,11 @@
15091514
resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958"
15101515
integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==
15111516

1517+
"@sindresorhus/merge-streams@^4.0.0":
1518+
version "4.0.0"
1519+
resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#abb11d99aeb6d27f1b563c38147a72d50058e339"
1520+
integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==
1521+
15121522
"@slack/types@^2.9.0":
15131523
version "2.19.0"
15141524
resolved "https://registry.yarnpkg.com/@slack/types/-/types-2.19.0.tgz#b076caed57ed2a758e5b7aed73bcdf9bba5b60d3"
@@ -4002,6 +4012,24 @@ execa@5.0.0:
40024012
signal-exit "^3.0.3"
40034013
strip-final-newline "^2.0.0"
40044014

4015+
execa@^9.6.1:
4016+
version "9.6.1"
4017+
resolved "https://registry.yarnpkg.com/execa/-/execa-9.6.1.tgz#5b90acedc6bdc0fa9b9a6ddf8f9cbb0c75a7c471"
4018+
integrity sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==
4019+
dependencies:
4020+
"@sindresorhus/merge-streams" "^4.0.0"
4021+
cross-spawn "^7.0.6"
4022+
figures "^6.1.0"
4023+
get-stream "^9.0.0"
4024+
human-signals "^8.0.1"
4025+
is-plain-obj "^4.1.0"
4026+
is-stream "^4.0.1"
4027+
npm-run-path "^6.0.0"
4028+
pretty-ms "^9.2.0"
4029+
signal-exit "^4.1.0"
4030+
strip-final-newline "^4.0.0"
4031+
yoctocolors "^2.1.1"
4032+
40054033
expect-type@^1.1.0:
40064034
version "1.3.0"
40074035
resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68"
@@ -4118,6 +4146,13 @@ figures@^3.0.0:
41184146
dependencies:
41194147
escape-string-regexp "^1.0.5"
41204148

4149+
figures@^6.1.0:
4150+
version "6.1.0"
4151+
resolved "https://registry.yarnpkg.com/figures/-/figures-6.1.0.tgz#935479f51865fa7479f6fa94fc6fc7ac14e62c4a"
4152+
integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==
4153+
dependencies:
4154+
is-unicode-supported "^2.0.0"
4155+
41214156
file-entry-cache@^6.0.1:
41224157
version "6.0.1"
41234158
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@@ -4396,6 +4431,14 @@ get-stream@^6.0.0:
43964431
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
43974432
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
43984433

4434+
get-stream@^9.0.0:
4435+
version "9.0.1"
4436+
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-9.0.1.tgz#95157d21df8eb90d1647102b63039b1df60ebd27"
4437+
integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==
4438+
dependencies:
4439+
"@sec-ant/readable-stream" "^0.4.1"
4440+
is-stream "^4.0.1"
4441+
43994442
get-symbol-description@^1.1.0:
44004443
version "1.1.0"
44014444
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee"
@@ -4507,7 +4550,7 @@ glob@^10.2.2, glob@^10.3.10, glob@^10.4.1:
45074550
package-json-from-dist "^1.0.0"
45084551
path-scurry "^1.11.1"
45094552

4510-
glob@^7.0.0, glob@^7.1.3:
4553+
glob@^7.1.3:
45114554
version "7.1.6"
45124555
resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz"
45134556
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -4834,6 +4877,11 @@ human-signals@^2.1.0:
48344877
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
48354878
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
48364879

4880+
human-signals@^8.0.1:
4881+
version "8.0.1"
4882+
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-8.0.1.tgz#f08bb593b6d1db353933d06156cedec90abe51fb"
4883+
integrity sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==
4884+
48374885
iconv-lite@0.6.3, iconv-lite@^0.6.2, iconv-lite@^0.6.3:
48384886
version "0.6.3"
48394887
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@@ -5016,11 +5064,6 @@ internal-slot@^1.1.0:
50165064
hasown "^2.0.2"
50175065
side-channel "^1.1.0"
50185066

5019-
interpret@^1.0.0:
5020-
version "1.2.0"
5021-
resolved "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz"
5022-
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
5023-
50245067
ip-address@^10.0.1:
50255068
version "10.1.0"
50265069
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4"
@@ -5231,7 +5274,7 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
52315274
resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz"
52325275
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
52335276

5234-
is-plain-obj@^4.0.0:
5277+
is-plain-obj@^4.0.0, is-plain-obj@^4.1.0:
52355278
version "4.1.0"
52365279
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0"
52375280
integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==
@@ -6503,6 +6546,14 @@ npm-run-path@^4.0.1:
65036546
dependencies:
65046547
path-key "^3.0.0"
65056548

6549+
npm-run-path@^6.0.0:
6550+
version "6.0.0"
6551+
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-6.0.0.tgz#25cfdc4eae04976f3349c0b1afc089052c362537"
6552+
integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==
6553+
dependencies:
6554+
path-key "^4.0.0"
6555+
unicorn-magic "^0.3.0"
6556+
65066557
nth-check@^2.0.1:
65076558
version "2.1.1"
65086559
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
@@ -6914,6 +6965,11 @@ parse-json@^5.2.0:
69146965
json-parse-even-better-errors "^2.3.0"
69156966
lines-and-columns "^1.1.6"
69166967

6968+
parse-ms@^4.0.0:
6969+
version "4.0.0"
6970+
resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-4.0.0.tgz#c0c058edd47c2a590151a718990533fd62803df4"
6971+
integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==
6972+
69176973
parse-path@^7.0.0:
69186974
version "7.1.0"
69196975
resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.1.0.tgz#41fb513cb122831807a4c7b29c8727947a09d8c6"
@@ -6990,6 +7046,11 @@ path-key@^3.0.0, path-key@^3.1.0:
69907046
resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
69917047
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
69927048

7049+
path-key@^4.0.0:
7050+
version "4.0.0"
7051+
resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
7052+
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
7053+
69937054
path-parse@^1.0.6:
69947055
version "1.0.6"
69957056
resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz"
@@ -7162,6 +7223,13 @@ pretty-format@^29.7.0:
71627223
ansi-styles "^5.0.0"
71637224
react-is "^18.0.0"
71647225

7226+
pretty-ms@^9.2.0:
7227+
version "9.3.0"
7228+
resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-9.3.0.tgz#dd2524fcb3c326b4931b2272dfd1e1a8ed9a9f5a"
7229+
integrity sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==
7230+
dependencies:
7231+
parse-ms "^4.0.0"
7232+
71657233
prismjs@^1.30.0:
71667234
version "1.30.0"
71677235
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9"
@@ -7351,13 +7419,6 @@ readdirp@^5.0.0:
73517419
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-5.0.0.tgz#fbf1f71a727891d685bb1786f9ba74084f6e2f91"
73527420
integrity sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==
73537421

7354-
rechoir@^0.6.2:
7355-
version "0.6.2"
7356-
resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz"
7357-
integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
7358-
dependencies:
7359-
resolve "^1.1.6"
7360-
73617422
redent@^3.0.0:
73627423
version "3.0.0"
73637424
resolved "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz"
@@ -7455,7 +7516,7 @@ resolve.exports@2.0.3:
74557516
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f"
74567517
integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==
74577518

7458-
resolve@^1.1.6, resolve@^1.10.0:
7519+
resolve@^1.10.0:
74597520
version "1.13.1"
74607521
resolved "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz"
74617522
integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
@@ -7914,15 +7975,6 @@ shell-quote@^1.8.2:
79147975
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b"
79157976
integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==
79167977

7917-
shelljs@0.8.5:
7918-
version "0.8.5"
7919-
resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz"
7920-
integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==
7921-
dependencies:
7922-
glob "^7.0.0"
7923-
interpret "^1.0.0"
7924-
rechoir "^0.6.2"
7925-
79267978
side-channel-list@^1.0.0:
79277979
version "1.0.0"
79287980
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
@@ -8282,6 +8334,11 @@ strip-final-newline@^2.0.0:
82828334
resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz"
82838335
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
82848336

8337+
strip-final-newline@^4.0.0:
8338+
version "4.0.0"
8339+
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz#35a369ec2ac43df356e3edd5dcebb6429aa1fa5c"
8340+
integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==
8341+
82858342
strip-indent@^3.0.0:
82868343
version "3.0.0"
82878344
resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz"

0 commit comments

Comments
 (0)