Compare commits

...
9 Commits
Author SHA1 Message Date
owenrees 51bfab5a64 guard env vars 2026-09-01 23:28:21 +02:00
owenrees 2856aaf0d8 no caching and force recreate 2026-09-01 22:50:30 +02:00
owenrees 0784d77684 add base 2026-09-01 22:38:50 +02:00
owenrees 266f2ea6dc remove cache 2026-09-01 22:30:04 +02:00
owenrees 487a1cbe91 change env vars 2026-09-01 22:10:00 +02:00
owenrees 172925c18e remove cache for one run 2026-09-01 22:07:27 +02:00
owenrees f0c6845422 add ignore files and echo maintenance mode for debugging 2026-09-01 22:05:09 +02:00
owenrees 629d1f5f69 update build env vars 2026-09-01 21:54:33 +02:00
owenrees 5735563024 update maintenance banner false/true (#3) 2026-09-01 21:46:59 +02:00
8 changed files with 44 additions and 18 deletions
+8
View File
@@ -0,0 +1,8 @@
node_modules
.output
.git
.gitignore
.env
.env.*
!.env.example
data
+1 -1
View File
@@ -1,7 +1,7 @@
VITE_API_BASE_URL= VITE_API_BASE_URL=
VITE_MATOMO_URL= VITE_MATOMO_URL=
VITE_MATOMO_SITE_ID= VITE_MATOMO_SITE_ID=
VITE_MAINTENANCE_MODE= # nothing = false, anything else = true VITE_MAINTENANCE_MODE="false" # use "true" or "false"
VITE_MAINTENANCE_MODE_MESSAGE="ChessScribe is currently undergoing maintenance. Some features may be unavailable." VITE_MAINTENANCE_MODE_MESSAGE="ChessScribe is currently undergoing maintenance. Some features may be unavailable."
DISCORD_CONTACT_WEBHOOK= DISCORD_CONTACT_WEBHOOK=
+5 -4
View File
@@ -30,13 +30,14 @@ jobs:
context: . context: .
push: true push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
cache-from: type=gha # cache-from: type=gha
cache-to: type=gha,mode=max # cache-to: type=gha,mode=max
no-cache: true
build-args: | build-args: |
VITE_API_BASE_URL=https://api.chess-scribe.org/api/v1 VITE_API_BASE_URL=https://api.chess-scribe.org/api/v1
VITE_MATOMO_URL=https://analytics.owenrees.eu VITE_MATOMO_URL=https://analytics.owenrees.eu
VITE_MATOMO_SITE_ID="3" VITE_MATOMO_SITE_ID="3"
VITE_MAINTENANCE_MODE= VITE_MAINTENANCE_MODE=false
VITE_MAINTENANCE_MODE_MESSAGE="ChessScribe is currently undergoing maintenance. Some features may be unavailable." VITE_MAINTENANCE_MODE_MESSAGE="ChessScribe is currently undergoing maintenance. Some features may be unavailable."
deploy: deploy:
@@ -56,4 +57,4 @@ jobs:
cd /home/${{ secrets.USERNAME }} cd /home/${{ secrets.USERNAME }}
echo "${{ secrets.GHCR_SECRET }}" | docker login ghcr.io -u ${{ env.GH_USER }} --password-stdin echo "${{ secrets.GHCR_SECRET }}" | docker login ghcr.io -u ${{ env.GH_USER }} --password-stdin
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
docker compose up -d docker compose up -d --force-recreate --remove-orphans
+6 -7
View File
@@ -1,17 +1,16 @@
import { Link } from "@tanstack/react-router"; import { Link } from "@tanstack/react-router";
import { Image } from "@unpic/react"; import { Image } from "@unpic/react";
import { z } from "zod";
import MaintenanceModeBanner from "#/components/MaintenanceModeBanner.tsx"; import MaintenanceModeBanner from "#/components/MaintenanceModeBanner.tsx";
import { env } from "#/env.ts"; import { env } from "#/env.ts";
import logo from "@/assets/images/logo.svg?url"; import logo from "@/assets/images/logo.svg?url";
const DEFAULT_MAINTENANCE_MESSAGE = "Maintenance Mode";
export default function Header() { export default function Header() {
const maintenanceModeMessage = env.VITE_MAINTENANCE_MODE const maintenanceModeMessage =
? z env.VITE_MAINTENANCE_MODE ?
.string() env.VITE_MAINTENANCE_MODE_MESSAGE?.trim() || DEFAULT_MAINTENANCE_MESSAGE
.transform((value) => (value.trim() === "" ? null : value)) : null;
.parse(env.VITE_MAINTENANCE_MODE_MESSAGE)
: null;
return ( return (
<header> <header>
+13 -4
View File
@@ -4,14 +4,23 @@ const clientSchema = z.object({
VITE_API_BASE_URL: z.url("Invalid API Base URL format"), VITE_API_BASE_URL: z.url("Invalid API Base URL format"),
VITE_MATOMO_URL: z.url("Invalid URL format"), VITE_MATOMO_URL: z.url("Invalid URL format"),
VITE_MATOMO_SITE_ID: z.string("Invalid Site ID"), VITE_MATOMO_SITE_ID: z.string("Invalid Site ID"),
VITE_MAINTENANCE_MODE: z.string("Invalid Maintenance Mode"), VITE_MAINTENANCE_MODE: z
.enum(
["true", "false"],
'Invalid Maintenance Mode (must be "true" or "false")',
)
.transform((v) => v === "true"),
VITE_MAINTENANCE_MODE_MESSAGE: z.string().optional(), VITE_MAINTENANCE_MODE_MESSAGE: z.string().optional(),
}); });
const serverSchema = z.object({ const serverSchema = z.object({
DISCORD_CONTACT_WEBHOOK: z.string("Invalid Discord Contact Webhook URL"), DISCORD_CONTACT_WEBHOOK: z
DISCORD_ERROR_LOG_WEBHOOK: z.string("Invalid Discord Error Log Webhook URL"), .string("Invalid Discord Contact Webhook URL")
LICHESS_CLIENT_ID: z.string("Invalid Lichess Client ID"), .optional(),
DISCORD_ERROR_LOG_WEBHOOK: z
.string("Invalid Discord Error Log Webhook URL")
.optional(),
LICHESS_CLIENT_ID: z.string("Invalid Lichess Client ID").optional(),
}); });
const fullSchema = z.object({ const fullSchema = z.object({
+4
View File
@@ -7,6 +7,10 @@ export const sendToDiscord = createServerFn({ method: "POST" })
data, data,
) )
.handler(async ({ data }) => { .handler(async ({ data }) => {
if (!env.DISCORD_CONTACT_WEBHOOK) {
return { ok: false, error: "Contact form is not configured" };
}
const response = await fetch(env.DISCORD_CONTACT_WEBHOOK, { const response = await fetch(env.DISCORD_CONTACT_WEBHOOK, {
method: "POST", method: "POST",
headers: { headers: {
+6 -2
View File
@@ -18,10 +18,14 @@ import {
const createVerifier = () => base64UrlEncode(randomBytes(32)); const createVerifier = () => base64UrlEncode(randomBytes(32));
const createChallenge = (verifier: string) => base64UrlEncode(sha256(verifier)); const createChallenge = (verifier: string) => base64UrlEncode(sha256(verifier));
const getRedirectUri = () => const getRedirectUri = () => {
process.env.NODE_ENV === "production" if (process.env.NODE_ENV === "production" && !env.LICHESS_CLIENT_ID) {
throw new Error("LICHESS_CLIENT_ID is not configured");
}
return process.env.NODE_ENV === "production"
? `https://${env.LICHESS_CLIENT_ID}/callback` ? `https://${env.LICHESS_CLIENT_ID}/callback`
: "http://localhost:3000/callback"; : "http://localhost:3000/callback";
};
export const getSession = createServerFn({ method: "GET" }).handler( export const getSession = createServerFn({ method: "GET" }).handler(
async () => { async () => {
+1
View File
@@ -18,6 +18,7 @@ const config = defineConfig({
prerender: { prerender: {
enabled: true, enabled: true,
crawlLinks: true, crawlLinks: true,
failOnError: true,
}, },
pages: [ pages: [
{ {