[Go to site: main page, start]

Workflows

Workflows

Overview

A workflow is an ordered list of processes that Latte runs to resolve dependencies or publish artifacts. When Latte needs to fetch an artifact, it tries each process in order and uses the first one that produces a result. When Latte publishes an artifact, it runs every process in order so the artifact ends up in every configured location.

Every project file defines two workflows:

  • workflow { ... } — the fetch-time workflow. Runs whenever Latte needs to download a dependency.
  • publishWorkflow { ... } — the publish-time workflow. Runs whenever Latte publishes a built artifact (for example, during a release).

The two blocks appear at the top level of the project(...) { } definition:

project(group: "com.example", name: "my-app", version: "1.0.0", licenses: ["MIT"]) {
  workflow {
    standard()
  }
  publishWorkflow {
    latte()
  }

  dependencies { /* ... */ }
}

Ordering matters. Workflows must be declared before dependencies { } in the project file — Latte parses the project(...) block linearly and needs the workflows in place before it can resolve dependency artifacts.

For concrete repository setup examples (public, private, Maven Central, S3), see Repositories. This page documents the DSL itself.

Fetch vs. publish semantics

WorkflowTriggerBehavior
workflowResolving or downloading a dependencyTries processes in order, stops at the first success.
publishWorkflowPublishing a built artifactRuns every process in order; artifact lands in all configured locations.

The workflow block

Inside workflow { } you can use any of the following methods:

MethodPurpose
standard()Shorthand for a sensible default fetch + publish setup.
fetch { ... }Explicitly declare the ordered list of fetch processes.
publish { ... }Explicitly declare the ordered list of publish processes (for the implicit publish side of workflow).
semanticVersions { ... }Provide version mappings for artifacts whose Maven versions aren’t SemVer-compliant.

standard()

Expands to the following defaults:

fetch {
  cache()
  url(url: "https://repository.lattejava.org")
  maven(url: "https://repo1.maven.org/maven2")
}
publish {
  cache()
}

Use standard() when you want the default behavior (check the local cache, then the Latte public repository, then Maven Central) and you don’t need custom repositories.

standard() only populates the implicit publish side of workflow. It does not add anything to publishWorkflow { }.

fetch { ... } and publish { ... }

Use these when you need to customize the list of fetch or publish processes. Both accept the same set of process methods.

workflow {
  fetch {
    cache()
    url(url: "https://repository.lattejava.org")
    maven(url: "https://repo1.maven.org/maven2")
  }
  publish {
    cache()
  }
}

You can combine standard() with custom fetch { } or publish { } blocks — the processes from each are appended in the order they appear.

semanticVersions { ... }

Maven does not enforce SemVer, but Latte does. When a transitive dependency has a non-SemVer version (for example, 1.0.0.Final), declare a mapping so Latte can resolve it:

workflow {
  standard()
  semanticVersions {
    mapping(id: "org.badver:badver:1.0.0.Final", version: "1.0.0")
  }
}

See Repositories — SemVer for the broader context on why Latte is strict about versions.

The publishWorkflow block

publishWorkflow { } takes processes directly — it does not have an inner fetch { } or publish { }. Every process you declare runs, in order, every time Latte publishes an artifact.

publishWorkflow {
  cache()
  s3(endpoint: "https://account-id.r2.cloudflarestorage.com", bucket: "my-repo",
     accessKeyId: global.repoAccessKey, secretAccessKey: global.repoSecretKey)
}

In this example, publishing an artifact writes it into the local cache first, then uploads it to the S3 bucket.

If your project never publishes artifacts, you can omit publishWorkflow { } entirely or leave it empty.

Processes

The following processes are available inside fetch { }, publish { }, and publishWorkflow { }. They are listed alphabetically.

cache

Adds a cache process that reads from (during fetch) or writes to (during publish) the Latte local cache and the local Maven cache (~/.m2/repository by default).

cache()
cache(dir: "/custom/latte/cache", mavenDir: "/custom/maven/cache", integrationDir: "/custom/integration/cache")
AttributeRequiredDefaultDescription
dirNoLatte’s cache directoryOverride the Latte cache directory.
mavenDirNo~/.m2/repositoryOverride the Maven cache directory.
integrationDirNoLatte’s cache directoryOverride the integration-build cache directory.

mavenCache

A variant of cache that reads only from the Maven cache (~/.m2/repository), not the Latte cache. Useful when you want to interoperate with artifacts produced by Maven locally but do not want them to leak into the Latte side of your workflow.

mavenCache()
mavenCache(dir: "/custom/maven/cache")
AttributeRequiredDefaultDescription
dirNo~/.m2/repositoryOverride the Maven cache directory.
integrationDirNoLatte’s cache directoryOverride the integration-build cache directory.

url

Adds an HTTP-based repository process. Supports HTTP Basic authentication.

url(url: "https://repository.lattejava.org")
url(url: "https://my-repo.internal.example.com", username: global.repoUsername, password: global.repoPassword)
AttributeRequiredDefaultDescription
urlYesBase URL of the HTTP repository.
usernameNoHTTP Basic username.
passwordNoHTTP Basic password.

maven

Adds a Maven-style HTTP repository process. When Latte fetches through this process, it reads the Maven POM and translates dependencies into the Latte dependency model. See Repositories — Maven Central for the translation rules.

maven()
maven(url: "https://repo1.maven.org/maven2")
maven(url: "https://maven.example.com/releases", username: "user", password: "pass")
AttributeRequiredDefaultDescription
urlNohttps://repo1.maven.org/maven2Base URL of the Maven repository.
usernameNoHTTP Basic username.
passwordNoHTTP Basic password.

s3

Adds an S3-compatible object storage process. Works with AWS S3, Cloudflare R2, MinIO, Backblaze B2, DigitalOcean Spaces, and any other S3-compatible service. See Repositories — S3-compatible providers for a catalogue.

s3(endpoint: "https://account-id.r2.cloudflarestorage.com", bucket: "my-repo",
   accessKeyId: global.repoAccessKey, secretAccessKey: global.repoSecretKey)
AttributeRequiredDefaultDescription
endpointYesS3-compatible endpoint URL.
bucketYesBucket name.
accessKeyIdYesAccess key.
secretAccessKeyYesSecret key.
regionNoautoRegion. Use auto for Cloudflare R2; use the actual region for AWS S3.

latte

Adds the Latte publish process, which publishes artifacts to the Latte public repository through its authenticated publish API. Instead of holding storage credentials, it uses the OAuth tokens stored by latte login to request a short-lived presigned upload URL for each artifact. This is the default publish process for projects created with latte init. See Publishing for the full workflow and the prerequisite login step.

publishWorkflow {
  latte()
}
AttributeRequiredDefaultDescription
apiURLNohttps://api.lattejava.orgBase URL of the publish API. Override only for local testing.

latte is publish-only — it does not fetch artifacts, so it belongs in publishWorkflow { } (or a publish { } block) only. It is not part of standard(); add it explicitly. Fetching from the public repository is handled by the url or s3 processes.

Common patterns

Default open-source project

workflow {
  standard()
}
publishWorkflow {
  latte()
}

Public repository plus a private S3 bucket

workflow {
  fetch {
    cache()
    url(url: "https://repository.lattejava.org")
    maven(url: "https://repo1.maven.org/maven2")
    s3(endpoint: "https://account-id.r2.cloudflarestorage.com", bucket: "my-repo",
       accessKeyId: global.repoAccessKey, secretAccessKey: global.repoSecretKey)
  }
  publish {
    cache()
  }
}
publishWorkflow {
  s3(endpoint: "https://account-id.r2.cloudflarestorage.com", bucket: "my-repo",
     accessKeyId: global.repoAccessKey, secretAccessKey: global.repoSecretKey)
}

Non-SemVer Maven dependencies

workflow {
  standard()
  semanticVersions {
    mapping(id: "org.badver:badver:1.0.0.Final", version: "1.0.0")
  }
}