diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7bd29c42b..9fd80f78a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: @@ -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 }} diff --git a/pkg/store/http_response_error_test.go b/pkg/store/http_response_error_test.go index 83e0adce9..fc86f5702 100644 --- a/pkg/store/http_response_error_test.go +++ b/pkg/store/http_response_error_test.go @@ -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) {