jdalrymple / gitbeaker

🦊🧪 A comprehensive and typed Gitlab SDK for Node.js, Browsers, Deno and CLI
Other
1.57k stars 298 forks source link

@gitbeaker/cli calls that error return an exit code of 0 #3657

Open robross0606 opened 22 hours ago

robross0606 commented 22 hours ago

Description

Invocations which do not have necessary parameters will return an error message along with help syntax and return a proper non-zero exit code. However, invocations which have enough info to make the REST call but fail due to server response return the raw JSON error response and do not react as a normal CLI tool would in that they do not output the error to stderr and do not result in a non-zero exit code. This makes its use in pipelines problematic because we must now somehow parse the response to understand it is an error. That somewhat defeats the purpose of the CLI tool, increasing complexity beyond using the raw API instead. Raw API tools like wget or curl recognize standard HTTP errors and have options to treat them as a proper exit code, which makes using this cli tool actually harder than raw API usage in many ways.

Steps to reproduce

Invoke any bad call which has enough information to construct a call but fail on the server side:

gitbeaker project-releases hello kitty

Expected behaviour

The error response should be returned via stderr and the exit code should not be 0 (which indicates a success).

Actual behaviour

The error response is return on stdout and the exit code is 0 which implies the cli command succeeded.

# gitbeaker project-releases create hello kitty
(node:115) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
GitbeakerRequestError: Not Found
    at throwFailedRequestError (file:///<redacted>/@gitbeaker/cli/lib/node_modules/@gitbeaker/cli/node_modules/@gitbeaker/rest/dist/index.mjs:41:9)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async defaultRequestHandler (file:///<redacted>/@gitbeaker/cli/lib/node_modules/@gitbeaker/cli/node_modules/@gitbeaker/rest/dist/index.mjs:74:48)
    at async file:///<redacted>/@gitbeaker/cli/lib/node_modules/@gitbeaker/cli/node_modules/@gitbeaker/core/dist/index.mjs:131:22
    at async Promise.all (index 10)
    at async Promise.all (index 125) {
  cause: {
    description: '404 Project Not Found',
    request: Request {
      method: 'POST',
      url: 'https://gitlab.com/api/v4/projects/hello/releases',
      headers: Headers { 'content-type': 'application/json' },
      destination: '',
      referrer: 'about:client',
      referrerPolicy: '',
      mode: 'cors',
      credentials: 'same-origin',
      cache: 'default',
      redirect: 'follow',
      integrity: '',
      keepalive: false,
      isReloadNavigation: false,
      isHistoryNavigation: false,
      signal: AbortSignal { aborted: false }
    },
    response: Response {
      status: 404,
      statusText: 'Not Found',
      headers: Headers {
        date: 'Mon, 18 Nov 2024 20:48:27 GMT',
        'content-type': 'application/json',
        'content-length': '35',
        connection: 'keep-alive',
        'cache-control': 'no-cache',
        'content-security-policy': "default-src 'none'",
        vary: 'Origin',
        'x-content-type-options': 'nosniff',
        'x-frame-options': 'SAMEORIGIN',
        'x-gitlab-meta': '{"correlation_id":"<redacted>","version":"1"}',
        'x-request-id': '<redacted>',
        'x-runtime': '0.022713',
        'strict-transport-security': 'max-age=31536000',
        'referrer-policy': 'strict-origin-when-cross-origin',
        'gitlab-lb': 'haproxy-main-06-lb-gprd',
        'gitlab-sv': 'api-gke-us-east1-b',
        'cf-cache-status': 'DYNAMIC',
        'report-to': '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=<redacted>"}],"group":"cf-nel","max_age":604800}',
        nel: '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}',
        'set-cookie': '<redacted>; path=/; domain=.gitlab.com; HttpOnly; Secure; SameSite=None',
        server: 'cloudflare',
        'cf-ray': '<redacted>'
      },
      body: ReadableStream { locked: true, state: 'closed', supportsBYOB: true },
      bodyUsed: true,
      ok: false,
      redirected: false,
      type: 'basic',
      url: 'https://gitlab.com/api/v4/projects/hello/releases'
    }
  }
}

# echo $?
0

Possible fixes

A failed call should at least result in an exit code other than 0. The cli tool does return a bad error code if incorrect number of required parameters are returned:

# gitbeaker project-releases create 

Usage: gitbeaker project-releases create [--project-id] <project-id> [options]

Required Options
  [--project-id] <project-id> [object Object]   [object Object]  [required] [string] [object Object]
...
Missing required argument: project-id

# echo $?
1

However, it does not result in a bad exit code if the REST call itself fails.

Checklist

robross0606 commented 6 hours ago

Since Sywac is being used behind the scenes, and error handling documentation is sparse, here is an open issue thread discussing error handling: https://github.com/sywac/sywac/issues/63

robross0606 commented 6 hours ago

While we're at it, are all those [object Object] in the usage documentation intended?

Required Options
  [--project-id] <project-id> [object Object]   [object Object]  [required] [string] [object Object]

Since the cli doesn't appear to accept "objects", it makes me think there's a bug in here related to toString().