From 48ec86487d1670c9487b0c0938485c51edab64c2 Mon Sep 17 00:00:00 2001 From: Colin McDonald Date: Fri, 11 Sep 2026 17:15:18 -0400 Subject: [PATCH] ci: deploy Workers through GitHub environments --- .github/workflows/deploy-workers.yml | 81 ++++++++++++++++++++++++++ README.md | 18 ++++++ package.json | 1 + pnpm-lock.yaml | 3 + src/context/preferences.svelte.spec.ts | 28 ++++----- wrangler.jsonc | 38 +++++++----- 6 files changed, 142 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/deploy-workers.yml diff --git a/.github/workflows/deploy-workers.yml b/.github/workflows/deploy-workers.yml new file mode 100644 index 000000000..57932fcc5 --- /dev/null +++ b/.github/workflows/deploy-workers.yml @@ -0,0 +1,81 @@ +name: Deploy Workers + +on: [push, workflow_dispatch] + +permissions: + contents: read + deployments: write + +concurrency: + group: deploy-workers-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/dev' }} + +jobs: + checks: + uses: ./.github/workflows/checks.yml + + deploy: + name: Deploy SkyCrypt + needs: checks + runs-on: ubuntu-latest + environment: + name: ${{ github.ref == 'refs/heads/dev' && 'cloudflare-production' || 'cloudflare-development' }} + deployment: false + env: + CLOUDFLARE_ENV: ${{ vars.CLOUDFLARE_ENV }} + + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Require Wrangler environment + if: vars.CLOUDFLARE_ENV == '' + run: | + echo "::error::Set CLOUDFLARE_ENV in the selected GitHub environment." + exit 1 + + - name: Install dependencies + uses: ./.github/actions/pnpm-install + + - name: Prepare build environment + run: cp .env.example .env + + - name: Build + run: pnpm build + env: + PUBLIC_COMMIT_HASH: ${{ github.sha }} + PUBLIC_SERVER_API_URL: https://sky.shiiyu.moe/api/ + PUBLIC_API_URL: https://sky.shiiyu.moe/api/ + SERVER_API_TOKEN: ${{ secrets.SERVER_API_TOKEN }} + + - name: Validate Worker bundle + run: pnpm exec wrangler deploy --dry-run --no-x-provision --env "$CLOUDFLARE_ENV" + + - name: Get preview alias + id: ref + if: github.ref != 'refs/heads/dev' + run: echo "ref_name=${GITHUB_REF_NAME//[^a-zA-Z0-9-]/-}" >> "$GITHUB_OUTPUT" + + - name: Initialize Preview Worker + if: github.ref != 'refs/heads/dev' + run: | + if pnpm exec wrangler versions list --env "$CLOUDFLARE_ENV" --json > "$RUNNER_TEMP/worker-versions.json" 2> "$RUNNER_TEMP/worker-versions-error.log"; then + exit 0 + fi + if ! grep -Fq '[code: 10007]' "$RUNNER_TEMP/worker-versions-error.log"; then + cat "$RUNNER_TEMP/worker-versions-error.log" >&2 + exit 1 + fi + pnpm exec wrangler deploy --no-x-provision --env "$CLOUDFLARE_ENV" + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + + - name: Deploy + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + gitHubToken: ${{ github.token }} + environment: ${{ vars.CLOUDFLARE_ENV }} + command: ${{ github.ref == 'refs/heads/dev' && 'deploy --no-x-provision' || format('versions upload --preview-alias {0}', steps.ref.outputs.ref_name) }} diff --git a/README.md b/README.md index dc9a629ed..f4a44cb53 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,24 @@ > git push origin dev --force-with-lease > ``` +## Lunar Client Workers deployment + +`.github/workflows/deploy-workers.yml` runs the existing lint, Svelte/TypeScript, and test checks before building and deploying this fork. `dev` selects the `cloudflare-production` GitHub environment; other branches select `cloudflare-development` and upload a preview version with a branch alias. A missing development Worker is initialized before its first preview upload. + +Each GitHub environment must supply the `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` secrets and the `CLOUDFLARE_ENV` variable (`production` or `development`). Restrict `cloudflare-production` to the `dev` branch. Account IDs come from those secrets, not Wrangler files. Both accounts use the Worker name `skycrypt-embed`; production owns `skycrypt-embed.lunarclient.com`, while development has no custom domain. Both environments retain the existing SkyCrypt API URLs. + +Before enabling this workflow, provision the GitHub environments and account credentials, configure any required runtime secrets in the destination accounts, and disable the old Workers Builds integration so it does not deploy alongside GitHub Actions. The destination production account must contain the `lunarclient.com` zone. Deployments use `--no-x-provision` and no longer bind the old shared-account observability Tail Worker. + +Local validation without deployment: + +```sh +pnpm install --frozen-lockfile +cp .env.example .env +CLOUDFLARE_ENV=development PUBLIC_API_URL=https://sky.shiiyu.moe/api/ PUBLIC_SERVER_API_URL=https://sky.shiiyu.moe/api/ pnpm build +pnpm exec wrangler deploy --dry-run --no-x-provision --env development +pnpm exec wrangler deploy --dry-run --no-x-provision --env production +``` +

diff --git a/package.json b/package.json index c796b6205..86d77a904 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "vite": "^8.2.2", "vitest": "^4.1.11", "vitest-browser-svelte": "^3.0.0", + "wrangler": "4.127.1", "zod": "^4.4.3" }, "simple-git-hooks": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c36248ae..181fda402 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -273,6 +273,9 @@ importers: vitest-browser-svelte: specifier: ^3.0.0 version: 3.0.0(svelte@5.56.10(@typescript-eslint/types@8.67.0))(vitest@4.1.11) + wrangler: + specifier: 4.127.1 + version: 4.127.1 zod: specifier: ^4.4.3 version: 4.4.3 diff --git a/src/context/preferences.svelte.spec.ts b/src/context/preferences.svelte.spec.ts index 65155e9df..dc7712d1d 100644 --- a/src/context/preferences.svelte.spec.ts +++ b/src/context/preferences.svelte.spec.ts @@ -28,9 +28,9 @@ describe("PreferencesContext Tests", () => { untrack(() => { expect(prefs.sectionOrder).toHaveLength(sections.length); - expect(prefs.performanceMode).toBe(false); + expect(prefs.performanceMode).toBe(true); expect(prefs.keybind).toBe("/"); - expect(prefs.showGlint).toBe(true); + expect(prefs.showGlint).toBe(false); expect(prefs.rainbowEnchantments).toBe(false); expect(prefs.mctooltip).toBe(false); }); @@ -300,12 +300,12 @@ describe("PreferencesContext Tests", () => { untrack(() => { const before = prefs.performanceMode; - prefs.performanceMode = true; + prefs.performanceMode = false; flushSync(); const after = prefs.performanceMode; - expect(before).toBe(false); - expect(after).toBe(true); + expect(before).toBe(true); + expect(after).toBe(false); }); }); @@ -336,12 +336,12 @@ describe("PreferencesContext Tests", () => { untrack(() => { const before = prefs.showGlint; - prefs.showGlint = false; + prefs.showGlint = true; flushSync(); const after = prefs.showGlint; - expect(before).toBe(true); - expect(after).toBe(false); + expect(before).toBe(false); + expect(after).toBe(true); }); }); @@ -470,15 +470,15 @@ describe("PreferencesContext Tests", () => { }); describe("performanceMode document.dataset", () => { - it("sets document.documentElement.dataset.performance to 'false' by default", ({ expect }) => { + it("sets document.documentElement.dataset.performance to 'true' by default", ({ expect }) => { const cleanup = $effect.root(() => { const prefs = new PreferencesContext(); untrack(() => { flushSync(); - expect(prefs.performanceMode).toBe(false); - expect(document.documentElement.dataset.performance).toBe("false"); + expect(prefs.performanceMode).toBe(true); + expect(document.documentElement.dataset.performance).toBe("true"); }); }); @@ -744,9 +744,9 @@ describe("PreferencesContext Tests", () => { untrack(() => { flushSync(); - expect(prefs.performanceMode).toBe(false); + expect(prefs.performanceMode).toBe(true); expect(prefs.keybind).toBe("/"); - expect(prefs.showGlint).toBe(true); + expect(prefs.showGlint).toBe(false); expect(prefs.rainbowEnchantments).toBe(false); }); }); @@ -791,7 +791,7 @@ describe("PreferencesContext Tests", () => { expect(prefs.performanceMode).toBe(true); expect(prefs.keybind).toBe("custom"); - expect(prefs.showGlint).toBe(true); + expect(prefs.showGlint).toBe(false); }); }); diff --git a/wrangler.jsonc b/wrangler.jsonc index 5182a5f77..1afa05195 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -1,5 +1,5 @@ { - "name": "skycrypt-embed-lunarclient-com", + "name": "skycrypt-embed", "main": ".svelte-kit/cloudflare/_worker.js", "compatibility_date": "2026-01-27", "compatibility_flags": ["nodejs_compat"], @@ -9,13 +9,7 @@ "binding": "ASSETS", "directory": ".svelte-kit/cloudflare" }, - "routes": [ - { - "pattern": "skycrypt-embed.lunarclient.com", - "custom_domain": true - } - ], - // Persist observability in Cloudflare and forward invocations to the central Tail Worker. + // Persist observability in the selected Cloudflare account. "observability": { "enabled": true, "logs": { @@ -32,13 +26,31 @@ "persist": true } }, - "tail_consumers": [ - { - "service": "moonsworth-workers-observability" - } - ], "vars": { "PUBLIC_SERVER_API_URL": "https://sky.shiiyu.moe/api/", "PUBLIC_API_URL": "https://sky.shiiyu.moe/api/" + }, + "env": { + "production": { + "name": "skycrypt-embed", + "routes": [ + { + "pattern": "skycrypt-embed.lunarclient.com", + "custom_domain": true + } + ], + "vars": { + "PUBLIC_SERVER_API_URL": "https://sky.shiiyu.moe/api/", + "PUBLIC_API_URL": "https://sky.shiiyu.moe/api/" + } + }, + "development": { + "name": "skycrypt-embed", + "routes": [], + "vars": { + "PUBLIC_SERVER_API_URL": "https://sky.shiiyu.moe/api/", + "PUBLIC_API_URL": "https://sky.shiiyu.moe/api/" + } + } } }