Skip to content

Commit abde035

Browse files
authored
Feat/improve ci (#8)
* small improvements Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * Update to the last dagger version Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * build multiarch images Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * Add helpers and fix app.yaml Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * Make the cluster name variable Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * Add more helpers, fix access to the API deployed in EKS Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * add get-ingress function Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * move env to workflow level Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> * split workflow in 2 jobs Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com> --------- Signed-off-by: Jean-Christophe Sirot <jcsirot@gmail.com>
1 parent 796d651 commit abde035

File tree

7 files changed

+201
-63
lines changed

7 files changed

+201
-63
lines changed

.github/workflows/deploy-with-dagger.yaml

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,44 @@ name: Publish image and deploy the application to EKS
22
on:
33
workflow_dispatch:
44

5+
env:
6+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
7+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
8+
59
jobs:
610
build:
7-
name: build, publish, deploy
11+
name: build, publish
812
runs-on: ubuntu-latest
913
steps:
1014
- name: Checkout
1115
uses: actions/checkout@v4
1216

13-
- name: Build, publish image
17+
- name: Build and publish image
1418
id: publish
15-
env:
16-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
17-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
1819
uses: dagger/dagger-for-github@v7
1920
with:
2021
version: "latest"
2122
verb: call
2223
args: publish --aws-access-key-id=env://AWS_ACCESS_KEY_ID --aws-secret-access-key=env://AWS_SECRET_ACCESS_KEY
2324
cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
2425

25-
- name: Build, publish image
26-
env:
27-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
28-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
26+
deploy:
27+
name: deploy
28+
runs-on: ubuntu-latest
29+
needs: build
30+
steps:
31+
- name: Deploy to K8S
32+
uses: dagger/dagger-for-github@v7
33+
with:
34+
version: "latest"
35+
verb: call
36+
args: deploy --image=${{ steps.publish.outputs.output }} --aws-access-key-id=env://AWS_ACCESS_KEY_ID --aws-secret-access-key=env://AWS_SECRET_ACCESS_KEY --cluster-name ${{ vars.CLUSTER_NAME }}
37+
cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
38+
39+
- name: Get Public URL
2940
uses: dagger/dagger-for-github@v7
3041
with:
3142
version: "latest"
3243
verb: call
33-
args: deploy --image=${{ steps.publish.outputs.output }} --aws-access-key-id=env://AWS_ACCESS_KEY_ID --aws-secret-access-key=env://AWS_SECRET_ACCESS_KEY
44+
args: get-ingress --aws-access-key-id=env://AWS_ACCESS_KEY_ID --aws-secret-access-key=env://AWS_SECRET_ACCESS_KEY --cluster-name ${{ vars.CLUSTER_NAME }}
3445
cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}

.github/workflows/deploy.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ jobs:
5252
env:
5353
IMAGE_TAG: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/parisjug-dagger-demo/translate-api:${{ env.TAG_VERSION }}
5454
run: |
55-
docker build -f src/main/docker/Dockerfile.jvm --platform linux/amd64 -t $IMAGE_TAG .
55+
docker build -f src/main/docker/Dockerfile.jvm --platform linux/amd64,linux/arm64 -t $IMAGE_TAG .
5656
docker push $IMAGE_TAG
5757
5858
- name: update kube config
5959
run: |
60-
aws eks --region ${{ secrets.AWS_REGION }} update-kubeconfig --name confused-classical-sheepdog
60+
aws eks --region ${{ secrets.AWS_REGION }} update-kubeconfig --name ${{ vars.CLUSTER_NAME }}
6161
6262
- name: deploy application to EKS
6363
env:

ci/pom.xml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,27 @@
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
66

7-
<groupId>io.dagger.modules.ci</groupId>
7+
<groupId>io.dagger.modules.daggermodule</groupId>
88
<artifactId>ci</artifactId>
99
<version>1.0-SNAPSHOT</version>
1010
<name>ci</name>
1111

1212
<properties>
1313
<maven.compiler.release>17</maven.compiler.release>
1414
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
<dagger.module.deps>0.16.3-ci-module</dagger.module.deps>
1516
</properties>
1617

1718
<dependencies>
1819
<dependency>
1920
<groupId>io.dagger</groupId>
2021
<artifactId>dagger-java-sdk</artifactId>
21-
<version>1.0.0-SNAPSHOT</version>
22+
<version>${dagger.module.deps}</version>
2223
</dependency>
2324
<dependency>
2425
<groupId>io.dagger</groupId>
2526
<artifactId>dagger-java-annotation-processor</artifactId>
26-
<version>1.0.0-SNAPSHOT</version>
27+
<version>${dagger.module.deps}</version>
2728
<scope>provided</scope>
2829
</dependency>
2930
<dependency>
@@ -63,6 +64,10 @@
6364
<version>3.3.1</version>
6465
</plugin>
6566
<plugin>
67+
<!--
68+
This plugin configuration is required by Dagger to generate the module.
69+
Please do not remove or modify it.
70+
-->
6671
<artifactId>maven-compiler-plugin</artifactId>
6772
<version>3.13.0</version>
6873
<configuration>
@@ -71,7 +76,7 @@
7176
<path>
7277
<groupId>io.dagger</groupId>
7378
<artifactId>dagger-java-annotation-processor</artifactId>
74-
<version>1.0.0-SNAPSHOT</version>
79+
<version>${dagger.module.deps}</version>
7580
</path>
7681
</annotationProcessorPaths>
7782
<annotationProcessors>
@@ -108,6 +113,35 @@
108113

109114
<plugins>
110115
<plugin>
116+
<!--
117+
This plugin configuration helps VS Code editor (and others) to find
118+
the generated code created by `dagger init` and `dagger develop` and
119+
helps for code completion.
120+
-->
121+
<groupId>org.codehaus.mojo</groupId>
122+
<artifactId>build-helper-maven-plugin</artifactId>
123+
<version>3.3.0</version>
124+
<executions>
125+
<execution>
126+
<id>add-generated-sources</id>
127+
<goals>
128+
<goal>add-source</goal>
129+
</goals>
130+
<configuration>
131+
<sources>
132+
<source>${project.build.directory}/generated-sources/dagger-io</source>
133+
<source>${project.build.directory}/generated-sources/dagger-module</source>
134+
<source>${project.build.directory}/generated-sources/entrypoint</source>
135+
</sources>
136+
</configuration>
137+
</execution>
138+
</executions>
139+
</plugin>
140+
<plugin>
141+
<!--
142+
This plugin configuration is required by Dagger to generate the module.
143+
Please do not remove or modify it.
144+
-->
111145
<groupId>org.apache.maven.plugins</groupId>
112146
<artifactId>maven-shade-plugin</artifactId>
113147
<version>3.5.0</version>

ci/src/main/java/io/dagger/modules/ci/Ci.java

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
package io.dagger.modules.ci;
22

3+
import static io.dagger.client.Dagger.dag;
4+
import static io.dagger.modules.ci.Utils.*;
5+
36
import io.dagger.client.AwsCli;
47
import io.dagger.client.CacheVolume;
5-
import io.dagger.client.Client.AwsCliArguments;
68
import io.dagger.client.Container;
79
import io.dagger.client.Container.PublishArguments;
8-
import io.dagger.client.Container.WithExecArguments;
910
import io.dagger.client.DaggerQueryException;
1011
import io.dagger.client.Directory;
1112
import io.dagger.client.Directory.DockerBuildArguments;
1213
import io.dagger.client.Platform;
1314
import io.dagger.client.Secret;
14-
import io.dagger.client.Service;
15-
import io.dagger.module.AbstractModule;
1615
import io.dagger.module.annotation.Default;
1716
import io.dagger.module.annotation.DefaultPath;
1817
import io.dagger.module.annotation.Function;
1918
import io.dagger.module.annotation.Object;
2019
import java.util.List;
2120
import java.util.concurrent.ExecutionException;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
2223

2324
/** Ci main object */
2425
@Object
25-
public class Ci extends AbstractModule {
26+
public class Ci {
2627

27-
/**
28-
* Builds the application and optionally run the tests
29-
*
30-
* @param source the source directory
31-
* @param skipTests whether to skip the tests
32-
*/
28+
static final Logger LOG = LoggerFactory.getLogger(Ci.class);
29+
30+
private static final List<String> ARCHS = List.of("amd64", "arm64");
31+
32+
/** Build and test the application */
3333
@Function
3434
public Container build(@DefaultPath(".") Directory source, @Default("false") boolean skipTests)
3535
throws ExecutionException, DaggerQueryException, InterruptedException {
@@ -49,10 +49,14 @@ public Container buildImage(@DefaultPath(".") Directory source)
4949
.withDockerfile("src/main/docker/Dockerfile.jvm"));
5050
}
5151

52-
private List<Container> buildImageMultiarch(Directory source) {
53-
List<String> variants = List.of("amd64", "arm64");
52+
/**
53+
* Build a list of Docker images for multiple architectures
54+
* @param source the source directory
55+
*/
56+
private List<Container> buildImageMultiarch(Directory source, List<String> variants) {
5457
List<Container> images = variants.stream().map(platform -> {
5558
try {
59+
LOG.info("Building image for {}", platform);
5660
return buildImage(source, platform);
5761
} catch (ExecutionException | DaggerQueryException | InterruptedException e) {
5862
throw new RuntimeException(e);
@@ -70,59 +74,69 @@ private Container buildImage(Directory source, String platform)
7074
.withDockerfile("src/main/docker/Dockerfile.jvm"));
7175
}
7276

73-
/**
74-
* Runs the application as a service
75-
*/
76-
@Function
77-
public Service run(@DefaultPath(".") Directory source, @Default("8080") int port,
78-
Secret awsAccessKeyId, Secret awsSecretAccessKey)
79-
throws ExecutionException, DaggerQueryException, InterruptedException {
80-
Container ctr = buildImage(source)
81-
.withSecretVariable("AWS_ACCESS_KEY_ID", awsAccessKeyId)
82-
.withSecretVariable("AWS_SECRET_ACCESS_KEY", awsSecretAccessKey);
83-
return ctr.asService();
84-
}
85-
8677
/**
8778
* Publishes the Docker image to ECR
79+
*
80+
* @param source the source directory
81+
* @param awsAccessKeyId the AWS access key ID
82+
* @param awsSecretAccessKey the AWS secret access key
83+
* @param region the AWS region
8884
*/
8985
@Function
90-
public String publish(@DefaultPath(".") Directory source, Secret awsAccessKeyId, Secret awsSecretAccessKey)
86+
public String publish(@DefaultPath(".") Directory source, Secret awsAccessKeyId,
87+
Secret awsSecretAccessKey, @Default("eu-west-1") String region)
9188
throws ExecutionException, DaggerQueryException, InterruptedException {
92-
AwsCli awsCli = dag.awsCli().withRegion("eu-west-1").withStaticCredentials(awsAccessKeyId, awsSecretAccessKey);
89+
AwsCli awsCli = aws(region, awsAccessKeyId, awsSecretAccessKey);
9390
Secret token = awsCli.ecr().getLoginPassword();
9491
String accountId = awsCli.sts().getCallerIdentity().account();
95-
String address = "%s.dkr.ecr.eu-west-1.amazonaws.com/parisjug-dagger-demo/translate-api:%s"
96-
.formatted(accountId, dag.gitInfo(source).commitHash().substring(0, 8));
97-
dag.container()
92+
String address = "%s.dkr.ecr.%s.amazonaws.com/parisjug-dagger-demo/translate-api:%s"
93+
.formatted(accountId, region, dag().gitInfo(source).commitHash().substring(0, 8));
94+
dag().container()
9895
.withRegistryAuth(address, "AWS", token)
99-
.publish(address, new PublishArguments().withPlatformVariants(buildImageMultiarch(source)));
96+
.publish(address, new PublishArguments()
97+
.withPlatformVariants(buildImageMultiarch(source, ARCHS)));
10098
return address;
10199
}
102100

103101
/**
104102
* Deploys the application to EKS
103+
*
104+
* @param source the source directory
105+
* @param image the image address to deploy
106+
* @param clusterName the name of the EKS cluster
107+
* @param awsAccessKeyId the AWS access key ID
108+
* @param awsSecretAccessKey the AWS secret access key
109+
* @param region the AWS region
105110
*/
106111
@Function
107-
public String deploy(@DefaultPath(".") Directory source, String image, Secret awsAccessKeyId, Secret awsSecretAccessKey)
112+
public String deploy(@DefaultPath(".") Directory source, String image, String clusterName,
113+
Secret awsAccessKeyId, Secret awsSecretAccessKey, @Default("eu-west-1") String region)
108114
throws ExecutionException, DaggerQueryException, InterruptedException {
109-
Container deployerCtr = dag.container().from("alpine")
110-
.withExec(List.of("apk", "add", "aws-cli", "kubectl"));
111-
String appYaml = source.file("src/main/kube/app.yaml").contents().replace("${IMAGE_TAG}", image);
112-
return dag.awsCli(new AwsCliArguments().withContainer(deployerCtr))
113-
.withRegion("eu-west-1")
114-
.withStaticCredentials(awsAccessKeyId, awsSecretAccessKey)
115-
.exec(List.of("eks", "update-kubeconfig", "--name", "confused-classical-sheepdog"))
116-
.withEnvVariable("IMAGE_TAG", image)
115+
String appYaml = envsubst(source.file("src/main/kube/app.yaml").contents(), "IMAGE_TAG", image);
116+
return kubectl(clusterName, region, awsAccessKeyId, awsSecretAccessKey)
117117
.withNewFile("/tmp/app.yaml", appYaml)
118118
.withExec(List.of("kubectl", "apply", "-f", "/tmp/app.yaml"))
119119
.stdout();
120120
}
121121

122+
/**
123+
* Returns the ingress address of the application
124+
* @return the ingress address
125+
*/
126+
@Function
127+
public String getIngress(String clusterName, Secret awsAccessKeyId, Secret awsSecretAccessKey,
128+
@Default("eu-west-1") String region)
129+
throws ExecutionException, DaggerQueryException, InterruptedException {
130+
String host = kubectl(clusterName, region, awsAccessKeyId, awsSecretAccessKey)
131+
.withExec(List.of("kubectl", "-n", "devoxxfr-dagger", "get", "ingress", "-o", "jsonpath={.items[0].status.loadBalancer.ingress[0].hostname}"))
132+
.stdout();
133+
return "http://%s".formatted(host);
134+
}
135+
122136
/** Build a ready-to-use development environment */
123137
private Container buildEnv(Directory source) {
124-
CacheVolume mavenCache = dag.cacheVolume("m2");
125-
return dag
138+
CacheVolume mavenCache = dag().cacheVolume("m2");
139+
return dag()
126140
.container()
127141
.from("maven:3-eclipse-temurin-21")
128142
.withDirectory("/src", source)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.dagger.modules.ci;
2+
3+
import static io.dagger.client.Dagger.dag;
4+
5+
import io.dagger.client.AwsCli;
6+
import io.dagger.client.Client.AwsCliArguments;
7+
import io.dagger.client.Container;
8+
import io.dagger.client.Container.WithExecArguments;
9+
import io.dagger.client.DaggerQueryException;
10+
import io.dagger.client.Secret;
11+
import java.util.List;
12+
import java.util.concurrent.ExecutionException;
13+
14+
final class Utils {
15+
16+
static AwsCli aws(String region, Secret awsAccessKeyId, Secret awsSecretAccessKey) {
17+
return dag().awsCli()
18+
.withRegion(region)
19+
.withStaticCredentials(awsAccessKeyId, awsSecretAccessKey);
20+
}
21+
22+
static Container kubectl(String clusterName, String region, Secret awsAccessKeyId, Secret awsSecretAccessKey) {
23+
Container customContainer = dag().container().from("alpine")
24+
.withExec(List.of("apk", "add", "aws-cli", "kubectl"));
25+
return dag().awsCli(new AwsCliArguments().withContainer(customContainer))
26+
.withRegion(region)
27+
.withStaticCredentials(awsAccessKeyId, awsSecretAccessKey)
28+
.exec(List.of("eks", "update-kubeconfig", "--name", clusterName));
29+
}
30+
31+
static String envsubst(String content, String... substitutions)
32+
throws ExecutionException, DaggerQueryException, InterruptedException {
33+
Container container = dag().container().from("alpine")
34+
.withExec(List.of("apk", "add", "envsubst"));
35+
for (int i = 0; i < substitutions.length; i += 2) {
36+
container = container.withEnvVariable(substitutions[i], substitutions[i + 1]);
37+
}
38+
return container
39+
.withExec(List.of("envsubst"), new WithExecArguments().withStdin(content))
40+
.stdout();
41+
}
42+
}

dagger.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ci",
3-
"engineVersion": "v0.16.1",
3+
"engineVersion": "v0.16.3",
44
"sdk": {
55
"source": "java"
66
},

0 commit comments

Comments
 (0)