Skip to content

Commit 2dc8f52

Browse files
respencer-nclclaude
andcommitted
Add packaging infrastructure for v1.3.0
New helpers for npm, Linux, and Homebrew packaging: - With.Packaging.npm(): Assembles Scala.js output into npm packages with npmPrepare (pure sbt) and npmPack tasks. Supports template mode and TypeScript definition auto-discovery. - With.Publishing.npm(): Publishes npm packages to npmjs.com and/or GitHub Packages with NPM_TOKEN/GITHUB_TOKEN auth. - With.Packaging.linux(): Creates tar.gz archives of Scala Native binaries with auto-detected OS/arch and optional overrides. - With.Packaging.homebrew(): Generates Homebrew formula .rb files for JVM universal or Scala Native variants with SHA256 hashing. - With.Packaging.windowsMsi(): Placeholder for future implementation. Includes 3 new scripted tests (20 total, all passing) and full README documentation with migration notes. Integration-tested in riddl project for npm packaging/publishing of riddl-lib to npmjs.com. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 4a8a48f commit 2dc8f52

File tree

24 files changed

+2242
-30
lines changed

24 files changed

+2242
-30
lines changed

CLAUDE.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ SBT plugin providing build infrastructure and configuration helpers for Ossum
1414
Inc. projects. Defines declarative project types and configuration options
1515
used across all Scala projects in the organization.
1616

17-
**Current version: 1.2.5** (released Jan 2026)
17+
**Current version: 1.3.0** (released Feb 2026)
1818

1919
## Project Types Provided
2020

@@ -98,10 +98,37 @@ provided transitively. Only use `With.Akka.forRelease()` if you need modules
9898
beyond what the server infrastructure provides (e.g., Kafka, Insights,
9999
Management, Projections).
100100

101+
**`With.Packaging.npm(...)`** - npm package assembly (v1.3.0+)
102+
- For Scala.js projects, assembles output into npm-publishable package
103+
- Signature: `(scope, pkgName, pkgDescription, keywords, esModule,
104+
templateFile)(project)`
105+
- Tasks: `npmPrepare` (pure sbt), `npmPack` (requires npm on PATH)
106+
- Template mode: set `templateFile` with `VERSION_PLACEHOLDER`
107+
- TypeScript defs auto-discovered from `<module>/types/index.d.ts`
108+
109+
**`With.Publishing.npm(...)`** - npm registry publishing (v1.3.0+)
110+
- Signature: `(registries)(project)` where registries is
111+
`Seq("npmjs")` and/or `Seq("github")`
112+
- Auth via `NPM_TOKEN` / `GITHUB_TOKEN` env vars
113+
114+
**`With.Packaging.homebrew(...)`** - Homebrew formula generation (v1.3.0+)
115+
- Signature: `(formulaName, binaryName, pkgDescription, homepage,
116+
javaVersion, tapRepo, variant)(project)`
117+
- Variants: `"universal"` (JVM with openjdk dep) or `"native"`
118+
- Task: `homebrewGenerate` produces `.rb` file with SHA256
119+
120+
**`With.Packaging.linux(...)`** - Native binary tar.gz archive (v1.3.0+)
121+
- Signature: `(pkgName, pkgDescription, arch, os, includeReadme,
122+
includeLicense)(project)`
123+
- Auto-detects host OS/arch (Scala Native compiles for host only)
124+
- Task: `linuxPackage` produces `<name>-<ver>-<os>-<arch>.tar.gz`
125+
101126
**Other parameterized options:**
102127
- `With.Laminar(...)` - Laminar + DOM dependencies
103128
- `With.MiMa(...)` - Binary compatibility checking
104129
- `With.Packaging.universal(...)` - Universal packaging
130+
- `With.Packaging.dockerDual(...)` - Dev/prod Docker images
131+
- `With.Packaging.windowsMsi(...)` - Placeholder (not yet implemented)
105132
- `With.GithubPublishing` - GitHub Packages publishing
106133

107134
**For all configuration options, examples, and migration notes, refer to
@@ -135,7 +162,7 @@ sbt scalafmt
135162
All Scala projects in ossuminc use this plugin. Add to `project/plugins.sbt`:
136163

137164
```scala
138-
addSbtPlugin("com.ossuminc" % "sbt-ossuminc" % "1.2.5")
165+
addSbtPlugin("com.ossuminc" % "sbt-ossuminc" % "1.3.0")
139166
```
140167

141168
### Example CrossModule Definition

NOTEBOOK.md

Lines changed: 103 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,78 @@
22

33
## Current Status
44

5-
**Version 1.2.5 released.** Fixed CI scripted tests and AKKA_REPO_TOKEN
6-
propagation. All 16 scripted tests now pass in CI.
7-
8-
**Active branch: feature/docker-dual** - Adding dual Docker image support
9-
(dev/prod) for RIDDL services deployment to GKE.
5+
**Version 1.3.0 released** (Feb 2026). Packaging infrastructure complete.
6+
7+
Previous release: v1.2.5 (Jan 2026).
8+
9+
### Resolved Design Questions
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.
15+
16+
2. **Homebrew formula variants**: Support both JVM universal and Native
17+
binary variants via a `variant` parameter (`"universal"` or `"native"`).
18+
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.
23+
24+
### Implementation Phases
25+
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 |
34+
35+
### Session Feb 3, 2026 — v1.3.0 Released
36+
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.
1077

1178
## Work Completed (Recent)
1279

@@ -268,28 +335,32 @@ Run scripted tests on every PR. Skip Akka test in CI (requires credentials).
268335

269336
## Test Coverage Status
270337

271-
### Current Test Results (Jan 29, 2026)
272-
273-
| Test Scenario | Purpose | Status |
274-
|----------------|-------------------------------|---------------------------|
275-
| akka | Akka dependencies | ✅ PASS |
276-
| asciidoc | AsciiDoc document generation | ✅ PASS |
277-
| basic | Basic module configuration | ✅ PASS |
278-
| cross | Cross-platform (JVM/JS/Native)| ✅ PASS |
279-
| everything | Full feature set | ✅ PASS |
280-
| idea-plugin | IntelliJ plugin development | ✅ PASS |
281-
| laminar | Laminar UI dependencies | ✅ PASS |
282-
| mima | Binary compatibility checking | ✅ PASS |
283-
| multi | Multi-module projects | ✅ PASS |
284-
| native | Scala Native compilation | ✅ PASS |
285-
| packaging | Universal packaging | ✅ PASS |
286-
| program | Executable programs | ✅ PASS |
287-
| publishing | Publishing helper (new) | ✅ PASS |
288-
| scalably-typed | TypeScript facades | ✅ PASS |
289-
| scalajs | Scala.js compilation | ✅ PASS |
290-
| scalatest | Scalatest helper (new) | ✅ PASS |
291-
292-
**Pass rate:** 16/16 (100%)
338+
### Current Test Results (Feb 3, 2026)
339+
340+
| Test Scenario | Purpose | Status |
341+
|------------------|--------------------------------|----------|
342+
| akka | Akka dependencies | ✅ PASS |
343+
| asciidoc | AsciiDoc document generation | ✅ PASS |
344+
| basic | Basic module configuration | ✅ PASS |
345+
| cross | Cross-platform (JVM/JS/Native) | ✅ PASS |
346+
| docker-dual | Dev/prod Docker images | ✅ PASS |
347+
| everything | Full feature set | ✅ PASS |
348+
| homebrew | Homebrew formula generation | ✅ PASS |
349+
| idea-plugin | IntelliJ plugin development | ✅ PASS |
350+
| laminar | Laminar UI dependencies | ✅ PASS |
351+
| linux-packaging | Native binary tar.gz archive | ✅ PASS |
352+
| mima | Binary compatibility checking | ✅ PASS |
353+
| multi | Multi-module projects | ✅ PASS |
354+
| native | Scala Native compilation | ✅ PASS |
355+
| npm-packaging | npm package assembly | ✅ PASS |
356+
| packaging | Universal packaging | ✅ PASS |
357+
| program | Executable programs | ✅ PASS |
358+
| publishing | Publishing helper | ✅ PASS |
359+
| scalably-typed | TypeScript facades | ✅ PASS |
360+
| scalajs | Scala.js compilation | ✅ PASS |
361+
| scalatest | Scalatest helper | ✅ PASS |
362+
363+
**Pass rate:** 20/20 (100%)
293364

294365
### Missing Test Coverage
295366

@@ -351,6 +422,11 @@ Create `examples/` with working `build.sbt` files:
351422

352423
| Decision | Rationale | Date |
353424
|----------|-----------|------|
425+
| Delegation pattern for new helpers | Keeps API at `With.Packaging.npm()` not `With.NpmPackaging` | 2026-02-03 |
426+
| `fullOptJS` for npm packaging | Closure Compiler optimization needed; not deprecated | 2026-02-03 |
427+
| `Def.task` for variant selection | sbt `.value` macro resolves all refs in task body | 2026-02-03 |
428+
| Auto-detect OS/arch for linux() | Scala Native compiles for host only; CI matrix for multi-arch | 2026-02-03 |
429+
| No JSON library for package.json | Avoids dependency; string builder sufficient for Scala 2.12 | 2026-02-03 |
354430
| Switch Sonatype → GitHub Packages | Simpler auth for ossuminc org | 2026-01-15 |
355431
| Use symlink approach | Consistent with project/ pattern | 2026-01-15 |
356432
| Rename With.Javascript → With.ScalaJS | Clearer naming | 2026-01-15 |

0 commit comments

Comments
 (0)