How would you route a publish to a release repository for a release version and a snapshot repository for a -SNAPSHOT version using the repository url?
answer
- version.endsWith("SNAPSHOT") ? snapshots : releases
- url computed at configuration time
- one repo computed vs two named repos
- version must be set first
- base url selects server layout
basics
~10 sSet the repository url conditionally on the version: if version ends with -SNAPSHOT use the snapshot URL, otherwise the releases URL. Often two layout paths under one base host.
solid answer
~40 sMany Maven servers expose separate release and snapshot endpoints. Since the publish repository `url` is just a property you assign in the DSL, you can compute it from the project `version`. A common pattern is a ternary on whether the version ends with `-SNAPSHOT`: ```kotlin publishing { repositories { maven { name = "myCompany" val releases = uri("https://repo.example.com/releases") val snapshots = uri("https://repo.example.com/snapshots") url = if (version.toString().endsWith("SNAPSHOT")) snapshots else releases } } } ``` This keeps one named repository (one set of tasks) while directing artifacts to the correct layout based on the build's version. The decision is made at configuration time from `project.version`, so it must already be set when the publishing block evaluates.
code
kotlin · 13 linespublishing {
repositories {
maven {
name = "myCompany"
url = uri(
if (version.toString().endsWith("SNAPSHOT"))
"https://repo.example.com/snapshots"
else
"https://repo.example.com/releases"
)
}
}
}go deeper
Recognise that release vs snapshot can go to different URLs based on the version suffix.
Write the conditional url from project.version.endsWith("SNAPSHOT") and know it's configuration-time.
Weigh one-computed-url vs two-named-repositories and the CI ergonomics of each; handle the unset-version pitfall.
Encode release/snapshot routing once in a shared convention plugin with validation, so no project hand-rolls the ternary inconsistently.
## Why two URLs Maven-style servers (Nexus, Artifactory) conventionally split storage into a *releases* repository (immutable, one version published once) and a *snapshots* repository (mutable, overwritten as development iterates). The `-SNAPSHOT` suffix on a version is the signal that the artifact is a work-in-progress and belongs in the snapshot store. ## Computing the url Because `url` is an ordinary assignable property of the `MavenArtifactRepository`, you can derive it from `project.version`: ```kotlin val isSnapshot = version.toString().endsWith("SNAPSHOT") url = uri(if (isSnapshot) "https://repo.example.com/snapshots" else "https://repo.example.com/releases") ``` This evaluates at **configuration time**, so `version` must be set before the `publishing` block runs (set it at the top of the build script, or in `gradle.properties`). ## One named repository vs two Two valid designs: 1. **One repository, computed url** (above) — a single name, one set of `publishTo<Name>Repository` tasks; the destination flips per build. Simplest for CI: the command is the same for release and snapshot builds. 2. **Two named repositories** — declare both `maven { name = "releases" }` and `maven { name = "snapshots" }`, generating two task sets, and invoke the appropriate one. More explicit but couples the CI command to the version type. ## Layout-based directories The `url` already encodes the directory layout: pointing at `/releases` vs `/snapshots` selects the server-side layout. Gradle's default Maven layout then arranges `group/artifact/version/…` underneath whichever base you chose. You rarely need to touch the repository's `layout` itself; choosing the right base `url` is the lever. ## Gotcha If `version` is still the default `unspecified` when this runs, the ternary silently routes to releases. Always ensure the version is assigned (and ideally validate it) before publishing.
- When is the url ternary evaluated, and why does that matter?At configuration time, when the publishing block runs. So `project.version` must already be set; if it is still `unspecified`, the condition is false and the build wrongly targets the releases URL.
- What is an alternative to computing one url?Declare two separately named repositories (`releases` and `snapshots`); Gradle generates two task sets and CI invokes the appropriate one based on the build type.
saying these in an interview costs you the question
- Assuming the url is recomputed at execution time — it is fixed at configuration time.
- Forgetting to set `version` before the publishing block, silently defaulting all builds to releases.