Skip to content

Commit 277fb3e

Browse files
committed
Automate NixOS plugin pin updates and restructure docs
Add scripts/update-nixos-plugin-pins.mjs, which pins the NixOS deployment doc to a GitHub release: it reads themeVersion from the release tag, derives spiVersion from the SPI jar file names, converts the sha256 digests the GitHub API reports per asset into SRI format (falling back to downloading and hashing when a digest is missing), and rewrites the pin block in docs/deployment-nixos.md. Each replacement is anchored to its jar file name and must match exactly once, so hashes can never be assigned to the wrong plugin and shape drift fails loudly. Exposed as `npm run update-nix-pins` with --tag, --check and --release-json flags. Wire it into CI: after create_github_release, the new update_nixos_plugin_pins job re-pins the doc against the freshly published tag and commits the result to main, so the checked-in Nix snippet always matches the latest release. Restructure docs/deployment-nixos.md around that motion: document the two version numbers (theme vs SPI), replace the placeholder-hash example with a real, verified pin block for v0.6.0 (release = ver: file: sha:), and rewrite the updating section as the end-to-end release flow. Fold the sha256-by-hand instructions into a fallback note. Restructure README.md: add a table of contents, group development and deployment sections, fix the duplicated section numbering, and document the release + pinning motion. Bump the version to 0.6.1 so merging this cuts a release that exercises the new pipeline end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MkN8eGu18MoULRF4XLb5Y4
1 parent 9c742ae commit 277fb3e

5 files changed

Lines changed: 385 additions & 82 deletions

File tree

‎.github/workflows/ci.yaml‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,31 @@ jobs:
8080
files: release-artifacts/*.jar
8181
env:
8282
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83+
84+
update_nixos_plugin_pins:
85+
name: Update NixOS plugin pins in docs
86+
runs-on: ubuntu-latest
87+
needs: [check_if_version_upgraded, create_github_release]
88+
if: needs.check_if_version_upgraded.outputs.is_pre_release != 'true'
89+
permissions:
90+
contents: write
91+
steps:
92+
- uses: actions/checkout@v4
93+
with:
94+
ref: main
95+
- uses: actions/setup-node@v4
96+
- name: Re-pin docs/deployment-nixos.md to the new release
97+
run: node scripts/update-nixos-plugin-pins.mjs --tag v${{ needs.check_if_version_upgraded.outputs.to_version }}
98+
env:
99+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
100+
- name: Commit and push updated pins
101+
run: |
102+
if git diff --quiet docs/deployment-nixos.md; then
103+
echo "Pins already up to date, nothing to commit."
104+
exit 0
105+
fi
106+
git config user.name "github-actions[bot]"
107+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
108+
git add docs/deployment-nixos.md
109+
git commit -m "docs: pin NixOS plugins to v${{ needs.check_if_version_upgraded.outputs.to_version }}"
110+
git push origin main

‎README.md‎

Lines changed: 67 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,42 @@ Keycloak login theme using helpwave hightide components, plus the Keycloak SPI
44
extensions that power the registration flow (Cloudflare Turnstile + privacy
55
acceptance) and the profile picture upload.
66

7-
## Quick start
7+
## Contents
8+
9+
- [Features](#features)
10+
- [Development](#development)
11+
- [Quick start](#quick-start)
12+
- [Building the theme](#building-the-theme)
13+
- [Building the Keycloak SPIs](#building-the-keycloak-spis)
14+
- [Local development with Docker](#local-development-with-docker)
15+
- [NixOS development](#nixos-development)
16+
- [Deployment](#deployment)
17+
- [1. Install the plugins](#1-install-the-plugins)
18+
- [2. Enable the Cloudflare Turnstile form action](#2-enable-the-cloudflare-turnstile-form-action)
19+
- [3. Enable the policy-acceptance required actions](#3-enable-the-policy-acceptance-required-actions)
20+
- [4. Configure the profile picture storage](#4-configure-the-profile-picture-storage)
21+
- [5. Wire the theme to the SPIs](#5-wire-the-theme-to-the-spis)
22+
- [Releases & version pinning](#releases--version-pinning)
823

9-
```bash
10-
npm ci
11-
```
24+
## Features
25+
26+
- hightide component integration
27+
- Realm indicator chip with deterministic color mapping
28+
- Custom login, register, and forgot password pages
29+
- Field-level validation matching hightide patterns
30+
- **Cloudflare Turnstile** CAPTCHA on signup (`helpwave-turnstile` FormAction SPI)
31+
- **Versioned policy consents** (privacy + future forms) via a reusable RequiredAction
32+
SPI (`helpwave-policy-acceptance`). Bumping the version on the realm re-prompts every
33+
user on next login; acceptance metadata is persisted on the user account.
34+
- **Profile picture upload** with server-side scaling to multiple sizes and storage in any
35+
S3-compatible bucket (`helpwave-picture` Realm Resource SPI)
1236

1337
## Development
1438

15-
### Linting and type checking
39+
### Quick start
1640

1741
```bash
42+
npm ci
1843
npm run lint
1944
npm run typecheck
2045
```
@@ -52,7 +77,7 @@ independently):
5277
Drop all three (alongside the theme jar) into Keycloak's `providers/` directory and run
5378
`kc.sh build`.
5479

55-
## Local development with Docker
80+
### Local development with Docker
5681

5782
Start keycloak and postgres services:
5883

@@ -72,36 +97,25 @@ Default admin credentials:
7297
- Username: `admin`
7398
- Password: `admin`
7499

75-
### Verification URLs
100+
For SPI configuration, copy [`.env.example`](.env.example) to `.env` and fill it in, then
101+
`docker compose --env-file .env up`.
76102

77103
After starting the services, you can access:
78104

79105
- Customer realm login: http://localhost:8080/realms/customer/protocol/openid-connect/auth?client_id=account-console&redirect_uri=http://localhost:8080/realms/customer/account/&response_type=code&scope=openid
80106
- Team realm login: http://localhost:8080/realms/team/protocol/openid-connect/auth?client_id=account-console&redirect_uri=http://localhost:8080/realms/team/account/&response_type=code&scope=openid
81107
- Keycloak admin console: http://localhost:8080/admin
82108

83-
## NixOS development
109+
### NixOS development
84110

85111
For nixos users, see [docs/nixos.md](docs/nixos.md) for nix-shell setup instructions.
86112

87-
## Features
88-
89-
- hightide component integration
90-
- Realm indicator chip with deterministic color mapping
91-
- Custom login, register, and forgot password pages
92-
- Field-level validation matching hightide patterns
93-
- **Cloudflare Turnstile** CAPTCHA on signup (`helpwave-turnstile` FormAction SPI)
94-
- **Versioned policy consents** (privacy + future forms) via a reusable RequiredAction
95-
SPI (`helpwave-policy-acceptance`). Bumping the version on the realm re-prompts every
96-
user on next login; acceptance metadata is persisted on the user account.
97-
- **Profile picture upload** with server-side scaling to multiple sizes and storage in any
98-
S3-compatible bucket (`helpwave-picture` Realm Resource SPI)
99-
100-
---
101-
102113
## Deployment
103114

104-
The release workflow publishes the following jars on every version bump in `package.json`:
115+
### 1. Install the plugins
116+
117+
Every release publishes the following jars (see
118+
[Releases & version pinning](#releases--version-pinning) for how releases are cut):
105119

106120
| Jar | Purpose |
107121
|--------------------------------------------------|--------------------------------------------------|
@@ -113,7 +127,13 @@ The release workflow publishes the following jars on every version bump in `pack
113127
Copy all jars into Keycloak's `providers/` directory (or mount them into the container)
114128
and run `kc.sh build` to rebuild the runtime, then start Keycloak normally.
115129

116-
### 1. Enable the Cloudflare Turnstile form action
130+
**On NixOS**, don't do any of this by hand: a complete `services.keycloak` example —
131+
including an auto-updated, hash-pinned plugin block and [sops-nix] secret handling —
132+
lives in [docs/deployment-nixos.md](docs/deployment-nixos.md).
133+
134+
[sops-nix]: https://github.com/Mic92/sops-nix
135+
136+
### 2. Enable the Cloudflare Turnstile form action
117137

118138
1. Open the Keycloak admin console.
119139
2. Go to **Authentication** → **Flows** and duplicate the built-in **registration** flow.
@@ -124,7 +144,7 @@ and run `kc.sh build` to rebuild the runtime, then start Keycloak normally.
124144
Get these from <https://dash.cloudflare.com/?to=/:account/turnstile>.
125145
5. Set this flow as the realm's **Registration flow** binding.
126146

127-
### 2. Enable the policy-acceptance required actions
147+
### 3. Enable the policy-acceptance required actions
128148

129149
1. **Authentication** → **Required actions** → enable
130150
**Privacy Policy Acceptance (helpwave)**.
@@ -142,7 +162,7 @@ Add more consent forms (e.g. terms of service, data-processing agreement) by add
142162
file. The React `Terms.tsx` page renders the policy variant automatically when a
143163
`policyId` attribute is set.
144164

145-
### 3. Configure the profile picture storage
165+
### 4. Configure the profile picture storage
146166

147167
The profile picture SPI accepts standard AWS S3 or Cloudflare R2 (any S3-compatible
148168
backend). It exposes itself at:
@@ -192,7 +212,7 @@ KC_SPI_REALM_RESTAPI_EXTENSION_HELPWAVE_PICTURE_SECRET_KEY=...
192212
KC_SPI_REALM_RESTAPI_EXTENSION_HELPWAVE_PICTURE_PUBLIC_BASE_URL=https://avatars.helpwave.de
193213
```
194214

195-
### 3. Wire the theme to the SPIs
215+
### 5. Wire the theme to the SPIs
196216

197217
Two Keycloakify env vars expose the SPI to the theme at render time:
198218

@@ -210,16 +230,26 @@ KC_PROFILE_PICTURE_API_URL=https://id.helpwave.de/realms/customer/helpwave-pictu
210230

211231
(Keycloakify reads `KC_<NAME>` and exposes it as `kcContext.properties.<NAME>`.)
212232

213-
### 4. NixOS deployment
233+
## Releases & version pinning
214234

215-
A complete `services.keycloak` example with [sops-nix] secret handling and the matching
216-
admin-console steps lives in [docs/deployment-nixos.md](docs/deployment-nixos.md). For
217-
local development with `docker compose`, copy [`.env.example`](.env.example) to `.env`
218-
and fill in the values.
235+
Cutting and consuming a release is a single repeatable motion:
219236

220-
[sops-nix]: https://github.com/Mic92/sops-nix
237+
1. **Bump** `version` in `package.json` on `main` (and the Maven version in
238+
`keycloak-extensions/pom.xml` + module poms if the SPIs changed).
239+
2. **CI releases**: the workflow builds the theme + SPIs and publishes a GitHub release
240+
`v<version>` with all jars attached.
241+
3. **CI re-pins the docs**: the `update_nixos_plugin_pins` job then updates the
242+
`themeVersion` / `spiVersion` / `sha256` pins in
243+
[docs/deployment-nixos.md](docs/deployment-nixos.md) from the release assets' digests
244+
and commits the result to `main` — the checked-in NixOS snippet always matches the
245+
latest release.
246+
4. **Deploy**: copy the refreshed pin block into your NixOS config and
247+
`nixos-rebuild switch`.
221248

222-
### 5. Releases
249+
To re-pin the docs manually (e.g. against a specific release):
223250

224-
Bump `version` in `package.json` on `main`. The CI workflow builds the theme + SPIs and
225-
publishes a GitHub release with all four jars attached.
251+
```bash
252+
npm run update-nix-pins # latest release
253+
npm run update-nix-pins -- --tag v0.6.0 # specific release
254+
npm run update-nix-pins -- --check # verify pins are current
255+
```

0 commit comments

Comments
 (0)