Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Before using most `nbctl` commands, you need to configure your Nudgebee API cred
This command interactively guides you through setting up a new configuration profile or updating an existing one. If `profile-name` is not provided, it defaults to `default`. You will be prompted for:

* **Nudgebee API Endpoint**: The URL of the Nudgebee API (e.g., `https://api.nudgebee.com`).
* **Nudgebee API Key**: Your personal API key for authentication.
* **Nudgebee API Key**: Your personal API token (`sk-nb-…`), created under **Settings → API Tokens**. `nbctl` sends it directly as a Bearer token on every request. Tokens created before direct token auth was supported are rejected with a 401 and must be recreated.
* **Nudgebee Username**: Your Nudgebee account username (e.g., your email).
* **Default Account ID**: The ID of the Nudgebee account you wish to interact with by default.

Expand Down
4 changes: 2 additions & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Helpers
The package `pkg/testutil` exposes the following useful helpers:

- `RunWithSimpleGraphQL(mockData any, cmd *cobra.Command, args []string) (string, error)`
- Convenience for mocking a GraphQL response. Automatically mocks `/api/auth/token` and
returns `{ "data": mockData }` at `/api/graphql`. Useful for simple, static tests.
- Convenience for mocking a GraphQL response. Returns `{ "data": mockData }` at
`/api/graphql`. Useful for simple, static tests.

- `RunWithMockServer(handler http.HandlerFunc, viperOverrides map[string]any, cmd *cobra.Command, args []string) (string, error)`
- More flexible: provide a handler to simulate complex behavior, and a small map of viper overrides (e.g. `api-key`, `username`). The helper sets the `endpoint` viper key to the test server URL and restores previous viper values after the test.
Expand Down
2 changes: 1 addition & 1 deletion cmd/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ var configureAddCmd = &cobra.Command{

// Validate the configuration by making a simple API call
fmt.Println("Validating configuration...")
gqlClient := client.NewClient(client.WithApiKey(apiKey), client.WithEndpoint(endpoint), client.WithUsername(username))
gqlClient := client.NewClient(client.WithApiKey(apiKey), client.WithEndpoint(endpoint))
req := client.NewRequest(`
query {
cloud_accounts: accounts_list(where: {}, limit: 1, offset: 0) {
Expand Down
20 changes: 0 additions & 20 deletions cmd/nubi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ func TestNubiCmd_AsyncQuery_TriggerError_JSON(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]any{
Expand Down Expand Up @@ -116,8 +114,6 @@ func TestNubiCmd_Query_AccessDenied_Text(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]any{
Expand Down Expand Up @@ -162,8 +158,6 @@ func TestNubiCmd_SyncQuery(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
resp := map[string]interface{}{
"data": map[string]interface{}{
Expand Down Expand Up @@ -225,8 +219,6 @@ func TestNubiCmd_SyncQuery_JSON(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
resp := map[string]interface{}{
"data": map[string]interface{}{
Expand Down Expand Up @@ -294,8 +286,6 @@ func TestNubiCmd_Query_Timeout(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
resp := map[string]interface{}{
"data": map[string]interface{}{
Expand Down Expand Up @@ -343,8 +333,6 @@ func TestNubiCmd_Query_Timeout_JSON(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
resp := map[string]interface{}{
"data": map[string]interface{}{
Expand Down Expand Up @@ -396,8 +384,6 @@ func TestNubiCmd_Query_TransientRetry(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
pollCount++
if pollCount == 2 {
Expand Down Expand Up @@ -815,8 +801,6 @@ func TestNubiCmd_Get_WithAccountId(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
var payload struct {
Query string `json:"query"`
Expand Down Expand Up @@ -882,8 +866,6 @@ func TestNubiCmd_Get_SessionId_WithAccountId(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
var payload struct {
Query string `json:"query"`
Expand Down Expand Up @@ -962,8 +944,6 @@ func TestNubiCmd_SyncQuery_SessionIdDiffersFromConversationId(t *testing.T) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.URL.Path {
case "/api/auth/token":
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
case "/api/graphql":
var payload struct {
Query string `json:"query"`
Expand Down
10 changes: 0 additions & 10 deletions cmd/workflow_apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ definition:
require.NoError(t, tmpFile.Close())

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
var reqBody struct {
Query string `json:"query"`
Expand Down Expand Up @@ -108,11 +103,6 @@ definition:
require.NoError(t, tmpFile.Close())

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
var reqBody struct {
Query string `json:"query"`
Expand Down
10 changes: 0 additions & 10 deletions cmd/workflow_cancel_execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ func TestWorkflowCancelExecutionCmd(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
var reqBody struct {
Query string `json:"query"`
Expand Down Expand Up @@ -62,11 +57,6 @@ func TestWorkflowCancelExecutionCmd_JSON(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
Expand Down
10 changes: 0 additions & 10 deletions cmd/workflow_delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ func TestWorkflowDeleteCmd(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
var reqBody struct {
Query string `json:"query"`
Expand Down Expand Up @@ -62,11 +57,6 @@ func TestWorkflowDeleteCmd_JSON(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
Expand Down
10 changes: 0 additions & 10 deletions cmd/workflow_pause_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ func TestWorkflowPauseCmd(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
var reqBody struct {
Query string `json:"query"`
Expand Down Expand Up @@ -62,11 +57,6 @@ func TestWorkflowPauseCmd_JSON(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
Expand Down
10 changes: 0 additions & 10 deletions cmd/workflow_resume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ func TestWorkflowResumeCmd(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
var reqBody struct {
Query string `json:"query"`
Expand Down Expand Up @@ -62,11 +57,6 @@ func TestWorkflowResumeCmd_JSON(t *testing.T) {
defer func() { _ = os.Unsetenv("NBCTL_TESTING") }()

handler := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
Expand Down
10 changes: 0 additions & 10 deletions cmd/workflow_validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ definition:
}

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
w.Header().Set("Content-Type", "application/json")
// Return top-level errors
Expand Down Expand Up @@ -186,11 +181,6 @@ definition:

// We need to use RunWithMockServer to simulate top-level errors (not wrapped in data)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/auth/token" {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{"token": "fake-token", "expiry": 3600})
return
}
if r.URL.Path == "/api/graphql" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
Expand Down
Loading
Loading