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
54 changes: 41 additions & 13 deletions tests/cli_e2e/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ func SkipWithoutTenantAccessToken(t *testing.T) {
if token == "" || appID == "" {
t.Skip("skipped: tenant test credentials not set")
}

// Scope standard env credentials to tests that explicitly require a live
// tenant token. Keeping TEST_* variables in the gotestsum parent prevents
// config and dry-run CLI subprocesses from activating the env provider.
t.Setenv("LARKSUITE_CLI_APP_ID", appID)
t.Setenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN", token)
}

// DryRunGet reads a field from the dry-run payload inside the standard success envelope.
Expand Down Expand Up @@ -245,14 +239,36 @@ func buildCommandEnv(req Request) []string {
for k, v := range req.Env {
overrides[k] = v
}
// Keep user-token injection scoped to user-only test commands so bot
// commands retain the process-level bot credentials.
if req.DefaultAs == "user" {
if appID := os.Getenv("TEST_BOT1_APP_ID"); appID != "" {
overrides["LARKSUITE_CLI_APP_ID"] = appID

// Shared TEST_* credentials are fallbacks for explicitly identified live
// commands. Existing standard env (including dry-run fixtures) and
// per-request overrides always take precedence.
switch req.DefaultAs {
case "bot":
if !hasCredentialEnv(req.Env,
"LARKSUITE_CLI_APP_ID",
"LARKSUITE_CLI_APP_SECRET",
"LARKSUITE_CLI_TENANT_ACCESS_TOKEN",
) {
appID := os.Getenv("TEST_BOT1_APP_ID")
token := os.Getenv("TEST_TENANT_ACCESS_TOKEN")
if appID != "" && token != "" {
overrides["LARKSUITE_CLI_APP_ID"] = appID
overrides["LARKSUITE_CLI_TENANT_ACCESS_TOKEN"] = token
}
}
if token := os.Getenv("TEST_USER_ACCESS_TOKEN"); token != "" {
overrides["LARKSUITE_CLI_USER_ACCESS_TOKEN"] = token
case "user":
if !hasCredentialEnv(req.Env,
"LARKSUITE_CLI_APP_ID",
"LARKSUITE_CLI_APP_SECRET",
"LARKSUITE_CLI_USER_ACCESS_TOKEN",
) {
appID := os.Getenv("TEST_BOT1_APP_ID")
token := os.Getenv("TEST_USER_ACCESS_TOKEN")
if appID != "" && token != "" {
overrides["LARKSUITE_CLI_APP_ID"] = appID
overrides["LARKSUITE_CLI_USER_ACCESS_TOKEN"] = token
}
}
}
for k, v := range overrides {
Expand All @@ -272,6 +288,18 @@ func buildCommandEnv(req Request) []string {
return env
}

func hasCredentialEnv(requestEnv map[string]string, keys ...string) bool {
for _, key := range keys {
if _, ok := requestEnv[key]; ok {
return true
}
if os.Getenv(key) != "" {
return true
}
}
return false
}

// RunCmdWithRetry reruns a command when the result matches the configured retry condition.
func RunCmdWithRetry(ctx context.Context, req Request, opts RetryOptions) (*Result, error) {
if opts.Attempts <= 0 {
Expand Down
58 changes: 49 additions & 9 deletions tests/cli_e2e/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,16 @@ func TestSkipWithoutTenantAccessToken(t *testing.T) {
assert.True(t, ran)
})

t.Run("scopes shared tenant credentials to the requiring test", func(t *testing.T) {
t.Run("accepts shared tenant credentials without mutating standard env", func(t *testing.T) {
t.Setenv("TEST_BOT1_APP_ID", "shared-test-app")
t.Setenv("TEST_TENANT_ACCESS_TOKEN", "shared-test-token")
t.Setenv("LARKSUITE_CLI_APP_ID", "")
t.Setenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN", "")

ok := t.Run("inner", func(t *testing.T) {
SkipWithoutTenantAccessToken(t)
assert.Equal(t, "shared-test-app", os.Getenv("LARKSUITE_CLI_APP_ID"))
assert.Equal(t, "shared-test-token", os.Getenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN"))
assert.Empty(t, os.Getenv("LARKSUITE_CLI_APP_ID"))
assert.Empty(t, os.Getenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN"))
})
require.True(t, ok)
assert.Empty(t, os.Getenv("LARKSUITE_CLI_APP_ID"))
Expand Down Expand Up @@ -274,25 +274,65 @@ func TestRunCmd(t *testing.T) {
assert.Equal(t, "hello from stdin\n", result.Stdout)
})

t.Run("injects user token env only for user commands", func(t *testing.T) {
t.Run("injects shared credentials by requested identity", func(t *testing.T) {
t.Setenv("LARKSUITE_CLI_APP_ID", "")
t.Setenv("LARKSUITE_CLI_APP_SECRET", "")
t.Setenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN", "")
t.Setenv("LARKSUITE_CLI_USER_ACCESS_TOKEN", "")
t.Setenv("TEST_BOT1_APP_ID", "cli_app_test")
t.Setenv("TEST_TENANT_ACCESS_TOKEN", "tat_test")
t.Setenv("TEST_USER_ACCESS_TOKEN", "uat_test")

env := buildCommandEnv(Request{DefaultAs: "user"})
env := buildCommandEnv(Request{DefaultAs: "bot"})
assert.Contains(t, env, "LARKSUITE_CLI_APP_ID=cli_app_test")
assert.Contains(t, env, "LARKSUITE_CLI_USER_ACCESS_TOKEN=uat_test")

env = buildCommandEnv(Request{DefaultAs: "bot"})
assert.NotContains(t, env, "LARKSUITE_CLI_APP_ID=cli_app_test")
assert.Contains(t, env, "LARKSUITE_CLI_TENANT_ACCESS_TOKEN=tat_test")
assert.NotContains(t, env, "LARKSUITE_CLI_USER_ACCESS_TOKEN=uat_test")

env = buildCommandEnv(Request{DefaultAs: "user"})
assert.Contains(t, env, "LARKSUITE_CLI_APP_ID=cli_app_test")
assert.Contains(t, env, "LARKSUITE_CLI_USER_ACCESS_TOKEN=uat_test")
assert.NotContains(t, env, "LARKSUITE_CLI_TENANT_ACCESS_TOKEN=tat_test")

env = buildCommandEnv(Request{})
assert.NotContains(t, env, "LARKSUITE_CLI_APP_ID=cli_app_test")
assert.NotContains(t, env, "LARKSUITE_CLI_TENANT_ACCESS_TOKEN=tat_test")
assert.NotContains(t, env, "LARKSUITE_CLI_USER_ACCESS_TOKEN=uat_test")
})

t.Run("preserves standard dry-run bot credentials", func(t *testing.T) {
t.Setenv("LARKSUITE_CLI_APP_ID", "dry-run-app")
t.Setenv("LARKSUITE_CLI_APP_SECRET", "dry-run-secret")
t.Setenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN", "")
t.Setenv("TEST_BOT1_APP_ID", "shared-test-app")
t.Setenv("TEST_TENANT_ACCESS_TOKEN", "shared-test-token")

env := buildCommandEnv(Request{DefaultAs: "bot"})
assert.Contains(t, env, "LARKSUITE_CLI_APP_ID=dry-run-app")
assert.Contains(t, env, "LARKSUITE_CLI_APP_SECRET=dry-run-secret")
assert.NotContains(t, env, "LARKSUITE_CLI_APP_ID=shared-test-app")
assert.NotContains(t, env, "LARKSUITE_CLI_TENANT_ACCESS_TOKEN=shared-test-token")
})

t.Run("request env overrides shared bot credentials", func(t *testing.T) {
t.Setenv("LARKSUITE_CLI_APP_ID", "")
t.Setenv("LARKSUITE_CLI_APP_SECRET", "")
t.Setenv("LARKSUITE_CLI_TENANT_ACCESS_TOKEN", "")
t.Setenv("TEST_BOT1_APP_ID", "shared-test-app")
t.Setenv("TEST_TENANT_ACCESS_TOKEN", "shared-test-token")

env := buildCommandEnv(Request{
DefaultAs: "bot",
Env: map[string]string{
"LARKSUITE_CLI_APP_ID": "request-app",
"LARKSUITE_CLI_TENANT_ACCESS_TOKEN": "",
},
})
assert.Contains(t, env, "LARKSUITE_CLI_APP_ID=request-app")
assert.Contains(t, env, "LARKSUITE_CLI_TENANT_ACCESS_TOKEN=")
assert.NotContains(t, env, "LARKSUITE_CLI_APP_ID=shared-test-app")
assert.NotContains(t, env, "LARKSUITE_CLI_TENANT_ACCESS_TOKEN=shared-test-token")
})
Comment thread
yxzhaao marked this conversation as resolved.

t.Run("retries structured retryable service errors by default", func(t *testing.T) {
fake := newFakeCLI(t)
statePath := filepath.Join(t.TempDir(), "retry-count")
Expand Down
Loading