• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jreleaser / jreleaser / #537

25 Sep 2025 02:50PM UTC coverage: 48.299% (-0.7%) from 48.959%
#537

push

github

web-flow
fix: check snapshot version for '-SNAPSHOT' tag

Fixe #1971

2 of 2 new or added lines in 1 file covered. (100.0%)

362 existing lines in 31 files now uncovered.

25821 of 53461 relevant lines covered (48.3%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.2
/core/jreleaser-model-impl/src/main/java/org/jreleaser/model/internal/packagers/JibPackager.java
1
/*
2
 * SPDX-License-Identifier: Apache-2.0
3
 *
4
 * Copyright 2020-2025 The JReleaser authors.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     https://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
package org.jreleaser.model.internal.packagers;
19

20
import com.fasterxml.jackson.annotation.JsonIgnore;
21
import org.jreleaser.model.Active;
22
import org.jreleaser.model.Stereotype;
23
import org.jreleaser.model.internal.JReleaserContext;
24
import org.jreleaser.model.internal.common.Artifact;
25
import org.jreleaser.model.internal.common.CommitAuthor;
26
import org.jreleaser.model.internal.common.CommitAuthorAware;
27
import org.jreleaser.model.internal.common.Domain;
28
import org.jreleaser.model.internal.distributions.Distribution;
29
import org.jreleaser.model.internal.project.Project;
30
import org.jreleaser.util.FileType;
31
import org.jreleaser.util.PlatformUtils;
32

33
import java.util.ArrayList;
34
import java.util.Collections;
35
import java.util.EnumSet;
36
import java.util.LinkedHashMap;
37
import java.util.List;
38
import java.util.Map;
39
import java.util.Set;
40
import java.util.stream.Collectors;
41

42
import static java.util.Collections.emptySet;
43
import static java.util.Collections.unmodifiableList;
44
import static java.util.Collections.unmodifiableMap;
45
import static java.util.Collections.unmodifiableSet;
46
import static java.util.Comparator.naturalOrder;
47
import static java.util.function.Function.identity;
48
import static java.util.stream.Collectors.toList;
49
import static java.util.stream.Collectors.toMap;
50
import static java.util.stream.Collectors.toSet;
51
import static org.jreleaser.model.Distribution.DistributionType.BINARY;
52
import static org.jreleaser.model.Distribution.DistributionType.FLAT_BINARY;
53
import static org.jreleaser.model.Distribution.DistributionType.JAVA_BINARY;
54
import static org.jreleaser.model.Distribution.DistributionType.JLINK;
55
import static org.jreleaser.model.Distribution.DistributionType.NATIVE_IMAGE;
56
import static org.jreleaser.model.Distribution.DistributionType.SINGLE_JAR;
57
import static org.jreleaser.model.api.packagers.JibPackager.SKIP_JIB;
58
import static org.jreleaser.util.CollectionUtils.setOf;
59
import static org.jreleaser.util.FileType.JAR;
60
import static org.jreleaser.util.FileType.ZIP;
61
import static org.jreleaser.util.StringUtils.isBlank;
62
import static org.jreleaser.util.StringUtils.isFalse;
63

64
/**
65
 * @author Andres Almiray
66
 * @since 1.6.0
67
 */
68
public final class JibPackager extends AbstractJibConfiguration<JibPackager> implements RepositoryPackager<org.jreleaser.model.api.packagers.JibPackager>, CommitAuthorAware {
1✔
69
    private static final Map<org.jreleaser.model.Distribution.DistributionType, Set<String>> SUPPORTED = new LinkedHashMap<>();
1✔
70
    //private static final long serialVersionUID = -5161609035832200577L;
71

72
    static {
73
        Set<String> extensions = setOf(ZIP.extension());
1✔
74
        SUPPORTED.put(NATIVE_IMAGE, extensions);
1✔
75
        SUPPORTED.put(BINARY, extensions);
1✔
76
        SUPPORTED.put(JAVA_BINARY, extensions);
1✔
77
        SUPPORTED.put(JLINK, extensions);
1✔
78
        SUPPORTED.put(SINGLE_JAR, setOf(JAR.extension()));
1✔
79
        SUPPORTED.put(FLAT_BINARY, emptySet());
1✔
80
    }
1✔
81

82
    private final Map<String, JibSpec> specs = new LinkedHashMap<>();
1✔
83
    private final CommitAuthor commitAuthor = new CommitAuthor();
1✔
84
    private final JibRepository repository = new JibRepository();
1✔
85

86
    private Boolean continueOnError;
87
    private Boolean skipPublishing;
88
    private String downloadUrl;
89
    private String version;
90

91
    @JsonIgnore
1✔
92
    private final org.jreleaser.model.api.packagers.JibPackager immutable = new org.jreleaser.model.api.packagers.JibPackager() {
1✔
93
        private static final long serialVersionUID = -7342134381722104328L;
94

95
        private Set<? extends org.jreleaser.model.api.packagers.JibConfiguration.Registry> registries;
96
        private Map<String, ? extends org.jreleaser.model.api.packagers.JibSpec> specs;
97

98
        @Override
99
        public Map<String, ? extends org.jreleaser.model.api.packagers.JibSpec> getSpecs() {
100
            if (null == specs) {
×
101
                specs = JibPackager.this.specs.values().stream()
×
102
                    .map(JibSpec::asImmutable)
×
103
                    .collect(toMap(org.jreleaser.model.api.packagers.JibSpec::getName, identity()));
×
104
            }
105
            return specs;
×
106
        }
107

108
        @Override
109
        public String getVersion() {
110
            return JibPackager.this.getVersion();
×
111
        }
112

113
        @Override
114
        public JibRepository getRepository() {
115
            return repository.asImmutable();
×
116
        }
117

118
        @Override
119
        public org.jreleaser.model.api.common.CommitAuthor getCommitAuthor() {
120
            return commitAuthor.asImmutable();
×
121
        }
122

123
        @Override
124
        public String getTemplateDirectory() {
125
            return JibPackager.this.getTemplateDirectory();
×
126
        }
127

128
        @Override
129
        public List<String> getSkipTemplates() {
130
            return unmodifiableList(JibPackager.this.getSkipTemplates());
×
131
        }
132

133
        @Override
134
        public String getBaseImage() {
135
            return JibPackager.this.getBaseImage();
×
136
        }
137

138
        @Override
139
        public String getCreationTime() {
140
            return JibPackager.this.getCreationTime();
×
141
        }
142

143
        @Override
144
        public Format getFormat() {
145
            return JibPackager.this.getFormat();
×
146
        }
147

148
        @Override
149
        public Map<String, String> getEnvironment() {
150
            return unmodifiableMap(JibPackager.this.getEnvironment());
×
151
        }
152

153
        @Override
154
        public Set<String> getVolumes() {
155
            return unmodifiableSet(JibPackager.this.getVolumes());
×
156
        }
157

158
        @Override
159
        public Set<String> getExposedPorts() {
160
            return unmodifiableSet(JibPackager.this.getExposedPorts());
×
161
        }
162

163
        @Override
164
        public String getUser() {
165
            return JibPackager.this.getUser();
×
166
        }
167

168
        @Override
169
        public String getWorkingDirectory() {
170
            return JibPackager.this.getWorkingDirectory();
×
171
        }
172

173
        @Override
174
        public Map<String, String> getLabels() {
175
            return unmodifiableMap(JibPackager.this.getLabels());
×
176
        }
177

178
        @Override
179
        public Set<String> getImageNames() {
180
            return unmodifiableSet(JibPackager.this.getImageNames());
×
181
        }
182

183
        @Override
184
        public Set<? extends org.jreleaser.model.api.packagers.JibConfiguration.Registry> getRegistries() {
185
            if (null == registries) {
×
186
                registries = JibPackager.this.getRegistries().stream()
×
187
                    .map(JibConfiguration.Registry::asImmutable)
×
188
                    .collect(toSet());
×
189
            }
190
            return registries;
×
191
        }
192

193
        @Override
194
        public org.jreleaser.model.api.packagers.PackagerRepository getPackagerRepository() {
195
            return getRepository();
×
196
        }
197

198
        @Override
199
        public String getType() {
200
            return TYPE;
×
201
        }
202

203
        @Override
204
        public String getDownloadUrl() {
205
            return downloadUrl;
×
206
        }
207

208
        @Override
209
        public boolean supportsPlatform(String platform) {
210
            return JibPackager.this.supportsPlatform(platform);
×
211
        }
212

213
        @Override
214
        public boolean supportsDistribution(org.jreleaser.model.Distribution.DistributionType distributionType) {
215
            return JibPackager.this.supportsDistribution(distributionType);
×
216
        }
217

218
        @Override
219
        public Set<String> getSupportedFileExtensions(org.jreleaser.model.Distribution.DistributionType distributionType) {
220
            return JibPackager.this.getSupportedFileExtensions(distributionType);
×
221
        }
222

223
        @Override
224
        public Set<Stereotype> getSupportedStereotypes() {
225
            return JibPackager.this.getSupportedStereotypes();
×
226
        }
227

228
        @Override
229
        public boolean isSnapshotSupported() {
230
            return JibPackager.this.isSnapshotSupported();
×
231
        }
232

233
        @Override
234
        public boolean isContinueOnError() {
235
            return JibPackager.this.isContinueOnError();
×
236
        }
237

238
        @Override
239
        public boolean isSkipPublishing() {
240
            return JibPackager.this.isSkipPublishing();
×
241
        }
242

243
        @Override
244
        public Active getActive() {
245
            return JibPackager.this.getActive();
×
246
        }
247

248
        @Override
249
        public boolean isEnabled() {
250
            return JibPackager.this.isEnabled();
×
251
        }
252

253
        @Override
254
        public Map<String, Object> asMap(boolean full) {
255
            return unmodifiableMap(JibPackager.this.asMap(full));
×
256
        }
257

258
        @Override
259
        public String getPrefix() {
260
            return JibPackager.this.prefix();
×
261
        }
262

263
        @Override
264
        public Map<String, Object> getExtraProperties() {
265
            return unmodifiableMap(JibPackager.this.getExtraProperties());
×
266
        }
267
    };
268

269
    @JsonIgnore
270
    private boolean failed;
271

272
    @Override
273
    public org.jreleaser.model.api.packagers.JibPackager asImmutable() {
UNCOV
274
        return immutable;
×
275
    }
276

277
    @Override
278
    public void merge(JibPackager source) {
279
        super.merge(source);
1✔
280
        this.continueOnError = merge(this.continueOnError, source.continueOnError);
1✔
281
        this.skipPublishing = merge(this.skipPublishing, source.skipPublishing);
1✔
282
        this.downloadUrl = merge(this.downloadUrl, source.downloadUrl);
1✔
283
        this.version = merge(this.version, source.version);
1✔
284
        this.failed = source.failed;
1✔
285
        setSpecs(mergeModel(this.specs, source.specs));
1✔
286
        setCommitAuthor(source.commitAuthor);
1✔
287
        setRepository(source.repository);
1✔
288
    }
1✔
289

290
    @Override
291
    public boolean resolveEnabled(Project project, Distribution distribution) {
292
        resolveEnabled(project);
×
293
        if (!supportsDistribution(distribution.getType())) {
×
294
            disable();
×
295
        }
296
        return isEnabled();
×
297
    }
298

299
    @Override
300
    public void fail() {
301
        this.failed = true;
×
302
    }
×
303

304
    @Override
305
    public boolean isFailed() {
306
        return failed;
×
307
    }
308

309
    @Override
310
    public boolean isContinueOnError() {
311
        return null != continueOnError && continueOnError;
1✔
312
    }
313

314
    @Override
315
    public void setContinueOnError(Boolean continueOnError) {
316
        this.continueOnError = continueOnError;
1✔
317
    }
1✔
318

319
    @Override
320
    public boolean isContinueOnErrorSet() {
321
        return null != continueOnError;
1✔
322
    }
323

324
    @Override
325
    public boolean isSkipPublishing() {
326
        return null != skipPublishing && skipPublishing;
1✔
327
    }
328

329
    @Override
330
    public void setSkipPublishing(Boolean skipPublishing) {
331
        this.skipPublishing = skipPublishing;
1✔
332
    }
1✔
333

334
    @Override
335
    public boolean isSkipPublishingSet() {
336
        return null != skipPublishing;
1✔
337
    }
338

339
    @Override
340
    public String getDownloadUrl() {
341
        return downloadUrl;
1✔
342
    }
343

344
    @Override
345
    public void setDownloadUrl(String downloadUrl) {
346
        this.downloadUrl = downloadUrl;
1✔
347
    }
1✔
348

349
    @Override
350
    public boolean supportsPlatform(String platform) {
351
        return isBlank(platform) || PlatformUtils.isUnix(platform);
1✔
352
    }
353

354
    @Override
355
    public boolean supportsDistribution(org.jreleaser.model.Distribution.DistributionType distributionType) {
356
        return SUPPORTED.containsKey(distributionType);
×
357
    }
358

359
    @Override
360
    public Set<String> getSupportedFileExtensions(org.jreleaser.model.Distribution.DistributionType distributionType) {
361
        return unmodifiableSet(SUPPORTED.getOrDefault(distributionType, emptySet()));
1✔
362
    }
363

364
    @Override
365
    public Set<Stereotype> getSupportedStereotypes() {
366
        return EnumSet.allOf(Stereotype.class);
×
367
    }
368

369
    @Override
370
    public List<Artifact> resolveCandidateArtifacts(JReleaserContext context, Distribution distribution) {
371
        if (distribution.getType() == FLAT_BINARY && supportsDistribution(distribution.getType())) {
1✔
372
            return distribution.getArtifacts().stream()
×
373
                .filter(Artifact::isActiveAndSelected)
×
374
                .filter(artifact -> supportsPlatform(artifact.getPlatform()))
×
375
                .filter(this::isNotSkipped)
×
376
                .sorted(Artifact.comparatorByPlatform())
×
377
                .collect(toList());
×
378
        }
379

380
        List<String> fileExtensions = new ArrayList<>(getSupportedFileExtensions(distribution.getType()));
1✔
381
        fileExtensions.sort(naturalOrder());
1✔
382

383
        return distribution.getArtifacts().stream()
1✔
384
            .filter(Artifact::isActiveAndSelected)
1✔
385
            .filter(artifact -> fileExtensions.stream().anyMatch(ext -> artifact.getResolvedPath(context, distribution).toString().endsWith(ext)))
1✔
386
            .filter(artifact -> supportsPlatform(artifact.getPlatform()))
1✔
387
            .filter(this::isNotSkipped)
1✔
388
            .sorted(Artifact.comparatorByPlatform().thenComparingInt(artifact -> {
1✔
389
                String ext = FileType.getExtension(artifact.getResolvedPath(context, distribution));
×
390
                return fileExtensions.indexOf(ext);
×
391
            }))
392
            .collect(toList());
1✔
393
    }
394

395
    @Override
396
    public List<Artifact> resolveArtifacts(JReleaserContext context, Distribution distribution) {
397
        return resolveCandidateArtifacts(context, distribution).stream()
×
398
            .filter(Artifact::resolvedPathExists)
×
399
            .collect(toList());
×
400
    }
401

402
    private boolean isNotSkipped(Artifact artifact) {
403
        return isFalse(artifact.getExtraProperties().get(SKIP_JIB));
1✔
404
    }
405

406
    @Override
407
    public boolean isSnapshotSupported() {
408
        return true;
×
409
    }
410

411
    @Override
412
    public String getType() {
413
        return TYPE;
1✔
414
    }
415

416
    public String getVersion() {
417
        return version;
1✔
418
    }
419

420
    public void setVersion(String version) {
421
        this.version = version;
1✔
422
    }
1✔
423

424
    @Override
425
    public CommitAuthor getCommitAuthor() {
426
        return commitAuthor;
1✔
427
    }
428

429
    @Override
430
    public void setCommitAuthor(CommitAuthor commitAuthor) {
431
        this.commitAuthor.merge(commitAuthor);
1✔
432
    }
1✔
433

434
    public List<JibSpec> getActiveSpecs() {
UNCOV
435
        return specs.values().stream()
×
UNCOV
436
            .filter(JibSpec::isEnabled)
×
UNCOV
437
            .collect(Collectors.toList());
×
438
    }
439

440
    public Map<String, JibSpec> getSpecs() {
441
        return specs;
1✔
442
    }
443

444
    public void setSpecs(Map<String, JibSpec> specs) {
445
        this.specs.clear();
1✔
446
        this.specs.putAll(specs);
1✔
447
    }
1✔
448

449
    public void addSpecs(Map<String, JibSpec> specs) {
450
        this.specs.putAll(specs);
×
451
    }
×
452

453
    public void addSpec(JibSpec spec) {
454
        this.specs.put(spec.getName(), spec);
×
455
    }
×
456

457
    @Override
458
    public Map<String, Object> asMap(boolean full) {
459
        if (!full && !isEnabled()) return Collections.emptyMap();
1✔
460

461
        Map<String, Object> map = new LinkedHashMap<>();
1✔
462
        map.put(getType(), super.asMap(full));
1✔
463
        return map;
1✔
464
    }
465

466
    @Override
467
    protected void asMap(boolean full, Map<String, Object> props) {
468
        props.put("version", version);
1✔
469
        props.put("commitAuthor", commitAuthor.asMap(full));
1✔
470
        props.put("repository", repository.asMap(full));
1✔
471
        props.put("downloadUrl", downloadUrl);
1✔
472
        props.put("continueOnError", isContinueOnError());
1✔
473
        props.put("skipPublishing", isSkipPublishing());
1✔
474
        List<Map<String, Object>> specs = this.specs.values()
1✔
475
            .stream()
1✔
476
            .filter(d -> full || d.isEnabled())
1✔
477
            .map(d -> d.asMap(full))
1✔
478
            .collect(Collectors.toList());
1✔
479
        if (!specs.isEmpty()) props.put("specs", specs);
1✔
480
    }
1✔
481

482
    public void setRepository(JibRepository repository) {
483
        this.repository.merge(repository);
1✔
484
    }
1✔
485

486
    @Override
487
    public RepositoryTap getRepositoryTap() {
488
        return getPackagerRepository();
1✔
489
    }
490

491
    public JibRepository getPackagerRepository() {
492
        return repository;
1✔
493
    }
494

495
    public static final class JibRepository extends AbstractRepositoryTap<JibRepository> implements Domain {
496
        private static final long serialVersionUID = 695045361878174791L;
497

498
        private Boolean versionedSubfolders;
499

500
        @JsonIgnore
1✔
501
        private final org.jreleaser.model.api.packagers.JibPackager.JibRepository immutable = new org.jreleaser.model.api.packagers.JibPackager.JibRepository() {
1✔
502
            private static final long serialVersionUID = -8630728744390799997L;
503

504
            @Override
505
            public boolean isVersionedSubfolders() {
506
                return JibRepository.this.isVersionedSubfolders();
×
507
            }
508

509
            @Override
510
            public String getBasename() {
511
                return JibRepository.this.getBasename();
×
512
            }
513

514
            @Override
515
            public String getCanonicalRepoName() {
516
                return JibRepository.this.getCanonicalRepoName();
×
517
            }
518

519
            @Override
520
            public String getName() {
521
                return JibRepository.this.getName();
×
522
            }
523

524
            @Override
525
            public String getTagName() {
526
                return JibRepository.this.getTagName();
×
527
            }
528

529
            @Override
530
            public String getBranch() {
531
                return JibRepository.this.getBranch();
×
532
            }
533

534
            @Override
535
            public String getBranchPush() {
536
                return JibRepository.this.getBranchPush();
×
537
            }
538

539
            @Override
540
            public String getUsername() {
541
                return JibRepository.this.getUsername();
×
542
            }
543

544
            @Override
545
            public String getToken() {
546
                return JibRepository.this.getToken();
×
547
            }
548

549
            @Override
550
            public String getCommitMessage() {
551
                return JibRepository.this.getCommitMessage();
×
552
            }
553

554
            @Override
555
            public Active getActive() {
556
                return JibRepository.this.getActive();
×
557
            }
558

559
            @Override
560
            public boolean isEnabled() {
561
                return JibRepository.this.isEnabled();
×
562
            }
563

564
            @Override
565
            public Map<String, Object> asMap(boolean full) {
566
                return unmodifiableMap(JibRepository.this.asMap(full));
×
567
            }
568

569
            @Override
570
            public String getOwner() {
571
                return JibRepository.this.getOwner();
×
572
            }
573

574
            @Override
575
            public String getPrefix() {
576
                return JibRepository.this.prefix();
×
577
            }
578

579
            @Override
580
            public Map<String, Object> getExtraProperties() {
581
                return unmodifiableMap(JibRepository.this.getExtraProperties());
×
582
            }
583
        };
584

585
        public JibRepository() {
586
            super("jib", "jib");
1✔
587
        }
1✔
588

589
        public org.jreleaser.model.api.packagers.JibPackager.JibRepository asImmutable() {
590
            return immutable;
×
591
        }
592

593
        @Override
594
        public void merge(JibRepository source) {
595
            super.merge(source);
1✔
596
            this.versionedSubfolders = this.merge(this.versionedSubfolders, source.versionedSubfolders);
1✔
597
        }
1✔
598

599
        @Override
600
        public String prefix() {
601
            return "repository";
×
602
        }
603

604
        public boolean isVersionedSubfolders() {
605
            return null != versionedSubfolders && versionedSubfolders;
1✔
606
        }
607

608
        public void setVersionedSubfolders(Boolean versionedSubfolders) {
609
            this.versionedSubfolders = versionedSubfolders;
1✔
610
        }
1✔
611

612
        public boolean isVersionedSubfoldersSet() {
613
            return null != versionedSubfolders;
1✔
614
        }
615

616
        @Override
617
        public Map<String, Object> asMap(boolean full) {
618
            Map<String, Object> map = super.asMap(full);
1✔
619
            map.put("versionedSubfolders", isVersionedSubfolders());
1✔
620
            return map;
1✔
621
        }
622
    }
623
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc