Skip to content

Commit c4fde03

Browse files
Merge branch 'master' into build-template
2 parents 115dd65 + cb7bb55 commit c4fde03

37 files changed

+758
-95
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.28.0
1+
1.30.0

build.gradle

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ dependencies {
3232
compileOnly 'io.micronaut:micronaut-inject-groovy'
3333
compileOnly 'io.micronaut:micronaut-http-validation'
3434
implementation 'jakarta.persistence:jakarta.persistence-api:3.0.0'
35-
implementation 'io.seqera:lib-cache-tiered-redis:1.0.0'
35+
implementation 'io.seqera:lib-cache-tiered-redis:1.1.0'
3636
implementation 'io.seqera:lib-lang:1.1.0'
37-
implementation 'io.seqera:lib-serde:1.1.0'
38-
implementation 'io.seqera:lib-serde-moshi:1.0.0'
39-
implementation 'io.seqera:lib-mail:1.3.0'
37+
implementation 'io.seqera:lib-serde:1.2.0'
38+
implementation 'io.seqera:lib-serde-moshi:1.1.0'
39+
implementation 'io.seqera:lib-mail:1.3.1'
4040
implementation 'io.seqera:lib-pool:1.0.0'
4141
implementation 'io.seqera:lib-retry:2.0.0'
4242
implementation 'io.seqera:lib-random:1.0.0'
@@ -101,7 +101,7 @@ dependencies {
101101
testImplementation 'org.testcontainers:testcontainers'
102102
testImplementation 'org.testcontainers:postgresql'
103103
testRuntimeOnly 'com.h2database:h2'
104-
testImplementation testFixtures('io.seqera:lib-fixtures-redis:1.0.0')
104+
testImplementation testFixtures('io.seqera:lib-fixtures-redis:1.1.0')
105105

106106
// rate limit
107107
implementation 'com.coveo:spillway:3.0.0'

changelog.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11
# Wave changelog
2+
1.30.0 - 27 Nov 2025
3+
- Add labels in ConfigSpec (#934) [67ac6c3dc]
4+
- Use Seqera-hosted buildkit image (#938) [c0c0b6465]
5+
- Add configurable singularity init container image (#937) [5c0fd3fce]
6+
- Fix YAML indentation in configure-wave.md (#936) [c09eba7ca]
7+
- Fix scan and mirror enabled flag bug (#935) [dc23d7bbe]
8+
- docs: Fix typos in Wave Kubernetes install (#930) [d3478f336]
9+
10+
1.29.1 - 19 Nov 2025
11+
- Fix scan requirement on createScanStorageOpts [33463ebd2]
12+
- Add node selectors in scan, mirror and transfer jobs (#905) [47a7c5ac4]
13+
14+
1.29.0 - 13 Nov 2024
15+
- Add S3 cache support for BuildKit (#927) [8dac665a0]
16+
- Update buildkit to 0.25.2 (#928) [68a6a2e4a]
17+
- Add docs for CRAN package support (#925) [482fc1d3c]
18+
- Fix product name capitalization in documentation (#883) [f03025535]
19+
- Update local dev config [059b2e4e]
20+
221
1.28.0 - 4 Nov 2024
322
- Add CRAN package support for Wave container builds (#874) [81b4e6681]
423

docs/configuration.md

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,26 @@ Configure the HTTP client with the following options:
110110
Configure how Wave builds container images and manages associated logs for monitoring, troubleshooting, and delivery with the following options:
111111

112112
`wave.build.buildkit-image` *(required)*
113-
: Sets the [Buildkit](https://github.com/moby/buildkit) container image used in the Wave build process (default: `moby/buildkit:v0.13.2-rootless`).
114-
115-
`wave.build.cache` *(required)*
116-
: Sets the container repository used to cache layers of images built by Wave.
113+
: Sets the [Buildkit](https://github.com/moby/buildkit) container image used in the Wave build process (default: `moby/buildkit:v0.25.2-rootless`).
114+
115+
`wave.build.cache` *(optional)*
116+
: Sets the cache repository for images built by Wave. Supports both container registry paths and S3 bucket paths.
117+
Examples:
118+
- Container registry: `registry.example.com/wave/cache`
119+
- S3 bucket: `s3://my-bucket/wave/cache`
120+
121+
`wave.build.cache-bucket-region` *(optional)*
122+
: Specifies the AWS region for the S3 cache bucket when using an S3 path in `wave.build.cache`.
123+
If not specified, Wave uses the `AWS_REGION` or `AWS_DEFAULT_REGION` environment variable.
124+
Example: `us-east-1`
125+
This setting is only used when `wave.build.cache` is configured with an S3 bucket path.
126+
127+
`wave.build.cache-bucket-upload-parallelism` *(optional)*
128+
: Controls the number of layers uploaded to S3 in parallel during cache export.
129+
Each individual layer is uploaded with 5 threads using the AWS SDK Upload Manager.
130+
If not specified, BuildKit uses its default parallelism behavior.
131+
Example: `8`
132+
This setting is only used when `wave.build.cache` is configured with an S3 bucket path.
117133

118134
`wave.build.cleanup` *(optional)*
119135
: Sets the cleanup strategy after the build process.
@@ -160,6 +176,91 @@ Configure how Wave builds container images and manages associated logs for monit
160176
: Sets the path to the directory used by Wave to store artifacts such as Containerfiles, Trivy cache for scan, Buildkit context, and authentication configuration files.
161177
For example, `/efs/wave/build`.
162178

179+
### S3 cache authentication
180+
181+
When using S3 as the BuildKit cache backend (by configuring `wave.build.cache` with an S3 bucket path), Wave relies on AWS native authentication mechanisms rather than static credentials in configuration files.
182+
183+
#### Kubernetes deployments
184+
185+
S3 cache uses **IAM Roles for Service Accounts (IRSA)** for secure, credential-free authentication.
186+
187+
Configure your Kubernetes ServiceAccount with an IAM role annotation:
188+
189+
```yaml
190+
apiVersion: v1
191+
kind: ServiceAccount
192+
metadata:
193+
name: wave-build-sa
194+
namespace: wave-build
195+
annotations:
196+
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/WaveBuildRole
197+
```
198+
199+
The IAM role must have permissions to access the S3 cache bucket:
200+
201+
```json
202+
{
203+
"Version": "2012-10-17",
204+
"Statement": [
205+
{
206+
"Effect": "Allow",
207+
"Action": [
208+
"s3:PutObject",
209+
"s3:GetObject",
210+
"s3:DeleteObject",
211+
"s3:ListBucket",
212+
"s3:AbortMultipartUpload",
213+
"s3:ListMultipartUploadParts",
214+
"s3:ListBucketMultipartUploads"
215+
],
216+
"Resource": [
217+
"arn:aws:s3:::my-bucket/wave/cache",
218+
"arn:aws:s3:::my-bucket/wave/cache/*"
219+
]
220+
}
221+
]
222+
}
223+
```
224+
225+
Update your Wave deployment to use the annotated ServiceAccount:
226+
227+
```yaml
228+
spec:
229+
template:
230+
spec:
231+
serviceAccountName: wave-build-sa
232+
```
233+
234+
#### Docker deployments
235+
236+
For Docker-based builds, use **EC2 Instance Profile** for automatic credential management.
237+
238+
Attach an IAM role to the EC2 instance running Docker with the S3 permissions shown above. BuildKit automatically uses the instance metadata service to obtain temporary credentials.
239+
240+
No additional configuration is required. The AWS SDK in BuildKit automatically discovers and uses the instance profile credentials.
241+
242+
:::note
243+
For development and testing purposes only, you can provide AWS credentials via environment variables:
244+
245+
```bash
246+
export AWS_ACCESS_KEY_ID=your_access_key
247+
export AWS_SECRET_ACCESS_KEY=your_secret_key
248+
export AWS_REGION=us-east-1
249+
```
250+
251+
**Warning:** This approach is not recommended for production environments as it requires managing static credentials. Always use EC2 Instance Profile for production Docker deployments.
252+
:::
253+
254+
#### Configuration example
255+
256+
```yaml
257+
wave:
258+
build:
259+
cache: "s3://wave-cache-bucket/buildkit"
260+
cache-bucket-region: "us-east-1" # Optional if AWS_REGION is set
261+
cache-bucket-upload-parallelism: 8 # Optional, controls parallel S3 uploads
262+
```
263+
163264
### Build process logs
164265

165266
Configure how Wave stores and delivers build logs from containers and Kubernetes pods, which can be retrieved later or included in build completion emails, with the following options:

docs/configure-wave.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,18 @@ MICRONAUT_ENVIRONMENTS: "postgres,redis,lite,mail"
2929
3030
```yaml
3131
mail:
32-
33-
smtp:
34-
host: "smtp.your-provider.com"
35-
port: "587"
36-
user: "your-smtp-username"
37-
password: "your-smtp-password"
38-
auth: true
39-
starttls:
40-
enable: true
41-
required: true
42-
ssl:
43-
protocols: "TLSv1.2"
32+
33+
smtp:
34+
host: "smtp.your-provider.com"
35+
port: "587"
36+
user: "your-smtp-username"
37+
password: "your-smtp-password"
38+
auth: true
39+
starttls:
40+
enable: true
41+
required: true
42+
ssl:
43+
protocols: "TLSv1.2"
4444
```
4545
4646
#### Configuration Options
@@ -82,7 +82,7 @@ MICRONAUT_ENVIRONMENTS: "postgres,redis,lite,mail,aws-ses"
8282

8383
```yaml
8484
mail:
85-
85+
8686
```
8787

8888
#### IAM permissions
@@ -135,7 +135,8 @@ Wave can perform security scanning on container builds. This feature requires th
135135
wave:
136136
build:
137137
enabled: true
138-
scan: true
138+
scan:
139+
enabled: true
139140
```
140141

141142
## ECR cache repository
@@ -154,11 +155,11 @@ Configure ECR cache repository in your Wave configuration:
154155

155156
```yaml
156157
wave:
157-
build:
158-
enabled: true
159-
cache:
160-
enabled: true
161-
repository: "123456789012.dkr.ecr.us-east-1.amazonaws.com/wave-cache"
158+
build:
159+
enabled: true
160+
cache:
161+
enabled: true
162+
repository: "123456789012.dkr.ecr.us-east-1.amazonaws.com/wave-cache"
162163
```
163164

164165
#### IAM permissions

docs/install/kubernetes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ data:
140140
# Platform integration (optional)
141141
tower:
142142
endpoint:
143-
url: "https://your-platform-server.com"
143+
url: "https://your-platform-server.com/api"
144144
145145
# Micronaut framework configuration
146146
micronaut:

docs/wave-lite.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Wave Lite enables the use of [Fusion file system](https://docs.seqera.io/fusion)
1010
## Installation
1111

1212
- [Docker Compose](./install/docker-compose.md)
13-
- [Kubernetes](./install/docker-compose.md)
13+
- [Kubernetes](./install/kubernetes.md)
1414

1515
:::info
1616
Docker Compose installations only support Wave in Lite mode. Wave's full build capabilities require specific integrations with Kubernetes and AWS EFS Storage, making EKS and AWS a hard dependency for fully-featured deployments. After you have successfully deployed Wave Lite in Kubernetes, see [Configure Wave Build](./install/configure-wave-build.md) to extend your installation to support build capabilities.

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
#
1818

1919
micronautVersion=4.9.4
20-
micronautEnvs=dev,mail,aws-ses
20+
micronautEnvs=local,mail,aws-ses

src/main/groovy/io/seqera/wave/auth/RegistryLookupCache.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import groovy.transform.CompileStatic
2626
import groovy.util.logging.Slf4j
2727
import io.micronaut.context.annotation.Value
2828
import io.micronaut.core.annotation.Nullable
29+
import io.seqera.serde.Encodable
2930
import io.seqera.serde.moshi.MoshiEncodeStrategy
30-
import io.seqera.serde.moshi.MoshiSerializable
3131
import io.seqera.cache.tiered.AbstractTieredCache
3232
import io.seqera.cache.tiered.L2TieredCache
3333
import jakarta.inject.Singleton
@@ -75,7 +75,7 @@ class RegistryLookupCache extends AbstractTieredCache<String, RegistryAuth> {
7575
}
7676

7777
static JsonAdapter.Factory factory() {
78-
PolymorphicJsonAdapterFactory.of(MoshiSerializable.class, "@type")
78+
PolymorphicJsonAdapterFactory.of(Encodable.class, "@type")
7979
.withSubtype(AbstractTieredCache.Entry.class, AbstractTieredCache.Entry.name)
8080
.withSubtype(RegistryAuth.class, RegistryAuth.name)
8181
}

src/main/groovy/io/seqera/wave/configuration/BuildConfig.groovy

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,33 @@ class BuildConfig {
4646
@Value('${wave.build.singularity-image}')
4747
String singularityImage
4848

49+
@Value('${wave.build.singularity-image-init:`public.cr.seqera.io/wave/busybox:latest`}')
50+
String singularityImageInit
51+
4952
@Value('${wave.build.repo}')
5053
String defaultBuildRepository
5154

55+
@Nullable
5256
@Value('${wave.build.cache}')
5357
String defaultCacheRepository
5458

59+
/**
60+
* AWS region for the S3 cache bucket specified in {@link #defaultCacheRepository}.
61+
* Only used when {@link #defaultCacheRepository} is an S3 bucket path.
62+
*/
63+
@Nullable
64+
@Value('${wave.build.cache-bucket-region}')
65+
String cacheBucketRegion
66+
67+
/**
68+
* Number of layers to upload to S3 in parallel during cache export.
69+
* Each individual layer is uploaded with 5 threads using the AWS SDK Upload Manager.
70+
* Only used when {@link #defaultCacheRepository} is an S3 bucket path.
71+
*/
72+
@Nullable
73+
@Value('${wave.build.cache-bucket-upload-parallelism}')
74+
Integer cacheBucketUploadParallelism
75+
5576
@Nullable
5677
@Value('${wave.build.public-repo}')
5778
String defaultPublicRepository
@@ -138,6 +159,8 @@ class BuildConfig {
138159
"singularity-image=${singularityImage}; " +
139160
"default-build-repository=${defaultBuildRepository}; " +
140161
"default-cache-repository=${defaultCacheRepository}; " +
162+
"cache-bucket-region=${cacheBucketRegion}; " +
163+
"cache-bucket-upload-parallelism=${cacheBucketUploadParallelism}; " +
141164
"default-public-repository=${defaultPublicRepository}; " +
142165
"build-workspace=${buildWorkspace}; " +
143166
"build-timeout=${defaultTimeout}; " +
@@ -156,6 +179,10 @@ class BuildConfig {
156179
if( trustedTimeout < defaultTimeout ) {
157180
log.warn "Trusted build timeout should be longer than default timeout - check configuration setting 'wave.build.trusted-timeout'"
158181
}
182+
// validate at least one cache location is configured
183+
if( !defaultCacheRepository ) {
184+
log.warn "No cache location configured - 'wave.build.cache' should be set to a container registry or S3 bucket path"
185+
}
159186
}
160187

161188
Duration buildMaxDuration(SubmitContainerTokenRequest request) {
@@ -199,4 +226,26 @@ class BuildConfig {
199226
final store = BucketTokenizer.from(locksPath)
200227
return store.scheme ? store.getKey() : null
201228
}
229+
230+
/**
231+
* Get the AWS region for S3 cache bucket.
232+
*
233+
* @return The AWS region to use for S3 cache operations, or {@code null} if not configured.
234+
* When {@code null}, BuildKit will use the AWS SDK default region resolution chain
235+
* (environment variables, EC2 instance metadata, etc.)
236+
*/
237+
String getCacheBucketRegion() {
238+
return cacheBucketRegion
239+
}
240+
241+
/**
242+
* Check if the given path is an S3 bucket path (object storage).
243+
* This is used to distinguish between container registry paths and object storage paths.
244+
*
245+
* @param path The path to check
246+
* @return {@code true} if the path starts with {@code s3://}, {@code false} otherwise
247+
*/
248+
static boolean isBucketPath(String path) {
249+
return path?.startsWith('s3://')
250+
}
202251
}

0 commit comments

Comments
 (0)