@clubedge/create-clubedge-app 0.20.0 → 0.21.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/CHANGELOG.md +9 -0
- package/README.md +16 -15
- package/package.json +5 -4
- package/template/.github/workflows/ci.yml +10 -10
- package/template/.github/workflows/clubedge-upgrade.yml +134 -0
- package/template/.github/workflows/deploy.yml +19 -19
- package/template/apps/start/package.json +1 -1
- package/template/apps/web/package.json +1 -1
- package/template/package.json +1 -1
- package/template/packages/auth/package.json +1 -1
- package/template/packages/auth-better-auth/package.json +1 -1
- package/template/packages/auth-supabase/package.json +1 -1
- package/template/packages/cache/package.json +1 -1
- package/template/packages/cache-redis/package.json +1 -1
- package/template/packages/core/package.json +1 -1
- package/template/packages/db/package.json +1 -1
- package/template/packages/email/package.json +1 -1
- package/template/packages/email-resend/package.json +1 -1
- package/template/packages/email-smtp/package.json +1 -1
- package/template/packages/jobs/package.json +1 -1
- package/template/packages/jobs-pg-boss/package.json +1 -1
- package/template/packages/local-db/package.json +1 -1
- package/template/packages/local-db/src/server.test.ts +3 -2
- package/template/packages/observability/package.json +1 -1
- package/template/packages/observability-otel/package.json +1 -1
- package/template/packages/observability-sentry/package.json +1 -1
- package/template/packages/payments/package.json +1 -1
- package/template/packages/payments/src/billing.test.ts +27 -4
- package/template/packages/payments-stripe/package.json +1 -1
- package/template/packages/storage/package.json +1 -1
- package/template/packages/storage-s3/package.json +1 -1
- package/template/packages/storage-supabase/package.json +1 -1
- package/template/packages/ui/package.json +1 -1
- package/template.lock.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `create-clubedge-app` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.21.0
|
|
6
|
+
|
|
7
|
+
- Default to Starter `v0.16.0` (#52), which adds:
|
|
8
|
+
- Starter upgrades as pull requests: every project gets `.github/workflows/clubedge-upgrade.yml`, which checks every Monday for a newer Starter release and opens a pull request with `pnpm clubedge upgrade`'s result, the release notes, and anything left to resolve, so the project's own CI tests the upgrade before it is merged.
|
|
9
|
+
- GitHub Actions on their Node 24 versions in `ci.yml` and `deploy.yml`, with Linux jobs on Ubuntu 24.04.
|
|
10
|
+
- Steadier tests: PGlite starts once per test file, with room for slow CI runners.
|
|
11
|
+
- Release tooling for maintainers (#51): `pnpm release patch|minor|major` opens the release pull request with a drafted changelog, `pnpm release tag` publishes it, and the Starter pin workflow opens a pull request when the Starter publishes a release.
|
|
12
|
+
- CI names the generated project's failing check, in an annotation and the job summary (#50).
|
|
13
|
+
|
|
5
14
|
## 0.20.0
|
|
6
15
|
|
|
7
16
|
- Conflicts are easier to resolve after `add`, `remove`, and `upgrade`:
|
package/README.md
CHANGED
|
@@ -127,7 +127,7 @@ pnpm dlx @clubedge/create-clubedge-app my-app --yes --no-git --framework tanstac
|
|
|
127
127
|
pnpm dlx @clubedge/create-clubedge-app my-app --ref main
|
|
128
128
|
|
|
129
129
|
# Reproduce a specific Starter release or commit
|
|
130
|
-
pnpm dlx @clubedge/create-clubedge-app my-app --ref v0.
|
|
130
|
+
pnpm dlx @clubedge/create-clubedge-app my-app --ref v0.16.0
|
|
131
131
|
pnpm dlx @clubedge/create-clubedge-app my-app --ref <commit-sha>
|
|
132
132
|
|
|
133
133
|
# Test local Starter changes before releasing them
|
|
@@ -146,7 +146,7 @@ pnpm clubedge add email resend payments stripe # several modules as
|
|
|
146
146
|
pnpm clubedge remove storage payments
|
|
147
147
|
pnpm dlx @clubedge/create-clubedge-app add infra local --dry-run
|
|
148
148
|
pnpm dlx @clubedge/create-clubedge-app@latest upgrade # to the newest CLI's Starter release
|
|
149
|
-
pnpm dlx @clubedge/create-clubedge-app upgrade --ref v0.
|
|
149
|
+
pnpm dlx @clubedge/create-clubedge-app upgrade --ref v0.16.0 # or a specific tag, branch, or commit
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
The CLI renders the project twice, from the Starter commit and modules recorded in your `package.json` and from the new state, and merges the difference into your project. The new state has other modules for `add` and `remove`, and the newer Starter with the same modules for `upgrade`. Modules a newer Starter introduces start as `none` where possible, so an upgrade never adds a service on its own.
|
|
@@ -194,27 +194,27 @@ When the app is ready, the CLI opens the preview in your browser (`--no-open` tu
|
|
|
194
194
|
Each CLI release is tested against one specific Starter release:
|
|
195
195
|
|
|
196
196
|
```text
|
|
197
|
-
create-clubedge-app v0.
|
|
197
|
+
create-clubedge-app v0.21.0
|
|
198
198
|
|
|
|
199
199
|
v
|
|
200
|
-
Clubedge Starter v0.
|
|
201
|
-
commit
|
|
200
|
+
Clubedge Starter v0.16.0
|
|
201
|
+
commit e233aa68ddc8c21df6cf2b01b9e26876d2e4aeca
|
|
202
202
|
```
|
|
203
203
|
|
|
204
204
|
The current relationship is:
|
|
205
205
|
|
|
206
206
|
| CLI release | Default Starter release | Meaning |
|
|
207
207
|
| --- | --- | --- |
|
|
208
|
-
| `create-clubedge-app@0.
|
|
208
|
+
| `create-clubedge-app@0.21.0` | `clubedge-starter@v0.16.0` | The CLI's required, tested default |
|
|
209
209
|
|
|
210
210
|
This means the same CLI version always scaffolds the same Starter revision by default. The CLI does not silently follow Starter `main`.
|
|
211
211
|
|
|
212
|
-
The `v0.
|
|
213
|
-
`
|
|
212
|
+
The `v0.16.0` tag is expected to resolve to commit
|
|
213
|
+
`e233aa68ddc8c21df6cf2b01b9e26876d2e4aeca`. The CLI verifies this before
|
|
214
214
|
scaffolding with the default reference and fails rather than silently using a
|
|
215
215
|
moved tag.
|
|
216
216
|
|
|
217
|
-
When the Starter changes, its maintainers first publish a new versioned release, such as `v0.
|
|
217
|
+
When the Starter changes, its maintainers first publish a new versioned release, such as `v0.16.0`. The CLI is then updated to use that release, all generated-project checks must pass, and a new CLI version is published. This keeps Starter and CLI releases independently versioned while preserving a tested compatibility relationship.
|
|
218
218
|
|
|
219
219
|
Every generated project records its CLI version, Starter repository, Starter ref, Starter commit, framework, and modules in `package.json` and `README.md`.
|
|
220
220
|
|
|
@@ -269,15 +269,15 @@ CI packs the CLI with `npm pack`, scaffolds clean projects from the packed tarba
|
|
|
269
269
|
1. Make and validate changes in `clubedge-starter`.
|
|
270
270
|
2. Run lint, typecheck, unit tests, browser tests, and production build.
|
|
271
271
|
3. Update the Starter package versions.
|
|
272
|
-
4. Commit `main`, create a release tag such as `v0.
|
|
272
|
+
4. Commit `main`, create a release tag such as `v0.16.0`, and publish the Starter release.
|
|
273
273
|
|
|
274
274
|
### CLI maintainers
|
|
275
275
|
|
|
276
|
-
1.
|
|
277
|
-
2.
|
|
278
|
-
3.
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
1. When the Starter publishes a release, the [Starter pin](.github/workflows/starter-pin.yml) workflow opens a pull request that moves `clubedge.starterRef` and `clubedge.starterCommit` in [`package.json`](package.json), and the docs that name them, to the new tag (daily, or run it by hand; locally: `pnpm release pin vX.Y.Z`). Its CI generates clean projects from that exact tag and runs install, lint, typecheck, unit tests, browser tests, production build, and runtime smoke checks. Merge it once they pass.
|
|
277
|
+
2. `pnpm release patch|minor|major` (from an up-to-date `main`; add `--dry-run` to preview) opens the release pull request: it bumps `version`, updates the version relationship here and in CONTRIBUTING, adds the release table rows for a minor or major release, and drafts the changelog entry from the pull requests merged since the last tag. Edit the draft in that pull request: it becomes the GitHub Release page.
|
|
278
|
+
3. After it is merged, `pnpm release tag` tags `main`. The Release workflow checks and publishes it to npm, creates the GitHub Release page from the changelog entry, and smoke-tests the published package.
|
|
279
|
+
|
|
280
|
+
The pin workflow needs **Settings → Actions → General → Allow GitHub Actions to create and approve pull requests**, or a `STARTER_PIN_TOKEN` secret (a fine-grained token with contents and pull requests write), which also lets its pull request start CI by itself.
|
|
281
281
|
|
|
282
282
|
The required CI job always tests the pinned default. The scheduled compatibility job tests Starter `main` early, but unreleased Starter changes must not change the stable CLI default.
|
|
283
283
|
|
|
@@ -299,6 +299,7 @@ Each phase ends with a Starter release and a CLI release pinned to it. The full
|
|
|
299
299
|
| 0.18.0 | v0.15.0 | `try`: a new project on a free, temporary Railway VM, with a preview URL and a claim link (experimental) |
|
|
300
300
|
| 0.19.0 | v0.15.0 | `pnpm clubedge try` uploads an existing project to the VM; the preview opens in the browser |
|
|
301
301
|
| 0.20.0 | v0.15.0 | The Starter's version of each conflicted file in `.clubedge/incoming/`, several modules at once, sharing a `try` preview by claiming the VM, `try --status` |
|
|
302
|
+
| 0.21.0 | v0.16.0 | Starter v0.16.0: upgrades delivered as pull requests, Node 24 actions; release tooling for maintainers |
|
|
302
303
|
| next | | Show the Starter's version of a conflicted file next to yours |
|
|
303
304
|
|
|
304
305
|
## Community
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clubedge/create-clubedge-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Create a Next.js or TanStack Start application from the Clubedge Starter reference implementation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@10.9.0",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"clubedge": {
|
|
24
24
|
"starterRepository": "Clubedge/clubedge-starter",
|
|
25
|
-
"starterRef": "v0.
|
|
26
|
-
"starterCommit": "
|
|
25
|
+
"starterRef": "v0.16.0",
|
|
26
|
+
"starterCommit": "e233aa68ddc8c21df6cf2b01b9e26876d2e4aeca"
|
|
27
27
|
},
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"repository": {
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
"test": "vitest run",
|
|
49
49
|
"bundle-template": "node scripts/bundle-template.mjs",
|
|
50
50
|
"start": "pnpm build && node ./bin/create.mjs",
|
|
51
|
-
"prepack": "pnpm build"
|
|
51
|
+
"prepack": "pnpm build",
|
|
52
|
+
"release": "node scripts/release.mjs"
|
|
52
53
|
},
|
|
53
54
|
"dependencies": {
|
|
54
55
|
"@clack/prompts": "^1.8.1",
|
|
@@ -8,13 +8,13 @@ permissions:
|
|
|
8
8
|
contents: read
|
|
9
9
|
jobs:
|
|
10
10
|
verify:
|
|
11
|
-
runs-on: ubuntu-
|
|
11
|
+
runs-on: ubuntu-24.04
|
|
12
12
|
env:
|
|
13
13
|
DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/postgres
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: pnpm/action-setup@
|
|
17
|
-
- uses: actions/setup-node@
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- uses: pnpm/action-setup@v6
|
|
17
|
+
- uses: actions/setup-node@v7
|
|
18
18
|
with:
|
|
19
19
|
node-version: 22
|
|
20
20
|
cache: pnpm
|
|
@@ -44,11 +44,11 @@ jobs:
|
|
|
44
44
|
- run: pnpm audit --audit-level high
|
|
45
45
|
|
|
46
46
|
e2e:
|
|
47
|
-
runs-on: ubuntu-
|
|
47
|
+
runs-on: ubuntu-24.04
|
|
48
48
|
steps:
|
|
49
|
-
- uses: actions/checkout@
|
|
50
|
-
- uses: pnpm/action-setup@
|
|
51
|
-
- uses: actions/setup-node@
|
|
49
|
+
- uses: actions/checkout@v7
|
|
50
|
+
- uses: pnpm/action-setup@v6
|
|
51
|
+
- uses: actions/setup-node@v7
|
|
52
52
|
with:
|
|
53
53
|
node-version: 22
|
|
54
54
|
cache: pnpm
|
|
@@ -57,7 +57,7 @@ jobs:
|
|
|
57
57
|
- run: pnpm test:e2e
|
|
58
58
|
|
|
59
59
|
docker:
|
|
60
|
-
runs-on: ubuntu-
|
|
60
|
+
runs-on: ubuntu-24.04
|
|
61
61
|
services:
|
|
62
62
|
postgres:
|
|
63
63
|
image: postgres:17
|
|
@@ -70,7 +70,7 @@ jobs:
|
|
|
70
70
|
options: >-
|
|
71
71
|
--health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 10
|
|
72
72
|
steps:
|
|
73
|
-
- uses: actions/checkout@
|
|
73
|
+
- uses: actions/checkout@v7
|
|
74
74
|
- name: Build the production image
|
|
75
75
|
run: docker build --tag app:ci .
|
|
76
76
|
- name: Run the image's migrations twice; the second run changes nothing
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
name: Starter upgrade
|
|
2
|
+
|
|
3
|
+
# Checks every Monday for a newer Clubedge Starter release. When there is one, it runs
|
|
4
|
+
# `pnpm clubedge upgrade` and opens a pull request with the release notes and anything left for
|
|
5
|
+
# you to resolve, so your CI tests the upgrade before you merge it. Run it by hand from the
|
|
6
|
+
# Actions tab, or delete this file to turn it off.
|
|
7
|
+
#
|
|
8
|
+
# It needs Settings -> Actions -> General -> "Allow GitHub Actions to create and approve pull
|
|
9
|
+
# requests", or a CLUBEDGE_UPGRADE_TOKEN secret (a fine-grained token with contents and pull
|
|
10
|
+
# requests write), which also lets the pull request start your CI by itself.
|
|
11
|
+
on:
|
|
12
|
+
schedule:
|
|
13
|
+
- cron: "17 7 * * 1"
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
pull-requests: write
|
|
19
|
+
actions: write
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: clubedge-upgrade
|
|
23
|
+
cancel-in-progress: false
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
upgrade:
|
|
27
|
+
# The Starter's own repository is the template every project comes from, not a project.
|
|
28
|
+
if: github.repository != 'Clubedge/clubedge-starter'
|
|
29
|
+
runs-on: ubuntu-24.04
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v7
|
|
32
|
+
- uses: pnpm/action-setup@v6
|
|
33
|
+
- uses: actions/setup-node@v7
|
|
34
|
+
with:
|
|
35
|
+
node-version: 22
|
|
36
|
+
- name: Upgrade to the newest Starter release
|
|
37
|
+
id: upgrade
|
|
38
|
+
shell: bash
|
|
39
|
+
run: |
|
|
40
|
+
before=$(node -p "require('./package.json').clubedge?.starterRef ?? ''")
|
|
41
|
+
if [ -z "$before" ]; then
|
|
42
|
+
echo "package.json records no Starter release: this project was not created by create-clubedge-app."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
# The newest CLI upgrades to the Starter release it is pinned to.
|
|
46
|
+
pnpm dlx @clubedge/create-clubedge-app@latest upgrade --no-install 2>&1 | tee "$RUNNER_TEMP/upgrade.log"
|
|
47
|
+
after=$(node -p "require('./package.json').clubedge.starterRef")
|
|
48
|
+
if [ "$after" = "$before" ] && [ -z "$(git status --porcelain)" ]; then
|
|
49
|
+
echo "Already on the newest Starter release, $before."
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
branch="clubedge/upgrade-$after"
|
|
53
|
+
if git ls-remote --exit-code --heads origin "$branch" >/dev/null; then
|
|
54
|
+
echo "$branch already exists: its pull request is open, or was closed on purpose."
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
# The lockfile follows the upgraded package.json files; a conflict there can stop it.
|
|
58
|
+
install="updated"
|
|
59
|
+
pnpm install --no-frozen-lockfile >"$RUNNER_TEMP/install.log" 2>&1 || install="failed"
|
|
60
|
+
{
|
|
61
|
+
echo "before=$before"
|
|
62
|
+
echo "after=$after"
|
|
63
|
+
echo "branch=$branch"
|
|
64
|
+
echo "install=$install"
|
|
65
|
+
if [ -d .clubedge/incoming ]; then echo "incoming=true"; fi
|
|
66
|
+
} >>"$GITHUB_OUTPUT"
|
|
67
|
+
- name: Keep the Starter's versions of conflicted files
|
|
68
|
+
if: steps.upgrade.outputs.incoming == 'true'
|
|
69
|
+
uses: actions/upload-artifact@v7
|
|
70
|
+
with:
|
|
71
|
+
name: starter-versions
|
|
72
|
+
path: .clubedge/incoming/
|
|
73
|
+
include-hidden-files: true
|
|
74
|
+
- name: Open the pull request
|
|
75
|
+
if: steps.upgrade.outputs.branch != ''
|
|
76
|
+
shell: bash
|
|
77
|
+
env:
|
|
78
|
+
GH_TOKEN: ${{ secrets.CLUBEDGE_UPGRADE_TOKEN || github.token }}
|
|
79
|
+
OWN_TOKEN: ${{ secrets.CLUBEDGE_UPGRADE_TOKEN != '' }}
|
|
80
|
+
BEFORE: ${{ steps.upgrade.outputs.before }}
|
|
81
|
+
AFTER: ${{ steps.upgrade.outputs.after }}
|
|
82
|
+
BRANCH: ${{ steps.upgrade.outputs.branch }}
|
|
83
|
+
INSTALL: ${{ steps.upgrade.outputs.install }}
|
|
84
|
+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
85
|
+
run: |
|
|
86
|
+
git config user.name "github-actions[bot]"
|
|
87
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
88
|
+
git switch --create "$BRANCH"
|
|
89
|
+
git add --all
|
|
90
|
+
git commit --quiet --message "chore: upgrade to Clubedge Starter $AFTER"
|
|
91
|
+
git push --quiet --set-upstream origin "$BRANCH"
|
|
92
|
+
|
|
93
|
+
repository=$(node -p "require('./package.json').clubedge.starterRepository ?? 'Clubedge/clubedge-starter'")
|
|
94
|
+
conflicts=$(git grep -l '^<<<<<<< yours' -- . || true)
|
|
95
|
+
{
|
|
96
|
+
echo "Upgrades this project from Clubedge Starter \`$BEFORE\` to [\`$AFTER\`](https://github.com/$repository/releases/tag/$AFTER), with \`pnpm clubedge upgrade\`. Your own edits are merged in; files you never changed take the new version."
|
|
97
|
+
echo
|
|
98
|
+
if [ -n "$conflicts" ]; then
|
|
99
|
+
echo "### Conflicts to resolve"
|
|
100
|
+
echo
|
|
101
|
+
echo "These files have lines both you and the Starter changed, marked \`<<<<<<< yours\` ... \`>>>>>>> clubedge\`. Keep your lines, the Starter's, or a mix, then delete the markers:"
|
|
102
|
+
echo
|
|
103
|
+
printf -- '- `%s`\n' $conflicts
|
|
104
|
+
echo
|
|
105
|
+
echo "The Starter's whole new version of each is in the **starter-versions** artifact of [the run]($RUN_URL), to compare with yours."
|
|
106
|
+
echo
|
|
107
|
+
fi
|
|
108
|
+
if [ "$INSTALL" = "failed" ]; then
|
|
109
|
+
echo "### pnpm install"
|
|
110
|
+
echo
|
|
111
|
+
echo "\`pnpm install\` did not complete on the upgraded project, usually because of a conflict in a \`package.json\`. Resolve it, then run \`pnpm install\` and commit \`pnpm-lock.yaml\`."
|
|
112
|
+
echo
|
|
113
|
+
fi
|
|
114
|
+
echo "### Before merging"
|
|
115
|
+
echo
|
|
116
|
+
echo "- Read the [release notes](https://github.com/$repository/releases/tag/$AFTER) for anything to do by hand."
|
|
117
|
+
echo "- Run \`pnpm db:migrate\` for new migrations, and your tests."
|
|
118
|
+
echo
|
|
119
|
+
echo "<details><summary>Upgrade output</summary>"
|
|
120
|
+
echo
|
|
121
|
+
echo '```'
|
|
122
|
+
tail -n 80 "$RUNNER_TEMP/upgrade.log"
|
|
123
|
+
echo '```'
|
|
124
|
+
echo
|
|
125
|
+
echo "</details>"
|
|
126
|
+
echo
|
|
127
|
+
echo "Opened by the Starter upgrade workflow (\`.github/workflows/clubedge-upgrade.yml\`)."
|
|
128
|
+
} >"$RUNNER_TEMP/body.md"
|
|
129
|
+
gh pr create --base "${{ github.event.repository.default_branch }}" --head "$BRANCH" \
|
|
130
|
+
--title "chore: upgrade to Clubedge Starter $AFTER" --body-file "$RUNNER_TEMP/body.md"
|
|
131
|
+
# Pull requests opened with the default token start no workflows: start CI on the branch.
|
|
132
|
+
if [ "$OWN_TOKEN" != "true" ] && [ -f .github/workflows/ci.yml ]; then
|
|
133
|
+
gh workflow run ci.yml --ref "$BRANCH" || echo "Start CI on $BRANCH by hand."
|
|
134
|
+
fi
|
|
@@ -12,26 +12,26 @@ jobs:
|
|
|
12
12
|
# Builds the production image and publishes it to this repository's GitHub Container Registry
|
|
13
13
|
# as ghcr.io/<owner>/<repository>, tagged with the commit and latest. No secret is needed.
|
|
14
14
|
image:
|
|
15
|
-
runs-on: ubuntu-
|
|
15
|
+
runs-on: ubuntu-24.04
|
|
16
16
|
permissions:
|
|
17
17
|
contents: read
|
|
18
18
|
packages: write
|
|
19
19
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
21
|
-
- uses: docker/setup-buildx-action@
|
|
22
|
-
- uses: docker/login-action@
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
- uses: docker/setup-buildx-action@v4
|
|
22
|
+
- uses: docker/login-action@v4
|
|
23
23
|
with:
|
|
24
24
|
registry: ghcr.io
|
|
25
25
|
username: ${{ github.actor }}
|
|
26
26
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
27
27
|
- id: meta
|
|
28
|
-
uses: docker/metadata-action@
|
|
28
|
+
uses: docker/metadata-action@v6
|
|
29
29
|
with:
|
|
30
30
|
images: ghcr.io/${{ github.repository }}
|
|
31
31
|
tags: |
|
|
32
32
|
type=sha
|
|
33
33
|
type=raw,value=latest
|
|
34
|
-
- uses: docker/build-push-action@
|
|
34
|
+
- uses: docker/build-push-action@v7
|
|
35
35
|
with:
|
|
36
36
|
context: .
|
|
37
37
|
push: true
|
|
@@ -40,9 +40,9 @@ jobs:
|
|
|
40
40
|
# clubedge:end
|
|
41
41
|
# clubedge:if deploy=fly
|
|
42
42
|
fly:
|
|
43
|
-
runs-on: ubuntu-
|
|
43
|
+
runs-on: ubuntu-24.04
|
|
44
44
|
steps:
|
|
45
|
-
- uses: actions/checkout@
|
|
45
|
+
- uses: actions/checkout@v7
|
|
46
46
|
- uses: superfly/flyctl-actions/setup-flyctl@master
|
|
47
47
|
# Builds on Fly's builders and runs the release command (migrations) before switching.
|
|
48
48
|
- run: flyctl deploy --remote-only
|
|
@@ -51,9 +51,9 @@ jobs:
|
|
|
51
51
|
# clubedge:end
|
|
52
52
|
# clubedge:if deploy=railway
|
|
53
53
|
railway:
|
|
54
|
-
runs-on: ubuntu-
|
|
54
|
+
runs-on: ubuntu-24.04
|
|
55
55
|
steps:
|
|
56
|
-
- uses: actions/checkout@
|
|
56
|
+
- uses: actions/checkout@v7
|
|
57
57
|
# Uploads this checkout; Railway builds the image and runs the pre-deploy migrations.
|
|
58
58
|
- run: npx --yes @railway/cli@4 up --ci --service "$RAILWAY_SERVICE"
|
|
59
59
|
env:
|
|
@@ -62,7 +62,7 @@ jobs:
|
|
|
62
62
|
# clubedge:end
|
|
63
63
|
# clubedge:if deploy=render
|
|
64
64
|
render:
|
|
65
|
-
runs-on: ubuntu-
|
|
65
|
+
runs-on: ubuntu-24.04
|
|
66
66
|
steps:
|
|
67
67
|
# The service's deploy hook starts a deploy of its branch, with its pre-deploy migrations.
|
|
68
68
|
- run: curl --fail --silent --show-error --request POST "$RENDER_DEPLOY_HOOK_URL"
|
|
@@ -71,15 +71,15 @@ jobs:
|
|
|
71
71
|
# clubedge:end
|
|
72
72
|
# clubedge:if deploy=vercel
|
|
73
73
|
vercel:
|
|
74
|
-
runs-on: ubuntu-
|
|
74
|
+
runs-on: ubuntu-24.04
|
|
75
75
|
env:
|
|
76
76
|
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
77
77
|
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
78
78
|
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
79
79
|
steps:
|
|
80
|
-
- uses: actions/checkout@
|
|
81
|
-
- uses: pnpm/action-setup@
|
|
82
|
-
- uses: actions/setup-node@
|
|
80
|
+
- uses: actions/checkout@v7
|
|
81
|
+
- uses: pnpm/action-setup@v6
|
|
82
|
+
- uses: actions/setup-node@v7
|
|
83
83
|
with:
|
|
84
84
|
node-version: 22
|
|
85
85
|
cache: pnpm
|
|
@@ -91,14 +91,14 @@ jobs:
|
|
|
91
91
|
# clubedge:end
|
|
92
92
|
# clubedge:if deploy=netlify
|
|
93
93
|
netlify:
|
|
94
|
-
runs-on: ubuntu-
|
|
94
|
+
runs-on: ubuntu-24.04
|
|
95
95
|
env:
|
|
96
96
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
97
97
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
|
98
98
|
steps:
|
|
99
|
-
- uses: actions/checkout@
|
|
100
|
-
- uses: pnpm/action-setup@
|
|
101
|
-
- uses: actions/setup-node@
|
|
99
|
+
- uses: actions/checkout@v7
|
|
100
|
+
- uses: pnpm/action-setup@v6
|
|
101
|
+
- uses: actions/setup-node@v7
|
|
102
102
|
with:
|
|
103
103
|
node-version: 22
|
|
104
104
|
cache: pnpm
|
package/template/package.json
CHANGED
|
@@ -8,11 +8,12 @@ describe("serveLocalPostgres", () => {
|
|
|
8
8
|
let server: LocalPostgresServer;
|
|
9
9
|
let url: string;
|
|
10
10
|
|
|
11
|
+
// Starting PGlite takes seconds on a busy CI runner.
|
|
11
12
|
beforeAll(async () => {
|
|
12
13
|
db = await PGlite.create();
|
|
13
14
|
server = await serveLocalPostgres(db, { port: 0 });
|
|
14
15
|
url = `postgresql://postgres:postgres@127.0.0.1:${server.port}/postgres`;
|
|
15
|
-
});
|
|
16
|
+
}, 30_000);
|
|
16
17
|
|
|
17
18
|
afterAll(async () => {
|
|
18
19
|
await server.close();
|
|
@@ -115,5 +116,5 @@ describe("LocalPostgresServer.close", () => {
|
|
|
115
116
|
await client.end({ timeout: 0 });
|
|
116
117
|
await db.close();
|
|
117
118
|
}
|
|
118
|
-
});
|
|
119
|
+
}, 30_000);
|
|
119
120
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clubedge/observability",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Observability interface: error reports and spans for @clubedge/core's telemetry hooks, and an in-memory provider for tests.",
|
|
5
5
|
"private": true,
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -2,7 +2,7 @@ import { PGlite } from "@electric-sql/pglite";
|
|
|
2
2
|
import { drizzle } from "drizzle-orm/pglite";
|
|
3
3
|
import { migrate } from "drizzle-orm/pglite/migrator";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
import { users, type Database } from "@clubedge/db";
|
|
7
7
|
import { createBilling, findSubscription, isEntitled, NoBillingAccountError } from "./billing";
|
|
8
8
|
import { subscriptions } from "./schema";
|
|
@@ -10,7 +10,7 @@ import type { PaymentEvent, PaymentProvider, SubscriptionSnapshot } from "./type
|
|
|
10
10
|
|
|
11
11
|
const folder = (path: string) => fileURLToPath(new URL(path, import.meta.url));
|
|
12
12
|
|
|
13
|
-
/** A
|
|
13
|
+
/** A PostgreSQL (PGlite) with the app's and the payment migrations applied. */
|
|
14
14
|
async function database() {
|
|
15
15
|
const client = await PGlite.create();
|
|
16
16
|
const db = drizzle({ client });
|
|
@@ -20,7 +20,19 @@ async function database() {
|
|
|
20
20
|
migrationsTable: "__drizzle_migrations_payments",
|
|
21
21
|
});
|
|
22
22
|
// The query builder is the same as the postgres.js driver's that the app uses.
|
|
23
|
-
return db as unknown as Database;
|
|
23
|
+
return { client, db: db as unknown as Database };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Empties the app's tables; the migration records live in the drizzle schema and stay. */
|
|
27
|
+
async function emptyTables(client: PGlite) {
|
|
28
|
+
const { rows } = await client.query<{ name: string }>(
|
|
29
|
+
"select tablename as name from pg_tables where schemaname = 'public'",
|
|
30
|
+
);
|
|
31
|
+
if (rows.length) {
|
|
32
|
+
await client.exec(
|
|
33
|
+
`truncate ${rows.map(({ name }) => `"${name}"`).join(", ")} restart identity cascade`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
/** A provider whose next webhook event the test chooses. */
|
|
@@ -53,11 +65,22 @@ const snapshot = (
|
|
|
53
65
|
const request = { body: "{}", headers: new Headers() };
|
|
54
66
|
|
|
55
67
|
describe("createBilling", () => {
|
|
68
|
+
let client: PGlite;
|
|
56
69
|
let db: Database;
|
|
57
70
|
let userId: string;
|
|
58
71
|
|
|
72
|
+
// One database for the file: starting PGlite and migrating takes seconds on a busy CI runner,
|
|
73
|
+
// so each test starts from empty tables instead of a new database.
|
|
74
|
+
beforeAll(async () => {
|
|
75
|
+
({ client, db } = await database());
|
|
76
|
+
}, 60_000);
|
|
77
|
+
|
|
78
|
+
afterAll(async () => {
|
|
79
|
+
await client.close();
|
|
80
|
+
});
|
|
81
|
+
|
|
59
82
|
beforeEach(async () => {
|
|
60
|
-
|
|
83
|
+
await emptyTables(client);
|
|
61
84
|
const [user] = await db
|
|
62
85
|
.insert(users)
|
|
63
86
|
.values({ email: "ada@example.com" })
|
package/template.lock.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"repository": "Clubedge/clubedge-starter",
|
|
3
|
-
"ref": "v0.
|
|
4
|
-
"commit": "
|
|
3
|
+
"ref": "v0.16.0",
|
|
4
|
+
"commit": "e233aa68ddc8c21df6cf2b01b9e26876d2e4aeca",
|
|
5
5
|
"files": [
|
|
6
6
|
".dockerignore",
|
|
7
7
|
".env.example",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
".github/ISSUE_TEMPLATE/feature_request.yml",
|
|
12
12
|
".github/pull_request_template.md",
|
|
13
13
|
".github/workflows/ci.yml",
|
|
14
|
+
".github/workflows/clubedge-upgrade.yml",
|
|
14
15
|
".github/workflows/deploy.yml",
|
|
15
16
|
"_gitignore",
|
|
16
17
|
".prettierignore",
|