Skip to content
Open
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
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
run:
shell: bash
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
Expand Down Expand Up @@ -46,10 +46,10 @@ jobs:
flags: ${{ runner.os }}

- name: Report Status
if: always()
uses: ravsamhq/notify-slack-action@v1
if: failure()
uses: 8398a7/action-slack@77eaa4f1c608a7d68b38af4e3f739dcd8cba273e
with:
status: ${{ job.status }}
notify_when: "failure"
fields: repo,workflow,job
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
18 changes: 10 additions & 8 deletions pkg/store/http_response_error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,34 @@ func doRequestWithToken(t *testing.T, status int, body, token string) *HTTPRespo
return NewHTTPResponseError(res)
}

func TestHTTPResponseError_UnauthorizedWithAPIKeyShowsHintThenOriginalMessage(t *testing.T) {
func TestHTTPResponseError_UnauthorizedWithAPIKeyShowsHintThenActionableMessage(t *testing.T) {
err := doRequestWithToken(t, http.StatusUnauthorized, unauthorizedBody, "bak-expired")

msg := err.Error()
assert.True(t, strings.HasPrefix(msg, expiredAPIKeyMessage+"\n"), "hint should come first: %q", msg)
assert.Contains(t, msg, "brev login --api-key")
// the original error is preserved after the hint
// The API-key guidance follows the existing hint without exposing raw control-plane JSON.
assert.True(t, strings.HasSuffix(msg, err.baseError()))
assert.Contains(t, msg, "401 Unauthorized")
assert.Contains(t, msg, "UnauthorizedError")
assert.Contains(t, msg, "your Brev API key is invalid or expired")
assert.Contains(t, msg, "BREV_API_KEY")
assert.NotContains(t, msg, "UnauthorizedError")
}

func TestHTTPResponseError_UnauthorizedWithoutAPIKeyKeepsOriginalMessage(t *testing.T) {
func TestHTTPResponseError_UnauthorizedWithoutAPIKeyShowsLoginGuidance(t *testing.T) {
// A non-API-key (e.g. browser login JWT) 401 must not claim the API key is bad.
err := doRequestWithToken(t, http.StatusUnauthorized, unauthorizedBody, "eyJhbGciOiJIUzI1NiJ9.e30.sig")

msg := err.Error()
assert.NotContains(t, msg, expiredAPIKeyMessage)
assert.Contains(t, msg, "401")
assert.Contains(t, msg, "UnauthorizedError")
assert.Equal(t, "you're logged out — run `brev login` to authenticate", msg)
assert.NotContains(t, msg, "UnauthorizedError")
}

func TestHTTPResponseError_UnauthorizedWithNoTokenKeepsOriginalMessage(t *testing.T) {
func TestHTTPResponseError_UnauthorizedWithNoTokenShowsLoginGuidance(t *testing.T) {
err := doRequestWithToken(t, http.StatusUnauthorized, unauthorizedBody, "")

assert.NotContains(t, err.Error(), expiredAPIKeyMessage)
assert.Equal(t, "you're logged out — run `brev login` to authenticate", err.Error())
}

func TestHTTPResponseError_NonUnauthorizedWithAPIKeyKeepsOriginalMessage(t *testing.T) {
Expand Down