diff options
| -rw-r--r-- | cmd/xesite/main.go | 18 | ||||
| -rw-r--r-- | internal/lume/lume.go | 98 | ||||
| -rw-r--r-- | lume/src/_includes/base.njk | 38 |
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"> |
