From 21c539e12db585b50440397825df00534a0807e7 Mon Sep 17 00:00:00 2001 From: yxzhaao Date: Tue, 21 Jul 2026 23:17:19 +0800 Subject: [PATCH] fix(e2e): inject shared credentials by identity --- tests/cli_e2e/core.go | 54 ++++++++++++++++++++++++++--------- tests/cli_e2e/core_test.go | 58 ++++++++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 22 deletions(-) diff --git a/tests/cli_e2e/core.go b/tests/cli_e2e/core.go index bac8fdb5b4..82b6e9fe93 100644 --- a/tests/cli_e2e/core.go +++ b/tests/cli_e2e/core.go @@ -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. @@ -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 { @@ -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 { diff --git a/tests/cli_e2e/core_test.go b/tests/cli_e2e/core_test.go index 8d83d4b2f2..2ebfc14e8a 100644 --- a/tests/cli_e2e/core_test.go +++ b/tests/cli_e2e/core_test.go @@ -190,7 +190,7 @@ 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", "") @@ -198,8 +198,8 @@ func TestSkipWithoutTenantAccessToken(t *testing.T) { 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")) @@ -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") + }) + t.Run("retries structured retryable service errors by default", func(t *testing.T) { fake := newFakeCLI(t) statePath := filepath.Join(t.TempDir(), "retry-count")