From 86dddf2dd0b1e0a10909a96d167a93749aa52856 Mon Sep 17 00:00:00 2001
From: Andrew Benton <andrew@sqlc.dev>
Date: Thu, 19 Oct 2023 09:31:16 -0700
Subject: [PATCH 1/3] feat: Abort compiler when rpc fails as unauthenticated

---
 internal/compiler/compile.go |  6 ++++++
 internal/rpc/errors.go       | 13 +++++++++++++
 internal/rpc/interceptor.go  |  7 +------
 3 files changed, 20 insertions(+), 6 deletions(-)
 create mode 100644 internal/rpc/errors.go

diff --git a/internal/compiler/compile.go b/internal/compiler/compile.go
index 9f4a5170ef..25debf2fe6 100644
--- a/internal/compiler/compile.go
+++ b/internal/compiler/compile.go
@@ -11,6 +11,7 @@ import (
 	"github.com/sqlc-dev/sqlc/internal/migrations"
 	"github.com/sqlc-dev/sqlc/internal/multierr"
 	"github.com/sqlc-dev/sqlc/internal/opts"
+	"github.com/sqlc-dev/sqlc/internal/rpc"
 	"github.com/sqlc-dev/sqlc/internal/source"
 	"github.com/sqlc-dev/sqlc/internal/sql/ast"
 	"github.com/sqlc-dev/sqlc/internal/sql/sqlerr"
@@ -64,6 +65,7 @@ func (c *Compiler) parseQueries(o opts.Parser) (*Result, error) {
 	if err != nil {
 		return nil, err
 	}
+fileLoop:
 	for _, filename := range files {
 		blob, err := os.ReadFile(filename)
 		if err != nil {
@@ -88,6 +90,10 @@ func (c *Compiler) parseQueries(o opts.Parser) (*Result, error) {
 					loc = e.Location
 				}
 				merr.Add(filename, src, loc, err)
+				// If this rpc unauthenticated error bubbles up, then all future parsing/analysis will fail
+				if errors.Is(err, rpc.ErrUnauthenticated) {
+					break fileLoop
+				}
 				continue
 			}
 			queryName := query.Metadata.Name
diff --git a/internal/rpc/errors.go b/internal/rpc/errors.go
new file mode 100644
index 0000000000..80953343f8
--- /dev/null
+++ b/internal/rpc/errors.go
@@ -0,0 +1,13 @@
+package rpc
+
+import (
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+const errMessageUnauthenticated = `rpc authentication failed
+
+You may be using a sqlc auth token that was created for a different project,
+or your auth token may have expired.`
+
+var ErrUnauthenticated = status.New(codes.Unauthenticated, errMessageUnauthenticated).Err()
diff --git a/internal/rpc/interceptor.go b/internal/rpc/interceptor.go
index b0262c09fc..ac0490bd1a 100644
--- a/internal/rpc/interceptor.go
+++ b/internal/rpc/interceptor.go
@@ -8,11 +8,6 @@ import (
 	"google.golang.org/grpc/status"
 )
 
-const errMessageUnauthenticated = `rpc authentication failed
-
-You may be using a sqlc auth token that was created for a different project,
-or your auth token may have expired.`
-
 func UnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
 	err := invoker(ctx, method, req, reply, cc, opts...)
 
@@ -20,7 +15,7 @@ func UnaryInterceptor(ctx context.Context, method string, req, reply interface{}
 	case codes.OK:
 		return nil
 	case codes.Unauthenticated:
-		return status.New(codes.Unauthenticated, errMessageUnauthenticated).Err()
+		return ErrUnauthenticated
 	default:
 		return err
 	}

From fe66c2c34b81ac861c3467480297f648c6782297 Mon Sep 17 00:00:00 2001
From: Kyle Conroy <kyle@sqlc.dev>
Date: Thu, 19 Oct 2023 10:58:30 -0700
Subject: [PATCH 2/3] test: Bump timeout to 20 minutes

---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c8bccb6bfc..f6eba6dcfe 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -57,7 +57,7 @@ jobs:
       run: go install ./...
 
     - name: test ./...
-      run: gotestsum --junitfile junit.xml -- --tags=examples ./...
+      run: gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m ./...
       env:
         MYSQL_DATABASE: mysql
         MYSQL_HOST: localhost

From 25761838a6fd8c79380e17b9d037ef94101f62c1 Mon Sep 17 00:00:00 2001
From: Andrew Benton <andrew@sqlc.dev>
Date: Thu, 19 Oct 2023 12:07:10 -0700
Subject: [PATCH 3/3] return early

---
 internal/compiler/compile.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/internal/compiler/compile.go b/internal/compiler/compile.go
index 25debf2fe6..19b737257c 100644
--- a/internal/compiler/compile.go
+++ b/internal/compiler/compile.go
@@ -65,7 +65,6 @@ func (c *Compiler) parseQueries(o opts.Parser) (*Result, error) {
 	if err != nil {
 		return nil, err
 	}
-fileLoop:
 	for _, filename := range files {
 		blob, err := os.ReadFile(filename)
 		if err != nil {
@@ -92,7 +91,7 @@ fileLoop:
 				merr.Add(filename, src, loc, err)
 				// If this rpc unauthenticated error bubbles up, then all future parsing/analysis will fail
 				if errors.Is(err, rpc.ErrUnauthenticated) {
-					break fileLoop
+					return nil, merr
 				}
 				continue
 			}