Skip to content

Commit c687458

Browse files
reidspencerclaude
andcommitted
Add UX improvements: optional deps, Publishing helper, better errors
Major changes since 1.1.0: BREAKING CHANGES: - CrossModule no longer auto-injects dependencies Users must now explicitly add With.Scalatest() and With.ScalaJavaTime() New Features: - With.Publishing helper (defaults to GitHub, .sonatype for Maven Central) - With.ScalaJavaTime() helper for opt-in java.time support - Parameterized versions in ScalaJS and Native helpers - Improved error messages when Root() not configured New Tests: - publishing - tests With.Publishing helper - scalatest - tests With.Scalatest helper All 16 scripted tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 47d6327 commit c687458

16 files changed

Lines changed: 318 additions & 188 deletions

File tree

NOTEBOOK.md

Lines changed: 82 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,27 @@
22

33
## Current Status
44

5-
Version 1.1.0 released and published to GitHub Packages. Comprehensive
6-
maintenance analysis completed (Jan 2026) identifying 15 UX issues with
7-
prioritized action plan. README completely rewritten with design philosophy
8-
and full helper documentation.
5+
Version 1.1.0 released. Significant maintenance work completed Jan 17, 2026
6+
addressing most of the 15 UX issues identified in the maintenance analysis.
7+
All 16 scripted tests now passing (100%). Key changes include:
8+
- CrossModule dependencies now opt-in (breaking change)
9+
- New helpers: `With.Publishing`, `With.ScalaJavaTime()`
10+
- Improved error messages when Root() not configured
11+
- Parameterized dependency versions in ScalaJS/Native helpers
912

1013
## Work Completed (Recent)
1114

15+
### Session Jan 17, 2026
16+
- [x] Refactored AutoPluginHelper to extend `(Project => Project)` for better UX
17+
- [x] Made CrossModule dependencies optional (breaking change)
18+
- [x] Created `With.ScalaJavaTime()` helper for opt-in java.time support
19+
- [x] Created `With.Publishing` helper (defaults to GitHub, `.sonatype` option)
20+
- [x] Improved Root requirement error messages for publishing helpers
21+
- [x] Parameterized dependency versions in ScalaJS and Native helpers
22+
- [x] Added scripted tests: `scalatest`, `publishing` (now 16/16 passing)
23+
- [x] Verified Akka and IntelliJ plugin tests pass (were already working)
24+
25+
### Previous Sessions
1226
- [x] Fixed ScalaJS helper to handle missing git commit/scmInfo gracefully
1327
- [x] Added deprecated `With.Javascript` alias for backward compatibility
1428
- [x] Updated all scripted tests to pass (14/14)
@@ -24,6 +38,7 @@ and full helper documentation.
2438
- [x] Comprehensive README rewrite with philosophy section
2539
- [x] Documented all parameterized helpers in README
2640
- [x] Fixed scalably-typed test (updated to scala-3.3.7)
41+
- [x] Removed hardcoded RIDDL values from Scala3.scala
2742

2843
## Resolved Issues
2944

@@ -47,145 +62,27 @@ Plus credentials in `~/.sbt/1.0/github.sbt`.
4762

4863
## Next Steps (Priority Order)
4964

50-
### 🔴 CRITICAL
65+
### ✅ COMPLETED (Jan 17, 2026)
5166

52-
#### 1. Remove hardcoded RIDDL values from Scala3.scala
53-
**File:** `src/main/scala/com/ossuminc/sbt/helpers/Scala3.scala`
67+
- ~~Remove hardcoded RIDDL values from Scala3.scala~~
68+
- ~~Refactor AutoPluginHelper to extend (Project => Project)~~
69+
- ~~Fix Akka test (already working)~~
70+
- ~~Fix IntelliJ plugin test (already working)~~
71+
- ~~Make CrossModule dependencies optional~~
72+
- ~~Add generic With.Publishing() helper~~
73+
- ~~Improve Root requirement error messages~~
74+
- ~~Parameterize dependency versions~~
75+
- ~~Add initial scripted tests for coverage~~
5476

55-
The following lines contain RIDDL-specific values that break reusability:
56-
- Line 22: `-project:RIDDL`
57-
- Line 25: `-siteroot:doc/src/hugo/static/apidoc`
58-
- Line 27: `-doc-canonical-base-url:https://riddl.tech/apidoc`
59-
- Line 47: `apiURL := Some(url("https://riddl.tech/apidoc/"))`
77+
### 🟡 REMAINING WORK
6078

61-
**Fix:** Make documentation options parameterizable:
62-
```scala
63-
def configure(
64-
version: Option[String] = None,
65-
scala3Options: Seq[String] = Seq.empty,
66-
projectName: Option[String] = None,
67-
docSiteRoot: Option[String] = None,
68-
docBaseURL: Option[String] = None
69-
)(project: Project): Project
70-
```
71-
72-
### ⚠️ HIGH PRIORITY
73-
74-
#### 2. Standardize naming conventions
75-
Migrate lowercase helpers to PascalCase objects with `apply()` methods:
76-
- `With.build_info``With.BuildInfo()`
77-
- `With.dynver``With.DynVer()`
78-
- `With.git``With.Git()`
79-
- `With.header``With.Header()`
80-
- `With.java``With.Java()`
81-
82-
Keep old names as deprecated aliases for one version.
83-
84-
### 🟡 MEDIUM PRIORITY
85-
86-
#### 3. Fix Akka test (license key required)
87-
**Root cause:** As of October 2024, Akka requires a license key and
88-
repository token.
89-
90-
**Fix:** Update `Akka.scala` to accept optional repository token:
91-
```scala
92-
def forRelease(
93-
release: String = "",
94-
repositoryToken: Option[String] = None
95-
)(project: Project): Project = {
96-
val akkaRepo = repositoryToken match {
97-
case Some(token) => s"https://repo.akka.io/$token/maven"
98-
case None => sys.env.get("AKKA_REPO_TOKEN") match {
99-
case Some(token) => s"https://repo.akka.io/$token/maven"
100-
case None => "https://repo.akka.io/maven" // Fallback
101-
}
102-
}
103-
// ...
104-
}
105-
```
106-
107-
**Resources:**
108-
- Get free token: https://akka.io/key
109-
- Akka License Docs: https://doc.akka.io/reference/release-notes/
110-
111-
#### 4. Fix IntelliJ plugin test (sbt-idea-plugin 5.x)
112-
**Root cause:** Upgraded from `org.jetbrains % sbt-idea-plugin % 4.1.2` to
113-
`org.jetbrains.scala % sbt-idea-plugin % 5.0.4` - major version with
114-
breaking changes.
115-
116-
**Investigation steps:**
117-
1. Run verbose test:
118-
`sbt "scripted sbt-ossuminc/idea-plugin" -Dsbt.scripted.log=true`
119-
2. Check sbt-idea-plugin 5.0 changelog on GitHub
120-
3. Verify if `packageArtifactZip` task name changed
121-
4. Update `IdeaPlugin.scala` helper if needed
122-
123-
#### 5. Make CrossModule dependencies optional
124-
**File:** `CrossModule.scala` (lines 59-64)
125-
126-
Currently auto-adds to ALL cross-platform projects:
127-
- `scala-java-time % 2.6.0`
128-
- `scalatest % 3.2.19` (test)
129-
130-
**Fix:** Remove automatic injection, make opt-in:
131-
```scala
132-
CrossModule("foo", "bar")(JVM, JS)
133-
.configure(With.Scalatest()) // Opt-in for testing
134-
.configure(With.ScalaJavaTime()) // Opt-in for java.time
135-
```
136-
137-
**Breaking change:** Users must explicitly add dependencies.
138-
139-
#### 6. Add generic `With.Publishing()` helper
140-
**New file:** `helpers/Publishing.scala`
141-
142-
```scala
143-
object Publishing extends AutoPluginHelper {
144-
def configure(project: Project): Project = {
145-
val preferGitHub = RootProjectInfo.Keys
146-
.preferGitHubPublishing.?.value.getOrElse(true)
147-
if (preferGitHub) GithubPublishing.configure(project)
148-
else SonatypePublishing.configure(project)
149-
}
150-
}
151-
```
152-
153-
#### 7. Improve Root requirement error messages
154-
**Files:** `GithubPublishing.scala`, `SonatypePublishing.scala`
155-
156-
Add validation:
157-
```scala
158-
def configure(project: Project): Project = {
159-
if (RootProjectInfo.Keys.gitHubOrganization.?.value.isEmpty) {
160-
sys.error(
161-
"You must define a Root(...) project before using GithubPublishing"
162-
)
163-
}
164-
// ... rest of implementation
165-
}
166-
```
167-
168-
#### 8. Parameterize dependency versions
169-
**Files:** `Javascript.scala`, `Native.scala`, `CrossModule.scala`
170-
171-
Allow overriding hardcoded versions:
172-
```scala
173-
def apply(
174-
// ... existing params ...
175-
scalaJavaTimeVersion: String = "2.6.0",
176-
scalatestVersion: String = "3.2.19"
177-
)(project: Project): Project
178-
```
179-
180-
### 🟢 LOW PRIORITY
181-
182-
#### 9. Remove or implement NodeTarget
79+
#### 1. Remove or implement NodeTarget
18380
**File:** `CrossModule.scala` (lines 21, 76-80)
18481

18582
Dead code - `NodePlatform.enable` does nothing. Either remove entirely or
18683
implement properly.
18784

188-
#### 10. Expose Miscellaneous helpers in With object
85+
#### 2. Expose Miscellaneous helpers in With object
18986
**File:** `OssumIncPlugin.scala`
19087

19188
Add to `With` object:
@@ -195,11 +92,11 @@ val UnmanagedJars = Miscellaneous.useUnmanagedJarLibs _
19592
val ShellPrompt = Miscellaneous.buildShellPrompt
19693
```
19794

198-
#### 11. Clarify composite helpers
95+
#### 3. Clarify composite helpers
19996
Document what `basic`, `typical`, `everything` include. Consider if
20097
`typical` should include publishing by default.
20198

202-
#### 12. Make Root project ID configurable
99+
#### 4. Make Root project ID configurable
203100
**File:** `Root.scala` (line 38)
204101

205102
Currently hardcoded to `"root"`. Add parameter:
@@ -211,39 +108,44 @@ def apply(
211108
): Project
212109
```
213110

214-
#### 13. Remove placeholder Packaging methods
111+
#### 5. Remove placeholder Packaging methods
215112
**File:** `Packaging.scala`
216113

217114
`jdkPackager()`, `linuxDebian()`, `linuxRPM()` do nothing. Either implement
218115
or remove.
219116

220-
#### 14. Remove `project/SonatypePublishing.scala`
117+
#### 6. Remove `project/SonatypePublishing.scala`
221118
No longer used after switching to GitHub Packages.
222119

223-
#### 15. Add CI/CD workflow for GitHub Actions
120+
#### 7. Add CI/CD workflow for GitHub Actions
224121
Run scripted tests on every PR. Skip Akka test in CI (requires credentials).
225122

226123
---
227124

228125
## Test Coverage Status
229126

230-
### Current Test Results (Jan 2026)
127+
### Current Test Results (Jan 17, 2026)
231128

232129
| Test Scenario | Purpose | Status |
233130
|----------------|-------------------------------|---------------------------|
131+
| akka | Akka dependencies | ✅ PASS |
132+
| asciidoc | AsciiDoc document generation | ✅ PASS |
234133
| basic | Basic module configuration | ✅ PASS |
235-
| multi | Multi-module projects | ✅ PASS |
236134
| cross | Cross-platform (JVM/JS/Native)| ✅ PASS |
135+
| everything | Full feature set | ✅ PASS |
136+
| idea-plugin | IntelliJ plugin development | ✅ PASS |
137+
| laminar | Laminar UI dependencies | ✅ PASS |
138+
| mima | Binary compatibility checking | ✅ PASS |
139+
| multi | Multi-module projects | ✅ PASS |
237140
| native | Scala Native compilation | ✅ PASS |
238-
| scalajs | Scala.js compilation | ✅ PASS |
239141
| packaging | Universal packaging | ✅ PASS |
240142
| program | Executable programs | ✅ PASS |
241-
| everything | Full feature set | ✅ PASS |
242-
| scalably-typed | TypeScript facades | ✅ PASS (fixed) |
243-
| akka | Akka dependencies | ⚠️ FAIL (needs license) |
244-
| idea-plugin | IntelliJ plugin development | ⚠️ FAIL (5.x API change) |
143+
| publishing | Publishing helper (new) | ✅ PASS |
144+
| scalably-typed | TypeScript facades | ✅ PASS |
145+
| scalajs | Scala.js compilation | ✅ PASS |
146+
| scalatest | Scalatest helper (new) | ✅ PASS |
245147

246-
**Pass rate:** 9/11 (82%)
148+
**Pass rate:** 16/16 (100%)
247149

248150
### Missing Test Coverage
249151

@@ -331,6 +233,38 @@ Current symlinks in `project/`:
331233

332234
## Migration Notes (for Breaking Changes)
333235

236+
### v1.2.0 Migration (from 1.1.0)
237+
238+
**CrossModule dependency changes (BREAKING):**
239+
```scala
240+
// Old (1.1.0 - automatic dependencies)
241+
CrossModule("foo", "bar")(JVM, JS)
242+
243+
// New (1.2.0 - explicit dependencies)
244+
CrossModule("foo", "bar")(JVM, JS)
245+
.configure(With.Scalatest()) // If you want testing
246+
.configure(With.ScalaJavaTime()) // If you need java.time
247+
```
248+
249+
**New helpers available:**
250+
- `With.Publishing` - Generic publishing (defaults to GitHub)
251+
- `With.Publishing.github` - Explicit GitHub Packages
252+
- `With.Publishing.sonatype` - Explicit Sonatype/Maven Central
253+
- `With.ScalaJavaTime()` - Add scala-java-time dependency
254+
255+
**Parameterized versions now supported:**
256+
```scala
257+
// ScalaJS and Native helpers now accept version parameters
258+
With.ScalaJS(
259+
scalaJavaTimeVersion = "2.6.0", // Override default
260+
scalatestVersion = "3.2.19" // Override default
261+
)
262+
263+
With.Native(
264+
scalatestVersion = "3.2.19" // Override default
265+
)
266+
```
267+
334268
### Future v2.0.0 Migration
335269

336270
**Naming convention changes (deprecated in 1.x, removed in 2.x):**
@@ -344,17 +278,6 @@ Current symlinks in `project/`:
344278
.configure(With.GitHubPublishing)
345279
```
346280

347-
**CrossModule dependency changes:**
348-
```scala
349-
// Old (automatic)
350-
CrossModule("foo", "bar")(JVM, JS)
351-
352-
// New (explicit)
353-
CrossModule("foo", "bar")(JVM, JS)
354-
.configure(With.Scalatest()) // If you want testing
355-
.configure(With.ScalaJavaTime()) // If you need java.time
356-
```
357-
358281
---
359282

360283
## References

src/main/scala/com/ossuminc/sbt/CrossModule.scala

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import scalajscrossproject.ScalaJSCrossPlugin.autoImport.*
88
import scalanativecrossproject.ScalaNativeCrossPlugin.autoImport.*
99

1010
import scala.scalanative.sbtplugin.ScalaNativePlugin
11-
import org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport.*
1211

1312
/** A CrossModule is a module that can be built for JVM, ScalaJS or Native execution. Use it like:
1413
* {{{val my_project = CrossModule("dir_name", "module_name")(ScalaJS + JVM +
@@ -53,18 +52,10 @@ object CrossModule {
5352
cp2
5453
} else
5554
cp2
55+
// Enable ScalaJS plugin for JS targets (dependencies are opt-in via helpers)
5656
val cp4 =
5757
if (targets.contains(CrossModule.JSTarget)) {
58-
cp3
59-
.jsEnablePlugins(ScalaJSPlugin)
60-
.jsSettings(
61-
libraryDependencies ++= Seq(
62-
"io.github.cquiroz" %%% "scala-java-time" % "2.6.0",
63-
"org.scalactic" %%% "scalactic" % "3.2.19" % "test",
64-
"org.scalatest" %%% "scalatest" % "3.2.19" % "test",
65-
"org.scalatest" %%% "scalatest-funspec" % "3.2.19" % "test"
66-
)
67-
)
58+
cp3.jsEnablePlugins(ScalaJSPlugin)
6859
} else cp3
6960
if (targets.contains(CrossModule.NativeTarget)) {
7061
val cp = cp4.nativeEnablePlugins(ScalaNativePlugin)

src/main/scala/com/ossuminc/sbt/OssumIncPlugin.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ object OssumIncPlugin extends AutoPlugin {
7575
/** Configure sbt-native-packager */
7676
def Packaging: helpers.Packaging.type = helpers.Packaging
7777

78+
/** Configure artifact publishing (defaults to GitHub Packages)
79+
*
80+
* Use `With.Publishing` for default (GitHub), or explicitly:
81+
* - `With.Publishing.github` for GitHub Packages
82+
* - `With.Publishing.sonatype` for Sonatype/Maven Central
83+
*/
84+
def Publishing: helpers.Publishing.type = helpers.Publishing
85+
7886
/** Configure the release process */
7987
def Release: helpers.Release.type = helpers.Release
8088

@@ -102,6 +110,9 @@ object OssumIncPlugin extends AutoPlugin {
102110
/** Configure Scala.js compilation */
103111
def ScalaJS: helpers.ScalaJS.type = helpers.ScalaJS
104112

113+
/** Add scala-java-time dependency for cross-platform java.time API */
114+
def ScalaJavaTime: helpers.ScalaJavaTime.type = helpers.ScalaJavaTime
115+
105116
/** Add ScalaTest libraries to the libraryDependencies */
106117
def Scalatest: helpers.Scalatest.type = helpers.Scalatest
107118

@@ -213,4 +224,15 @@ object OssumIncPlugin extends AutoPlugin {
213224
}
214225

215226
override def projectSettings: Seq[Setting[_]] = Nil
227+
228+
override def buildSettings: Seq[Setting[_]] = Seq(
229+
// Provide default (sentinel) values for RootProjectInfo keys
230+
// These will be overridden when Root() is called
231+
helpers.RootProjectInfo.Keys.gitHubOrganization :=
232+
helpers.RootProjectInfo.NOT_CONFIGURED,
233+
helpers.RootProjectInfo.Keys.gitHubRepository :=
234+
helpers.RootProjectInfo.NOT_CONFIGURED,
235+
helpers.RootProjectInfo.Keys.copyrightHolder :=
236+
helpers.RootProjectInfo.NOT_CONFIGURED
237+
)
216238
}

0 commit comments

Comments
 (0)