Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.prod.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ PUBLIC_TURNSTILE_SITE_KEY=REPLACE_WITH_PRODUCTION_TURNSTILE_SITE_KEY
# GAS values used by `npm run gas:push:production` and `npm run gas:deploy:production`
GAS_SCRIPT_ID=REPLACE_WITH_PRODUCTION_GAS_SCRIPT_ID
GAS_TURNSTILE_SECRET=REPLACE_WITH_PRODUCTION_TURNSTILE_SECRET
GAS_PUBLIC_SITE_URL=https://t.purr.tw
GAS_PUBLIC_SITE_URL=https://s.purr.tw
GAS_ENFORCE_CAPTCHA=true
GAS_ENFORCE_ACCESS_CONTROL=true
GAS_DEPLOYMENT_DESCRIPTION=shortyou-production
Expand Down
74 changes: 52 additions & 22 deletions .github/workflows/gas-cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,24 @@ on:
pull_request:
paths:
- 'gas/**'
- 'scripts/build-gas.mjs'
- 'scripts/env-utils.mjs'
- 'scripts/push-gas.mjs'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.gas.json'
- '.github/workflows/gas-cicd.yml'
push:
branches:
- main
paths:
- 'gas/**'
- 'scripts/build-gas.mjs'
- 'scripts/env-utils.mjs'
- 'scripts/push-gas.mjs'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.gas.json'
- '.github/workflows/gas-cicd.yml'
workflow_dispatch:

Expand Down Expand Up @@ -53,6 +65,15 @@ jobs:
runs-on: ubuntu-latest
needs: validate
environment: production
env:
PUBLIC_API_URL: ${{ vars.PUBLIC_API_URL || secrets.PUBLIC_API_URL }}
GAS_PUBLIC_SITE_URL: ${{ vars.GAS_PUBLIC_SITE_URL }}
GAS_ENFORCE_CAPTCHA: ${{ vars.GAS_ENFORCE_CAPTCHA || 'true' }}
GAS_ENFORCE_ACCESS_CONTROL: ${{ vars.GAS_ENFORCE_ACCESS_CONTROL || 'true' }}
GAS_DEPLOYMENT_DESCRIPTION: ${{ vars.GAS_DEPLOYMENT_DESCRIPTION || 'shortyou-prod' }}
GAS_SCRIPT_ID: ${{ secrets.GAS_SCRIPT_ID }}
GAS_DEPLOYMENT_ID: ${{ secrets.GAS_DEPLOYMENT_ID }}
GAS_TURNSTILE_SECRET: ${{ secrets.GAS_TURNSTILE_SECRET }}
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -65,38 +86,47 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Build GAS backend (TypeScript -> JavaScript)
run: npm run build

- name: Install clasp
run: npm i -g @google/clasp

- name: Prepare clasp auth
env:
CLASPRC_JSON: ${{ secrets.CLASPRC_JSON }}
GAS_SCRIPT_ID: ${{ secrets.GAS_SCRIPT_ID }}
run: |
if [ -z "$CLASPRC_JSON" ] || [ -z "$GAS_SCRIPT_ID" ]; then
echo "Missing required secrets: CLASPRC_JSON / GAS_SCRIPT_ID"
if [ -z "$CLASPRC_JSON" ]; then
echo "Missing required secret: CLASPRC_JSON"
exit 1
fi
printf '%s' "$CLASPRC_JSON" > "$HOME/.clasprc.json"
cat > gas/.clasp.json <<EOF
{
"scriptId": "$GAS_SCRIPT_ID",
"rootDir": "./"
}
EOF

- name: Push and deploy GAS
env:
GAS_DEPLOYMENT_ID: ${{ secrets.GAS_DEPLOYMENT_ID }}
- name: Validate production deploy inputs
run: |
cd gas
clasp push --force
clasp version "ci-${GITHUB_SHA}"
if [ -n "$GAS_DEPLOYMENT_ID" ]; then
clasp deploy -i "$GAS_DEPLOYMENT_ID" -d "ci-${GITHUB_SHA}"
else
clasp deploy -d "ci-${GITHUB_SHA}"
missing=0
for name in \
PUBLIC_API_URL \
GAS_PUBLIC_SITE_URL \
GAS_ENFORCE_CAPTCHA \
GAS_ENFORCE_ACCESS_CONTROL \
GAS_SCRIPT_ID \
GAS_DEPLOYMENT_ID
do
if [ -z "${!name}" ]; then
echo "Missing required deploy input: $name"
missing=1
fi
done
case "$(printf '%s' "$GAS_ENFORCE_CAPTCHA" | tr '[:upper:]' '[:lower:]')" in
true)
if [ -z "$GAS_TURNSTILE_SECRET" ]; then
echo "Missing required deploy input: GAS_TURNSTILE_SECRET"
missing=1
fi
;;
esac
if [ "$missing" -ne 0 ]; then
exit 1
fi

- name: Push, deploy, and sync runtime config
run: |
node scripts/push-gas.mjs --env production --deploy
Comment thread
HeiTang marked this conversation as resolved.
23 changes: 23 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
env:
PUBLIC_API_URL: ${{ vars.PUBLIC_API_URL || secrets.PUBLIC_API_URL }}
PUBLIC_TURNSTILE_SITE_KEY: ${{ vars.PUBLIC_TURNSTILE_SITE_KEY || secrets.PUBLIC_TURNSTILE_SITE_KEY }}
GAS_PUBLIC_SITE_URL: ${{ vars.GAS_PUBLIC_SITE_URL }}

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
Expand All @@ -61,3 +62,25 @@ jobs:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

healthcheck:
runs-on: ubuntu-latest
needs: deploy
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Verify live frontend GAS target
env:
HEALTHCHECK_FRONTEND_URL: ${{ vars.GAS_PUBLIC_SITE_URL }}
EXPECTED_GAS_DEPLOYMENT_ID: ${{ secrets.GAS_DEPLOYMENT_ID }}
EXPECTED_PUBLIC_SITE_URL: ${{ vars.GAS_PUBLIC_SITE_URL }}
EXPECTED_RUNTIME_ENVIRONMENT: production
run: |
npm run check:production-health -- --retries 24 --retry-delay-ms 10000
35 changes: 35 additions & 0 deletions .github/workflows/production-healthcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Production Frontend Health Check

on:
workflow_dispatch:
schedule:
- cron: '17 * * * *'

permissions:
contents: read

concurrency:
group: production-healthcheck
cancel-in-progress: false

jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Verify live frontend GAS target
env:
HEALTHCHECK_FRONTEND_URL: ${{ vars.GAS_PUBLIC_SITE_URL }}
EXPECTED_GAS_DEPLOYMENT_ID: ${{ secrets.GAS_DEPLOYMENT_ID }}
EXPECTED_PUBLIC_SITE_URL: ${{ vars.GAS_PUBLIC_SITE_URL }}
EXPECTED_RUNTIME_ENVIRONMENT: production
run: |
npm run check:production-health -- --retries 2 --retry-delay-ms 5000
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ ShortYou is a lightweight, self-hostable URL shortener with a split frontend/bac

## Quick Start

1. Visit [https://t.purr.tw/](https://t.purr.tw/) to open the homepage.
1. Visit [https://s.purr.tw/](https://s.purr.tw/) to open the homepage.

2. Existing short links look like `https://t.purr.tw/#your-alias`.
2. Existing short links look like `https://s.purr.tw/#your-alias`.

3. If you receive a dedicated create link, open it to enter authorized create mode.

Expand Down Expand Up @@ -142,12 +142,14 @@ ShortYou uses split deployment by default, so the frontend can stay on static ho

### 1. Prepare environment settings

- For the frontend, you need at least `PUBLIC_API_URL` and `PUBLIC_TURNSTILE_SITE_KEY`.
- For the frontend, you need `PUBLIC_API_URL`, `PUBLIC_TURNSTILE_SITE_KEY`, and either `PUBLIC_SITE_URL` or `GAS_PUBLIC_SITE_URL`.

| Parameter | Description | Default |
| --- | --- | --- |
| `PUBLIC_API_URL` | Public URL of the GAS Web App | None |
| `PUBLIC_TURNSTILE_SITE_KEY` | Cloudflare Turnstile site key | None |
| `PUBLIC_SITE_URL` | Public frontend site URL used for Astro site metadata and generated deploy artifacts | None |
| `GAS_PUBLIC_SITE_URL` | Compatible fallback for the same frontend site URL in shared CI/deploy environments | None |

- For the backend, you need at least `GAS_SCRIPT_ID`, `GAS_PUBLIC_SITE_URL`, `GAS_ENFORCE_CAPTCHA`, and `GAS_ENFORCE_ACCESS_CONTROL`.

Expand All @@ -168,6 +170,7 @@ ShortYou uses split deployment by default, so the frontend can stay on static ho
- Deploy `dist/` to GitHub Pages or another static host.

- The frontend connects to the target GAS Web App through `PUBLIC_API_URL`.
- Generated deploy artifacts such as `dist/CNAME` and `dist/robots.txt` use `PUBLIC_SITE_URL` first and fall back to `GAS_PUBLIC_SITE_URL`.

### 3. Push or deploy the backend

Expand Down
9 changes: 6 additions & 3 deletions README.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ ShortYou 是一個輕量、可自行部署的短網址服務,採用前後端

## 快速使用

1. 開啟 [https://t.purr.tw/](https://t.purr.tw/) 進入首頁。
1. 開啟 [https://s.purr.tw/](https://s.purr.tw/) 進入首頁。

2. 已建立的短連結格式如 `https://t.purr.tw/#your-alias`。
2. 已建立的短連結格式如 `https://s.purr.tw/#your-alias`。

3. 如果你收到專屬建立連結,開啟後即可進入授權建立模式。

Expand Down Expand Up @@ -141,12 +141,14 @@ ShortYou 預設採前後端分離部署,這樣可以讓前端維持靜態托

### 1. 準備環境設定

- 以前端來說,至少需要 `PUBLIC_API_URL` 與 `PUBLIC_TURNSTILE_SITE_KEY`
- 以前端來說,需要 `PUBLIC_API_URL`、`PUBLIC_TURNSTILE_SITE_KEY`,以及 `PUBLIC_SITE_URL` 或 `GAS_PUBLIC_SITE_URL` 其中之一

| 參數 | 說明 | 預設值 |
| --- | --- | --- |
| `PUBLIC_API_URL` | GAS Web App 的公開 URL | 無 |
| `PUBLIC_TURNSTILE_SITE_KEY` | Cloudflare Turnstile 的 site key | 無 |
| `PUBLIC_SITE_URL` | 前端站點公開 URL,供 Astro site metadata 與部署產物生成使用 | 無 |
| `GAS_PUBLIC_SITE_URL` | 在共用 CI/部署環境中可作為相容替代值的前端站點 URL | 無 |

- 以後端來說,至少需要 `GAS_SCRIPT_ID`、`GAS_PUBLIC_SITE_URL`、`GAS_ENFORCE_CAPTCHA`、`GAS_ENFORCE_ACCESS_CONTROL`。

Expand All @@ -167,6 +169,7 @@ ShortYou 預設採前後端分離部署,這樣可以讓前端維持靜態托
- 將 `dist/` 部署到 GitHub Pages 或其他靜態主機。

- 前端會依 `PUBLIC_API_URL` 連到對應的 GAS Web App。
- `dist/CNAME` 與 `dist/robots.txt` 等部署產物會優先使用 `PUBLIC_SITE_URL`,若未提供則回退到 `GAS_PUBLIC_SITE_URL`。

### 3. 推送或發版後端

Expand Down
3 changes: 2 additions & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import { requirePublicSiteUrl } from './scripts/site-url.mjs';

export default defineConfig({
site: 'https://t.purr.tw',
site: requirePublicSiteUrl(process.env, 'Missing required site URL for Astro config'),
integrations: [tailwind()]
});
Loading
Loading