@podosoft/podokit 0.16.3 → 0.17.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/dist/deploy-compose-exec.d.ts +93 -0
- package/dist/deploy-compose-exec.js +198 -0
- package/dist/deploy-compose-profile.d.ts +107 -0
- package/dist/deploy-compose-profile.js +361 -0
- package/dist/deploy-compose-render.d.ts +48 -0
- package/dist/deploy-compose-render.js +333 -0
- package/dist/deploy-compose-sync.d.ts +144 -0
- package/dist/deploy-compose-sync.js +412 -0
- package/dist/deploy-compose.d.ts +98 -0
- package/dist/deploy-compose.js +667 -0
- package/dist/deploy-dispatch.d.ts +33 -0
- package/dist/deploy-dispatch.js +58 -0
- package/dist/deploy-driver.d.ts +25 -0
- package/dist/deploy-driver.js +78 -0
- package/dist/deploy-profile.d.ts +4 -7
- package/dist/deploy-profile.js +86 -274
- package/dist/deploy-render.js +10 -1
- package/dist/deploy-schema.d.ts +56 -0
- package/dist/deploy-schema.js +261 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +178 -6
- package/dist/lib.d.ts +9 -0
- package/dist/lib.js +30 -1
- package/dist/templates/fullstack-nest-svelte/AGENTS.md +2 -1
- package/dist/templates/fullstack-nest-svelte/Dockerfile.dev +34 -3
- package/dist/templates/fullstack-nest-svelte/apps/api/Dockerfile +68 -7
- package/dist/templates/fullstack-nest-svelte/apps/web/Dockerfile +60 -8
- package/dist/templates/fullstack-nest-svelte/apps/web/package.json +2 -1
- package/dist/templates/fullstack-nest-svelte/apps/web/server.js +31 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/api.ts +2 -2
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/backend-proxy.test.ts +79 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/backend-proxy.ts +24 -1
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/ws-upgrade.js +267 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/lib/server/ws-upgrade.test.js +134 -0
- package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/api/[...path]/+server.ts +6 -2
- package/dist/templates/fullstack-nest-svelte/apps/web/src/routes/api/auth/[...all]/+server.ts +6 -2
- package/dist/templates/fullstack-nest-svelte/apps/web/vite.config.ts +17 -7
- package/dist/templates/fullstack-nest-svelte/dot-agents/skills/podokit-deploy/SKILL.md +55 -10
- package/dist/templates/fullstack-nest-svelte/dot-agents/skills/podokit-deploy/references/profile.md +50 -1
- package/dist/templates/fullstack-nest-svelte/dot-agents/skills/podokit-deploy/references/release.md +64 -0
- package/dist/templates/fullstack-nest-svelte/dot-agents/skills/podokit-deploy-fast/SKILL.md +92 -0
- package/dist/templates/fullstack-nest-svelte/dot-claude/skills/podokit-deploy/SKILL.md +1 -1
- package/dist/templates/fullstack-nest-svelte/dot-claude/skills/podokit-deploy-fast/SKILL.md +8 -0
- package/dist/templates/fullstack-nest-svelte/dot-dockerignore +7 -0
- package/dist/templates/fullstack-nest-svelte/dot-env.example +7 -0
- package/dist/templates/fullstack-nest-svelte/dot-github/workflows/release.yml +142 -0
- package/dist/templates/fullstack-nest-svelte/infra/k3s/README.md +18 -0
- package/dist/templates/fullstack-nest-svelte/infra/k3s/api-deployment.yaml +6 -1
- package/dist/templates/fullstack-nest-svelte/infra/k3s/ingress.yaml +8 -0
- package/dist/templates/fullstack-nest-svelte/infra/k3s/web-deployment.yaml +11 -1
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/components/account-page.svelte +3 -2
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/device-label.test.ts +62 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/lib/device-label.ts +50 -0
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(admin)/admin/sessions/+page.svelte +3 -2
- package/dist/templates/modules/admin-dashboard/files/apps/web/src/routes/(admin)/admin/users/+page.svelte +3 -2
- package/dist/templates/modules/bullmq/files/infra/k3s/worker-deployment.yaml +2 -1
- package/dist/templates/todo/AGENTS.md +2 -1
- package/dist/templates/todo/Dockerfile.dev +34 -3
- package/dist/templates/todo/apps/api/Dockerfile +68 -7
- package/dist/templates/todo/apps/web/Dockerfile +60 -8
- package/dist/templates/todo/apps/web/package.json +2 -1
- package/dist/templates/todo/apps/web/server.js +31 -0
- package/dist/templates/todo/apps/web/src/lib/server/api.ts +2 -2
- package/dist/templates/todo/apps/web/src/lib/server/backend-proxy.test.ts +79 -0
- package/dist/templates/todo/apps/web/src/lib/server/backend-proxy.ts +24 -1
- package/dist/templates/todo/apps/web/src/lib/server/ws-upgrade.js +267 -0
- package/dist/templates/todo/apps/web/src/lib/server/ws-upgrade.test.js +134 -0
- package/dist/templates/todo/apps/web/src/routes/api/[...path]/+server.ts +6 -2
- package/dist/templates/todo/apps/web/src/routes/api/auth/[...all]/+server.ts +6 -2
- package/dist/templates/todo/apps/web/vite.config.ts +17 -7
- package/dist/templates/todo/dot-agents/skills/podokit-deploy/SKILL.md +55 -10
- package/dist/templates/todo/dot-agents/skills/podokit-deploy/references/profile.md +47 -0
- package/dist/templates/todo/dot-agents/skills/podokit-deploy/references/release.md +64 -0
- package/dist/templates/todo/dot-agents/skills/podokit-deploy-fast/SKILL.md +92 -0
- package/dist/templates/todo/dot-claude/skills/podokit-deploy/SKILL.md +1 -1
- package/dist/templates/todo/dot-claude/skills/podokit-deploy-fast/SKILL.md +8 -0
- package/dist/templates/todo/dot-dockerignore +7 -0
- package/dist/templates/todo/dot-env.example +7 -0
- package/dist/templates/todo/dot-github/workflows/release.yml +142 -0
- package/dist/templates/todo/infra/k3s/README.md +18 -0
- package/dist/templates/todo/infra/k3s/api-deployment.yaml +6 -1
- package/dist/templates/todo/infra/k3s/ingress.yaml +8 -0
- package/dist/templates/todo/infra/k3s/web-deployment.yaml +11 -1
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Build and publish the release images for a tag.
|
|
2
|
+
#
|
|
3
|
+
# `podo deploy` consumes images; it does not build them. This is the other half:
|
|
4
|
+
# tagging a commit produces the two images that `podo deploy apply` then rolls out.
|
|
5
|
+
# It stops at the push, because rolling out requires confirming a plan hash and that
|
|
6
|
+
# approval belongs to a person.
|
|
7
|
+
#
|
|
8
|
+
# ── Which runner, and what it costs ──────────────────────────────────────────────
|
|
9
|
+
#
|
|
10
|
+
# GitHub-hosted runners are free for PUBLIC repositories only. In a PRIVATE
|
|
11
|
+
# repository every minute is metered against the account's included Actions minutes
|
|
12
|
+
# and billed beyond them -- and image builds are the most expensive job most
|
|
13
|
+
# projects run. A self-hosted runner consumes no Actions minutes at all, whatever
|
|
14
|
+
# the repository's visibility.
|
|
15
|
+
#
|
|
16
|
+
# So the runner is a variable rather than a constant:
|
|
17
|
+
#
|
|
18
|
+
# PODOKIT_RUNNER repository or organization variable, a JSON array of labels.
|
|
19
|
+
# Unset -> ["ubuntu-latest"], which is right for a public
|
|
20
|
+
# repository and costs money in a private one.
|
|
21
|
+
# Self-hosted example: ["self-hosted","Linux","X64"]
|
|
22
|
+
#
|
|
23
|
+
# Set it before the first tag if this repository is private. Nothing here warns you
|
|
24
|
+
# when you have not: the workflow succeeds either way, and the difference shows up
|
|
25
|
+
# on a bill.
|
|
26
|
+
#
|
|
27
|
+
# ── The other two variables ──────────────────────────────────────────────────────
|
|
28
|
+
#
|
|
29
|
+
# PODOKIT_DEPLOY_PROFILE which .podokit/deploy/<name>.json names the image
|
|
30
|
+
# repositories. Unset -> production.
|
|
31
|
+
# PODOKIT_IMAGE_PLATFORM the architecture the deployment target runs.
|
|
32
|
+
# Unset -> linux/amd64. Building for the wrong one
|
|
33
|
+
# produces "exec format error" at rollout, after the
|
|
34
|
+
# migration has already run.
|
|
35
|
+
#
|
|
36
|
+
# ── Secrets ──────────────────────────────────────────────────────────────────────
|
|
37
|
+
#
|
|
38
|
+
# REGISTRY_USERNAME / REGISTRY_PASSWORD credentials for the registry named by
|
|
39
|
+
# the profile. A robot or deploy account is enough, but note that some registries
|
|
40
|
+
# refuse to let a robot CREATE a repository -- push the first tag of a new
|
|
41
|
+
# repository with an account that can, or create it in the registry first.
|
|
42
|
+
|
|
43
|
+
name: release
|
|
44
|
+
|
|
45
|
+
on:
|
|
46
|
+
push:
|
|
47
|
+
tags:
|
|
48
|
+
- "v*.*.*"
|
|
49
|
+
|
|
50
|
+
concurrency:
|
|
51
|
+
group: release-${{ github.ref }}
|
|
52
|
+
cancel-in-progress: false
|
|
53
|
+
|
|
54
|
+
jobs:
|
|
55
|
+
images:
|
|
56
|
+
# One job builds both images rather than a matrix of two. A self-hosted pool is
|
|
57
|
+
# usually small, and fanning out here takes runners away from every other
|
|
58
|
+
# repository that shares it for no wall-clock gain on a multi-core machine.
|
|
59
|
+
runs-on: ${{ fromJSON(vars.PODOKIT_RUNNER || '["ubuntu-latest"]') }}
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v5
|
|
62
|
+
|
|
63
|
+
- uses: actions/setup-node@v6
|
|
64
|
+
with:
|
|
65
|
+
node-version: 22
|
|
66
|
+
cache: npm
|
|
67
|
+
|
|
68
|
+
- run: npm ci --no-audit --no-fund
|
|
69
|
+
|
|
70
|
+
# Verify before publishing. An image built from a commit that never passed is
|
|
71
|
+
# indistinguishable from one that did, once it is in the registry.
|
|
72
|
+
- run: npm run lint
|
|
73
|
+
- run: npm test
|
|
74
|
+
|
|
75
|
+
- name: Read the release target from the deployment profile
|
|
76
|
+
id: profile
|
|
77
|
+
run: |
|
|
78
|
+
node --input-type=module -e '
|
|
79
|
+
import { readFileSync } from "node:fs";
|
|
80
|
+
const name = process.env.PROFILE || "production";
|
|
81
|
+
const path = `.podokit/deploy/${name}.json`;
|
|
82
|
+
let profile;
|
|
83
|
+
try {
|
|
84
|
+
profile = JSON.parse(readFileSync(path, "utf8"));
|
|
85
|
+
} catch {
|
|
86
|
+
throw new Error(`No deployment profile at ${path}. Run podo deploy init first.`);
|
|
87
|
+
}
|
|
88
|
+
const { apiRepository, webRepository } = profile.release ?? {};
|
|
89
|
+
if (!apiRepository || !webRepository) {
|
|
90
|
+
throw new Error(`${path} does not declare release.apiRepository and release.webRepository.`);
|
|
91
|
+
}
|
|
92
|
+
// Everything before the first slash is a registry host only when it
|
|
93
|
+
// looks like one; otherwise the reference is a Docker Hub short name.
|
|
94
|
+
const first = apiRepository.split("/")[0];
|
|
95
|
+
const registry = /[.:]/.test(first) ? first : "";
|
|
96
|
+
const out = [
|
|
97
|
+
`api=${apiRepository}`,
|
|
98
|
+
`web=${webRepository}`,
|
|
99
|
+
`registry=${registry}`,
|
|
100
|
+
`tag=${process.env.GITHUB_REF_NAME}`,
|
|
101
|
+
].join("\n");
|
|
102
|
+
process.stdout.write(out + "\n");
|
|
103
|
+
' >> "$GITHUB_OUTPUT"
|
|
104
|
+
env:
|
|
105
|
+
PROFILE: ${{ vars.PODOKIT_DEPLOY_PROFILE }}
|
|
106
|
+
|
|
107
|
+
- uses: docker/setup-buildx-action@v3
|
|
108
|
+
|
|
109
|
+
- uses: docker/login-action@v3
|
|
110
|
+
with:
|
|
111
|
+
registry: ${{ steps.profile.outputs.registry }}
|
|
112
|
+
username: ${{ secrets.REGISTRY_USERNAME }}
|
|
113
|
+
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
114
|
+
|
|
115
|
+
- name: Build and push the API image
|
|
116
|
+
uses: docker/build-push-action@v6
|
|
117
|
+
with:
|
|
118
|
+
context: .
|
|
119
|
+
file: apps/api/Dockerfile
|
|
120
|
+
platforms: ${{ vars.PODOKIT_IMAGE_PLATFORM || 'linux/amd64' }}
|
|
121
|
+
push: true
|
|
122
|
+
tags: ${{ steps.profile.outputs.api }}:${{ steps.profile.outputs.tag }}
|
|
123
|
+
cache-from: type=gha,scope=api
|
|
124
|
+
cache-to: type=gha,scope=api,mode=max
|
|
125
|
+
|
|
126
|
+
- name: Build and push the web image
|
|
127
|
+
uses: docker/build-push-action@v6
|
|
128
|
+
with:
|
|
129
|
+
context: .
|
|
130
|
+
file: apps/web/Dockerfile
|
|
131
|
+
platforms: ${{ vars.PODOKIT_IMAGE_PLATFORM || 'linux/amd64' }}
|
|
132
|
+
push: true
|
|
133
|
+
tags: ${{ steps.profile.outputs.web }}:${{ steps.profile.outputs.tag }}
|
|
134
|
+
cache-from: type=gha,scope=web
|
|
135
|
+
cache-to: type=gha,scope=web,mode=max
|
|
136
|
+
|
|
137
|
+
- name: Report what to deploy
|
|
138
|
+
run: |
|
|
139
|
+
echo "Pushed ${{ steps.profile.outputs.api }}:${{ steps.profile.outputs.tag }}" >> "$GITHUB_STEP_SUMMARY"
|
|
140
|
+
echo "Pushed ${{ steps.profile.outputs.web }}:${{ steps.profile.outputs.tag }}" >> "$GITHUB_STEP_SUMMARY"
|
|
141
|
+
echo "" >> "$GITHUB_STEP_SUMMARY"
|
|
142
|
+
echo 'Roll out with `podo deploy plan --profile <name> --release ${{ steps.profile.outputs.tag }}`, then apply the printed hash.' >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Example k3s manifests
|
|
2
|
+
|
|
3
|
+
These are **illustrative**. `podo deploy` does not read or apply them.
|
|
4
|
+
|
|
5
|
+
For a real deployment, initialize a profile and let PodoKit render the manifests it
|
|
6
|
+
will actually apply — with image digests, probes, disruption budgets, a migration
|
|
7
|
+
Job, and a confirmation hash:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
podo deploy init --profile production --context production --host app.example.com
|
|
11
|
+
podo deploy render --profile production --release v1.2.3
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Keep these files if you want a starting point for hand-managed manifests, or delete
|
|
15
|
+
the directory if you deploy with `podo deploy`. If you do apply them by hand, replace
|
|
16
|
+
every `example.com` and `ghcr.io/example/...` placeholder first, and note that the
|
|
17
|
+
image tags below are placeholders too: the deployment tooling rejects `latest`,
|
|
18
|
+
branch tags, and empty tags, and so should you.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# Example only. See README.md in this directory; `podo deploy` renders its own.
|
|
1
2
|
apiVersion: apps/v1
|
|
2
3
|
kind: Deployment
|
|
3
4
|
metadata:
|
|
@@ -13,7 +14,8 @@ spec:
|
|
|
13
14
|
spec:
|
|
14
15
|
containers:
|
|
15
16
|
- name: api
|
|
16
|
-
|
|
17
|
+
# Placeholder. Use one immutable, stable SemVer tag for api and web.
|
|
18
|
+
image: ghcr.io/example/podokit-api:v0.0.0
|
|
17
19
|
ports:
|
|
18
20
|
- containerPort: 3000
|
|
19
21
|
envFrom:
|
|
@@ -22,3 +24,6 @@ spec:
|
|
|
22
24
|
readinessProbe:
|
|
23
25
|
httpGet: { path: /health/ready, port: 3000 }
|
|
24
26
|
initialDelaySeconds: 5
|
|
27
|
+
livenessProbe:
|
|
28
|
+
httpGet: { path: /health, port: 3000 }
|
|
29
|
+
initialDelaySeconds: 15
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# Example only. See README.md in this directory; `podo deploy` renders its own.
|
|
1
2
|
apiVersion: traefik.io/v1alpha1
|
|
2
3
|
kind: Middleware
|
|
3
4
|
metadata:
|
|
@@ -14,6 +15,13 @@ metadata:
|
|
|
14
15
|
annotations:
|
|
15
16
|
traefik.ingress.kubernetes.io/router.middlewares: podokit-compression@kubernetescrd
|
|
16
17
|
spec:
|
|
18
|
+
# Name the controller explicitly rather than relying on a default IngressClass.
|
|
19
|
+
ingressClassName: traefik
|
|
20
|
+
# app-config sets an https:// origin, so the route has to terminate TLS. Create the
|
|
21
|
+
# Secret out of band (cert-manager, or an existing certificate) and name it here.
|
|
22
|
+
tls:
|
|
23
|
+
- hosts: [example.com]
|
|
24
|
+
secretName: app-tls
|
|
17
25
|
rules:
|
|
18
26
|
- host: example.com
|
|
19
27
|
http:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# Example only. See README.md in this directory; `podo deploy` renders its own.
|
|
1
2
|
apiVersion: apps/v1
|
|
2
3
|
kind: Deployment
|
|
3
4
|
metadata:
|
|
@@ -13,8 +14,17 @@ spec:
|
|
|
13
14
|
spec:
|
|
14
15
|
containers:
|
|
15
16
|
- name: web
|
|
16
|
-
|
|
17
|
+
# Placeholder. Use one immutable, stable SemVer tag for api and web.
|
|
18
|
+
image: ghcr.io/example/podokit-web:v0.0.0
|
|
17
19
|
ports:
|
|
18
20
|
- containerPort: 3000
|
|
19
21
|
envFrom:
|
|
20
22
|
- configMapRef: { name: app-config }
|
|
23
|
+
# Without these a rolling update sends traffic to a process that has not
|
|
24
|
+
# bound its port yet.
|
|
25
|
+
readinessProbe:
|
|
26
|
+
httpGet: { path: /, port: 3000 }
|
|
27
|
+
initialDelaySeconds: 5
|
|
28
|
+
livenessProbe:
|
|
29
|
+
httpGet: { path: /, port: 3000 }
|
|
30
|
+
initialDelaySeconds: 15
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@podosoft/podokit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "An opinionated but extensible starter toolkit and CLI for full-stack TypeScript apps with NestJS, SvelteKit, TailwindCSS, shadcn-svelte, Docker, and k3s.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|