chore: prepare repo for public release
This commit is contained in:
1 parent
8b7c333a5f
commit
f7cbed956d
14 files changed
+377
-13067
No files matched your search
@@ -0,0 +1,16 @@
|
||||
.git
|
||||
.github
|
||||
.wrangler
|
||||
coverage
|
||||
dist
|
||||
dist-oci
|
||||
node_modules
|
||||
test
|
||||
worker-configuration.d.ts
|
||||
.dev.vars
|
||||
.dev.vars.*
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.DS_Store
|
||||
*.log
|
||||
@@ -43,3 +43,18 @@ updates:
|
||||
- "patch"
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "10:00"
|
||||
timezone: "Asia/Shanghai"
|
||||
open-pull-requests-limit: 2
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "docker"
|
||||
commit-message:
|
||||
prefix: "build"
|
||||
include: "scope"
|
||||
@@ -24,10 +24,7 @@ jobs:
|
||||
github.event.pull_request.draft == false &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
contains(github.event.pull_request.labels.*.name, 'dependencies') &&
|
||||
(
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event.pull_request.user.login == 'dependabot[bot]'
|
||||
)
|
||||
github.event.pull_request.user.login == 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
@@ -43,10 +40,7 @@ jobs:
|
||||
github.event.action == 'unlabeled' &&
|
||||
github.event.label.name == 'dependencies' &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
(
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event.pull_request.user.login == 'dependabot[bot]'
|
||||
)
|
||||
github.event.pull_request.user.login == 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
|
||||
@@ -2,41 +2,13 @@ name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
merge_group:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
||||
with:
|
||||
bun-version: 1.3.12
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Worker types
|
||||
run: bun run cf-typegen
|
||||
|
||||
- name: Type check
|
||||
run: bun run typecheck
|
||||
|
||||
- name: Run Worker tests
|
||||
run: bun run test
|
||||
|
||||
- name: Check generated Worker types
|
||||
run: bun run cf-typegen:check
|
||||
|
||||
- name: Verify Wrangler dry-run build
|
||||
run: bunx wrangler deploy --dry-run
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/validate-reusable.yml
|
||||
@@ -1,45 +0,0 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: production-deploy
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
if: ${{ secrets.CLOUDFLARE_API_TOKEN != '' && secrets.CLOUDFLARE_ACCOUNT_ID != '' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
||||
with:
|
||||
bun-version: 1.3.12
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Worker types
|
||||
run: bun run cf-typegen
|
||||
|
||||
- name: Validate before deploy
|
||||
run: bun run check
|
||||
|
||||
- name: Deploy Worker
|
||||
run: bun run deploy
|
||||
@@ -0,0 +1,115 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
deploy_worker:
|
||||
description: Deploy the Worker to production
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
publish_oci:
|
||||
description: Publish the OCI image to GHCR
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/validate-reusable.yml
|
||||
|
||||
deploy-worker:
|
||||
needs:
|
||||
- validate
|
||||
if: >
|
||||
needs.validate.result == 'success' &&
|
||||
secrets.CLOUDFLARE_API_TOKEN != '' &&
|
||||
secrets.CLOUDFLARE_ACCOUNT_ID != '' &&
|
||||
(
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs.deploy_worker && github.ref == 'refs/heads/main')
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
environment: production
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
||||
with:
|
||||
bun-version: 1.3.12
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Worker types
|
||||
run: bun run cf-typegen
|
||||
|
||||
- name: Deploy Worker
|
||||
run: bun run deploy
|
||||
|
||||
publish-oci:
|
||||
needs:
|
||||
- validate
|
||||
if: >
|
||||
needs.validate.result == 'success' &&
|
||||
(
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
||||
(
|
||||
github.event_name == 'workflow_dispatch' &&
|
||||
inputs.publish_oci &&
|
||||
github.ref == 'refs/heads/main'
|
||||
)
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
env:
|
||||
IMAGE_NAME: ghcr.io/xixu-me/paseo-relay
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and publish OCI image
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
provenance: true
|
||||
sbom: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ env.IMAGE_NAME }}:main
|
||||
@@ -0,0 +1,111 @@
|
||||
name: Validate Reusable
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
validate-worker:
|
||||
name: validate-worker
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
||||
with:
|
||||
bun-version: 1.3.12
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Generate Worker types
|
||||
run: bun run cf-typegen
|
||||
|
||||
- name: Type check
|
||||
run: bun run typecheck
|
||||
|
||||
- name: Run Worker tests
|
||||
run: bun run test
|
||||
|
||||
- name: Check generated Worker types
|
||||
run: bun run cf-typegen:check
|
||||
|
||||
- name: Verify Wrangler dry-run build
|
||||
run: bunx wrangler deploy --dry-run
|
||||
|
||||
validate-oci:
|
||||
name: validate-oci
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
||||
with:
|
||||
bun-version: 1.3.12
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Build OCI image
|
||||
run: docker build -t paseo-relay:ci .
|
||||
|
||||
- name: Smoke test OCI image
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
if [[ $status -ne 0 ]]; then
|
||||
docker logs paseo-relay-ci || true
|
||||
fi
|
||||
docker rm -f paseo-relay-ci >/dev/null 2>&1 || true
|
||||
exit $status
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
docker run -d --name paseo-relay-ci -p 8080:8080 paseo-relay:ci >/dev/null
|
||||
|
||||
for attempt in {1..20}; do
|
||||
status="$(curl --silent --show-error --output health.json --write-out '%{http_code}' http://127.0.0.1:8080/health || true)"
|
||||
if [[ "$status" == "200" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
test "${status:-}" = "200"
|
||||
grep -q '"status":"ok"' health.json
|
||||
|
||||
python3 - <<'PY'
|
||||
import socket
|
||||
|
||||
request = (
|
||||
"GET /ws?role=server&serverId=smoke&v=2 HTTP/1.1\r\n"
|
||||
"Host: 127.0.0.1:8080\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"\r\n"
|
||||
)
|
||||
|
||||
with socket.create_connection(("127.0.0.1", 8080), timeout=5) as conn:
|
||||
conn.sendall(request.encode("ascii"))
|
||||
response = conn.recv(4096).decode("latin1", "replace")
|
||||
|
||||
print(response)
|
||||
if not response.startswith("HTTP/1.1 101"):
|
||||
raise SystemExit("expected HTTP/1.1 101 Switching Protocols")
|
||||
PY
|
||||
@@ -2,7 +2,11 @@ node_modules/
|
||||
.wrangler/
|
||||
coverage/
|
||||
dist/
|
||||
dist-oci/
|
||||
worker-configuration.d.ts
|
||||
.dev.vars
|
||||
.dev.vars.*
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.DS_Store
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
FROM oven/bun:1.3.12-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json bun.lock wrangler.jsonc tsconfig.json ./
|
||||
COPY src ./src
|
||||
|
||||
RUN bun install --frozen-lockfile
|
||||
RUN bunx wrangler deploy --dry-run --outdir=dist-oci
|
||||
|
||||
FROM node:25-slim AS runtime
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
case "${TARGETARCH}" in \
|
||||
amd64) WORKERD_PKG="@cloudflare/workerd-linux-64" ;; \
|
||||
arm64) WORKERD_PKG="@cloudflare/workerd-linux-arm64" ;; \
|
||||
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" && exit 1 ;; \
|
||||
esac && \
|
||||
npm install -g "${WORKERD_PKG}" && \
|
||||
ln -s "/usr/local/lib/node_modules/${WORKERD_PKG}/bin/workerd" /usr/local/bin/workerd
|
||||
|
||||
WORKDIR /worker
|
||||
|
||||
COPY --from=builder /app/dist-oci ./dist-oci
|
||||
COPY config.capnp ./config.capnp
|
||||
|
||||
RUN mkdir -p /var/lib/paseo-relay/do && \
|
||||
chown -R node:node /worker /var/lib/paseo-relay
|
||||
|
||||
VOLUME ["/var/lib/paseo-relay/do"]
|
||||
EXPOSE 8080
|
||||
USER node
|
||||
|
||||
CMD ["workerd", "serve", "config.capnp", "--directory-path", "relay-storage=/var/lib/paseo-relay/do"]
|
||||
@@ -0,0 +1,51 @@
|
||||
using Workerd = import "/workerd/workerd.capnp";
|
||||
|
||||
const config :Workerd.Config = (
|
||||
services = [
|
||||
(
|
||||
name = "main",
|
||||
worker = .worker,
|
||||
),
|
||||
(
|
||||
name = "relay-storage",
|
||||
disk = (
|
||||
writable = true,
|
||||
allowDotfiles = true,
|
||||
),
|
||||
),
|
||||
],
|
||||
sockets = [
|
||||
(
|
||||
name = "http",
|
||||
address = "*:8080",
|
||||
service = "main",
|
||||
http = (),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
const worker :Workerd.Worker = (
|
||||
modules = [
|
||||
(
|
||||
name = "worker",
|
||||
esModule = embed "dist-oci/index.js",
|
||||
),
|
||||
],
|
||||
compatibilityDate = "2026-04-11",
|
||||
durableObjectNamespaces = [
|
||||
(
|
||||
className = "RelayDurableObject",
|
||||
uniqueKey = "paseo-relay-oci-relaydurableobject-v1",
|
||||
enableSql = true,
|
||||
),
|
||||
],
|
||||
bindings = [
|
||||
(
|
||||
name = "RELAY",
|
||||
durableObjectNamespace = "RelayDurableObject",
|
||||
),
|
||||
],
|
||||
durableObjectStorage = (
|
||||
localDisk = "relay-storage",
|
||||
),
|
||||
);
|
||||
+11
-1
@@ -1,8 +1,15 @@
|
||||
{
|
||||
"name": "paseo-relay",
|
||||
"private": true,
|
||||
"description": "Self-hosted Paseo relay.",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"keywords": [
|
||||
"paseo",
|
||||
"relay",
|
||||
"cloudflare-workers",
|
||||
"durable-objects"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/xixu-me/paseo-relay.git"
|
||||
@@ -19,7 +26,10 @@
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"cf-typegen": "bunx wrangler types",
|
||||
"cf-typegen:check": "bunx wrangler types --check"
|
||||
"cf-typegen:check": "bunx wrangler types --check",
|
||||
"oci:bundle": "bunx wrangler deploy --dry-run --outdir=dist-oci",
|
||||
"oci:build": "bun run oci:bundle && docker build -t paseo-relay:latest .",
|
||||
"oci:run": "docker run --rm -p 8080:8080 -v paseo-relay-data:/var/lib/paseo-relay/do paseo-relay:latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@getpaseo/relay": "^0.1.52"
|
||||
|
||||
@@ -50,4 +50,15 @@ describe("paseo relay worker", () => {
|
||||
expect(response.status).toBe(101);
|
||||
expect(response.webSocket).toBeDefined();
|
||||
});
|
||||
|
||||
it("upgrades a valid websocket relay v2 control request", async () => {
|
||||
const response = await SELF.fetch("http://example.com/ws?role=server&serverId=daemon-1&v=2", {
|
||||
headers: {
|
||||
Upgrade: "websocket",
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.status).toBe(101);
|
||||
expect(response.webSocket).toBeDefined();
|
||||
});
|
||||
});
|
||||
Vendored
-12979
File diff suppressed because it is too large.
Load diff
@@ -27,12 +27,10 @@
|
||||
"logs": {
|
||||
"enabled": true,
|
||||
"head_sampling_rate": 1,
|
||||
"persist": true,
|
||||
"invocation_logs": true,
|
||||
},
|
||||
"traces": {
|
||||
"enabled": true,
|
||||
"persist": true,
|
||||
"head_sampling_rate": 1,
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user