serverless-ircd 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deploy-aws.yml +156 -32
- package/.github/workflows/deploy-cf-tcp.yml +11 -9
- package/.github/workflows/deploy-cf.yml +14 -14
- package/CHANGELOG.md +305 -0
- package/README.md +134 -41
- package/apps/aws-stack/README.md +3 -5
- package/apps/aws-stack/bin/aws.ts +82 -9
- package/apps/aws-stack/cdk.json +0 -3
- package/apps/aws-stack/package.json +3 -4
- package/apps/aws-stack/src/aws-stack.ts +177 -52
- package/apps/aws-stack/src/static-site.ts +323 -0
- package/apps/aws-stack/tests/smoke-helpers.test.ts +1 -1
- package/apps/aws-stack/tests/stack.test.ts +267 -92
- package/apps/aws-stack/tests/static-site.test.ts +491 -0
- package/apps/aws-stack/tests/synth-no-bundle.test.ts +0 -1
- package/apps/cf-tcp-container/package.json +2 -3
- package/apps/cf-tcp-container/src/container-server.ts +12 -9
- package/apps/cf-tcp-container/wrangler.toml +1 -10
- package/apps/cf-worker/package.json +3 -4
- package/apps/cf-worker/wrangler.toml +12 -71
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/server.ts +21 -17
- package/apps/web/landing/favicon.ico +0 -0
- package/apps/web/landing/index.html +1 -0
- package/apps/web/package.json +2 -2
- package/apps/web/scripts/build.mjs +66 -4
- package/apps/web/src/build-env.ts +125 -4
- package/apps/web/src/config-schema.ts +20 -6
- package/apps/web/static/{config.staging.json → config.prod-aws.json} +3 -2
- package/apps/web/tests/build-env.test.ts +210 -9
- package/apps/web/tests/build-smoke.test.ts +2 -2
- package/apps/web/tests/config-schema.test.ts +149 -25
- package/docs/AWS-Deployment.md +670 -96
- package/docs/AWS-TCP-Deployment.md +20 -45
- package/docs/Cloudflare-Deployment-Guide.md +87 -113
- package/docs/Cloudflare-TCP-Deployment.md +25 -49
- package/docs/Release-Process.md +27 -23
- package/docs/Services.md +69 -22
- package/docs/WebClientGuide.md +35 -26
- package/package.json +7 -10
- package/packages/aws-adapter/package.json +1 -1
- package/packages/aws-adapter/src/cdk-table-defs.ts +6 -11
- package/packages/aws-adapter/src/config-loader.ts +19 -2
- package/packages/aws-adapter/src/dynamo-services-store.ts +7 -0
- package/packages/aws-adapter/src/handlers/connect.ts +26 -0
- package/packages/aws-adapter/src/handlers/default.ts +190 -123
- package/packages/aws-adapter/src/handlers/index.ts +67 -23
- package/packages/aws-adapter/src/handlers/nlb-stream.ts +3 -6
- package/packages/aws-adapter/src/index.ts +5 -7
- package/packages/aws-adapter/src/origin-allowlist.ts +94 -0
- package/packages/aws-adapter/src/serialize.ts +15 -0
- package/packages/aws-adapter/src/tables.ts +2 -12
- package/packages/aws-adapter/tests/aws-harness.ts +0 -1
- package/packages/aws-adapter/tests/config-loader.test.ts +66 -0
- package/packages/aws-adapter/tests/connect.test.ts +124 -1
- package/packages/aws-adapter/tests/default-occ.test.ts +219 -0
- package/packages/aws-adapter/tests/dynamo-services-store-unit.test.ts +11 -0
- package/packages/aws-adapter/tests/handlers.test.ts +117 -11
- package/packages/aws-adapter/tests/migrate-accounts-to-services.test.ts +164 -0
- package/packages/aws-adapter/tests/origin-allowlist.test.ts +110 -0
- package/packages/aws-adapter/tests/ping-checker.test.ts +0 -1
- package/packages/aws-adapter/tests/stats.test.ts +0 -3
- package/packages/aws-adapter/tests/sweeper.test.ts +0 -1
- package/packages/aws-adapter/tests/tables.test.ts +1 -8
- package/packages/aws-adapter/tests/transactions.test.ts +0 -1
- package/packages/cf-adapter/package.json +1 -5
- package/packages/cf-adapter/src/cf-runtime.ts +59 -8
- package/packages/cf-adapter/src/channel-do.ts +13 -3
- package/packages/cf-adapter/src/connection-do.ts +266 -109
- package/packages/cf-adapter/src/d1-services-store.ts +63 -26
- package/packages/cf-adapter/src/env.ts +11 -10
- package/packages/cf-adapter/src/index.ts +0 -6
- package/packages/cf-adapter/tests/cf-runtime.test.ts +101 -1
- package/packages/cf-adapter/tests/channel-do.test.ts +118 -1
- package/packages/cf-adapter/tests/connection-do-coverage.test.ts +460 -0
- package/packages/cf-adapter/tests/connection-do-pure.test.ts +95 -54
- package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +62 -38
- package/packages/cf-adapter/tests/d1-services-store.test.ts +53 -2
- package/packages/cf-adapter/tests/serialize.test.ts +25 -0
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/irc-core/package.json +1 -1
- package/packages/irc-core/src/account-migration.ts +140 -0
- package/packages/irc-core/src/commands/account-auth.ts +16 -19
- package/packages/irc-core/src/commands/memoserv.ts +1 -1
- package/packages/irc-core/src/commands/nickserv.ts +122 -11
- package/packages/irc-core/src/commands/registration.ts +2 -2
- package/packages/irc-core/src/commands/sasl.ts +22 -31
- package/packages/irc-core/src/config.ts +35 -9
- package/packages/irc-core/src/credential-hashing.ts +11 -54
- package/packages/irc-core/src/index.ts +1 -0
- package/packages/irc-core/src/ports.ts +159 -179
- package/packages/irc-core/src/types.ts +38 -10
- package/packages/irc-core/tests/account-migration.test.ts +133 -0
- package/packages/irc-core/tests/commands/markread.test.ts +54 -0
- package/packages/irc-core/tests/commands/memoserv.test.ts +19 -0
- package/packages/irc-core/tests/commands/nickserv.test.ts +237 -1
- package/packages/irc-core/tests/commands/oper.test.ts +15 -0
- package/packages/irc-core/tests/commands/registration.test.ts +140 -133
- package/packages/irc-core/tests/commands/sasl.test.ts +159 -178
- package/packages/irc-core/tests/commands/unified-account.test.ts +102 -84
- package/packages/irc-core/tests/credential-hashing.test.ts +0 -78
- package/packages/irc-core/tests/message-store.test.ts +5 -0
- package/packages/irc-core/tests/persistent-services-store.test.ts +71 -12
- package/packages/irc-core/tests/ports.test.ts +71 -0
- package/packages/irc-core/tests/services-store.test.ts +204 -0
- package/packages/irc-core/vitest.config.ts +6 -1
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-server/src/actor.ts +0 -14
- package/packages/irc-server/tests/actor.test.ts +19 -47
- package/packages/irc-test-support/package.json +1 -1
- package/pnpm-workspace.yaml +1 -0
- package/scripts/__tests__/deploy-web-aws.test.ts +491 -0
- package/scripts/deploy-web-aws.mjs +290 -0
- package/scripts/package.json +23 -0
- package/scripts/tsconfig.test.json +12 -0
- package/scripts/vitest.config.ts +19 -0
- package/tools/ci-hardening/package.json +1 -1
- package/tools/ci-hardening/src/index.ts +2 -0
- package/tools/ci-hardening/src/validate.ts +57 -0
- package/tools/ci-hardening/tests/deploy-aws-oidc.test.ts +96 -0
- package/tools/ci-hardening/tests/validate.test.ts +42 -0
- package/tools/load-test/package.json +1 -1
- package/tools/migrate-accounts-to-services.ts +270 -0
- package/tools/package.json +2 -1
- package/tools/seed-aws-accounts.ts +35 -10
- package/tools/seed-cf-accounts.ts +42 -9
- package/tools/tcp-ws-forwarder/package.json +1 -1
- package/packages/aws-adapter/src/account-store.ts +0 -121
- package/packages/aws-adapter/src/dynamo-account-store.ts +0 -95
- package/packages/aws-adapter/tests/account-store-dynamo.test.ts +0 -223
- package/packages/aws-adapter/tests/account-store.test.ts +0 -276
- package/packages/cf-adapter/src/d1-account-store.ts +0 -198
- package/packages/cf-adapter/tests/d1-account-store.test.ts +0 -274
- package/packages/irc-core/tests/account-store.test.ts +0 -131
|
@@ -2,30 +2,31 @@ name: deploy-aws
|
|
|
2
2
|
|
|
3
3
|
# AWS CDK deploy pipeline.
|
|
4
4
|
#
|
|
5
|
-
#
|
|
5
|
+
# This workflow is `workflow_dispatch`-only — there is no automatic
|
|
6
|
+
# push-to-main trigger. A maintainer runs it by hand to ship the single
|
|
7
|
+
# AWS stack target (`apps/aws-stack`):
|
|
6
8
|
# 1. Install deps (frozen lockfile).
|
|
7
9
|
# 2. Build the aws-adapter + irc-core/irc-server so the CDK stack
|
|
8
10
|
# typechecks against real workspace packages.
|
|
9
11
|
# 3. `cdk deploy --all` the `apps/aws-stack` stack (API Gateway v2
|
|
10
|
-
# WebSocket API, Lambda, DynamoDB tables)
|
|
11
|
-
# account/region.
|
|
12
|
+
# WebSocket API, Lambda, DynamoDB tables).
|
|
12
13
|
# 4. Replay the smoke e2e (`scripts/smoke.mjs`) against the deployed
|
|
13
14
|
# WebSocket endpoint — CONNECT/REGISTER/JOIN/PRIVMSG/QUIT. Failure
|
|
14
15
|
# blocks the merge (the deploy job is required on `main`).
|
|
15
16
|
#
|
|
16
17
|
# Secrets / variables (configure under repo Settings → Secrets and
|
|
17
18
|
# variables → Actions):
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
19
|
+
# AWS_DEPLOY_ROLE_ARN REQUIRED. ARN of the IAM role the workflow
|
|
20
|
+
# assumes via GitHub OIDC web identity. The
|
|
21
|
+
# role's trust policy MUST condition on
|
|
22
|
+
# `token.actions.githubusercontent.com:sub`
|
|
23
|
+
# = `repo:<owner>/<repo>:ref:refs/heads/main`
|
|
24
|
+
# (see docs/AWS-Deployment.md §17 for the
|
|
25
|
+
# trust-policy snippet). Long-lived access
|
|
26
|
+
# keys (`AWS_ACCESS_KEY_ID` /
|
|
27
|
+
# `AWS_SECRET_ACCESS_KEY`) are NOT accepted —
|
|
28
|
+
# a single exfil vector against them is full
|
|
29
|
+
# AWS account takeover.
|
|
29
30
|
# AWS_REGION AWS region to deploy into (e.g. us-east-1).
|
|
30
31
|
#
|
|
31
32
|
# Repo variable (Settings → Secrets and variables → Variables):
|
|
@@ -38,22 +39,23 @@ name: deploy-aws
|
|
|
38
39
|
# behaviour).
|
|
39
40
|
|
|
40
41
|
on:
|
|
41
|
-
# Automatic push trigger disabled; deploy only runs manually.
|
|
42
42
|
workflow_dispatch:
|
|
43
43
|
|
|
44
|
-
# OIDC web identity
|
|
44
|
+
# GitHub OIDC web identity: id-token write so Actions can mint a JWT
|
|
45
|
+
# for `sts:AssumeRoleWithWebIdentity`; contents:read for checkout.
|
|
46
|
+
# Least-privilege — no other GITHUB_TOKEN permissions granted.
|
|
45
47
|
permissions:
|
|
46
48
|
id-token: write
|
|
47
49
|
contents: read
|
|
48
50
|
|
|
49
51
|
# Prevent two deploys racing the same CloudFormation stack.
|
|
50
52
|
concurrency:
|
|
51
|
-
group: aws-
|
|
53
|
+
group: aws-deploy
|
|
52
54
|
cancel-in-progress: false
|
|
53
55
|
|
|
54
56
|
jobs:
|
|
55
|
-
deploy
|
|
56
|
-
name: cdk deploy --all
|
|
57
|
+
deploy:
|
|
58
|
+
name: cdk deploy --all
|
|
57
59
|
runs-on: ubuntu-latest
|
|
58
60
|
timeout-minutes: 10
|
|
59
61
|
steps:
|
|
@@ -81,20 +83,55 @@ jobs:
|
|
|
81
83
|
- name: Test
|
|
82
84
|
run: pnpm test
|
|
83
85
|
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
86
|
+
# Fail fast before any AWS call if the OIDC role ARN is missing.
|
|
87
|
+
# `AWS_DEPLOY_ROLE_ARN` is the ONLY accepted credential source —
|
|
88
|
+
# long-lived access keys are intentionally not wired in.
|
|
89
|
+
- name: Assert OIDC deploy role ARN is set
|
|
90
|
+
if: env.AWS_DEPLOY_ROLE_ARN == ''
|
|
91
|
+
env:
|
|
92
|
+
AWS_DEPLOY_ROLE_ARN: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
93
|
+
run: |
|
|
94
|
+
echo "::error::AWS_DEPLOY_ROLE_ARN secret is empty — configure the GitHub OIDC IAM role trust before deploying (see docs/AWS-Deployment.md §17)."
|
|
95
|
+
exit 1
|
|
96
|
+
|
|
97
|
+
# OIDC-only: assume the configured role via web identity. No
|
|
98
|
+
# static access keys are accepted; if the role ARN is empty the
|
|
99
|
+
# step above has already failed the job.
|
|
88
100
|
- name: Configure AWS credentials
|
|
89
101
|
uses: aws-actions/configure-aws-credentials@v4
|
|
90
102
|
with:
|
|
91
103
|
aws-region: ${{ secrets.AWS_REGION }}
|
|
92
104
|
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
93
|
-
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
94
|
-
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
95
105
|
|
|
96
|
-
-
|
|
97
|
-
|
|
106
|
+
# Defence-in-depth: confirm sts:AssumeRoleWithWebIdentity actually
|
|
107
|
+
# minted the configured role and the job is NOT running on
|
|
108
|
+
# ambient static credentials. Aborts before any `cdk deploy`.
|
|
109
|
+
- name: Assert assumed role matches AWS_DEPLOY_ROLE_ARN
|
|
110
|
+
env:
|
|
111
|
+
AWS_DEPLOY_ROLE_ARN: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
112
|
+
run: |
|
|
113
|
+
set -euo pipefail
|
|
114
|
+
CALLER_ARN=$(aws sts get-caller-identity --query 'Arn' --output text)
|
|
115
|
+
ASSUMED_ROLE_ARN="${AWS_DEPLOY_ROLE_ARN}"
|
|
116
|
+
# The caller ARN for an OIDC-assumed role looks like
|
|
117
|
+
# arn:aws:sts::<account>:assumed-role/<role-name>/GitHubActions
|
|
118
|
+
# while AWS_DEPLOY_ROLE_ARN is the role ARN
|
|
119
|
+
# arn:aws:iam::<account>:role/<role-name>
|
|
120
|
+
# Compare by role-name + account-id so the two shapes match.
|
|
121
|
+
CALLER_ROLE=$(echo "$CALLER_ARN" | sed -n 's#.*assumed-role/\([^/]*\).*#\1#p')
|
|
122
|
+
CALLER_ACCT=$(echo "$CALLER_ARN" | sed -n 's#arn:aws:sts::\([0-9]*\).*#\1#p')
|
|
123
|
+
CONFIG_ROLE=$(echo "$ASSUMED_ROLE_ARN" | sed -n 's#.*/role/\([^/]*\)#\1#p')
|
|
124
|
+
CONFIG_ACCT=$(echo "$ASSUMED_ROLE_ARN" | sed -n 's#arn:aws:iam::\([0-9]*\).*#\1#p')
|
|
125
|
+
if [ -z "$CALLER_ROLE" ] || [ -z "$CONFIG_ROLE" ] \
|
|
126
|
+
|| [ "$CALLER_ROLE" != "$CONFIG_ROLE" ] \
|
|
127
|
+
|| [ "$CALLER_ACCT" != "$CONFIG_ACCT" ]; then
|
|
128
|
+
echo "::error::STS caller-identity does not match AWS_DEPLOY_ROLE_ARN (got '$CALLER_ARN', expected role '$CONFIG_ROLE' in account '$CONFIG_ACCT'). OIDC did not mint the configured role — aborting before cdk deploy."
|
|
129
|
+
exit 1
|
|
130
|
+
fi
|
|
131
|
+
echo "OIDC role assertion passed: $CALLER_ROLE in account $CALLER_ACCT"
|
|
132
|
+
|
|
133
|
+
- name: Deploy stack
|
|
134
|
+
run: pnpm deploy:aws
|
|
98
135
|
|
|
99
136
|
- name: Resolve smoke URL
|
|
100
137
|
id: smoke-url
|
|
@@ -105,16 +142,15 @@ jobs:
|
|
|
105
142
|
echo "url=$AWS_SMOKE_URL" >> "$GITHUB_OUTPUT"
|
|
106
143
|
else
|
|
107
144
|
# Fall back to the stack's ConnectUrl CloudFormation output.
|
|
108
|
-
# Stack name is `IrcAwsStack
|
|
109
|
-
# `IrcAwsStack-staging`.
|
|
145
|
+
# Stack name is `IrcAwsStack` (single target, no env suffix).
|
|
110
146
|
URL=$(aws cloudformation describe-stacks \
|
|
111
|
-
--stack-name IrcAwsStack
|
|
147
|
+
--stack-name IrcAwsStack \
|
|
112
148
|
--query 'Stacks[0].Outputs[?OutputKey==`ConnectUrl`].OutputValue' \
|
|
113
149
|
--output text 2>/dev/null || true)
|
|
114
150
|
if [ -n "$URL" ]; then
|
|
115
151
|
echo "url=$URL" >> "$GITHUB_OUTPUT"
|
|
116
152
|
else
|
|
117
|
-
echo "::warning::Unable to resolve the
|
|
153
|
+
echo "::warning::Unable to resolve the WebSocket URL (set the AWS_SMOKE_URL repo variable or check the stack ConnectUrl output); smoke step will be skipped."
|
|
118
154
|
echo "url=" >> "$GITHUB_OUTPUT"
|
|
119
155
|
fi
|
|
120
156
|
fi
|
|
@@ -123,4 +159,92 @@ jobs:
|
|
|
123
159
|
if: steps.smoke-url.outputs.url != ''
|
|
124
160
|
env:
|
|
125
161
|
SMOKE_URL: ${{ steps.smoke-url.outputs.url }}
|
|
126
|
-
run: pnpm smoke:aws
|
|
162
|
+
run: pnpm smoke:aws -- --url "$SMOKE_URL"
|
|
163
|
+
|
|
164
|
+
# ---------------------------------------------------------------------------
|
|
165
|
+
# deploy-web — AWS web client two-phase deploy (s3 sync + CloudFront
|
|
166
|
+
# invalidation, stack-output-driven).
|
|
167
|
+
#
|
|
168
|
+
# The SPA lives in S3 behind CloudFront (provisioned by the StaticSite
|
|
169
|
+
# construct in apps/aws-stack). It ships SEPARATELY from the runtime
|
|
170
|
+
# stack because the deploy pipeline needs the stack's CloudFormation
|
|
171
|
+
# outputs (the API Gateway WebSocket URL, the S3 bucket name, the
|
|
172
|
+
# CloudFront distribution ID) to exist BEFORE it can bake the SPA —
|
|
173
|
+
# `cdk deploy` therefore runs first (the `deploy` job above), then this
|
|
174
|
+
# job reads the outputs and:
|
|
175
|
+
# 1. `aws cloudformation describe-stacks --stack-name IrcAwsStack`
|
|
176
|
+
# reads `ConnectUrl`, `WebsiteBucketName`, `WebsiteDistributionId`.
|
|
177
|
+
# 2. `pnpm --filter @serverless-ircd/web run build:prod-aws -- --api-url <url>`
|
|
178
|
+
# bakes the SPA with the real wss URL (no hardcoded URLs in the repo).
|
|
179
|
+
# 3. `aws s3 sync apps/web/dist s3://<bucket> --delete` uploads the
|
|
180
|
+
# build (the CLI skips unchanged objects via etag comparison).
|
|
181
|
+
# 4. `aws cloudfront create-invalidation --distribution-id <id> --paths /*`
|
|
182
|
+
# busts the edge cache.
|
|
183
|
+
#
|
|
184
|
+
# Why a script instead of CDK `BucketDeployment`: the script reads
|
|
185
|
+
# post-deploy outputs that do not exist at synth time, avoids
|
|
186
|
+
# re-synth-on-every-deploy, and is faster. See
|
|
187
|
+
# `scripts/deploy-web-aws.mjs` and `docs/AWS-Deployment.md`.
|
|
188
|
+
#
|
|
189
|
+
# Staleness note: T170 collapsed the staging/prod split — there is no
|
|
190
|
+
# `staging` branch and this job is `workflow_dispatch`-only on the
|
|
191
|
+
# current branch, mirroring the parent pipeline. A maintainer runs the
|
|
192
|
+
# workflow by hand to ship the AWS web client.
|
|
193
|
+
# ---------------------------------------------------------------------------
|
|
194
|
+
deploy-web:
|
|
195
|
+
name: web deploy (s3 sync + CloudFront invalidation)
|
|
196
|
+
needs: deploy
|
|
197
|
+
runs-on: ubuntu-latest
|
|
198
|
+
timeout-minutes: 15
|
|
199
|
+
steps:
|
|
200
|
+
- name: Checkout
|
|
201
|
+
uses: actions/checkout@v4
|
|
202
|
+
with:
|
|
203
|
+
# The web client build requires the Kiwi IRC upstream submodule
|
|
204
|
+
# and the docs/ submodule (rendered into dist/docs/ by build.mjs).
|
|
205
|
+
submodules: recursive
|
|
206
|
+
|
|
207
|
+
- name: Checkout submodules (worktree-safe fallback)
|
|
208
|
+
run: |
|
|
209
|
+
# `submodules: recursive` covers the normal case; this fallback
|
|
210
|
+
# ensures the Kiwi + docs submodules are present even when the
|
|
211
|
+
# checkout action's recursive flag was a no-op (older runners /
|
|
212
|
+
# path-filter configurations).
|
|
213
|
+
git submodule update --init --recursive
|
|
214
|
+
|
|
215
|
+
- name: Setup pnpm
|
|
216
|
+
uses: pnpm/action-setup@v4
|
|
217
|
+
|
|
218
|
+
- name: Setup Node
|
|
219
|
+
uses: actions/setup-node@v4
|
|
220
|
+
with:
|
|
221
|
+
node-version: 24
|
|
222
|
+
cache: pnpm
|
|
223
|
+
|
|
224
|
+
- name: Install dependencies
|
|
225
|
+
run: pnpm install --frozen-lockfile
|
|
226
|
+
|
|
227
|
+
# Fail fast before any AWS call if the OIDC role ARN is missing.
|
|
228
|
+
# Mirrors the guard in the `deploy` job — the `deploy-web` job
|
|
229
|
+
# also assumes the role via OIDC and accepts no static keys.
|
|
230
|
+
- name: Assert OIDC deploy role ARN is set
|
|
231
|
+
if: env.AWS_DEPLOY_ROLE_ARN == ''
|
|
232
|
+
env:
|
|
233
|
+
AWS_DEPLOY_ROLE_ARN: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
234
|
+
run: |
|
|
235
|
+
echo "::error::AWS_DEPLOY_ROLE_ARN secret is empty — configure the GitHub OIDC IAM role trust before deploying (see docs/AWS-Deployment.md §17)."
|
|
236
|
+
exit 1
|
|
237
|
+
|
|
238
|
+
- name: Configure AWS credentials
|
|
239
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
240
|
+
with:
|
|
241
|
+
aws-region: ${{ secrets.AWS_REGION }}
|
|
242
|
+
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
243
|
+
|
|
244
|
+
# Two-phase deploy: describe-stacks → bake (--api-url) → s3 sync →
|
|
245
|
+
# create-invalidation. Implemented in scripts/deploy-web-aws.mjs;
|
|
246
|
+
# exits non-zero with a clear message if any required stack output
|
|
247
|
+
# is missing (i.e. the parent `deploy` job did not run first or the
|
|
248
|
+
# stack's `webSite` prop is not configured).
|
|
249
|
+
- name: Deploy web client (bake + s3 sync + CloudFront invalidation)
|
|
250
|
+
run: node scripts/deploy-web-aws.mjs
|
|
@@ -6,8 +6,11 @@ name: deploy-cf-tcp
|
|
|
6
6
|
# Containers and applies the Spectrum TLS config (terraform). Spectrum
|
|
7
7
|
# terminates TLS on :6697 and forwards plaintext TCP to the container.
|
|
8
8
|
#
|
|
9
|
-
# This pipeline
|
|
10
|
-
#
|
|
9
|
+
# This pipeline is `workflow_dispatch`-only — there is no automatic
|
|
10
|
+
# push-to-main trigger. A maintainer runs it by hand to ship the single
|
|
11
|
+
# TCP container target. It runs alongside deploy-cf.yml (the WebSocket
|
|
12
|
+
# path); the two are independent, so a deployment can enable either or
|
|
13
|
+
# both transports.
|
|
11
14
|
#
|
|
12
15
|
# Secrets (configure under repo Settings → Secrets and variables → Actions):
|
|
13
16
|
# CLOUDFLARE_API_TOKEN Spectrum/Containers API token.
|
|
@@ -16,16 +19,15 @@ name: deploy-cf-tcp
|
|
|
16
19
|
# CF_TCP_ORIGIN_ADDRESS Hostname/IP of the container origin.
|
|
17
20
|
|
|
18
21
|
on:
|
|
19
|
-
# Automatic push trigger disabled; deploy only runs manually.
|
|
20
22
|
workflow_dispatch:
|
|
21
23
|
|
|
22
24
|
concurrency:
|
|
23
|
-
group: cf-tcp-
|
|
25
|
+
group: cf-tcp-deploy
|
|
24
26
|
cancel-in-progress: false
|
|
25
27
|
|
|
26
28
|
jobs:
|
|
27
|
-
deploy
|
|
28
|
-
name: deploy cf-tcp
|
|
29
|
+
deploy:
|
|
30
|
+
name: deploy cf-tcp
|
|
29
31
|
runs-on: ubuntu-latest
|
|
30
32
|
timeout-minutes: 15
|
|
31
33
|
steps:
|
|
@@ -53,19 +55,19 @@ jobs:
|
|
|
53
55
|
- name: Test
|
|
54
56
|
run: pnpm --filter '@serverless-ircd/cf-tcp-container' test
|
|
55
57
|
|
|
56
|
-
- name: Deploy container
|
|
58
|
+
- name: Deploy container
|
|
57
59
|
working-directory: apps/cf-tcp-container
|
|
58
60
|
env:
|
|
59
61
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
60
62
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
61
|
-
run: wrangler deploy
|
|
63
|
+
run: wrangler deploy
|
|
62
64
|
|
|
63
65
|
- name: Apply Spectrum TLS config
|
|
64
66
|
working-directory: apps/cf-tcp-container/terraform
|
|
65
67
|
env:
|
|
66
68
|
TF_VAR_zone_id: ${{ secrets.CF_ZONE_ID }}
|
|
67
69
|
TF_VAR_origin_address: ${{ secrets.CF_TCP_ORIGIN_ADDRESS }}
|
|
68
|
-
TF_VAR_hostname: irc
|
|
70
|
+
TF_VAR_hostname: irc.example.com
|
|
69
71
|
run: |
|
|
70
72
|
terraform init
|
|
71
73
|
terraform apply -auto-approve
|
|
@@ -2,12 +2,13 @@ name: deploy-cf
|
|
|
2
2
|
|
|
3
3
|
# Cloudflare Workers deploy pipeline.
|
|
4
4
|
#
|
|
5
|
-
#
|
|
5
|
+
# This workflow is `workflow_dispatch`-only — there is no automatic
|
|
6
|
+
# push-to-main trigger. A maintainer runs it by hand to ship the single
|
|
7
|
+
# Cloudflare Worker target (`apps/cf-worker`):
|
|
6
8
|
# 1. Install deps (frozen lockfile).
|
|
7
9
|
# 2. Build the cf-adapter + irc-core/irc-server so the Worker entry
|
|
8
10
|
# typechecks against real workspace packages.
|
|
9
|
-
# 3. `wrangler deploy
|
|
10
|
-
# `serverless-ircd-staging` Worker + DO namespace.
|
|
11
|
+
# 3. `wrangler deploy` the `apps/cf-worker` worker.
|
|
11
12
|
# 4. Replay the smoke e2e (`scripts/smoke.mjs`) against the deployed
|
|
12
13
|
# URL — CONNECT/REGISTER/JOIN/PRIVMSG/QUIT. Failure blocks the
|
|
13
14
|
# merge (the deploy job is required on `main`).
|
|
@@ -19,23 +20,22 @@ name: deploy-cf
|
|
|
19
20
|
# CLOUDFLARE_ACCOUNT_ID Optional; required if the token's account
|
|
20
21
|
# context is ambiguous.
|
|
21
22
|
#
|
|
22
|
-
# The smoke URL is derived from the
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
23
|
+
# The smoke URL is derived from the Worker name (`serverless-ircd`)
|
|
24
|
+
# plus the deployer's account subdomain. Override by setting
|
|
25
|
+
# `CF_SMOKE_URL` in the repo Variables store when custom routes are
|
|
26
|
+
# wired.
|
|
26
27
|
|
|
27
28
|
on:
|
|
28
|
-
# Automatic push trigger disabled; deploy only runs manually.
|
|
29
29
|
workflow_dispatch:
|
|
30
30
|
|
|
31
31
|
# Prevent two deploys racing the same DO namespace.
|
|
32
32
|
concurrency:
|
|
33
|
-
group: cf-
|
|
33
|
+
group: cf-deploy
|
|
34
34
|
cancel-in-progress: false
|
|
35
35
|
|
|
36
36
|
jobs:
|
|
37
|
-
deploy
|
|
38
|
-
name: wrangler deploy
|
|
37
|
+
deploy:
|
|
38
|
+
name: wrangler deploy
|
|
39
39
|
runs-on: ubuntu-latest
|
|
40
40
|
timeout-minutes: 10
|
|
41
41
|
steps:
|
|
@@ -63,12 +63,12 @@ jobs:
|
|
|
63
63
|
- name: Test
|
|
64
64
|
run: pnpm test
|
|
65
65
|
|
|
66
|
-
- name: Deploy
|
|
66
|
+
- name: Deploy Worker
|
|
67
67
|
working-directory: apps/cf-worker
|
|
68
68
|
env:
|
|
69
69
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
70
70
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
71
|
-
run: pnpm deploy
|
|
71
|
+
run: pnpm run deploy
|
|
72
72
|
|
|
73
73
|
- name: Resolve smoke URL
|
|
74
74
|
id: smoke-url
|
|
@@ -82,7 +82,7 @@ jobs:
|
|
|
82
82
|
# The subdomain is per-account; if CF_SMOKE_URL isn't set we
|
|
83
83
|
# fall back to a workers.dev route that the deployer must
|
|
84
84
|
# configure once via the Cloudflare dashboard.
|
|
85
|
-
echo "::warning::CF_SMOKE_URL repo variable is not set; smoke step will be skipped. Set it to the
|
|
85
|
+
echo "::warning::CF_SMOKE_URL repo variable is not set; smoke step will be skipped. Set it to the Worker's wss:// URL."
|
|
86
86
|
echo "url=" >> "$GITHUB_OUTPUT"
|
|
87
87
|
fi
|
|
88
88
|
|