|
2 | 2 |
|
3 | 3 | ## Current Status |
4 | 4 |
|
5 | | -**Version 1.3.0 released** (Feb 2026). Packaging infrastructure complete. |
| 5 | +**Version 1.3.0 released** (Feb 2026). No active work items. |
6 | 6 |
|
7 | | -Previous release: v1.2.5 (Jan 2026). |
| 7 | +Previous releases: v1.2.5 (Jan 2026), v1.2.4 (Jan 2026). |
8 | 8 |
|
9 | | -### Resolved Design Questions |
| 9 | +## Work Completed (Recent) |
10 | 10 |
|
11 | | -1. **Scala.js optimization task**: Use `fullOptJS` (applies Google Closure |
12 | | - Compiler optimization). NOT `fullLinkJS` — the plan's original |
13 | | - recommendation was incorrect; `fullOptJS` is not deprecated and produces |
14 | | - the optimized output needed for npm packaging. |
| 11 | +### Session Feb 3, 2026 — v1.3.0 Released |
15 | 12 |
|
16 | | -2. **Homebrew formula variants**: Support both JVM universal and Native |
17 | | - binary variants via a `variant` parameter (`"universal"` or `"native"`). |
| 13 | +Implemented complete packaging infrastructure across 6 phases. |
| 14 | +Integration-tested in riddl project (npm packaging/publishing to |
| 15 | +npmjs.com for ossum.ai site consumption). See `PACKAGING-PLAN.md` |
| 16 | +for the original design document. |
18 | 17 |
|
19 | | -3. **Linux tar.gz architecture**: Auto-detect host OS and architecture as |
20 | | - default (since Scala Native can only compile for the host platform), |
21 | | - with optional `arch` and `os` parameter overrides. Multi-arch |
22 | | - distribution requires CI matrix runners for each target platform. |
| 18 | +**New helpers:** |
| 19 | +- `With.Packaging.npm()` — npm package assembly from Scala.js output |
| 20 | +- `With.Publishing.npm()` — publish to npmjs.com and/or GitHub Packages |
| 21 | +- `With.Packaging.linux()` — tar.gz archives of Scala Native binaries |
| 22 | +- `With.Packaging.homebrew()` — Homebrew formula generation (JVM/Native) |
| 23 | +- `With.Packaging.windowsMsi()` — placeholder for future implementation |
23 | 24 |
|
24 | | -### Implementation Phases |
| 25 | +**New files:** `NpmPackaging.scala`, `NpmPublishing.scala`, |
| 26 | +`HomebrewPackaging.scala` |
25 | 27 |
|
26 | | -| Phase | Feature | Status | |
27 | | -|-------|---------|--------| |
28 | | -| 1 | NpmPackaging (`npmPrepare`, `npmPack`) | ✅ DONE | |
29 | | -| 2 | NpmPublishing (`npmPublish*` tasks) | ✅ DONE | |
30 | | -| 3 | Linux tar.gz packaging | ✅ DONE | |
31 | | -| 4 | Homebrew formula generation | ✅ DONE | |
32 | | -| 5 | Windows MSI placeholder | ✅ DONE | |
33 | | -| 6 | Documentation & Release (tag 1.3.0) | ✅ DONE | |
| 28 | +**Modified files:** `Packaging.scala` (added linux(), npm(), homebrew(), |
| 29 | +windowsMsi() delegation + linuxPackage keys), `Publishing.scala` (added |
| 30 | +npm() delegation) |
34 | 31 |
|
35 | | -### Session Feb 3, 2026 — v1.3.0 Released |
| 32 | +**New scripted tests:** `npm-packaging`, `linux-packaging`, `homebrew` |
| 33 | +(20 total, all passing) |
36 | 34 |
|
37 | | -All 6 phases of the packaging plan implemented and released. |
38 | | -Integration-tested in riddl project (npm packaging/publishing to |
39 | | -npmjs.com for ossum.ai site consumption). |
40 | | - |
41 | | -**New files created:** |
42 | | -- `NpmPackaging.scala` — Keys, `npm()` method, `npmPrepare`/`npmPack` |
43 | | - tasks, template mode with `VERSION_PLACEHOLDER`, TypeScript defs |
44 | | - convention (`js/types/index.d.ts`), JSON generation via string builder |
45 | | -- `NpmPublishing.scala` — `npmPublish`, `npmPublishNpmjs`, |
46 | | - `npmPublishGithub` tasks, auth via env vars (`NPM_TOKEN`, |
47 | | - `GITHUB_TOKEN`), extracted helper methods to avoid sbt `.value` macro |
48 | | - restrictions inside lambdas |
49 | | -- `HomebrewPackaging.scala` — `homebrewGenerate` task, supports |
50 | | - `"universal"` (JVM with openjdk dep) and `"native"` (Scala Native) |
51 | | - variants, SHA256 from local artifact, Ruby class name generation, |
52 | | - uses `Def.task` variant selection at build-definition time to avoid |
53 | | - sbt macro restrictions |
54 | | - |
55 | | -**Modified files:** |
56 | | -- `Packaging.scala` — Added delegation methods `npm()`, `homebrew()`, |
57 | | - `linux()`, `windowsMsi()` (placeholder); added `linuxPackage`, |
58 | | - `linuxPackageArch`, `linuxPackageOs` keys; added `detectArch`, |
59 | | - `detectOs` private helpers; imported Scala Native `nativeLink` |
60 | | -- `Publishing.scala` — Added `npm()` delegation method |
61 | | - |
62 | | -**New scripted tests (20 total now):** |
63 | | -- `npm-packaging` — Verifies `npmPrepare` produces `package.json`, |
64 | | - `main.js`, `README.md` with correct content assertions |
65 | | -- `linux-packaging` — Verifies config settings (doesn't link; consistent |
66 | | - with existing `native` test pattern) |
67 | | -- `homebrew` — Runs `homebrewGenerate` on a `Program`, verifies formula |
68 | | - contains class name, description, homepage, JDK dep, license, SHA256 |
69 | | - |
70 | | -**Technical lessons learned:** |
71 | | -- sbt `.value` is a macro — ALL `.value` calls in a task body are |
72 | | - resolved regardless of runtime control flow (match/if/foreach). Must |
73 | | - either extract to helper methods (NpmPublishing) or use `Def.task` |
74 | | - variant selection at build-definition time (HomebrewPackaging). |
75 | | -- `fullOptJS` is NOT deprecated; it applies Google Closure Compiler |
76 | | - optimization needed for production npm packages. |
| 35 | +### Session Feb 2, 2026 — Docker Dual-Image Support |
77 | 36 |
|
78 | | -## Work Completed (Recent) |
| 37 | +Added `With.Packaging.dockerDual()` for separate dev/prod Docker images. |
| 38 | +Dev image uses `eclipse-temurin:25-jdk-noble` (arm64), prod uses |
| 39 | +`gcr.io/distroless/java25-debian13:nonroot` (amd64). Scripted test added. |
79 | 40 |
|
80 | 41 | ### Session Jan 28-29, 2026 - v1.2.5 Released (CI Fixes) |
81 | 42 |
|
@@ -202,89 +163,6 @@ Plus credentials in `~/.sbt/1.0/github.sbt`. |
202 | 163 |
|
203 | 164 | ## Next Steps (Priority Order) |
204 | 165 |
|
205 | | -### ✅ COMPLETED (Jan 17, 2026) |
206 | | - |
207 | | -- ~~Remove hardcoded RIDDL values from Scala3.scala~~ ✓ |
208 | | -- ~~Refactor AutoPluginHelper to extend (Project => Project)~~ ✓ |
209 | | -- ~~Fix Akka test (already working)~~ ✓ |
210 | | -- ~~Fix IntelliJ plugin test (already working)~~ ✓ |
211 | | -- ~~Make CrossModule dependencies optional~~ ✓ |
212 | | -- ~~Add generic With.Publishing() helper~~ ✓ |
213 | | -- ~~Improve Root requirement error messages~~ ✓ |
214 | | -- ~~Parameterize dependency versions~~ ✓ |
215 | | -- ~~Add initial scripted tests for coverage~~ ✓ |
216 | | - |
217 | | -### 🔵 ACTIVE: Docker Dual-Image Support (feature/docker-dual) |
218 | | - |
219 | | -**Goal:** Add `With.Packaging.dockerDual()` helper to support building separate |
220 | | -dev and prod Docker images for RIDDL services (MCP, Sim, Gen). |
221 | | - |
222 | | -**Requirements gathered in ossum-ops session (Feb 2, 2026):** |
223 | | - |
224 | | -| Aspect | Dev Image | Prod Image | |
225 | | -|--------|-----------|------------| |
226 | | -| Base | `eclipse-temurin:25-jdk-noble` | `gcr.io/distroless/java25-debian13:nonroot` | |
227 | | -| Arch | `linux/arm64` (Apple Silicon) | `linux/amd64` (GKE) | |
228 | | -| Tags | `:dev-latest`, `:dev-<version>` | `:latest`, `:<version>` | |
229 | | -| Tools | JDK (jcmd, jstack, jmap) | JRE only (minimal) | |
230 | | -| Shell | Yes (Ubuntu bash) | No (distroless) | |
231 | | - |
232 | | -**Design decisions:** |
233 | | -1. Two separate images (not multi-arch buildx) |
234 | | -2. `docker:publishLocal` defaults to dev image |
235 | | -3. Explicit `dockerPublishProd` task for production |
236 | | -4. CI builds only prod images |
237 | | -5. Both use staged layout (no sbt-assembly fat JAR) |
238 | | -6. Custom Dockerfile for prod to handle classpath with distroless |
239 | | - |
240 | | -**API design:** |
241 | | -```scala |
242 | | -// In project's build.sbt - minimal configuration |
243 | | -.configure( |
244 | | - With.Packaging.dockerDual( |
245 | | - mainClass = "com.ossuminc.riddl.mcp.Main", |
246 | | - pkgName = "riddl-mcp-server", |
247 | | - exposedPorts = Seq(8080, 8558, 9001) |
248 | | - ) |
249 | | -) |
250 | | - |
251 | | -// Optional overrides if needed |
252 | | -.settings( |
253 | | - dockerRepository := Some("custom-registry.io") |
254 | | -) |
255 | | -``` |
256 | | - |
257 | | -**Implementation tasks:** |
258 | | -- [x] Update `Packaging.scala` with `dockerDual()` helper |
259 | | -- [x] Add `dockerPublishProd` task definition |
260 | | -- [x] Generate custom Dockerfile for distroless (via `dockerCommands`) |
261 | | -- [x] Set default repository to `ghcr.io/ossuminc` |
262 | | -- [x] Configure non-root user for both images |
263 | | -- [x] Add architecture settings (arm64 dev, amd64 prod) |
264 | | -- [x] Add tag pattern logic (`:dev-*` vs `:<version>`) |
265 | | -- [x] Add scripted test for docker-dual |
266 | | -- [x] Update README.md with documentation |
267 | | - |
268 | | -**Session Feb 2, 2026 - Implementation Complete** |
269 | | - |
270 | | -All implementation tasks completed. The `dockerDual()` helper is ready for use. |
271 | | -Scripted test passes (17/17 tests now). PR can be created for review. |
272 | | - |
273 | | -**Custom Dockerfile for distroless prod:** |
274 | | -```dockerfile |
275 | | -FROM gcr.io/distroless/java25-debian13:nonroot |
276 | | -WORKDIR /opt/docker |
277 | | -COPY --chown=nonroot:nonroot opt/docker/lib lib |
278 | | -ENTRYPOINT ["java", "-cp", "/opt/docker/lib/*", "<MainClass>"] |
279 | | -``` |
280 | | - |
281 | | -**References:** |
282 | | -- [distroless Java README](https://github.com/GoogleContainerTools/distroless/blob/main/java/README.md) |
283 | | -- [sbt-native-packager Docker](https://www.scala-sbt.org/sbt-native-packager/formats/docker.html) |
284 | | -- ossum-ops/lago/ARCHITECTURE.md (for deployment context) |
285 | | - |
286 | | ---- |
287 | | - |
288 | 166 | ### 🟡 REMAINING WORK |
289 | 167 |
|
290 | 168 | #### 1. Remove or implement NodeTarget |
|
0 commit comments