@@ -0,0 +1,66 | |||
|
1 | package org.implab.gradle.containers; | |
|
2 | ||
|
3 | import java.io.Serializable; | |
|
4 | import java.util.Optional; | |
|
5 | ||
|
6 | public class ImageName implements Serializable { | |
|
7 | ||
|
8 | private static final long serialVersionUID = -1990105923537254552L; | |
|
9 | ||
|
10 | final String authority; | |
|
11 | ||
|
12 | final String name; | |
|
13 | ||
|
14 | final String tag; | |
|
15 | ||
|
16 | public ImageName() { | |
|
17 | name = null; | |
|
18 | authority = null; | |
|
19 | tag = null; | |
|
20 | } | |
|
21 | ||
|
22 | private ImageName(String authority, String name, String tag) { | |
|
23 | this.authority = authority; | |
|
24 | this.name = name; | |
|
25 | this.tag = tag; | |
|
26 | } | |
|
27 | ||
|
28 | public String getAuthority() { | |
|
29 | return authority; | |
|
30 | } | |
|
31 | ||
|
32 | public ImageName authority(String authority) { | |
|
33 | return new ImageName(authority, name, tag); | |
|
34 | } | |
|
35 | ||
|
36 | public String getName() { | |
|
37 | return name; | |
|
38 | } | |
|
39 | ||
|
40 | public ImageName name(String name) { | |
|
41 | return new ImageName(authority, name, tag); | |
|
42 | } | |
|
43 | ||
|
44 | public String getTag() { | |
|
45 | return tag; | |
|
46 | } | |
|
47 | ||
|
48 | public ImageName tag(String tag) { | |
|
49 | return new ImageName(authority, name, tag); | |
|
50 | } | |
|
51 | ||
|
52 | public ImageName copy() { | |
|
53 | return new ImageName(authority, name, tag); | |
|
54 | } | |
|
55 | ||
|
56 | @Override | |
|
57 | public String toString() { | |
|
58 | StringBuilder sb = new StringBuilder(); | |
|
59 | ||
|
60 | Optional.ofNullable(authority).ifPresent(s -> sb.append(s).append("/")); | |
|
61 | Optional.ofNullable(name).ifPresent(s -> sb.append(s)); | |
|
62 | Optional.ofNullable(tag).ifPresent(s-> sb.append(":").append(s)); | |
|
63 | ||
|
64 | return sb.toString(); | |
|
65 | } | |
|
66 | } |
@@ -0,0 +1,42 | |||
|
1 | package org.implab.gradle.containers.tasks; | |
|
2 | ||
|
3 | import java.util.List; | |
|
4 | import java.util.concurrent.Callable; | |
|
5 | ||
|
6 | import org.gradle.api.provider.ListProperty; | |
|
7 | import org.gradle.api.provider.Property; | |
|
8 | import org.gradle.api.tasks.Input; | |
|
9 | import org.gradle.api.tasks.Optional; | |
|
10 | import org.implab.gradle.containers.ImageName; | |
|
11 | ||
|
12 | public abstract class TagImage extends CliTask { | |
|
13 | ||
|
14 | @Input | |
|
15 | public abstract Property<ImageName> getSrcImage(); | |
|
16 | ||
|
17 | @Input | |
|
18 | public abstract Property<ImageName> getDestImage(); | |
|
19 | ||
|
20 | @Input | |
|
21 | @Optional | |
|
22 | public abstract Property<String> getTransport(); | |
|
23 | ||
|
24 | @Input | |
|
25 | @Optional | |
|
26 | public abstract ListProperty<String> getOptions(); | |
|
27 | ||
|
28 | public TagImage option(Callable<String> provider) { | |
|
29 | getOptions().add(getProject().provider(provider)); | |
|
30 | return this; | |
|
31 | } | |
|
32 | ||
|
33 | @Override | |
|
34 | protected void preparingCommand(List<String> commandLine) { | |
|
35 | super.preparingCommand(commandLine); | |
|
36 | ||
|
37 | commandLine.add("tag"); | |
|
38 | commandLine.addAll(getOptions().get()); | |
|
39 | commandLine.add(getSrcImage().get().toString()); | |
|
40 | commandLine.add(getDestImage().get().toString()); | |
|
41 | } | |
|
42 | } |
@@ -1,34 +1,27 | |||
|
1 | 1 | plugins { |
|
2 | 2 | id "java-gradle-plugin" |
|
3 |
id "com.gradle.plugin-publish" version "0.1 |
|
|
3 | id "com.gradle.plugin-publish" version "0.16.0" | |
|
4 | 4 | } |
|
5 | 5 | |
|
6 | 6 | |
|
7 | 7 | repositories { |
|
8 | 8 | mavenCentral() |
|
9 | 9 | } |
|
10 | 10 | |
|
11 | 11 | gradlePlugin { |
|
12 | website = 'https://code.implab.org/implab/gradle-container-plugin' | |
|
13 | vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin' | |
|
14 | ||
|
15 | 12 | plugins { |
|
16 | 13 | containerPlugin { |
|
17 | 14 | id = 'org.implab.gradle-container' |
|
15 | displayName = "Container building plugin" | |
|
16 | description = 'Build and publish container images with docker or podman. Simple wrapper around cli.' | |
|
18 | 17 | implementationClass = 'org.implab.gradle.containers.ContainerPlugin' |
|
19 | 18 | } |
|
20 | 19 | } |
|
21 | 20 | } |
|
22 | 21 | |
|
23 | 22 | pluginBundle { |
|
24 | 23 | website = 'https://code.implab.org/implab/gradle-container-plugin' |
|
25 | 24 | vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin' |
|
26 | 25 | |
|
27 | 26 | tags = ['containers', 'image', 'docker', 'podman'] |
|
28 | ||
|
29 | plugins { | |
|
30 | containerPlugin { | |
|
31 | description = 'Build and publish container images with docker or podman' | |
|
32 | } | |
|
33 | } | |
|
34 | 27 | } |
@@ -1,2 +1,2 | |||
|
1 | 1 | group=org.implab.gradle |
|
2 |
version=1. |
|
|
2 | version=1.1 No newline at end of file |
@@ -1,58 +1,94 | |||
|
1 | 1 | package org.implab.gradle.containers; |
|
2 | 2 | |
|
3 | import java.util.Optional; | |
|
4 | ||
|
5 | import org.gradle.api.Project; | |
|
3 | 6 | import org.gradle.api.file.DirectoryProperty; |
|
4 | 7 | import org.gradle.api.file.ProjectLayout; |
|
5 | 8 | import org.gradle.api.file.RegularFileProperty; |
|
6 | 9 | import org.gradle.api.model.ObjectFactory; |
|
7 | 10 | import org.gradle.api.provider.Property; |
|
11 | import org.gradle.api.provider.Provider; | |
|
8 | 12 | |
|
9 | 13 | public class ContainerExtension { |
|
10 | 14 | |
|
11 | 15 | private final Property<String> cliCmd; |
|
12 | 16 | |
|
13 | 17 | private final Property<String> imageAuthority; |
|
14 | 18 | |
|
15 | 19 | private final Property<String> imageGroup; |
|
16 | 20 | |
|
21 | private final Property<String> imageShortName; | |
|
22 | ||
|
23 | private final Property<String> imageTag; | |
|
24 | ||
|
25 | private final Property<ImageName> imageName; | |
|
26 | ||
|
17 | 27 | private final DirectoryProperty contextDir; |
|
18 | 28 | |
|
19 | 29 | private final RegularFileProperty imageIdFile; |
|
20 | 30 | |
|
21 | public ContainerExtension(ObjectFactory factory, ProjectLayout layout) { | |
|
31 | public ContainerExtension(ObjectFactory factory, ProjectLayout layout, Project project) { | |
|
22 | 32 | contextDir = factory.directoryProperty(); |
|
23 | 33 | contextDir.convention(layout.getBuildDirectory().dir("context")); |
|
24 | 34 | |
|
25 | 35 | imageIdFile = factory.fileProperty(); |
|
26 | 36 | imageIdFile.convention(layout.getBuildDirectory().file("imageId")); |
|
27 | 37 | |
|
28 | 38 | cliCmd = factory.property(String.class); |
|
29 | 39 | cliCmd.set("docker"); |
|
30 | 40 | |
|
31 | 41 | imageAuthority = factory.property(String.class); |
|
32 | 42 | imageGroup = factory.property(String.class); |
|
43 | imageShortName = factory.property(String.class); | |
|
44 | ||
|
45 | imageShortName.convention(project.getName()); | |
|
46 | ||
|
47 | imageTag = factory.property(String.class); | |
|
48 | imageTag.set(project | |
|
49 | .provider(() -> Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest"))); | |
|
50 | ||
|
51 | Provider<String> imageRepository = imageGroup.map(g -> g + "/" + imageShortName.get()).orElse(imageShortName); | |
|
52 | ||
|
53 | imageName = factory.property(ImageName.class); | |
|
54 | imageName.convention(project.provider( | |
|
55 | () -> new ImageName().authority(imageAuthority.get()).name(imageRepository.get()).tag(imageTag.get()))); | |
|
33 | 56 | } |
|
34 | 57 | |
|
35 | 58 | public Property<String> getCliCmd() { |
|
36 | 59 | return cliCmd; |
|
37 | 60 | } |
|
38 | 61 | |
|
39 | 62 | public void setCliCmd(String cliCmd) { |
|
40 | 63 | this.cliCmd.set(cliCmd); |
|
41 | 64 | } |
|
42 | 65 | |
|
43 | 66 | public DirectoryProperty getContextDirectory() { |
|
44 | 67 | return contextDir; |
|
45 | 68 | } |
|
46 | 69 | |
|
47 | 70 | public RegularFileProperty getImageIdFile() { |
|
48 | 71 | return imageIdFile; |
|
49 | 72 | } |
|
50 | 73 | |
|
51 | 74 | public Property<String> getImageAuthority() { |
|
52 | 75 | return imageAuthority; |
|
53 | 76 | } |
|
54 | 77 | |
|
55 | 78 | public Property<String> getImageGroup() { |
|
56 | 79 | return imageGroup; |
|
57 | 80 | } |
|
81 | ||
|
82 | public Property<ImageName> getImageName() { | |
|
83 | return imageName; | |
|
84 | } | |
|
85 | ||
|
86 | public Property<String> getImageShortName() { | |
|
87 | return imageShortName; | |
|
88 | } | |
|
89 | ||
|
90 | public ImageName createImageName() { | |
|
91 | return new ImageName(); | |
|
92 | } | |
|
93 | ||
|
58 | 94 | } No newline at end of file |
@@ -1,102 +1,95 | |||
|
1 | 1 | package org.implab.gradle.containers; |
|
2 | 2 | |
|
3 | import java.util.Optional; | |
|
4 | ||
|
5 | 3 | import org.gradle.api.Plugin; |
|
6 | 4 | import org.gradle.api.Project; |
|
7 | 5 | import org.gradle.api.artifacts.Dependency; |
|
8 | 6 | import org.gradle.api.file.ProjectLayout; |
|
9 | 7 | import org.gradle.api.model.ObjectFactory; |
|
10 | 8 | import org.gradle.api.plugins.ExtraPropertiesExtension; |
|
11 | import org.gradle.api.provider.Provider; | |
|
12 | 9 | import org.gradle.api.tasks.Copy; |
|
13 | 10 | import org.gradle.api.tasks.Delete; |
|
14 | 11 | import org.gradle.api.tasks.TaskProvider; |
|
15 | 12 | import org.implab.gradle.containers.tasks.BuildImage; |
|
16 | 13 | import org.implab.gradle.containers.tasks.PushImage; |
|
17 | 14 | import org.implab.gradle.containers.tasks.SaveImage; |
|
15 | import org.implab.gradle.containers.tasks.TagImage; | |
|
18 | 16 | |
|
19 | 17 | public class ContainerPlugin implements Plugin<Project> { |
|
20 | 18 | |
|
21 | 19 | public static final String BUILD_GROUP = "build"; |
|
22 | 20 | |
|
23 | 21 | public static final String CONTAINER_EXTENSION_NAME = "container"; |
|
24 | 22 | |
|
25 | 23 | public static final String ARCHIVE_CONFIGURATION = "archive"; |
|
26 | 24 | |
|
27 | 25 | private ContainerExtension containerExtension; |
|
28 | 26 | |
|
29 | 27 | public void apply(Project project) { |
|
30 | 28 | ObjectFactory factory = project.getObjects(); |
|
31 | 29 | ProjectLayout layout = project.getLayout(); |
|
32 | containerExtension = new ContainerExtension(factory, layout); | |
|
30 | containerExtension = new ContainerExtension(factory, layout, project); | |
|
33 | 31 | |
|
34 | 32 | containerExtension.getImageAuthority() |
|
35 | 33 | .convention(project.provider(() -> (String) project.getProperties().get("imagesAuthority"))); |
|
36 | 34 | |
|
37 | 35 | containerExtension.getImageGroup() |
|
38 | 36 | .convention(project.provider(() -> (String) project.getProperties().get("imagesGroup"))); |
|
39 | 37 | |
|
40 | 38 | project.getExtensions().add(CONTAINER_EXTENSION_NAME, containerExtension); |
|
41 | 39 | |
|
42 | 40 | ExtraPropertiesExtension extras = project.getExtensions().getExtraProperties(); |
|
43 | 41 | extras.set(BuildImage.class.getSimpleName(), BuildImage.class); |
|
44 | 42 | extras.set(PushImage.class.getSimpleName(), PushImage.class); |
|
45 | 43 | extras.set(SaveImage.class.getSimpleName(), SaveImage.class); |
|
44 | extras.set(TagImage.class.getSimpleName(), TagImage.class); | |
|
46 | 45 | |
|
47 | 46 | project.getConfigurations().create(Dependency.DEFAULT_CONFIGURATION, c -> { |
|
48 | 47 | c.setCanBeConsumed(true); |
|
49 | 48 | c.setCanBeResolved(false); |
|
50 | 49 | }); |
|
51 | 50 | |
|
52 | 51 | project.getConfigurations().create(ARCHIVE_CONFIGURATION, c -> { |
|
53 | 52 | c.setCanBeConsumed(true); |
|
54 | 53 | c.setCanBeResolved(false); |
|
55 | 54 | }); |
|
56 | 55 | |
|
57 | 56 | TaskProvider<Copy> processResourcesTask = project.getTasks().register("processResources", Copy.class, t -> { |
|
58 | 57 | t.setGroup(BUILD_GROUP); |
|
59 | 58 | t.from(layout.getProjectDirectory().dir("src/main")); |
|
60 | 59 | t.into(containerExtension.getContextDirectory()); |
|
61 | 60 | }); |
|
62 | 61 | |
|
63 | 62 | TaskProvider<BuildImage> buildImageTask = project.getTasks().register("buildImage", BuildImage.class, t -> { |
|
64 | 63 | t.setGroup(BUILD_GROUP); |
|
65 | 64 | t.dependsOn(processResourcesTask); |
|
66 | 65 | |
|
67 | 66 | t.getContextDirectory().set(containerExtension.getContextDirectory()); |
|
68 | 67 | t.getImageIdFile().set(containerExtension.getImageIdFile()); |
|
69 | 68 | |
|
70 |
|
|
|
71 | .orElse(project.getName()); | |
|
72 | ||
|
73 | t.getImageAuthority().set(containerExtension.getImageAuthority()); | |
|
74 | t.getImageQName().convention(imageName); | |
|
75 | t.getImageVersion() | |
|
76 | .convention(Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest")); | |
|
69 | t.getImageName().set(containerExtension.getImageName()); | |
|
77 | 70 | }); |
|
78 | 71 | |
|
79 | 72 | project.getTasks().register("clean", Delete.class, t -> { |
|
80 | 73 | t.delete(layout.getBuildDirectory()); |
|
81 | 74 | }); |
|
82 | 75 | |
|
83 | 76 | project.getTasks().register("build", t -> { |
|
84 | 77 | t.setGroup(BUILD_GROUP); |
|
85 | 78 | t.dependsOn(buildImageTask); |
|
86 | 79 | }); |
|
87 | 80 | |
|
88 | 81 | project.getTasks().register("pushImage", PushImage.class, t -> { |
|
89 | 82 | t.dependsOn(buildImageTask); |
|
90 |
t.get |
|
|
83 | t.getImageName().set(buildImageTask.flatMap(b -> b.getImageName())); | |
|
91 | 84 | }); |
|
92 | 85 | |
|
93 | 86 | project.getTasks().register("saveImage", SaveImage.class, t -> { |
|
94 | 87 | t.dependsOn(buildImageTask); |
|
95 |
t.getImage().set(buildImageTask.flatMap(b -> b.getImage |
|
|
88 | t.getImage().set(buildImageTask.flatMap(b -> b.getImageName())); | |
|
96 | 89 | }); |
|
97 | 90 | |
|
98 | 91 | project.getArtifacts().add(Dependency.DEFAULT_CONFIGURATION, buildImageTask.flatMap(x -> x.getImageIdFile()), t -> { |
|
99 | 92 | t.builtBy(buildImageTask); |
|
100 | 93 | }); |
|
101 | 94 | } |
|
102 | 95 | } |
@@ -1,62 +1,43 | |||
|
1 | 1 | package org.implab.gradle.containers.tasks; |
|
2 | 2 | |
|
3 | 3 | import java.util.List; |
|
4 | 4 | |
|
5 | 5 | import org.gradle.api.file.DirectoryProperty; |
|
6 | 6 | import org.gradle.api.file.RegularFileProperty; |
|
7 | 7 | import org.gradle.api.provider.Property; |
|
8 | import org.gradle.api.provider.Provider; | |
|
9 | 8 | import org.gradle.api.tasks.Input; |
|
10 | 9 | import org.gradle.api.tasks.InputDirectory; |
|
11 | import org.gradle.api.tasks.Internal; | |
|
12 | 10 | import org.gradle.api.tasks.OutputFile; |
|
13 | 11 | import org.gradle.api.tasks.SkipWhenEmpty; |
|
14 | 12 | import org.implab.gradle.Utils; |
|
15 |
import org.implab.gradle.containers.Image |
|
|
13 | import org.implab.gradle.containers.ImageName; | |
|
16 | 14 | |
|
17 | 15 | public abstract class BuildImage extends CliTask { |
|
18 | 16 | @InputDirectory |
|
19 | 17 | @SkipWhenEmpty |
|
20 | 18 | public abstract DirectoryProperty getContextDirectory(); |
|
21 | 19 | |
|
22 | @Internal | |
|
23 | public abstract Property<String> getImageQName(); | |
|
24 | ||
|
25 | @Internal | |
|
26 | public abstract Property<String> getImageVersion(); | |
|
27 | ||
|
28 | @Internal | |
|
29 | public abstract Property<String> getImageAuthority(); | |
|
30 | ||
|
31 | 20 | @Input |
|
32 |
public |
|
|
33 | return getProject().provider(() -> { | |
|
34 | ImageTag tag = new ImageTag(); | |
|
35 | tag.setQName(getImageQName().getOrNull()); | |
|
36 | tag.setAuthority(getImageAuthority().getOrNull()); | |
|
37 | tag.setVersion(getImageVersion().getOrNull()); | |
|
38 | return tag; | |
|
39 | }); | |
|
40 | } | |
|
21 | public abstract Property<ImageName> getImageName(); | |
|
41 | 22 | |
|
42 | 23 | @OutputFile |
|
43 | 24 | public abstract RegularFileProperty getImageIdFile(); |
|
44 | 25 | |
|
45 | 26 | public BuildImage() { |
|
46 | 27 | |
|
47 | 28 | setWorkingDir(getContextDirectory().getAsFile()); |
|
48 | 29 | } |
|
49 | 30 | |
|
50 | 31 | @Override |
|
51 | 32 | protected void preparingCommand(List<String> commandLine) { |
|
52 | 33 | super.preparingCommand(commandLine); |
|
53 | 34 | |
|
54 | 35 | commandLine.addAll(List.of("build", ".", "-q", "-t")); |
|
55 |
commandLine.add(getImage |
|
|
36 | commandLine.add(getImageName().get().toString()); | |
|
56 | 37 | } |
|
57 | 38 | |
|
58 | 39 | @Override |
|
59 | 40 | protected void processStarted(Process p) { |
|
60 | 41 | Utils.redirectIO(p.getInputStream(), getImageIdFile().get().getAsFile()); |
|
61 | 42 | } |
|
62 | 43 | } |
@@ -1,51 +1,38 | |||
|
1 | 1 | package org.implab.gradle.containers.tasks; |
|
2 | 2 | |
|
3 | 3 | import java.util.List; |
|
4 | 4 | import java.util.concurrent.Callable; |
|
5 | 5 | |
|
6 | 6 | import org.gradle.api.provider.ListProperty; |
|
7 | 7 | import org.gradle.api.provider.Property; |
|
8 | import org.gradle.api.provider.Provider; | |
|
9 | 8 | import org.gradle.api.tasks.Input; |
|
10 | import org.gradle.api.tasks.Internal; | |
|
11 | 9 | import org.gradle.api.tasks.Optional; |
|
12 |
import org.implab.gradle.containers.Image |
|
|
10 | import org.implab.gradle.containers.ImageName; | |
|
13 | 11 | |
|
14 | 12 | public abstract class PushImage extends CliTask { |
|
15 | 13 | |
|
16 | 14 | @Input |
|
17 |
public abstract Property<Image |
|
|
18 | ||
|
19 | @Input | |
|
20 | @Optional | |
|
21 | public abstract Property<ImageTag> getDestImage(); | |
|
15 | public abstract Property<ImageName> getImageName(); | |
|
22 | 16 | |
|
23 | 17 | @Input |
|
24 | 18 | @Optional |
|
25 | 19 | public abstract Property<String> getTransport(); |
|
26 | 20 | |
|
27 | 21 | @Input |
|
28 | 22 | @Optional |
|
29 | 23 | public abstract ListProperty<String> getOptions(); |
|
30 | 24 | |
|
31 | 25 | public PushImage option(Callable<String> provider) { |
|
32 | 26 | getOptions().add(getProject().provider(provider)); |
|
33 | 27 | return this; |
|
34 | 28 | } |
|
35 | 29 | |
|
36 | @Internal | |
|
37 | public Provider<String> getDestination() { | |
|
38 | return getDestImage().flatMap(tag -> getTransport().orElse("").map(t -> t + tag.toString())); | |
|
39 | } | |
|
40 | ||
|
41 | 30 | @Override |
|
42 | 31 | protected void preparingCommand(List<String> commandLine) { |
|
43 | 32 | super.preparingCommand(commandLine); |
|
44 | 33 | |
|
45 | 34 | commandLine.add("push"); |
|
46 | 35 | commandLine.addAll(getOptions().get()); |
|
47 |
commandLine.add(get |
|
|
48 | if (getDestination().isPresent()) | |
|
49 | commandLine.add(getDestination().get()); | |
|
36 | commandLine.add(getImageName().get().toString()); | |
|
50 | 37 | } |
|
51 | 38 | } |
@@ -1,91 +1,91 | |||
|
1 | 1 | package org.implab.gradle.containers.tasks; |
|
2 | 2 | |
|
3 | 3 | import java.util.ArrayList; |
|
4 | 4 | import java.util.List; |
|
5 | 5 | import java.util.Optional; |
|
6 | 6 | |
|
7 | 7 | import org.gradle.api.file.DirectoryProperty; |
|
8 | 8 | import org.gradle.api.file.RegularFile; |
|
9 | 9 | import org.gradle.api.provider.Property; |
|
10 | 10 | import org.gradle.api.provider.Provider; |
|
11 | 11 | import org.gradle.api.tasks.Input; |
|
12 | 12 | import org.gradle.api.tasks.Internal; |
|
13 | 13 | import org.gradle.api.tasks.OutputFile; |
|
14 | 14 | import org.gradle.api.tasks.TaskExecutionException; |
|
15 | 15 | import org.implab.gradle.Utils; |
|
16 |
import org.implab.gradle.containers.Image |
|
|
16 | import org.implab.gradle.containers.ImageName; | |
|
17 | 17 | |
|
18 | 18 | public abstract class SaveImage extends CliTask { |
|
19 | 19 | |
|
20 | 20 | @Input |
|
21 |
public abstract Property<Image |
|
|
21 | public abstract Property<ImageName> getImage(); | |
|
22 | 22 | |
|
23 | 23 | @OutputFile |
|
24 | 24 | public Provider<RegularFile> getArchiveFile() { |
|
25 | 25 | return getDestinationDirectory().file(getArchiveFileName()); |
|
26 | 26 | } |
|
27 | 27 | |
|
28 | 28 | @Internal |
|
29 | 29 | public abstract DirectoryProperty getDestinationDirectory(); |
|
30 | 30 | |
|
31 | 31 | @Internal |
|
32 | 32 | public abstract Property<String> getArchiveFileName(); |
|
33 | 33 | |
|
34 | 34 | @Internal |
|
35 | 35 | public abstract Property<String> getArchiveBaseName(); |
|
36 | 36 | |
|
37 | 37 | @Internal |
|
38 | 38 | public abstract Property<String> getArchiveVersion(); |
|
39 | 39 | |
|
40 | 40 | @Internal |
|
41 | 41 | public abstract Property<String> getArchiveClassifier(); |
|
42 | 42 | |
|
43 | 43 | @Internal |
|
44 | 44 | public abstract Property<String> getArchiveExtension(); |
|
45 | 45 | |
|
46 | 46 | public SaveImage() { |
|
47 | 47 | getArchiveFileName().convention(getProject().provider(this::conventionalArchiveFileName)); |
|
48 | 48 | getArchiveBaseName().convention(getProject().provider(this::conventionalArchiveBaseName)); |
|
49 | 49 | getArchiveVersion().convention(getProject().provider(() -> getProject().getVersion()).map(x -> x.toString())); |
|
50 | 50 | getDestinationDirectory().convention(getProject().getLayout().getBuildDirectory()); |
|
51 | 51 | getArchiveExtension().convention("tar"); |
|
52 | 52 | } |
|
53 | 53 | |
|
54 | 54 | private String conventionalArchiveBaseName() { |
|
55 | 55 | ArrayList<String> parts = new ArrayList<>(); |
|
56 | 56 | Optional.of(getProject().getGroup()).map(x -> x.toString()).ifPresent(parts::add); |
|
57 | 57 | parts.add(getProject().getName()); |
|
58 | 58 | return String.join("-", parts); |
|
59 | 59 | } |
|
60 | 60 | |
|
61 | 61 | private String conventionalArchiveFileName() { |
|
62 | 62 | ArrayList<String> parts = new ArrayList<>(); |
|
63 | 63 | |
|
64 | 64 | if (getArchiveBaseName().isPresent()) |
|
65 | 65 | parts.add(getArchiveBaseName().get()); |
|
66 | 66 | |
|
67 | 67 | if (getArchiveVersion().isPresent()) |
|
68 | 68 | parts.add(getArchiveVersion().get()); |
|
69 | 69 | |
|
70 | 70 | if (getArchiveClassifier().isPresent()) |
|
71 | 71 | parts.add(getArchiveClassifier().get()); |
|
72 | 72 | |
|
73 | 73 | if (parts.size() == 0) |
|
74 | 74 | throw new TaskExecutionException(this, new Exception("The archiveFileName ism't specified")); |
|
75 | 75 | |
|
76 | 76 | return String.join("-", parts) + "." + getArchiveExtension().get(); |
|
77 | 77 | } |
|
78 | 78 | |
|
79 | 79 | @Override |
|
80 | 80 | protected void preparingCommand(List<String> commandLine) { |
|
81 | 81 | super.preparingCommand(commandLine); |
|
82 | 82 | |
|
83 | 83 | commandLine.add("save"); |
|
84 | 84 | commandLine.add(getImage().get().toString()); |
|
85 | 85 | } |
|
86 | 86 | |
|
87 | 87 | @Override |
|
88 | 88 | protected void processStarted(Process p) { |
|
89 | 89 | Utils.redirectIO(p.getInputStream(), getArchiveFile().get().getAsFile()); |
|
90 | 90 | } |
|
91 | 91 | } |
@@ -1,83 +1,110 | |||
|
1 | 1 | # Build and publish images with docker/podman |
|
2 | 2 | |
|
3 | 3 | ## SYNOPSIS |
|
4 | 4 | |
|
5 | 5 | ```gradle |
|
6 | 6 | |
|
7 | 7 | plugins { |
|
8 |
id 'org.implab.gradle-container' version |
|
|
8 | id 'org.implab.gradle-container' version '1.1' | |
|
9 | 9 | } |
|
10 | 10 | |
|
11 | 11 | container { |
|
12 | 12 | // if you want to use podman |
|
13 | 13 | cliCmd = "podman" |
|
14 | 14 | } |
|
15 | 15 | |
|
16 | 16 | configurations { |
|
17 | 17 | app |
|
18 | 18 | } |
|
19 | 19 | |
|
20 | 20 | dependencies { |
|
21 | 21 | // the application that needs to be built and packed |
|
22 | 22 | app project(":server") |
|
23 | 23 | } |
|
24 | 24 | |
|
25 | 25 | // add custom task to copy application files |
|
26 | 26 | // to the docker build context. |
|
27 | 27 | task copyApp(type: Copy) { |
|
28 | 28 | processResources.dependsOn it |
|
29 | 29 | |
|
30 | 30 | into container.contextDirectory.dir("root/opt/myapp") |
|
31 | 31 | from configurations.app |
|
32 | 32 | } |
|
33 | 33 | |
|
34 | 34 | task printVersion { |
|
35 | 35 | doLast { |
|
36 | 36 | println "tag: ${buildImage.imageTag.get()}" |
|
37 | 37 | println "archive: ${saveImage.archiveFileName.get()}" |
|
38 | 38 | } |
|
39 | 39 | } |
|
40 | 40 | |
|
41 | 41 | |
|
42 | 42 | ``` |
|
43 | 43 | |
|
44 | 44 | ## Description |
|
45 | 45 | |
|
46 | 46 | This plugin is a simple wrapper around docker CLI. All the image |
|
47 | 47 | building process is deligated to the `Dockerfile` which will run |
|
48 | 48 | in the prepeared build context. |
|
49 | 49 | |
|
50 | 50 | ### Project structure |
|
51 | 51 | |
|
52 | 52 | * `build/` |
|
53 | 53 | * `context/` - the build context where `docker build` command will run. |
|
54 | 54 | * `imageid` - the file storing the id of the image has been built. |
|
55 | 55 | * `image-name-1.2.3.tgz` - the exported image if `saveImage` has been executed. |
|
56 | 56 | * `src` |
|
57 | 57 | * `main` - the source files which will be copied to the build context. |
|
58 | 58 | |
|
59 | 59 | ## Properties |
|
60 | 60 | |
|
61 | 61 | `imagesAuthority` - the registry where the image should be published. |
|
62 | 62 | for example `docker.io` |
|
63 | 63 | |
|
64 | 64 | `imagesGroup` - the path to the image in the repository. |
|
65 | 65 | |
|
66 | 66 | ## Tasks |
|
67 | 67 | |
|
68 | 68 | ### buildImage |
|
69 | 69 | |
|
70 | 70 | The task builds the image. Wrapper around the `docker build` command. |
|
71 | 71 | |
|
72 | 72 | ### saveImage |
|
73 | 73 | |
|
74 | 74 | The task exports image as the .tar archive. |
|
75 | 75 | |
|
76 | 76 | ### pushImage |
|
77 | 77 | |
|
78 | 78 | The task pushes the image to the remote repository. |
|
79 | 79 | |
|
80 | 80 | ### processResources |
|
81 | 81 | |
|
82 | 82 | The copy task, it prepares the build context. Use it to customize |
|
83 | 83 | the build context. |
|
84 | ||
|
85 | ### tagImage | |
|
86 | ||
|
87 | since: 1.1 | |
|
88 | ||
|
89 | ```gradle | |
|
90 | task tagLatest(type: TagImage) { | |
|
91 | srcImage = container.imageName | |
|
92 | destImage = container.imageName.map { it.tag("latest") } | |
|
93 | } | |
|
94 | ||
|
95 | ``` | |
|
96 | ||
|
97 | ## Changes | |
|
98 | ||
|
99 | ### 1.1 | |
|
100 | ||
|
101 | Warning! This version isn't fully backward compatible with 1.0 version. | |
|
102 | ||
|
103 | * Added `TagImage` task type | |
|
104 | * `ImageTag` class is replaced with `ImageName` class | |
|
105 | * `BuildImage`, `PushImage` tasks are now accepting only `imageName` property | |
|
106 | * Added `imageName`, `imageShortName`, `imageTag` properties to `container` extension | |
|
107 | ||
|
108 | ### 1.0 | |
|
109 | ||
|
110 | Initial release. Default tasks to build and publish container images. |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now