aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/xesite/main.go18
-rw-r--r--internal/lume/lume.go98
-rw-r--r--lume/src/_includes/base.njk38
3 files changed, 118 insertions, 36 deletions
diff --git a/cmd/xesite/main.go b/cmd/xesite/main.go
index 4793f38..a59e690 100644
--- a/cmd/xesite/main.go
+++ b/cmd/xesite/main.go
@@ -24,6 +24,7 @@ var (
bind = flag.String("bind", ":3000", "Port to listen on")
devel = flag.Bool("devel", false, "Enable development mode")
dataDir = flag.String("data-dir", "./var", "Directory to store data in")
+ futureSightURL = flag.String("future-sight-url", "", "URL to use for future sight preview deploys")
gitBranch = flag.String("git-branch", "main", "Git branch to clone")
gitRepo = flag.String("git-repo", "https://github.com/Xe/site", "Git repository to clone")
githubSecret = flag.String("github-secret", "", "GitHub secret to use for webhooks")
@@ -54,14 +55,15 @@ func main() {
}
fs, err := lume.New(ctx, &lume.Options{
- Branch: *gitBranch,
- Repo: *gitRepo,
- StaticSiteDir: "lume",
- URL: *siteURL,
- Development: *devel,
- PatreonClient: pc,
- DataDir: *dataDir,
- MiURL: *miURL,
+ Branch: *gitBranch,
+ Repo: *gitRepo,
+ StaticSiteDir: "lume",
+ URL: *siteURL,
+ Development: *devel,
+ PatreonClient: pc,
+ DataDir: *dataDir,
+ MiURL: *miURL,
+ FutureSightURL: *futureSightURL,
})
if err != nil {
log.Fatal(err)
diff --git a/internal/lume/lume.go b/internal/lume/lume.go
index aa84abe..c7230c6 100644
--- a/internal/lume/lume.go
+++ b/internal/lume/lume.go
@@ -2,6 +2,7 @@ package lume
import (
"archive/zip"
+ "bytes"
"context"
"encoding/json"
"errors"
@@ -12,6 +13,7 @@ import (
"io/fs"
"log"
"log/slog"
+ "mime/multipart"
"net/http"
"os"
"os/exec"
@@ -26,6 +28,7 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"gopkg.in/mxpv/patreon-go.v1"
"tailscale.com/metrics"
+ "within.website/x/web"
"xeiaso.net/v4/internal/config"
"xeiaso.net/v4/internal/jsonfeed"
"xeiaso.net/v4/pb/external/mi"
@@ -40,11 +43,13 @@ var (
_ fs.FS = (*FS)(nil)
- opens = metrics.LabelMap{Label: "name"}
- builds = expvar.NewInt("gauge_xesite_builds")
- updates = expvar.NewInt("gauge_xesite_updates")
- updateErrors = expvar.NewInt("gauge_xesite_update_errors")
- lastBuildTime = expvar.NewInt("gauge_xesite_last_build_time_ms")
+ opens = metrics.LabelMap{Label: "name"}
+ builds = expvar.NewInt("gauge_xesite_builds")
+ updates = expvar.NewInt("gauge_xesite_updates")
+ updateErrors = expvar.NewInt("gauge_xesite_update_errors")
+ lastBuildTime = expvar.NewInt("gauge_xesite_last_build_time_ms")
+ futureSightPokes = expvar.NewInt("gauge_xesite_future_sight_pokes")
+ futureSightErrors = expvar.NewInt("gauge_xesite_future_sight_errors")
)
func init() {
@@ -127,14 +132,15 @@ func (f *FS) Open(name string) (fs.File, error) {
}
type Options struct {
- Development bool
- Branch string
- Repo string
- StaticSiteDir string
- URL string
- PatreonClient *patreon.Client
- DataDir string
- MiURL string
+ Development bool
+ Branch string
+ Repo string
+ StaticSiteDir string
+ URL string
+ PatreonClient *patreon.Client
+ DataDir string
+ MiURL string
+ FutureSightURL string
}
func New(ctx context.Context, o *Options) (*FS, error) {
@@ -217,6 +223,10 @@ func New(ctx context.Context, o *Options) (*FS, error) {
slog.Debug("mi integration enabled")
}
+ if o.FutureSightURL != "" {
+ slog.Debug("future sight integration enabled")
+ }
+
conf, err := config.Load(filepath.Join(fs.repoDir, "config.dhall"))
if err != nil {
log.Fatal(err)
@@ -231,6 +241,10 @@ func New(ctx context.Context, o *Options) (*FS, error) {
go fs.mimiRefresh()
fs.lastBuildTime = time.Now()
+ if o.FutureSightURL != "" {
+ go fs.FutureSight(context.Background())
+ }
+
return fs, nil
}
@@ -300,6 +314,10 @@ func (f *FS) Update(ctx context.Context) error {
go f.mimiRefresh()
+ if f.opt.FutureSightURL != "" {
+ go f.FutureSight(context.Background())
+ }
+
return nil
}
@@ -616,3 +634,57 @@ func (f *FS) mimiRefresh() {
}
}
}
+
+func (f *FS) FutureSight(ctx context.Context) {
+ if err := f.futureSight(ctx); err != nil {
+ slog.Error("failed to poke future sight", "err", err)
+ futureSightErrors.Add(1)
+ return
+ }
+
+ futureSightPokes.Add(1)
+}
+
+func (f *FS) futureSight(ctx context.Context) error {
+ zipLoc := filepath.Join(f.opt.DataDir, "site.zip")
+
+ fin, err := os.Open(zipLoc)
+ if err != nil {
+ return fmt.Errorf("lume: can't open site zip for future sight: %w", err)
+ }
+ defer fin.Close()
+
+ buf := bytes.NewBuffer(nil)
+ writer := multipart.NewWriter(buf)
+
+ part, err := writer.CreateFormFile("file", filepath.Base(zipLoc))
+ if err != nil {
+ return fmt.Errorf("lume: can't create form file: %w", err)
+ }
+
+ if _, err := io.Copy(part, fin); err != nil {
+ return fmt.Errorf("lume: can't copy file to buffer: %w", err)
+ }
+
+ if err := writer.Close(); err != nil {
+ return fmt.Errorf("lume: can't close writer: %w", err)
+ }
+
+ req, err := http.NewRequestWithContext(ctx, "POST", f.opt.FutureSightURL+"/upload", buf)
+ if err != nil {
+ return fmt.Errorf("lume: can't create request: %w", err)
+ }
+
+ req.Header.Set("Content-Type", writer.FormDataContentType())
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return fmt.Errorf("lume: can't post to future sight: %w", err)
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return web.NewError(http.StatusOK, resp)
+ }
+
+ return nil
+}
diff --git a/lume/src/_includes/base.njk b/lume/src/_includes/base.njk
index c7c44b7..82e52c6 100644
--- a/lume/src/_includes/base.njk
+++ b/lume/src/_includes/base.njk
@@ -59,6 +59,10 @@
<meta name="twitter:card" content="summary_large_image"/>
{% endif %}
{% endif %}
+
+ {% if commit.hash == "development" %}
+ <meta name="robots" content="noindex" />
+ {% endif %}
</head>
<body class="px-4 py-2 mx-auto bg-bg-hard dark:bg-bgDark-hard text-fg-0 dark:text-fgDark-0 lg:max-w-5xl">
@@ -113,22 +117,26 @@
</nav>
</header>
- <!--
- <div id="sticky-banner" tabindex="-1" class="flex justify-between w-full p-4 border-b border-fg-2 bg-bg-0 dark:bg-bgDark-0 dark:border-fg-2">
- <div class="flex items-center mx-auto">
- <p class="flex items-center font-normal">
- <span class="inline-flex p-1 mr-3 bg-bg-1 rounded-full dark:bg-bgDark-1 w-6 h-6 items-center justify-center">
- <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-exclamation-mark" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
- <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
- <path d="M12 19v.01"></path>
- <path d="M12 15v-10"></path>
- </svg>
- <span class="sr-only">Exclamation</span>
- </span>
- <span>Xe is now available for employment. Should you or your company be interested, please <a href="/contact/" class="underline">contact Xe</a> for more information. Remote positions only. Must hire in Canada.</span>
- </p>
+ {% if commit.hash == "development" %}
+ <div id="sticky-banner" tabindex="-1" class="flex justify-between w-full p-4 border-b border-fg-2 bg-bg-0 dark:bg-bgDark-0 dark:border-fg-2">
+ <div class="flex items-center mx-auto">
+ <p class="flex items-center font-normal">
+ <span class="inline-flex p-1 mr-3 bg-bg-1 rounded-full dark:bg-bgDark-1 w-6 h-6 items-center justify-center">
+ <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-exclamation-mark" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
+ <path d="M12 19v.01"></path>
+ <path d="M12 15v-10"></path>
+ </svg>
+ <span class="sr-only">Exclamation</span>
+ </span>
+ <span>You have stumbled across the development site for xeiaso.net. Please do not share this link with others, don't be the reason I need something more robust than the honor system.</span>
+ </p>
+ </div>
</div>
- </div>
+ {% endif %}
+
+ <!--
+
-->
<div class="mt-4 p-2">