Skip to content

Commit

Permalink
Revert "about.daangn.com: 구 배포 리소스 제거 (#1013)" (#1014)
Browse files Browse the repository at this point in the history
This reverts commit 719eabe.
  • Loading branch information
cometkim authored Jun 10, 2024
1 parent 1b08008 commit 22aa342
Show file tree
Hide file tree
Showing 12 changed files with 596 additions and 0 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/deploy-about-daangn-com-production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Deploy about-daangn-com-production

on:
workflow_dispatch:
push:
paths:
- _workers/about-daangn-com-production/**
- .github/workflows/deploy-about-daangn-com-production.yml
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v4

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

- name: Install Dependencies
run: yarn install --immutable

- name: Get the Wrangler version
id: wrangler-version
run: |
yarn workspace about-daangn-com-production wrangler --version |\
cut -f 2 | sed 's/^/WRANGLER_VERSION=/' >> "$GITHUB_OUTPUT"
- name: Deploy Pages
uses: cloudflare/wrangler-action@v3
with:
command: pages deploy
workingDirectory: _workers/about-daangn-com-production
packageManager: yarn
wranglerVersion: ${{ steps.wrangler-version.outputs.WRANGLER_VERSION }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
174 changes: 174 additions & 0 deletions .github/workflows/deploy-about-daangn-com.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: Deploy about.daangn.com

on:
workflow_dispatch:
push:
paths:
- .github/workflows/deploy-about-daangn-com.yml
- _packages/@karrotmarket/gatsby-*/**
- about.daangn.com/**
branches:
- main

jobs:
build:
name: Build
runs-on: ubuntu-latest
concurrency:
group: workflow-${{ github.workflow }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4

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

- name: Install Dependencies
run: yarn install --immutable

- name: Restore about.daangn.com content cache
id: content-cache
# Uses actions/cache instead of actions/upload-artifacts
#
# The implementation quality of actions/cache is superior to that of upload-artifacts/download-artifacts.
# However, there are complex constraints.
# See https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
#
# The current site artifact is about 500MB due to zstd compression.
#
# Choose appropriate key stretagy to reduce cache thrashing and maximize hits.
uses: actions/cache/restore@v4
with:
path: |
about.daangn.com/public
key: about_daangn_com-public-latest

- name: Restore about.daangn.com build cache
id: build-cache
uses: actions/cache/restore@v4
with:
path: |
about.daangn.com/.cache
key: about_daangn_com-${{ runner.os }}-cache-latest

- name: Build about.daangn.com
id: build
run: yarn workspace about.daangn.com build

# 빌드 직후에 워크플로우 취소되면 조금 곤란할 수도...
- name: Install actions-cache extension
run: gh extension install actions/gh-actions-cache
env:
GH_TOKEN: ${{ github.token }}

- name: Cleanup about.daangn.com stale content cache
run: |
gh actions-cache delete about_daangn_com-public-latest \
-R ${{ github.repository }} \
-B ${{ github.ref }} \
--confirm || echo "not exist"
env:
GH_TOKEN: ${{ github.token }}

- name: Persist about.daangn.com content cache
uses: actions/cache/save@v4
with:
path: about.daangn.com/public
key: about_daangn_com-public-latest

- name: Cleanup about.daangn.com stale build cache
run: |
gh actions-cache delete about_daangn_com-${{ runner.os }}-cache-latest \
-R ${{ github.repository }} \
-B ${{ github.ref }} \
--confirm || echo "not exist"
env:
GH_TOKEN: ${{ github.token }}

- name: Persist about.daangn.com build cache
uses: actions/cache/save@v4
with:
path: about.daangn.com/.cache
key: about_daangn_com-${{ runner.os }}-cache-latest

# 배포는 Atomicity 보장을 위해 Concurrency 제약이 있으면 안됨
# 실제로는 빌드 디펜던시가 걸려서 배포 경합은 없을 것
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Setup Rclone
uses: cometkim/rclone-actions/setup-rclone@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Configure Rclone
run: |
mkdir -p ~/.config/rclone
{
echo "[r2]"
echo "type = s3"
echo "provider = Cloudflare"
echo "access_key_id = ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}"
echo "secret_access_key = ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}"
echo "endpoint = https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com"
echo "acl = private"
} > ~/.config/rclone/rclone.conf
- name: Get date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
- name: Restore about.daangn.com latest content cache
id: content-cache
uses: actions/cache/restore@v4
with:
path: |
about.daangn.com/public
key: about_daangn_com-public-latest
fail-on-cache-miss: true

- name: Upload artifacts (immutable first)
run: |
rclone copy \
--checksum \
--fast-list \
--transfers 8 \
--checkers 50 \
--buffer-size 128M \
--log-level INFO \
--stats 5 \
--immutable --ignore-existing \
about.daangn.com/public/static r2:websites-about-daangn-com/static
- name: Upload artifacts (rest)
run: |
rclone copy \
--checksum \
--fast-list \
--transfers 8 \
--checkers 50 \
--buffer-size 128M \
--log-level INFO \
--stats 5 \
--exclude "about.daangn.com/public/static/**" \
about.daangn.com/public r2:websites-about-daangn-com
- name: Invalidate PUBLIC_TAG
run: |
echo "${{ hashFiles('about.daangn.com/public/**') }}" |\
npx wrangler pages secret put PUBLIC_TAG \
--project about-daangn-com-production
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
1 change: 1 addition & 0 deletions _workers/about-daangn-com-production/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.wrangler/
19 changes: 19 additions & 0 deletions _workers/about-daangn-com-production/functions/_middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Hono } from 'hono';
import { cors } from 'hono/cors';

import { serve } from './serve.ts';

const app = new Hono<HonoEnv>()
// TODO: 그냥 service bindings 을 써서 same-origin 으로 만들자..
.use(
'/completed/',
cors({
origin: '*',
allowMethods: ['HEAD', 'GET', 'OPTIONS'],
}),
)
.use(serve);

export const onRequest: PagesFunction<Env> = (context) => {
return app.fetch(context.request, context.env, context);
};
14 changes: 14 additions & 0 deletions _workers/about-daangn-com-production/functions/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Env = {
/**
* Public content (주로 `index.html`) 의 Cache invalidation 용으로 사용됩니다.
*
* Note: 값 구성을 유연하게 하기 위해 시크릿으로 따로 관리됩니다. (실제 보안이 필요한 값은 아님)
*/
PUBLIC_TAG: string,

CONTENT_BUCKET: R2Bucket,
}

type HonoEnv = {
Bindings: Env,
};
82 changes: 82 additions & 0 deletions _workers/about-daangn-com-production/functions/serve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { Context } from 'hono';
import { serveStatic as makeServe } from 'hono/serve-static';
import { mimes as baseMimes } from 'hono/utils/mime';

export const serve = makeServe<HonoEnv>({
getContent: async (assetPath, c) => {
// biome-ignore lint/style/noParameterAssign: it's fine
assetPath = decodeURIComponent(assetPath);

console.debug(`getContent: ${assetPath}`);
if (
assetPath.startsWith('static/') ||
// assets with chunk hash
/-[a-z0-9]{20}\.(js|js\.map|css|txt)$/.test(assetPath)
) {
console.debug('getContent (immutable)');
c.header('Cache-Control', 'public, max-age=31536000, immutable');
return await getAssetResponse('about-daangn-com-production:immutable', assetPath, c);
} else {
console.debug('getContent (public)');
c.header('Cache-Control', 'public, max-age=0, s-maxage=86400, must-revalidate');
return await getAssetResponse(
`about-daangn-com-production:public:${c.env.PUBLIC_TAG}`,
assetPath,
c,
);
}
},
onNotFound: async (assetPath, c) => {
console.debug(`onNotFound: ${assetPath}`);
const notFoundPage = await getAssetResponse(
`about-daangn-com-production:public:${c.env.PUBLIC_TAG}`,
'404.html',
c,
);
if (notFoundPage) {
c.newResponse(notFoundPage.body, notFoundPage);
} else {
c.newResponse('Not found', { status: 404 });
}
},
mimes: {
...baseMimes,
webmanifest: 'application/manifest+json',
map: 'application/json',
xsl: 'text/xsl',
},
});

async function getAssetResponse(
cacheName: string,
assetPath: string,
c: Context<HonoEnv>,
): Promise<Response | null> {
console.debug(`getAssetResponse: ${assetPath}`);

// console.debug(`cache open: ${cacheName}`);
// const cache = await caches.open(cacheName);
//
// let res = await cache.match(c.req.raw);
// if (res) {
// console.debug('cache hit');
// return res;
// }

const object = await c.env.CONTENT_BUCKET.get(assetPath);
if (!object) {
console.debug('object not found');
return null;
}

const objectHeaders = new Headers();
object.writeHttpMetadata(objectHeaders);

const res = new Response(object.body, {
headers: objectHeaders,
});

// c.executionCtx.waitUntil(cache.put(c.req.raw, res.clone()));

return res;
}
14 changes: 14 additions & 0 deletions _workers/about-daangn-com-production/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "about-daangn-com-production",
"private": true,
"dependencies": {
"@microlabs/otel-cf-workers": "^1.0.0-rc.36",
"@opentelemetry/api": "^1.8.0",
"hono": "^4.3.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20240605.0",
"typescript": "^5.4.5",
"wrangler": "^3.59.0"
}
}
3 changes: 3 additions & 0 deletions _workers/about-daangn-com-production/public/_headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/completed/
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: HEAD, GET, OPTIONS
1 change: 1 addition & 0 deletions _workers/about-daangn-com-production/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Disallow: *
12 changes: 12 additions & 0 deletions _workers/about-daangn-com-production/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"allowImportingTsExtensions": true,
"noEmit": true,
"skipLibCheck": true,
"strict": true,
"types": ["@cloudflare/workers-types/experimental"]
},
"include": ["functions"]
}
13 changes: 13 additions & 0 deletions _workers/about-daangn-com-production/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name = "about-daangn-com-production"
compatibility_date = "2024-04-03"
compatibility_flags = ["nodejs_compat"]
# upload_source_maps = true

pages_build_output_dir = "public"

# [secrets]
# PUBLIC_TAG=""

[[r2_buckets]]
binding = "CONTENT_BUCKET"
bucket_name = "websites-about-daangn-com"
Loading

0 comments on commit 22aa342

Please sign in to comment.