@vercel/go 3.4.5 → 3.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14171,6 +14171,32 @@ var goGlobalCachePath = (0, import_path4.join)(
14171
14171
  "golang"
14172
14172
  );
14173
14173
  var OUT_EXTENSION = process.platform === "win32" ? ".exe" : "";
14174
+ function getGoCommandOutput(error) {
14175
+ const stderr = error.stderr?.trim();
14176
+ const stdout = error.stdout?.trim();
14177
+ const all = error.all?.trim();
14178
+ if (stderr && stdout && stdout !== stderr) {
14179
+ return `stderr:
14180
+ ${stderr}
14181
+
14182
+ stdout:
14183
+ ${stdout}`;
14184
+ }
14185
+ return stderr || stdout || all;
14186
+ }
14187
+ function enrichGoCommandError(error) {
14188
+ if (!(error instanceof Error)) {
14189
+ return error;
14190
+ }
14191
+ const output = getGoCommandOutput(error);
14192
+ if (!output || error.message.includes(output)) {
14193
+ return error;
14194
+ }
14195
+ error.message = `${error.message}
14196
+
14197
+ ${output}`;
14198
+ return error;
14199
+ }
14174
14200
  async function getAnalyzedEntrypoint({
14175
14201
  entrypoint,
14176
14202
  modulePath,
@@ -14233,7 +14259,7 @@ var GoWrapper = class {
14233
14259
  this.env = env;
14234
14260
  this.opts = opts;
14235
14261
  }
14236
- execute(...args) {
14262
+ async execute(...args) {
14237
14263
  const { opts, env } = this;
14238
14264
  (0, import_build_utils.debug)(
14239
14265
  `Exec: go ${args.map((a) => a.includes(" ") ? `"${a}"` : a).join(" ")}`
@@ -14241,7 +14267,21 @@ var GoWrapper = class {
14241
14267
  (0, import_build_utils.debug)(` CWD=${opts.cwd}`);
14242
14268
  (0, import_build_utils.debug)(` GOROOT=${(env || opts.env).GOROOT}`);
14243
14269
  (0, import_build_utils.debug)(` GO_BUILD_FLAGS=${(env || opts.env).GO_BUILD_FLAGS}`);
14244
- return (0, import_execa.default)("go", args, { stdio: "inherit", ...opts, env });
14270
+ const captureAndForwardOutput = opts.stdio === void 0 || opts.stdio === "inherit";
14271
+ const subprocess = (0, import_execa.default)("go", args, {
14272
+ ...opts,
14273
+ env,
14274
+ stdio: captureAndForwardOutput ? "pipe" : opts.stdio
14275
+ });
14276
+ if (captureAndForwardOutput) {
14277
+ subprocess.stdout?.pipe(process.stdout);
14278
+ subprocess.stderr?.pipe(process.stderr);
14279
+ }
14280
+ try {
14281
+ return await subprocess;
14282
+ } catch (error) {
14283
+ throw enrichGoCommandError(error);
14284
+ }
14245
14285
  }
14246
14286
  mod() {
14247
14287
  return this.execute("mod", "tidy");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/go",
3
- "version": "3.4.5",
3
+ "version": "3.4.7",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -32,7 +32,7 @@
32
32
  "typescript": "4.9.5",
33
33
  "xdg-app-paths": "5.1.0",
34
34
  "yauzl-promise": "2.1.3",
35
- "@vercel/build-utils": "13.8.0"
35
+ "@vercel/build-utils": "13.12.1"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "node ../../utils/build-builder.mjs",
package/vc-init.go CHANGED
@@ -14,6 +14,7 @@ package main
14
14
  import (
15
15
  "context"
16
16
  "encoding/json"
17
+ "errors"
17
18
  "fmt"
18
19
  "net"
19
20
  "net/http"
@@ -53,6 +54,16 @@ type RequestContext struct {
53
54
  RequestID uint64 `json:"requestId"`
54
55
  }
55
56
 
57
+ type UnrecoverableErrorMessage struct {
58
+ Type string `json:"type"`
59
+ Payload UnrecoverableErrorPayload `json:"payload"`
60
+ }
61
+
62
+ type UnrecoverableErrorPayload struct {
63
+ ExitCode int `json:"exitCode"`
64
+ Message string `json:"message"`
65
+ }
66
+
56
67
  var (
57
68
  ipcConn net.Conn
58
69
  ipcMutex sync.Mutex
@@ -78,6 +89,19 @@ func sendIPCMessage(msg interface{}) error {
78
89
  return err
79
90
  }
80
91
 
92
+ // fatal reports a fatal init error via IPC and exits.
93
+ func fatal(exitCode int, msg string) {
94
+ fmt.Fprintln(os.Stderr, msg)
95
+ sendIPCMessage(UnrecoverableErrorMessage{
96
+ Type: "unrecoverable-error",
97
+ Payload: UnrecoverableErrorPayload{
98
+ ExitCode: exitCode,
99
+ Message: msg,
100
+ },
101
+ })
102
+ os.Exit(exitCode)
103
+ }
104
+
81
105
  func connectIPC() error {
82
106
  ipcPath := os.Getenv("VERCEL_IPC_PATH")
83
107
  if ipcPath == "" {
@@ -106,15 +130,13 @@ func main() {
106
130
  // Find a free port for the user's server
107
131
  userPort, err := findFreePort()
108
132
  if err != nil {
109
- fmt.Fprintf(os.Stderr, "Failed to find free port: %v\n", err)
110
- os.Exit(1)
133
+ fatal(1, fmt.Sprintf("Failed to find free port: %v", err))
111
134
  }
112
135
 
113
136
  // Start the user's server binary
114
137
  userBinary := "./user-server"
115
138
  if _, err := os.Stat(userBinary); os.IsNotExist(err) {
116
- fmt.Fprintf(os.Stderr, "User server binary not found: %s\n", userBinary)
117
- os.Exit(1)
139
+ fatal(1, fmt.Sprintf("User server binary not found: %s", userBinary))
118
140
  }
119
141
 
120
142
  ctx, cancel := context.WithCancel(context.Background())
@@ -126,15 +148,30 @@ func main() {
126
148
  cmd.Stderr = os.Stderr
127
149
 
128
150
  if err := cmd.Start(); err != nil {
129
- fmt.Fprintf(os.Stderr, "Failed to start user server: %v\n", err)
130
- os.Exit(1)
151
+ fatal(1, fmt.Sprintf("Failed to start user server: %v", err))
131
152
  }
132
153
 
133
- // Wait for user's server to be ready
134
- if err := waitForServer(userPort, 30*time.Second); err != nil {
135
- fmt.Fprintf(os.Stderr, "User server failed to start: %v\n", err)
136
- cmd.Process.Kill()
137
- os.Exit(1)
154
+ // Race server readiness against early child death.
155
+ childDone := make(chan error, 1)
156
+ go func() { childDone <- cmd.Wait() }()
157
+
158
+ serverReady := make(chan error, 1)
159
+ go func() { serverReady <- waitForServer(userPort, 30*time.Second) }()
160
+
161
+ select {
162
+ case waitErr := <-childDone:
163
+ // Child exited before the server became ready.
164
+ exitCode := 1
165
+ var exitErr *exec.ExitError
166
+ if errors.As(waitErr, &exitErr) {
167
+ exitCode = exitErr.ExitCode()
168
+ }
169
+ fatal(exitCode, "User server exited during startup")
170
+ case err := <-serverReady:
171
+ if err != nil {
172
+ cmd.Process.Kill()
173
+ fatal(1, fmt.Sprintf("User server failed to start: %v", err))
174
+ }
138
175
  }
139
176
 
140
177
  // Create reverse proxy to user's server
package/vc-utils.go CHANGED
@@ -3,7 +3,6 @@ package main
3
3
  import (
4
4
  "fmt"
5
5
  "net"
6
- "net/http"
7
6
  "os"
8
7
  "strings"
9
8
  "time"
@@ -20,19 +19,46 @@ func findFreePort() (int, error) {
20
19
  }
21
20
 
22
21
  func waitForServer(port int, timeout time.Duration) error {
22
+ const (
23
+ dialTimeout = 200 * time.Millisecond
24
+ pollInterval = 50 * time.Millisecond
25
+ )
26
+
27
+ addr := fmt.Sprintf("127.0.0.1:%d", port)
23
28
  deadline := time.Now().Add(timeout)
24
- url := fmt.Sprintf("http://127.0.0.1:%d/", port)
29
+ var lastErr error
25
30
 
26
31
  for time.Now().Before(deadline) {
27
- resp, err := http.Get(url)
32
+ remaining := time.Until(deadline)
33
+ if remaining <= 0 {
34
+ break
35
+ }
36
+
37
+ attemptTimeout := dialTimeout
38
+ if remaining < attemptTimeout {
39
+ attemptTimeout = remaining
40
+ }
41
+
42
+ conn, err := net.DialTimeout("tcp", addr, attemptTimeout)
28
43
  if err == nil {
29
- resp.Body.Close()
44
+ conn.Close()
30
45
  return nil
31
46
  }
32
- time.Sleep(50 * time.Millisecond)
47
+
48
+ lastErr = err
49
+ time.Sleep(pollInterval)
50
+ }
51
+
52
+ if lastErr != nil {
53
+ return fmt.Errorf(
54
+ "server did not start listening on %s within %v: %w",
55
+ addr,
56
+ timeout,
57
+ lastErr,
58
+ )
33
59
  }
34
60
 
35
- return fmt.Errorf("server did not start within %v", timeout)
61
+ return fmt.Errorf("server did not start listening on %s within %v", addr, timeout)
36
62
  }
37
63
 
38
64
  func normalizeServiceRoutePrefix(rawPrefix string) string {