Skip to content

Commit a7eed65

Browse files
committed
feat: add manual test workflow for CLI authentication
Add semi-automated testing workflow for project use tests that require human browser-based authentication. These tests ensure the --local flag works correctly with CLI key authentication. Implementation: - Created project_use_manual_test.go with 4 manual tests (build tag: manual) - Added RequireCLIAuthentication() helper that forces fresh login - Helper clears existing auth, runs 'hookdeck login', waits for user - Existing automated tests remain in project_use_test.go (run in CI) - Manual tests only run with: go test -tags=manual Testing workflow: - Tests clear authentication and require fresh CLI login - User completes browser authentication when prompted - Tests verify local config creation with project selection - Validates security warnings and smart default behavior Documentation: - Updated test/acceptance/README.md with manual test instructions - Explained difference between automated (CI) and manual tests - Provided examples of running manual tests locally - Documented which tests require human authentication Feature implementation: - Added security warning output in project_use.go for new local configs - Fixed config writing logic in config.go to properly handle new files - Refactored project_use_test.go to separate automated vs manual tests - Updated test comments to clarify CI vs local execution requirements Related: Completes semi-automated testing for --local flag feature
1 parent a81a219 commit a7eed65

File tree

6 files changed

+576
-171
lines changed

6 files changed

+576
-171
lines changed

pkg/cmd/project_use.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ func (lc *projectUseCmd) runProjectUseCmd(cmd *cobra.Command, args []string) err
243243
if strings.Contains(configPath, ".hookdeck/config.toml") {
244244
if isNewConfig && lc.local {
245245
fmt.Printf("Created: %s\n", configPath)
246+
// Show security warning for new local configs
247+
fmt.Printf("\n%s\n", color.Yellow("Security:"))
248+
fmt.Printf(" Local config files contain credentials and should NOT be committed to source control.\n")
249+
fmt.Printf(" Add .hookdeck/ to your .gitignore file.\n")
246250
} else {
247251
fmt.Printf("Updated: %s\n", configPath)
248252
}

pkg/config/config.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,21 +205,19 @@ func (c *Config) writeProjectConfig(configPath string, isNewFile bool) error {
205205
// Create a new viper instance for the config
206206
v := viper.New()
207207
v.SetConfigType("toml")
208-
v.SetConfigFile(configPath)
209208

210-
// Try to read existing config (ignore error if doesn't exist)
211-
_ = v.ReadInConfig()
209+
// If file exists, read it first to preserve any other settings
210+
if !isNewFile {
211+
v.SetConfigFile(configPath)
212+
_ = v.ReadInConfig() // Ignore error - we'll overwrite anyway
213+
}
212214

213215
// Set all profile fields
214216
c.setProfileFieldsInViper(v)
215217

216-
// Write config file
217-
var writeErr error
218-
if isNewFile {
219-
writeErr = v.SafeWriteConfig()
220-
} else {
221-
writeErr = v.WriteConfig()
222-
}
218+
// Write config file using WriteConfigAs which explicitly takes a path
219+
// This avoids the viper internal "configPath" issue
220+
writeErr := v.WriteConfigAs(configPath)
223221
if writeErr != nil {
224222
return fmt.Errorf("failed to write config to %s: %w", configPath, writeErr)
225223
}

test/acceptance/README.md

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
This directory contains Go-based acceptance tests for the Hookdeck CLI. These tests verify end-to-end functionality by executing the CLI and validating outputs.
44

5+
## Test Categories
6+
7+
Tests are divided into two categories:
8+
9+
### 1. Automated Tests (CI-Compatible)
10+
These tests run automatically in CI using API keys from `hookdeck ci`. They don't require human interaction.
11+
12+
**Files:** All test files without build tags (e.g., `basic_test.go`, `connection_test.go`, `project_use_test.go`)
13+
14+
### 2. Manual Tests (Require Human Interaction)
15+
These tests require browser-based authentication via `hookdeck login` and must be run manually by developers.
16+
17+
**Files:** Test files with `//go:build manual` tag (e.g., `project_use_manual_test.go`)
18+
19+
**Why Manual?** These tests access endpoints (like `/teams`) that require CLI authentication keys obtained through interactive browser login, which aren't available to CI service accounts.
20+
521
## Setup
622

723
### Local Development
@@ -21,14 +37,19 @@ In CI environments (GitHub Actions), set the `HOOKDECK_CLI_TESTING_API_KEY` envi
2137

2238
## Running Tests
2339

24-
### Run all acceptance tests:
40+
### Run all automated (CI) tests:
2541
```bash
2642
go test ./test/acceptance/... -v
2743
```
2844

29-
### Run specific test:
45+
### Run manual tests (requires human authentication):
46+
```bash
47+
go test -tags=manual -v ./test/acceptance/
48+
```
49+
50+
### Run specific manual test:
3051
```bash
31-
go test ./test/acceptance/... -v -run TestCLIBasics
52+
go test -tags=manual -run TestProjectUseLocalCreatesConfig -v ./test/acceptance/
3253
```
3354

3455
### Skip acceptance tests (short mode):
@@ -38,12 +59,89 @@ go test ./test/acceptance/... -short
3859

3960
All acceptance tests are skipped when `-short` flag is used, allowing fast unit test runs.
4061

62+
## Manual Test Workflow
63+
64+
When you run manual tests, here's what happens:
65+
66+
### Example Session
67+
```bash
68+
$ go test -tags=manual -v ./test/acceptance/
69+
70+
=== RUN TestProjectUseLocalCreatesConfig
71+
72+
🔐 Fresh Authentication Required
73+
=================================
74+
These tests require fresh CLI authentication with project access.
75+
76+
Step 1: Clearing existing authentication...
77+
✅ Authentication cleared
78+
79+
Step 2: Starting login process...
80+
Running: hookdeck login
81+
82+
[Browser opens for authentication - complete the login process]
83+
84+
Please complete the browser authentication if not already done.
85+
Press Enter when you've successfully logged in and are ready to continue...
86+
87+
[User presses Enter]
88+
89+
Verifying authentication...
90+
✅ Authenticated successfully: Logged in as user@example.com on project my-project in organization Acme Inc
91+
92+
--- PASS: TestProjectUseLocalCreatesConfig (15.34s)
93+
94+
=== RUN TestProjectUseSmartDefault
95+
✅ Already authenticated (from previous test)
96+
--- PASS: TestProjectUseSmartDefault (1.12s)
97+
98+
...
99+
```
100+
101+
### What the Helper Does
102+
103+
The [`RequireCLIAuthenticationOnce(t)`](helpers.go:268) helper function:
104+
105+
1. **Clears existing authentication** by running `hookdeck logout` and deleting config files
106+
2. **Runs `hookdeck login`** which opens a browser for authentication
107+
3. **Waits for you to press Enter** after completing browser authentication (gives you full control)
108+
4. **Verifies authentication** by running `hookdeck whoami`
109+
5. **Fails the test** if authentication doesn't succeed
110+
6. **Runs only once per test session** - subsequent tests in the same run reuse the authentication
111+
112+
### Which Tests Require Manual Authentication
113+
114+
**Automated Tests (project_use_test.go):**
115+
- ✅ `TestProjectUseLocalAndConfigFlagConflict` - Flag validation only, no API calls
116+
- ✅ `TestLocalConfigHelpers` - Helper function tests, no API calls
117+
118+
**Manual Tests (project_use_manual_test.go):**
119+
- 🔐 `TestProjectUseLocalCreatesConfig` - Requires `/teams` endpoint access
120+
- 🔐 `TestProjectUseSmartDefault` - Requires `/teams` endpoint access
121+
- 🔐 `TestProjectUseLocalCreateDirectory` - Requires `/teams` endpoint access
122+
- 🔐 `TestProjectUseLocalSecurityWarning` - Requires `/teams` endpoint access
123+
124+
### Tips for Running Manual Tests
125+
126+
- **Run all manual tests together** to authenticate only once:
127+
```bash
128+
go test -tags=manual -v ./test/acceptance/
129+
```
130+
131+
- **Authentication persists** across tests in the same run (handled by `RequireCLIAuthenticationOnce`)
132+
133+
- **Fresh authentication each run** - existing auth is always cleared at the start
134+
135+
- **Be ready to authenticate** - the browser will open automatically when you run the tests
136+
41137
## Test Structure
42138

43139
### Files
44140

45141
- **`helpers.go`** - Test infrastructure and utilities
46142
- `CLIRunner` - Executes CLI commands via `go run main.go`
143+
- `RequireCLIAuthentication(t)` - Forces fresh CLI authentication for manual tests
144+
- `RequireCLIAuthenticationOnce(t)` - Authenticates once per test run
47145
- Helper functions for creating/deleting test resources
48146
- JSON parsing utilities
49147
- Data structures (Connection, etc.)
@@ -65,6 +163,16 @@ All acceptance tests are skipped when `-short` flag is used, allowing fast unit
65163
- Context-based process management
66164
- Background process handling
67165

166+
- **`project_use_test.go`** - Project use automated tests (CI-compatible)
167+
- Flag validation tests
168+
- Helper function tests
169+
- Tests that don't require `/teams` endpoint access
170+
171+
- **`project_use_manual_test.go`** - Project use manual tests (requires human auth)
172+
- Build tag: `//go:build manual`
173+
- Tests that require browser-based authentication
174+
- Tests that access `/teams` endpoint
175+
68176
- **`.env`** - Local environment variables (git-ignored)
69177
70178
### Key Components

0 commit comments

Comments
 (0)