Skip to content

Commit eae014b

Browse files
authored
Add Kubernetes deployment docs and refactor Claude skills (#362)
* Remove stale patches from template-app overlay The Deployment/streamlit patch with Ingress-shaped path /spec/rules/0/host never applied and produced a silent no-op. The duplicate IngressRoute service-name patch was redundant with the first IngressRoute patch block. This brings the on-disk overlay in line with the production cluster's running version. * Rename configure-deployment skill to configure-docker-compose-deployment First step of splitting the skill into three focused skills (configure-app-settings, configure-docker-compose-deployment, configure-k8s-deployment). Rename is in its own commit so git log --follow traces the docker-compose content cleanly. * Scope docker-compose skill to docker-compose-only Removes app-level content (settings.json, Dockerfile choice, production app examples) that will live in configure-app-settings. Adds a prerequisite note pointing to configure-app-settings. * Add configure-app-settings skill Covers app-level configuration (settings.json, Dockerfile choice, README, dependencies) shared by every deployment mode. Prerequisite for configure-docker-compose-deployment and configure-k8s-deployment. * Fix settings.json key-field list inconsistency The Key fields prose listed max_threads (not in the JSON sample) and omitted enable_workspaces (which is in the sample). Align the prose with the sample and describe max_threads separately since it is a nested object rather than a flat field. * Add configure-k8s-deployment skill New skill walking through Kustomize overlay creation and kubectl apply for deploying a forked app to Kubernetes. Patch list reflects the three-patch canonical shape (IngressRoute match + service, streamlit Redis URL, rq-worker Redis URL). * Fix inline-code rendering in k8s skill The Host(`...`) escape syntax produced literal backslashes that broke the inline-code span when rendered by markdown parsers. Rewrite as Host(...) without nested backticks so the span renders cleanly. * Add K8s deployment doc — overview and architecture sections * Add K8s deployment doc — manifest reference section * Add K8s deployment doc — fork-and-deploy guide * Add K8s deployment doc — CI/CD pipeline section * Clarify PR-blocking behavior depends on branch protection The workflow does not block merges directly — it produces a check status that a branch-protection rule can gate on. Make the preconditions explicit. * Register Kubernetes Deployment page in Streamlit documentation * Cross-link docs/deployment.md to Kubernetes deployment page Adds a preamble listing both deployment paths and introduces a ## Docker Compose heading above the existing content. The existing docker-compose content is preserved verbatim. * Add smoke test for Kubernetes Deployment documentation page Extends the parametrized test_documentation cases to cover the new Documentation page added by this branch, closing the gap where it was the only selectbox entry without test coverage.
1 parent 4069e11 commit eae014b

8 files changed

Lines changed: 399 additions & 59 deletions

File tree

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Configure Deployment
1+
# Configure App Settings
22

3-
Set up Docker, settings, and CI/CD configuration for a new or forked app.
3+
Set up app-level configuration (settings, Dockerfile, README) for a new or forked OpenMS streamlit app. Run before `configure-docker-compose-deployment` or `configure-k8s-deployment`.
44

55
## Instructions
66

@@ -12,18 +12,18 @@ Set up Docker, settings, and CI/CD configuration for a new or forked app.
1212

1313
2. **Update `settings.json`**:
1414

15-
```json
16-
{
17-
"app-name": "Your App Name",
18-
"github-user": "YourGitHubUser",
19-
"repository-name": "your-repo-name",
20-
"version": "0.1.0",
21-
"online_deployment": false,
22-
"enable_workspaces": true
23-
}
24-
```
15+
```json
16+
{
17+
"app-name": "Your App Name",
18+
"github-user": "YourGitHubUser",
19+
"repository-name": "your-repo-name",
20+
"version": "0.1.0",
21+
"online_deployment": false,
22+
"enable_workspaces": true
23+
}
24+
```
2525

26-
Key fields: `app-name`, `github-user`, `repository-name`, `version`, `online_deployment`, `max_threads`.
26+
Key fields: `app-name`, `github-user`, `repository-name`, `version`, `online_deployment`, `enable_workspaces`. `max_threads` (a nested object with `local`/`online` keys in `settings.json`) caps worker parallelism — tune it if your cluster or host has specific CPU constraints.
2727

2828
3. **Choose and update Dockerfile**:
2929

@@ -36,30 +36,7 @@ Key fields: `app-name`, `github-user`, `repository-name`, `version`, `online_dep
3636
- `GITHUB_USER` and `GITHUB_REPO` environment variables
3737
- Python dependencies in `requirements.txt`
3838

39-
4. **Update `docker-compose.yml`**:
40-
41-
```yaml
42-
services:
43-
your-app-name:
44-
build: .
45-
ports:
46-
- "8501:8501"
47-
volumes:
48-
- workspaces-your-repo-name:/workspaces-your-repo-name
49-
50-
volumes:
51-
workspaces-your-repo-name:
52-
```
53-
54-
Service name and volume name should use the repository name.
55-
56-
5. **Update `clean-up-workspaces.py`**:
57-
58-
```python
59-
workspaces_directory = Path("/workspaces-your-repo-name")
60-
```
61-
62-
6. **Update `README.md`** with the new app name, description, and instructions.
39+
4. **Update `README.md`** with the new app name, description, and instructions.
6340

6441
## Dockerfile Decision Guide
6542

@@ -72,11 +49,8 @@ workspaces_directory = Path("/workspaces-your-repo-name")
7249
## Reference Files
7350

7451
- App settings: `settings.json`
75-
- Docker: `Dockerfile`, `Dockerfile_simple`, `docker-compose.yml`
52+
- Docker: `Dockerfile`, `Dockerfile_simple`
7653
- Build docs: `docs/build_app.md`
77-
- Deployment docs: `docs/deployment.md`
78-
- CI/CD: `.github/workflows/` (Docker build, Windows exe, linting, tests)
79-
- Workspace cleanup: `clean-up-workspaces.py`
8054

8155
## Real-World Examples
8256

@@ -87,8 +61,10 @@ workspaces_directory = Path("/workspaces-your-repo-name")
8761
## Checklist
8862

8963
- [ ] `settings.json` updated with app name, GitHub user/repo, version
90-
- [ ] Correct Dockerfile chosen and configured (GITHUB_USER, GITHUB_REPO)
91-
- [ ] `docker-compose.yml` updated with service name and volume
92-
- [ ] `clean-up-workspaces.py` updated with workspace directory path
64+
- [ ] Correct Dockerfile chosen and configured (`GITHUB_USER`, `GITHUB_REPO`)
9365
- [ ] `requirements.txt` or `environment.yml` updated with dependencies
9466
- [ ] `README.md` updated
67+
68+
## Next Steps
69+
70+
Run `configure-docker-compose-deployment` and/or `configure-k8s-deployment` to set up the deployment path(s).
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Configure Docker Compose Deployment
2+
3+
Set up docker-compose-specific configuration for a new or forked OpenMS streamlit app.
4+
5+
## Prerequisite
6+
7+
Run `configure-app-settings` first. This skill assumes `settings.json`, the Dockerfile, and app metadata (app name, GitHub user/repo, README) are already configured.
8+
9+
## Instructions
10+
11+
1. **Update `docker-compose.yml`**:
12+
13+
```yaml
14+
services:
15+
your-app-name:
16+
build: .
17+
ports:
18+
- "8501:8501"
19+
volumes:
20+
- workspaces-your-repo-name:/workspaces-your-repo-name
21+
22+
volumes:
23+
workspaces-your-repo-name:
24+
```
25+
26+
Service name and volume name should use the repository name.
27+
28+
2. **Update `clean-up-workspaces.py`**:
29+
30+
```python
31+
workspaces_directory = Path("/workspaces-your-repo-name")
32+
```
33+
34+
3. **Build and run**:
35+
36+
```bash
37+
docker-compose up --build -d
38+
```
39+
40+
## Reference Files
41+
42+
- Docker Compose: `docker-compose.yml`
43+
- Workspace cleanup: `clean-up-workspaces.py`
44+
- Full reference: see the "Developers Guide: Deployment" Documentation page in the running Streamlit app.
45+
46+
## Checklist
47+
48+
- [ ] `docker-compose.yml` updated with service name and volume
49+
- [ ] `clean-up-workspaces.py` updated with workspace directory path
50+
- [ ] Successfully builds and starts with `docker-compose up --build -d`
51+
- [ ] App accessible at http://localhost:8501
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Configure Kubernetes Deployment
2+
3+
Create a Kustomize overlay for deploying a forked OpenMS streamlit app to Kubernetes.
4+
5+
## Prerequisite
6+
7+
Run `configure-app-settings` first. This skill assumes `settings.json`, the Dockerfile, and app metadata are already configured.
8+
9+
## Cluster Prerequisites
10+
11+
- `kubectl` configured for the target cluster
12+
- A storage class that supports `ReadWriteOnce` volumes (default: `cinder-csi` for de.NBI / OpenStack)
13+
- An ingress controller (default: Traefik; nginx also supported via the base `Ingress` resource)
14+
- Read access to GHCR for pulling the app image
15+
- A DNS record pointing to the cluster's ingress load balancer
16+
17+
## Instructions
18+
19+
1. **Let CI build and push the image.**
20+
21+
Push your changes to `main` or create a tag. The workflow `.github/workflows/build-and-push-image.yml` publishes the image to `ghcr.io/<your-org>/<your-repo>:<tag>`.
22+
23+
2. **Copy the template overlay.**
24+
25+
```bash
26+
cp -r k8s/overlays/template-app k8s/overlays/<your-app-name>
27+
```
28+
29+
3. **Edit `k8s/overlays/<your-app-name>/kustomization.yaml`**:
30+
31+
- Change `namePrefix` from `template-app-` to `<your-app-name>-`
32+
- Change `commonLabels.app` from `template-app` to `<your-app-name>`
33+
- Change `images[0].newName` to `ghcr.io/<your-org>/<your-repo>`
34+
- In the IngressRoute patch, update:
35+
- the `Host(...)` match — change the quoted hostname to your own
36+
- the service name reference from `template-app-streamlit` to `<your-app-name>-streamlit`
37+
- In both Deployment patches (`streamlit` and `rq-worker`), update the Redis URL from `redis://template-app-redis:6379/0` to `redis://<your-app-name>-redis:6379/0`
38+
39+
The overlay leaves the nginx `Ingress` unpatched because production deployments use Traefik. If you are deploying to an nginx-only cluster, substitute an Ingress host patch for the IngressRoute patch.
40+
41+
4. **Validate the overlay builds.**
42+
43+
```bash
44+
kubectl kustomize k8s/overlays/<your-app-name>/
45+
```
46+
47+
Should print the rendered manifests with no errors.
48+
49+
5. **Deploy.**
50+
51+
```bash
52+
kubectl apply -k k8s/overlays/<your-app-name>/
53+
```
54+
55+
6. **Verify.**
56+
57+
```bash
58+
kubectl -n openms get pods -l app=<your-app-name>
59+
kubectl -n openms rollout status deployment/<your-app-name>-streamlit --timeout=120s
60+
```
61+
62+
Smoke-test the ingress URL in a browser.
63+
64+
## Reference Files
65+
66+
- Overlay template: `k8s/overlays/template-app/kustomization.yaml`
67+
- Base manifests: `k8s/base/*.yaml`
68+
- CI: `.github/workflows/build-and-push-image.yml`, `.github/workflows/k8s-manifests-ci.yml`
69+
- Full reference: see the "Developers Guide: Kubernetes Deployment" Documentation page in the running Streamlit app.
70+
71+
## Checklist
72+
73+
- [ ] Image built and pushed to GHCR (via CI or manual push to `main`/tag)
74+
- [ ] Overlay copied to `k8s/overlays/<your-app-name>/`
75+
- [ ] `namePrefix`, `commonLabels.app`, `images[0].newName` updated
76+
- [ ] IngressRoute patch updated (host + service reference)
77+
- [ ] Redis URL updated in both Deployment patches
78+
- [ ] `kubectl kustomize` succeeds
79+
- [ ] `kubectl apply -k` succeeds
80+
- [ ] All pods Running, `rollout status` succeeds
81+
- [ ] App accessible via the ingress hostname

content/documentation.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"Developers Guide: TOPP Workflow Framework",
1818
"Developer Guide: Windows Executables",
1919
"Developers Guide: Deployment",
20+
"Developers Guide: Kubernetes Deployment",
2021
]
2122
page = cols[0].selectbox(
2223
"**Content**",
@@ -106,4 +107,13 @@
106107
if page == pages[5]:
107108
with open(Path("docs", "deployment.md"), "r", encoding="utf-8") as f:
108109
content = f.read()
109-
st.markdown(content)
110+
st.markdown(content)
111+
112+
#############################################################################################
113+
# Kubernetes Deployment
114+
#############################################################################################
115+
116+
if page == pages[6]:
117+
with open(Path("docs", "kubernetes-deployment.md"), "r", encoding="utf-8") as f:
118+
content = f.read()
119+
st.markdown(content)

docs/deployment.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# OpenMS streamlit app deployment
22

3+
OpenMS streamlit apps can be deployed two ways:
4+
5+
- **Kubernetes** — Kustomize manifests under `k8s/` with CI-built images pushed to GHCR. See the "Developers Guide: Kubernetes Deployment" page.
6+
- **Docker Compose** — described below. Uses the external [OpenMS/streamlit-deployment](https://github.com/OpenMS/streamlit-deployment) repo to aggregate multiple apps as submodules.
7+
8+
If you're using Claude Code, the `configure-app-settings` and `configure-docker-compose-deployment` skills automate the docker-compose path; `configure-app-settings` + `configure-k8s-deployment` automate the Kubernetes path.
9+
10+
---
11+
12+
## Docker Compose
13+
314
Multiple streamlit apps based on the [OpenMS streamlit template](https://github.com/OpenMS/streamlit-template/) can be deployed together using docker compose.
415

516
## Features

0 commit comments

Comments
 (0)