summaryrefslogtreecommitdiff
path: root/internal/deploy/deploy.go
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-08-06 23:22:03 -0500
committerClaude <noreply@anthropic.com>2026-08-06 23:22:03 -0500
commitf34ba20fc566ab861179a8ac2fd55eaabbc6a327 (patch)
treef3b421a59cff06d1fa83ae3f75065971dcc750df /internal/deploy/deploy.go
parentfc0c6951d7ac36dd8f30ace929991197dc99ae54 (diff)
Add skiff config set/unset/list, backed by /app/env in the app's dataset
Config vars are plain env vars, injected into both the running app (via rc.d) and the release phase, and versioned on the same ZFS snapshot timeline as deploys - a bad config change gets the same automatic snapshot/restart/health-check/rollback guarantee a bad deploy already gets. Extracts deploy.go's health check into internal/health so both paths share it. Verified end-to-end against a FreeBSD VM: config set/unset, automatic rollback on a health-check failure, and explicit `skiff rollback` all correctly carry the env file along with the rest of the dataset.
Diffstat (limited to 'internal/deploy/deploy.go')
-rw-r--r--internal/deploy/deploy.go31
1 files changed, 2 insertions, 29 deletions
diff --git a/internal/deploy/deploy.go b/internal/deploy/deploy.go
index a25701a..5430b7f 100644
--- a/internal/deploy/deploy.go
+++ b/internal/deploy/deploy.go
@@ -8,12 +8,11 @@ import (
"context"
"fmt"
"io"
- "net/http"
"os"
"path/filepath"
- "time"
"skiff/internal/appmeta"
+ "skiff/internal/health"
"skiff/internal/jailmgr"
"skiff/internal/layout"
"skiff/internal/nginx"
@@ -76,7 +75,7 @@ func Run(ctx context.Context, out io.Writer, cfg layout.Config, app, sha string)
return fmt.Errorf("read app metadata: %w", err)
}
- if err := waitHealthy(ctx, meta); err != nil {
+ if err := health.WaitHealthy(ctx, meta); err != nil {
fmt.Fprintf(out, "==> health check failed (%v), rolling back to pre-%s\n", err, sha)
if rbErr := zfsutil.Rollback(ctx, out, dataset, snapshotTag); rbErr != nil {
return fmt.Errorf("health check failed AND rollback failed: %v / %w", err, rbErr)
@@ -107,29 +106,3 @@ func swapCurrent(currentPath, newTarget string) error {
}
return os.Rename(tmp, currentPath)
}
-
-func waitHealthy(ctx context.Context, meta appmeta.Meta) error {
- url := fmt.Sprintf("http://%s:%d%s", meta.IP, meta.Port, meta.HealthPath)
- deadline := time.Now().Add(layout.HealthTimeoutSecs * time.Second)
- client := &http.Client{Timeout: 2 * time.Second}
-
- var lastErr error
- for time.Now().Before(deadline) {
- req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
- if err != nil {
- return err
- }
- resp, err := client.Do(req)
- if err == nil {
- resp.Body.Close()
- if resp.StatusCode < 300 {
- return nil
- }
- lastErr = fmt.Errorf("status %d", resp.StatusCode)
- } else {
- lastErr = err
- }
- time.Sleep(500 * time.Millisecond)
- }
- return fmt.Errorf("never became healthy at %s: %w", url, lastErr)
-}