aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2024-06-08 13:39:52 -0700
committerXe Iaso <me@xeiaso.net>2024-06-08 13:41:05 -0700
commitbb8a5a886c993fc943277e56b4c9065c1f3a82b2 (patch)
tree14de5be85b83b17553092f1f1c78b2b0d0b4cba3
parent2f9125d0cbe232dbb0dcd64eab33af356d5d615c (diff)
downloadx-bb8a5a886c993fc943277e56b4c9065c1f3a82b2.tar.xz
x-bb8a5a886c993fc943277e56b4c9065c1f3a82b2.zip
cmd: add command future-sight for preview deployments
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--.go.mod.sri2
-rw-r--r--cmd/future-sight/.gitignore1
-rw-r--r--cmd/future-sight/main.go325
-rw-r--r--cmd/future-sight/manifest.dev.yaml195
-rw-r--r--cmd/future-sight/manifest.yaml226
-rwxr-xr-xcmd/future-sight/port-forward.sh10
-rw-r--r--cmd/future-sight/var/.gitignore2
-rw-r--r--cmd/future-sight/yeetfile.js5
-rw-r--r--cmd/mi/services/posse/posse.go3
-rw-r--r--cmd/xedn/main.go2
-rw-r--r--flake.nix15
-rw-r--r--go.mod5
-rw-r--r--go.sum10
-rw-r--r--internal/xesite/xesite.go (renamed from cmd/xedn/internal/xesite/xesite.go)0
-rw-r--r--proto/future-sight.proto5
-rw-r--r--proto/future-sight/future-sight.pb.go145
-rw-r--r--proto/generate.go1
17 files changed, 948 insertions, 4 deletions
diff --git a/.go.mod.sri b/.go.mod.sri
index 9517b90..9efdb77 100644
--- a/.go.mod.sri
+++ b/.go.mod.sri
@@ -1 +1 @@
-sha256-C9WPTIYksC9AFsbIV+AAp/ylXl6tDJexlPd7gnJzfLo=
+sha256-EB0G+BwyFCgu+2Z6IeUzRrDGkt6Hw+FixX+C7gIkYHI=
diff --git a/cmd/future-sight/.gitignore b/cmd/future-sight/.gitignore
new file mode 100644
index 0000000..abe61a7
--- /dev/null
+++ b/cmd/future-sight/.gitignore
@@ -0,0 +1 @@
+.env.prod \ No newline at end of file
diff --git a/cmd/future-sight/main.go b/cmd/future-sight/main.go
new file mode 100644
index 0000000..4948324
--- /dev/null
+++ b/cmd/future-sight/main.go
@@ -0,0 +1,325 @@
+package main
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/base64"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "log/slog"
+ "net/http"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "github.com/aws/aws-sdk-go-v2/aws"
+ "github.com/aws/aws-sdk-go-v2/credentials"
+ "github.com/aws/aws-sdk-go-v2/service/s3"
+ "github.com/nats-io/nats.go"
+ "github.com/redis/go-redis/v9"
+ "golang.org/x/sync/errgroup"
+ "google.golang.org/protobuf/proto"
+ "within.website/x/internal"
+ "within.website/x/internal/xesite"
+ pb "within.website/x/proto/future-sight"
+ "within.website/x/web/useragent"
+)
+
+var (
+ apiBind = flag.String("api-bind", ":8080", "address to bind API to")
+ bind = flag.String("bind", ":8081", "address to bind zipserver to")
+
+ awsAccessKeyID = flag.String("aws-access-key-id", "", "AWS access key ID")
+ awsSecretKey = flag.String("aws-secret-access-key", "", "AWS secret access key")
+ awsEndpointS3 = flag.String("aws-endpoint-url-s3", "http://localhost:9000", "AWS S3 endpoint")
+ awsRegion = flag.String("aws-region", "auto", "AWS region")
+ bucketName = flag.String("bucket-name", "xesite-preview-versions", "bucket to fetch previews from")
+ dataDir = flag.String("data-dir", "./var", "directory to store data in (not permanent)")
+ natsURL = flag.String("nats-url", "nats://localhost:4222", "nats url")
+ usePathStyle = flag.Bool("use-path-style", false, "use path style for S3")
+ valkeyHost = flag.String("valkey-host", "localhost:6379", "host:port for valkey")
+ valkeyPassword = flag.String("valkey-password", "", "password for valkey")
+)
+
+func main() {
+ internal.HandleStartup()
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ creds := credentials.NewStaticCredentialsProvider(*awsAccessKeyID, *awsSecretKey, "")
+
+ s3c := s3.New(s3.Options{
+ AppID: useragent.GenUserAgent("future-sight-push", "https://xeiaso.net"),
+ BaseEndpoint: awsEndpointS3,
+ ClientLogMode: aws.LogRetries | aws.LogRequest | aws.LogResponse,
+ Credentials: creds,
+ EndpointResolver: s3.EndpointResolverFromURL(*awsEndpointS3),
+ //Logger: logging.NewStandardLogger(os.Stderr),
+ UsePathStyle: *usePathStyle,
+ Region: *awsRegion,
+ })
+
+ slog.Debug("details",
+ "awsAccessKeyID", *awsAccessKeyID,
+ "awsSecretKey", *awsSecretKey,
+ "awsEndpointS3", *awsEndpointS3,
+ "awsRegion", *awsRegion,
+ "bucketName", *bucketName,
+ "natsURL", *natsURL,
+ "usePathStyle", *usePathStyle,
+ "valkeyHost", *valkeyHost,
+ "valkeyPassword", *valkeyPassword,
+ )
+
+ vk := redis.NewClient(&redis.Options{
+ Addr: *valkeyHost,
+ Password: *valkeyPassword,
+ DB: 0,
+ })
+ defer vk.Close()
+
+ if _, err := vk.Ping(context.Background()).Result(); err != nil {
+ log.Fatal(err)
+ }
+
+ nc, err := nats.Connect(*natsURL)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer nc.Close()
+
+ zs, err := xesite.NewZipServer(filepath.Join(*dataDir, "current.zip"), *dataDir)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ s := &Server{
+ s3c: s3c,
+ vk: vk,
+ nc: nc,
+ zs: zs,
+ dir: *dataDir,
+ }
+
+ currentVersion, err := vk.Get(ctx, "future-sight:current").Result()
+ if err != nil && err != redis.Nil {
+ log.Fatal(err)
+ }
+
+ if currentVersion != "" {
+ nv := pb.NewVersion{
+ Slug: currentVersion,
+ }
+
+ if err := s.fetchVersion(ctx, &nv); err != nil {
+ slog.Error("can't fetch current version", "err", err)
+ }
+ }
+
+ if _, err := nc.Subscribe("future-sight-push", s.HandleFutureSightPushMsg); err != nil {
+ log.Fatal(err)
+ }
+
+ apiMux := http.NewServeMux()
+ apiMux.HandleFunc("/upload", s.UploadVersion)
+ apiMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintln(w, "OK")
+ })
+
+ g, _ := errgroup.WithContext(context.Background())
+
+ g.Go(func() error {
+ slog.Info("listening", "for", "api", "addr", *apiBind)
+ return http.ListenAndServe(*apiBind, apiMux)
+ })
+
+ g.Go(func() error {
+ slog.Info("listening", "for", "zipserver", "addr", *bind)
+ return http.ListenAndServe(*bind, zs)
+ })
+
+ if err := g.Wait(); err != nil {
+ slog.Error("error doing work", "err", err)
+ os.Exit(1)
+ }
+}
+
+type Server struct {
+ s3c *s3.Client
+ vk *redis.Client
+ nc *nats.Conn
+ zs *xesite.ZipServer
+ dir string
+}
+
+func (s *Server) UploadVersion(w http.ResponseWriter, r *http.Request) {
+ ctx, cancel := context.WithCancel(r.Context())
+ defer cancel()
+
+ slog.Info("uploading version")
+
+ if err := r.ParseMultipartForm(10 << 24); err != nil {
+ slog.Error("failed to parse form", "err", err)
+ http.Error(w, "failed to parse form", http.StatusBadRequest)
+ return
+ }
+
+ f, header, err := r.FormFile("file")
+ if err != nil {
+ slog.Error("failed to get file", "err", err)
+ http.Error(w, "failed to get file", http.StatusBadRequest)
+ return
+ }
+ defer f.Close()
+
+ slog.Info("got file", "filename", header.Filename)
+
+ fout, err := os.CreateTemp(s.dir, "future-sight-upload-*")
+ if err != nil {
+ slog.Error("failed to create temp file", "err", err)
+ http.Error(w, "failed to create temp file", http.StatusInternalServerError)
+ return
+ }
+ defer fout.Close()
+ defer os.Remove(fout.Name())
+
+ if _, err := io.Copy(fout, f); err != nil {
+ slog.Error("failed to copy file", "err", err)
+ http.Error(w, "failed to copy file", http.StatusInternalServerError)
+ return
+ }
+
+ hash, err := hashFileSha256(fout)
+ if err != nil {
+ slog.Error("failed to hash file", "err", err)
+ http.Error(w, "failed to hash file", http.StatusInternalServerError)
+ return
+ }
+
+ st, err := fout.Stat()
+ if err != nil {
+ slog.Error("failed to stat file", "err", err)
+ http.Error(w, "failed to stat file", http.StatusInternalServerError)
+ return
+ }
+
+ slog.Info("hashed file", "hash", hash)
+
+ if _, err := s.s3c.PutObject(ctx, &s3.PutObjectInput{
+ Bucket: bucketName,
+ Key: aws.String(hash),
+ Body: fout,
+ ContentType: aws.String("application/zip"),
+ ContentLength: aws.Int64(st.Size()),
+ Metadata: map[string]string{
+ "host_os": runtime.GOOS,
+ },
+ }); err != nil {
+ slog.Error("failed to push file", "bucketName", *bucketName, "hash", hash, "err", err)
+ http.Error(w, "failed to push file", http.StatusInternalServerError)
+ return
+ }
+
+ nv := &pb.NewVersion{
+ Slug: hash,
+ }
+
+ if err := s.PushVersion(ctx, nv); err != nil {
+ slog.Error("failed to push version", "slug", nv.Slug, "err", err)
+ http.Error(w, "failed to push version", http.StatusInternalServerError)
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+}
+
+func (s *Server) PushVersion(ctx context.Context, nv *pb.NewVersion) error {
+ slog.Info("got new version", "version", nv)
+
+ msg, err := proto.Marshal(nv)
+ if err != nil {
+ slog.Error("failed to marshal message", "slug", nv.Slug, "err", err)
+ return err
+ }
+
+ if err := s.nc.Publish("future-sight-push", msg); err != nil {
+ slog.Error("failed to publish message", "slug", nv.Slug, "err", err)
+ return err
+ }
+
+ if _, err := s.vk.Set(ctx, "future-sight:current", nv.Slug, 0).Result(); err != nil {
+ slog.Error("failed to set current version", "slug", nv.Slug, "err", err)
+ return err
+ }
+
+ return nil
+}
+
+func (s *Server) HandleFutureSightPushMsg(msg *nats.Msg) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ nv := new(pb.NewVersion)
+ if err := proto.Unmarshal(msg.Data, nv); err != nil {
+ slog.Error("failed to unmarshal message", "err", err)
+ return
+ }
+
+ if err := s.fetchVersion(ctx, nv); err != nil {
+ slog.Error("failed to handle message", "slug", nv.Slug, "err", err)
+ return
+ }
+
+ slog.Info("handled message", "slug", nv.Slug)
+}
+
+func (s *Server) fetchVersion(ctx context.Context, nv *pb.NewVersion) error {
+ os.Remove(filepath.Join(s.dir, "current.zip"))
+
+ fout, err := os.Create(filepath.Join(s.dir, "current.zip"))
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ obj, err := s.s3c.GetObject(ctx, &s3.GetObjectInput{
+ Bucket: bucketName,
+ Key: aws.String(nv.Slug),
+ })
+ if err != nil {
+ os.Remove(filepath.Join(s.dir, "current.zip"))
+ slog.Error("failed to get object", "slug", nv.Slug, "err", err)
+ return err
+ }
+ defer obj.Body.Close()
+
+ if _, err := io.Copy(fout, obj.Body); err != nil {
+ os.Remove(filepath.Join(s.dir, "current.zip"))
+ slog.Error("failed to copy object", "slug", nv.Slug, "err", err)
+ return err
+ }
+
+ if err := s.zs.Update(filepath.Join(s.dir, "current.zip")); err != nil {
+ slog.Error("failed to update zipserver", "slug", nv.Slug, "err", err)
+ return err
+ }
+
+ return nil
+}
+
+// hashFileSha256 hashes a file with Sha256 and returns the hash as a base64 encoded string.
+func hashFileSha256(fin *os.File) (string, error) {
+ h := sha256.New()
+ if _, err := io.Copy(h, fin); err != nil {
+ return "", err
+ }
+
+ // rewind the file
+ if _, err := fin.Seek(0, io.SeekStart); err != nil {
+ return "", err
+ }
+
+ return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
+}
diff --git a/cmd/future-sight/manifest.dev.yaml b/cmd/future-sight/manifest.dev.yaml
new file mode 100644
index 0000000..49a71f6
--- /dev/null
+++ b/cmd/future-sight/manifest.dev.yaml
@@ -0,0 +1,195 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: future-sight
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: nats
+ namespace: future-sight
+spec:
+ replicas: 1
+ strategy: {}
+ selector:
+ matchLabels:
+ app: nats
+ template:
+ metadata:
+ labels:
+ app: nats
+ spec:
+ containers:
+ - name: nats
+ image: nats:2-alpine
+ ports:
+ - containerPort: 4222
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: nats
+ namespace: future-sight
+spec:
+ selector:
+ app: nats
+ ports:
+ - port: 4222
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: valkey-secret
+ namespace: future-sight
+ labels:
+ app: valkey
+data:
+ VALKEY_PASSWORD: hunter2
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: valkey
+ namespace: future-sight
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: valkey
+ template:
+ metadata:
+ labels:
+ app: valkey
+ spec:
+ containers:
+ - name: valkey
+ image: 'docker.io/bitnami/valkey:latest'
+ imagePullPolicy: Always
+ ports:
+ - containerPort: 6379
+ envFrom:
+ - configMapRef:
+ name: valkey-secret
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: valkey
+ namespace: future-sight
+ labels:
+ app: valkey
+spec:
+ type: ClusterIP
+ ports:
+ - port: 6379
+ selector:
+ app: valkey
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: minio
+ namespace: future-sight
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 10Gi
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: minio
+ namespace: future-sight
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: minio
+ template:
+ metadata:
+ labels:
+ app: minio
+ spec:
+ volumes:
+ - name: data
+ persistentVolumeClaim:
+ claimName: minio
+ containers:
+ - name: minio
+ volumeMounts:
+ - name: data
+ mountPath: /data
+ image: minio/minio
+ args:
+ - server
+ - /data
+ - --console-address=:9001
+ env:
+ - name: MINIO_ACCESS_KEY
+ value: "minio"
+ - name: MINIO_SECRET_KEY
+ value: "minio123"
+ - name: MINIO_ROOT_USER
+ value: root
+ - name: MINIO_ROOT_PASSWORD
+ value: hunter22
+ ports:
+ - containerPort: 9000
+ name: http
+ - containerPort: 9001
+ name: webui
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: create-bucket
+ namespace: future-sight
+spec:
+ template:
+ spec:
+ containers:
+ - name: create-bucket
+ image: minio/mc
+ command: ["/bin/sh"]
+ args:
+ - "-c"
+ - |
+ /usr/bin/mc config host add k8s http://minio:9000 minio minio123;
+ /usr/bin/mc rm -r --force myminio/xesite-preview-versions;
+ /usr/bin/mc mb myminio/xesite-preview-versions;
+ /usr/bin/mc policy download myminio/xesite-preview-versions;
+ exit 0;
+ restartPolicy: Never
+ backoffLimit: 4
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: minio
+ namespace: future-sight
+spec:
+ type: ClusterIP
+ ports:
+ - name: http
+ port: 80
+ targetPort: 9000
+ protocol: TCP
+ selector:
+ app: minio
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: minio-webui
+ namespace: future-sight
+spec:
+ type: ClusterIP
+ ports:
+ - name: webui
+ port: 80
+ targetPort: 9001
+ protocol: TCP
+ selector:
+ app: minio \ No newline at end of file
diff --git a/cmd/future-sight/manifest.yaml b/cmd/future-sight/manifest.yaml
new file mode 100644
index 0000000..3260bd5
--- /dev/null
+++ b/cmd/future-sight/manifest.yaml
@@ -0,0 +1,226 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: future-sight
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: nats
+ namespace: future-sight
+spec:
+ replicas: 1
+ strategy: {}
+ selector:
+ matchLabels:
+ app: nats
+ template:
+ metadata:
+ labels:
+ app: nats
+ spec:
+ containers:
+ - name: nats
+ image: nats:2-alpine
+ ports:
+ - containerPort: 4222
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: nats
+ namespace: future-sight
+spec:
+ selector:
+ app: nats
+ ports:
+ - port: 4222
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: valkey-secret
+ namespace: future-sight
+ labels:
+ app: valkey
+data:
+ VALKEY_PASSWORD: hunter2
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: valkey
+ namespace: future-sight
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: valkey
+ template:
+ metadata:
+ labels:
+ app: valkey
+ spec:
+ containers:
+ - name: valkey
+ image: 'docker.io/bitnami/valkey:latest'
+ imagePullPolicy: Always
+ ports:
+ - containerPort: 6379
+ envFrom:
+ - configMapRef:
+ name: valkey-secret
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: valkey
+ namespace: future-sight
+ labels:
+ app: valkey
+spec:
+ type: ClusterIP
+ ports:
+ - port: 6379
+ selector:
+ app: valkey
+---
+apiVersion: onepassword.com/v1
+kind: OnePasswordItem
+metadata:
+ name: tigris-creds
+ namespace: future-sight
+ labels:
+ app.kubernetes.io/name: future-sight
+spec:
+ itemPath: "vaults/Kubernetes/items/Tigris creds"
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: future-sight
+ namespace: future-sight
+ labels:
+ app.kubernetes.io/name: future-sight
+data:
+ BUCKET_NAME: xesite-preview-versions
+ DATA_DIR: /cache
+ NATS_URL: nats://nats:4222
+ VALKEY_HOST: valkey:6379
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: future-sight
+ namespace: future-sight
+ labels:
+ app.kubernetes.io/name: future-sight
+ annotations:
+ operator.1password.io/auto-restart: "true"
+spec:
+ replicas: 3
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: future-sight
+ template:
+ metadata:
+ namespace: future-sight
+ labels:
+ app.kubernetes.io/name: future-sight
+ spec:
+ volumes:
+ - name: tigris
+ secret:
+ secretName: tigris-creds
+ - name: cache
+ emptyDir: {}
+ securityContext:
+ fsGroup: 1000
+ containers:
+ - name: main
+ image: ghcr.io/xe/x/future-sight:latest
+ imagePullPolicy: Always
+ resources:
+ limits:
+ cpu: "250m"
+ memory: "512Mi"
+ requests:
+ cpu: "100m"
+ memory: "256Mi"
+ securityContext:
+ runAsUser: 1000
+ runAsGroup: 1000
+ runAsNonRoot: true
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ seccompProfile:
+ type: RuntimeDefault
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8080
+ httpHeaders:
+ - name: X-Kubernetes
+ value: "is kinda okay"
+ initialDelaySeconds: 3
+ periodSeconds: 3
+ volumeMounts:
+ - name: tigris
+ mountPath: /run/secrets/tigris
+ - name: cache
+ mountPath: /cache
+ envFrom:
+ - configMapRef:
+ name: valkey-secret
+ - configMapRef:
+ name: future-sight
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: future-sight
+ namespace: future-sight
+ labels:
+ app.kubernetes.io/name: future-sight
+spec:
+ selector:
+ app.kubernetes.io/name: future-sight
+ ports:
+ - protocol: TCP
+ port: 80
+ targetPort: 8081
+ name: web
+ - protocol: TCP
+ port: 8080
+ targetPort: 8080
+ name: api
+ type: ClusterIP
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: future-sight
+ namespace: future-sight
+ labels:
+ app.kubernetes.io/name: future-sight
+ annotations:
+ cert-manager.io/cluster-issuer: "letsencrypt-prod"
+spec:
+ ingressClassName: nginx
+ tls:
+ - hosts:
+ - preview.xeiaso.net
+ secretName: preview-xeiaso-net-tls
+ rules:
+ - host: preview.xeiaso.net
+ http:
+ paths:
+ - pathType: Prefix
+ path: "/"
+ backend:
+ service:
+ name: future-sight
+ port:
+ name: http \ No newline at end of file
diff --git a/cmd/future-sight/port-forward.sh b/cmd/future-sight/port-forward.sh
new file mode 100755
index 0000000..984ebb7
--- /dev/null
+++ b/cmd/future-sight/port-forward.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+kubectl apply -f manifest.dev.yaml
+
+kubectl port-forward -n future-sight svc/nats 4222:4222 &
+kubectl port-forward -n future-sight deploy/minio 9000:9000 &
+kubectl port-forward -n future-sight deploy/minio 9001:9001 &
+kubectl port-forward -n future-sight svc/valkey 6379:6379 &
+
+wait \ No newline at end of file
diff --git a/cmd/future-sight/var/.gitignore b/cmd/future-sight/var/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/cmd/future-sight/var/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore \ No newline at end of file
diff --git a/cmd/future-sight/yeetfile.js b/cmd/future-sight/yeetfile.js
new file mode 100644
index 0000000..1b31c6c
--- /dev/null
+++ b/cmd/future-sight/yeetfile.js
@@ -0,0 +1,5 @@
+nix.build(".#docker.future-sight");
+docker.load("./result");
+docker.push(`ghcr.io/xe/x/future-sight`);
+yeet.run("kubectl", "apply", "-f=manifest.yaml");
+yeet.run("sh", "-c", "kubectl rollout restart -n future-sight deployments/future-sight");
diff --git a/cmd/mi/services/posse/posse.go b/cmd/mi/services/posse/posse.go
index 7645470..6c6702b 100644
--- a/cmd/mi/services/posse/posse.go
+++ b/cmd/mi/services/posse/posse.go
@@ -65,7 +65,8 @@ func New(ctx context.Context, dao *models.DAO, cfg Config) (*Announcer, error) {
func (a *Announcer) Announce(ctx context.Context, it *jsonfeed.Item) (*emptypb.Empty, error) {
switch {
case strings.Contains(it.GetUrl(), "svc.alrest.xeserv.us"),
- strings.Contains(it.GetUrl(), "shark-harmonic.ts.net"):
+ strings.Contains(it.GetUrl(), "shark-harmonic.ts.net"),
+ strings.Contains(it.GetUrl(), "preview.xeiaso.net"):
slog.Info("skipping announcement", "url", it.GetUrl(), "reason", "staging URLs")
return &emptypb.Empty{}, nil
}
diff --git a/cmd/xedn/main.go b/cmd/xedn/main.go
index 5ede100..1b545d4 100644
--- a/cmd/xedn/main.go
+++ b/cmd/xedn/main.go
@@ -26,8 +26,8 @@ import (
"tailscale.com/metrics"
"tailscale.com/tsnet"
"tailscale.com/tsweb"
- "within.website/x/cmd/xedn/internal/xesite"
"within.website/x/internal"
+ "within.website/x/internal/xesite"
"within.website/x/web/fly/flymachines"
"within.website/x/web/stablediffusion"
)
diff --git a/flake.nix b/flake.nix
index b88806c..ba67b90 100644
--- a/flake.nix
+++ b/flake.nix
@@ -89,6 +89,13 @@
];
};
+ future-sight = pkgs.buildGo122Module {
+ pname = "future-sight";
+ inherit version vendorHash;
+ src = ./.;
+ subPackages = [ "cmd/future-sight" ];
+ };
+
mi = pkgs.buildGo122Module {
pname = "mi";
inherit version vendorHash;
@@ -269,7 +276,7 @@
path = "make-mastodon-app";
};
- inherit xedn xedn-static robocadey2 azurda mimi mi tourian sapientwindex within-website;
+ inherit xedn xedn-static future-sight robocadey2 azurda mimi mi tourian sapientwindex within-website;
aegis = copyFile { pname = "aegis"; };
cadeybot = copyFile { pname = "cadeybot"; };
@@ -298,6 +305,7 @@
azurda = self.packages.${system}.azurda;
within-website = self.packages.${system}.within-website;
hlang = self.packages.${system}.hlang;
+ future-sight = self.packages.${system}.future-sight;
simple = { name, cmd, pkg, contents ? [ pkgs.cacert ] }:
pkgs.dockerTools.buildLayeredImage {
@@ -311,6 +319,11 @@
};
in
{
+ future-sight = simple {
+ name = "ghcr.io/xe/x/future-sight";
+ pkg = future-sight;
+ cmd = [ "${future-sight}/bin/future-sight" ];
+ };
within-website = simple {
name = "ghcr.io/xe/x/within-website";
pkg = within-website;
diff --git a/go.mod b/go.mod
index 5095cf4..3e9b6c6 100644
--- a/go.mod
+++ b/go.mod
@@ -106,6 +106,7 @@ require (
github.com/cloudflare/circl v1.3.8 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.7.1 // indirect
@@ -178,12 +179,16 @@ require (
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
+ github.com/nats-io/nats.go v1.35.0 // indirect
+ github.com/nats-io/nkeys v0.4.7 // indirect
+ github.com/nats-io/nuid v1.0.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/term v1.2.0-beta.2 // indirect
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
+ github.com/redis/go-redis/v9 v9.5.3 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
diff --git a/go.sum b/go.sum
index 048c6f9..f2c3699 100644
--- a/go.sum
+++ b/go.sum
@@ -261,6 +261,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa/go.mod h1:Nx87SkVqTKd8UtT+xu7sM/l+LgXs6c0aHrlKusR+2EQ=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:YTIHhz/QFSYnu/EhlF2SpU2Uk+32abacUYA5ZPljz1A=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
@@ -752,6 +754,12 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mymmrac/telego v0.29.2 h1:5+fQ/b8d8Ld6ihCJ0OLe1CwUdT3t1sIUl3RaSaSvRJs=
github.com/mymmrac/telego v0.29.2/go.mod h1:BsKr+GF9BHqaVaLBwsZeDnfuJcJx2olWuDEtKm4zHMc=
+github.com/nats-io/nats.go v1.35.0 h1:XFNqNM7v5B+MQMKqVGAyHwYhyKb48jrenXNxIU20ULk=
+github.com/nats-io/nats.go v1.35.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
+github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
+github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
+github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/ncruces/go-sqlite3 v0.16.0 h1:O7eULuEjvSBnS1QCN+dDL/ixLQZoUGWr466A02Gx1xc=
github.com/ncruces/go-sqlite3 v0.16.0/go.mod h1:2TmAeD93ImsKXJRsUIKohfMvt17dZSbS6pzJ3k6YYFg=
@@ -842,6 +850,8 @@ github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
+github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
diff --git a/cmd/xedn/internal/xesite/xesite.go b/internal/xesite/xesite.go
index 7ef525b..7ef525b 100644
--- a/cmd/xedn/internal/xesite/xesite.go
+++ b/internal/xesite/xesite.go
diff --git a/proto/future-sight.proto b/proto/future-sight.proto
new file mode 100644
index 0000000..7501649
--- /dev/null
+++ b/proto/future-sight.proto
@@ -0,0 +1,5 @@
+syntax = "proto3";
+package within.website.x.future_sight;
+option go_package = "within.website/x/proto/future-sight";
+
+message NewVersion { string slug = 1; } \ No newline at end of file
diff --git a/proto/future-sight/future-sight.pb.go b/proto/future-sight/future-sight.pb.go
new file mode 100644
index 0000000..cff7336
--- /dev/null
+++ b/proto/future-sight/future-sight.pb.go
@@ -0,0 +1,145 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.32.0
+// protoc v4.24.4
+// source: future-sight.proto
+
+package future_sight
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type NewVersion struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Slug string `protobuf:"bytes,1,opt,name=slug,proto3" json:"slug,omitempty"`
+}
+
+func (x *NewVersion) Reset() {
+ *x = NewVersion{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_future_sight_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *NewVersion) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NewVersion) ProtoMessage() {}
+
+func (x *NewVersion) ProtoReflect() protoreflect.Messag