Skip to content

Commit 6074e53

Browse files
authored
Handle offline scenarios more gracefully (#305)
If a Yarn install command fails due to connectivity issues, we should provide actionable advice on next steps to the user.
1 parent f7968ef commit 6074e53

File tree

4 files changed

+83
-18
lines changed

4 files changed

+83
-18
lines changed

.changeset/mean-rice-film.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'skuba': patch
3+
---
4+
5+
**configure, init:** Improve error messaging in offline scenarios

src/cli/configure/index.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,29 @@ export const configure = async () => {
106106
streamStdio: 'yarn',
107107
});
108108

109-
log.plain('Installing dependencies...');
110-
await exec('yarn', 'install', '--silent');
109+
log.newline();
110+
try {
111+
await exec('yarn', 'install');
112+
} catch {
113+
log.newline();
114+
log.warn(log.bold('✗ Failed to install dependencies. Resume with:'));
115+
116+
log.newline();
117+
log.plain(log.bold('yarn install'));
118+
log.plain(log.bold('yarn format'));
119+
120+
log.newline();
121+
process.exit(1);
122+
}
111123
}
112124

113125
if (fixConfiguration || fixDependencies) {
114126
log.newline();
115-
log.ok(`Try running ${log.bold('yarn format')}.`);
127+
log.ok(log.bold('✔ All done! Try running:'));
128+
129+
log.newline();
130+
log.plain(log.bold('yarn format'));
116131
}
132+
133+
log.newline();
117134
};

src/cli/init/index.ts

+27-12
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,37 @@ export const init = async () => {
7979
log.newline();
8080
await initialiseRepo(exec, templateData);
8181

82-
log.plain('Installing dependencies...');
83-
await exec(
84-
'yarn',
85-
'add',
86-
'--dev',
87-
'--exact',
88-
'--silent',
89-
`skuba@${skubaVersionInfo.local}`,
90-
);
82+
const skubaSlug = `skuba@${skubaVersionInfo.local}`;
83+
84+
let depsInstalled = false;
85+
try {
86+
await exec('yarn', 'add', '--dev', skubaSlug);
87+
depsInstalled = true;
88+
} catch {}
9189

9290
await commitChanges(exec, `Clone ${templateName}`);
9391

92+
if (!depsInstalled) {
93+
log.newline();
94+
log.warn(log.bold('✗ Failed to install dependencies. Resume with:'));
95+
96+
log.newline();
97+
log.plain(log.bold('cd', destinationDir));
98+
log.plain(log.bold('yarn add --dev', skubaSlug));
99+
log.plain(log.bold('git add --all'));
100+
log.plain(log.bold('git commit --message', `'Pin ${skubaSlug}'`));
101+
log.plain(log.bold('git push --set-upstream origin master'));
102+
103+
log.newline();
104+
process.exit(1);
105+
}
106+
107+
log.newline();
108+
log.ok(log.bold('✔ All done! Try running:'));
109+
94110
log.newline();
95-
log.ok('✔ All done! Try running:');
111+
log.plain(log.bold('cd', destinationDir));
112+
log.plain(log.bold('git push --set-upstream origin master'));
96113

97114
log.newline();
98-
log.ok(log.bold('cd', destinationDir));
99-
log.ok(log.bold('git push --set-upstream origin master'));
100115
};

src/utils/exec.ts

+31-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,33 @@ import npmWhich from 'npm-which';
1010
import { ConcurrentlyErrors, isErrorWithCode } from './error';
1111
import { log } from './logging';
1212

13+
class YarnSpamFilter extends stream.Transform {
14+
silenced = false;
15+
16+
_transform(
17+
chunk: any,
18+
_encoding: BufferEncoding,
19+
callback: stream.TransformCallback,
20+
) {
21+
const str = Buffer.from(chunk).toString();
22+
23+
// Yarn spews the entire installed dependency tree after this message
24+
if (str.startsWith('info Direct dependencies')) {
25+
this.silenced = true;
26+
}
27+
28+
if (
29+
!this.silenced &&
30+
// This isn't very useful given the command generates a lockfile
31+
!str.startsWith('info No lockfile found')
32+
) {
33+
this.push(chunk);
34+
}
35+
36+
callback();
37+
}
38+
}
39+
1340
class YarnWarningFilter extends stream.Transform {
1441
_transform(
1542
chunk: any,
@@ -54,10 +81,11 @@ const runCommand = (command: string, args: string[], opts?: ExecOptions) => {
5481

5582
switch (opts?.streamStdio) {
5683
case 'yarn':
57-
const filter = new YarnWarningFilter();
84+
const stderrFilter = new YarnWarningFilter();
85+
const stdoutFilter = new YarnSpamFilter();
5886

59-
subprocess.stderr?.pipe(filter).pipe(process.stderr);
60-
subprocess.stdout?.pipe(process.stdout);
87+
subprocess.stderr?.pipe(stderrFilter).pipe(process.stderr);
88+
subprocess.stdout?.pipe(stdoutFilter).pipe(process.stdout);
6189

6290
break;
6391

0 commit comments

Comments
 (0)