| 855 | } |
| 856 | |
| 857 | func waitForHealthy(ctx context.Context, logger slog.Logger, apiURL string) error { |
| 858 | logger.Info(ctx, "waiting for server to become ready") |
| 859 | ctx, cancel := context.WithTimeout(ctx, healthTimeout) |
| 860 | defer cancel() |
| 861 | |
| 862 | _, err := poll(ctx, 500*time.Millisecond, |
| 863 | func(ctx context.Context) (struct{}, bool, error) { |
| 864 | req, err := http.NewRequestWithContext( |
| 865 | ctx, "GET", apiURL+"/healthz", nil) |
| 866 | if err != nil { |
| 867 | return struct{}{}, false, nil |
| 868 | } |
| 869 | resp, err := http.DefaultClient.Do(req) |
| 870 | if err != nil { |
| 871 | return struct{}{}, false, nil |
| 872 | } |
| 873 | _ = resp.Body.Close() |
| 874 | return struct{}{}, resp.StatusCode == http.StatusOK, nil |
| 875 | }) |
| 876 | if err != nil { |
| 877 | return xerrors.Errorf("server did not become ready in %s: %w", healthTimeout, err) |
| 878 | } |
| 879 | logger.Info(ctx, "server is ready to accept connections") |
| 880 | return nil |
| 881 | } |
| 882 | |
| 883 | func setupFirstUser(ctx context.Context, logger slog.Logger, cfg *devConfig, apiURL string) (*codersdk.Client, error) { |
| 884 | serverURL, _ := url.Parse(apiURL) |