• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / cloud-foundry-tools-api / 4173844924

pending completion
4173844924

Pull #161

github

GitHub
Merge 8ead83807 into cd358e984
Pull Request #161: feat: add quote-vcap flag to bind-local

187 of 188 branches covered (99.47%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

468 of 471 relevant lines covered (99.36%)

11.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.37
/src/cli.ts
1
/* eslint-disable @typescript-eslint/no-explicit-any */
2
import { SpawnOptions, spawn } from "child_process";
1✔
3
import { parse } from "comment-json";
1✔
4
import * as _ from "lodash";
1✔
5
import { CliResult, CF_CMD_EXIT_CODE, CancellationToken } from "./types";
1✔
6

7
export class Cli {
1✔
8
  public static execute(args?: string[], options?: SpawnOptions, token?: CancellationToken): Promise<CliResult> {
9
    token = token || {
16✔
10
      isCancellationRequested: false,
11
      onCancellationRequested: () => {
12
        return;
5✔
13
      },
14
    };
15
    Cli.updateSpawnOptions(options);
16✔
16

17
    return new Promise<CliResult>((resolve) => {
16✔
18
      let stderr = "";
16✔
19
      let stdout = "";
16✔
20

21
      if (token.isCancellationRequested) {
16✔
22
        Cli.cliResultOnExit(stdout, resolve, stderr, CF_CMD_EXIT_CODE.CANCEL_REQ);
1✔
23
        return;
1✔
24
      }
25
      const childProcess = spawn(Cli.CF_CMD, args, options);
15✔
26

27
      childProcess.stdin.end();
15✔
28

29
      childProcess.stdout.on("data", (data: string) => {
15✔
30
        stdout = stdout.concat(data);
15✔
31
      });
32

33
      childProcess.stderr.on("data", (data: string) => {
15✔
34
        stderr = stderr.concat(data);
2✔
35
      });
36

37
      childProcess.on("exit", (code: number) => {
15✔
38
        Cli.cliResultOnExit(stdout, resolve, stderr, code);
13✔
39
      });
40

41
      childProcess.on("error", (err: any) => {
15✔
42
        const message = (
43
          _.get(err, "code") === "ENOENT" ? `${Cli.CF_CMD}: command not found` : _.get(err, "message")
2✔
44
        ) as string;
45
        resolve({ stdout: stdout, stderr: stderr, error: message, exitCode: CF_CMD_EXIT_CODE.ERROR });
2✔
46
      });
47

48
      // eslint-disable-next-line @typescript-eslint/no-unsafe-call
49
      token.onCancellationRequested(() => {
15✔
50
        childProcess.kill();
×
51
        Cli.cliResultOnExit("", resolve, "", CF_CMD_EXIT_CODE.CANCELED);
×
52
      });
53
    });
54
  }
55

56
  private static readonly CF_LOGIN_ERROR = "Not logged in. Use 'cf login' to log in.";
1✔
57
  private static readonly CF_CMD = "cf";
1✔
58

59
  private static cliResultOnExit(
60
    stdout: string,
61
    resolve: (value?: CliResult | PromiseLike<CliResult>) => void,
62
    stderr: string,
63
    code: number
64
  ) {
65
    if (stdout) {
14✔
66
      if (stdout.indexOf("error_code") > 0) {
12✔
67
        try {
2✔
68
          // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
69
          const cfErr = parse(stdout);
2✔
70
          const message = (
71
            _.get(cfErr, "code") === 10002 ? Cli.CF_LOGIN_ERROR : _.get(cfErr, "description", "Internal error occured")
2✔
72
          ) as string;
73
          resolve({ stdout: stdout, stderr: stderr, exitCode: CF_CMD_EXIT_CODE.ERROR, error: message });
2✔
74
          return;
2✔
75
        } catch (e) {
76
          // ignore, as probably not an error
77
        }
78
      } else if (stdout.startsWith("FAILED") && stdout.indexOf("Error creating request") > 0) {
10✔
79
        // most probably not logged in
80
        resolve({ stdout: stdout, stderr: stderr, error: Cli.CF_LOGIN_ERROR, exitCode: CF_CMD_EXIT_CODE.ERROR });
1✔
81
        return;
1✔
82
      } else if (/failed.*\bError\b:/g.test(stdout)) {
9✔
83
        // lgtm [js/polynomial-redos]
84
        // DEVXBUGS-5660
85
        try {
1✔
86
          parse(stdout); // ignore, well structured data - probably not an error
1✔
87
        } catch (e) {
88
          resolve({ stdout: stdout, stderr: stderr, error: stdout, exitCode: CF_CMD_EXIT_CODE.ERROR });
1✔
89
          return;
1✔
90
        }
91
      } else if (stdout.startsWith("FAILED") && stdout.indexOf("No API endpoint set") > 0) {
8✔
92
        // DEVXBUGS-6488
93
        resolve({ stdout: stdout, stderr: stderr, error: stdout, exitCode: CF_CMD_EXIT_CODE.ERROR });
1✔
94
        return;
1✔
95
      }
96
    }
97
    resolve({ stdout: stdout, stderr: stderr, exitCode: code });
9✔
98
  }
99

100
  private static updateSpawnOptions(options: SpawnOptions) {
101
    if (options) {
16✔
102
      options.env = {
2✔
103
        ...process.env,
104
        NODE_VERSION: process.versions.node,
105
        ...options.env,
106
      };
107
      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
108
      _.defaults(options, { cwd: _.get(options, "cmd", __dirname) });
2✔
109
    }
110
  }
111
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc