diff --git a/.gitignore b/.gitignore
index aab87fa..00ba3cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
target/
testGit/
+application-local.properties
diff --git a/pom.xml b/pom.xml
index 5750576..0850c95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
0.8.0
20.2.0
2.11.2
+ 5.9.0.202009080501-r
@@ -60,10 +61,19 @@
org.springframework.boot
spring-boot-starter-actuator
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
+
+ org.eclipse.jgit
+ org.eclipse.jgit
+ ${org.eclipse.jgit.version}
+
diff --git a/src/main/java/tk/antoine_roux/wiki/ControllerHandlers.java b/src/main/java/tk/antoine_roux/wiki/ControllerHandlers.java
index 125cf8f..7b21d91 100644
--- a/src/main/java/tk/antoine_roux/wiki/ControllerHandlers.java
+++ b/src/main/java/tk/antoine_roux/wiki/ControllerHandlers.java
@@ -1,5 +1,6 @@
package tk.antoine_roux.wiki;
+import org.eclipse.jgit.api.errors.GitAPIException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -9,17 +10,20 @@ import org.springframework.web.bind.annotation.*;
import tk.antoine_roux.wiki.annotation.ApiPrefix;
import tk.antoine_roux.wiki.annotation.ApiVersion;
import tk.antoine_roux.wiki.configuration.Exception.DeleteRunnerException;
-import tk.antoine_roux.wiki.model.internal.HookEvent;
-import tk.antoine_roux.wiki.model.internal.Job;
+import tk.antoine_roux.wiki.model.internal.GitlabCI;
import tk.antoine_roux.wiki.model.internal.Runner;
import tk.antoine_roux.wiki.model.request.AddRunner;
+import tk.antoine_roux.wiki.model.request.HookEvent;
import tk.antoine_roux.wiki.model.request.JobRequest;
import tk.antoine_roux.wiki.model.request.TokenRunner;
+import tk.antoine_roux.wiki.model.response.JobResponse;
import tk.antoine_roux.wiki.model.response.RegisterRunnerResponse;
+import tk.antoine_roux.wiki.service.GitService;
import tk.antoine_roux.wiki.service.JobManager;
import tk.antoine_roux.wiki.service.RunnerRegistrar;
import tk.antoine_roux.wiki.utilitary.Boolean;
+import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Map;
import java.util.Optional;
@@ -35,11 +39,13 @@ public class ControllerHandlers {
private final RunnerRegistrar runnerRegistrar;
private final JobManager jobManager;
+ private final GitService gitService;
@Autowired
- public ControllerHandlers(RunnerRegistrar runnerRegistrar, JobManager jobManager) {
+ public ControllerHandlers(RunnerRegistrar runnerRegistrar, JobManager jobManager, GitService gitService) {
this.runnerRegistrar = runnerRegistrar;
this.jobManager = jobManager;
+ this.gitService = gitService;
}
/**
@@ -102,8 +108,8 @@ public class ControllerHandlers {
@ApiVersion(API_VERSION)
@PostMapping("/jobs/request")
- public ResponseEntity jobRequest(@RequestBody JobRequest jobRequest) {
- Optional currentJob = this.jobManager.popJob(jobRequest);
+ public ResponseEntity jobRequest(@RequestBody JobRequest jobRequest) {
+ Optional currentJob = this.jobManager.popJob(jobRequest);
return currentJob
.map(job -> ResponseEntity.status(HttpStatus.CREATED).body(job))
.orElseGet(() -> ResponseEntity.noContent().build());
@@ -118,12 +124,13 @@ public class ControllerHandlers {
@ApiVersion(API_VERSION)
@PostMapping("/webhook")
- public ResponseEntity webhook(@RequestBody HookEvent webHookData) {
+ public ResponseEntity webhook(@RequestBody HookEvent webHookData) throws IOException, GitAPIException {
ResponseEntity.BodyBuilder responseEntity;
- Optional job = webHookData.toJob();
+ Optional gitlabCI = this.gitService.getYMLGitlabCI(webHookData);
- if (job.isPresent()) {
- this.jobManager.stackJob(job.get());
+ if (gitlabCI.isPresent()) {
+ JobResponse job = gitlabCI.get().buildJobResponse();
+ this.jobManager.stackJob(job);
responseEntity = ResponseEntity.ok();
} else {
responseEntity = ResponseEntity.unprocessableEntity();
diff --git a/src/main/java/tk/antoine_roux/wiki/MainLauncher.java b/src/main/java/tk/antoine_roux/wiki/MainLauncher.java
index 3a6f6cc..a7cfccd 100644
--- a/src/main/java/tk/antoine_roux/wiki/MainLauncher.java
+++ b/src/main/java/tk/antoine_roux/wiki/MainLauncher.java
@@ -2,15 +2,18 @@ package tk.antoine_roux.wiki;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;
+import tk.antoine_roux.wiki.configuration.GitConfiguration;
/**
* Main class
*/
// force spring application to not use glibc or any non jdk code which is bad for graalvm
@SpringBootApplication(proxyBeanMethods = false)
+@EnableConfigurationProperties(GitConfiguration.GitlabCIContextProperties.class)
public class MainLauncher {
/**
diff --git a/src/main/java/tk/antoine_roux/wiki/configuration/GitConfiguration.java b/src/main/java/tk/antoine_roux/wiki/configuration/GitConfiguration.java
new file mode 100644
index 0000000..16c903e
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/configuration/GitConfiguration.java
@@ -0,0 +1,50 @@
+package tk.antoine_roux.wiki.configuration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+@Configuration(proxyBeanMethods = false)
+public class GitConfiguration {
+
+ @Bean
+ public YAMLFactory yamlFactory() {
+ return YAMLFactory.builder().build();
+ }
+
+ @Bean(name = "YAMLObjectMapper")
+ public ObjectMapper ObjectMapper(YAMLFactory yamlFactory) {
+ return new ObjectMapper(yamlFactory);
+ }
+
+ @Bean
+ public UsernamePasswordCredentialsProvider credentialsProvider(GitlabCIContextProperties gitlabCIContextProperties, Environment environment) {
+ return new UsernamePasswordCredentialsProvider(gitlabCIContextProperties.getUsername(), gitlabCIContextProperties.getPassword());
+ }
+
+ @ConfigurationProperties("gitlab-ci")
+ public static class GitlabCIContextProperties {
+ private String username;
+ private String password;
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return this.password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+ }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/configuration/WebConfiguration.java b/src/main/java/tk/antoine_roux/wiki/configuration/WebConfiguration.java
index 903850b..f051f40 100644
--- a/src/main/java/tk/antoine_roux/wiki/configuration/WebConfiguration.java
+++ b/src/main/java/tk/antoine_roux/wiki/configuration/WebConfiguration.java
@@ -1,7 +1,13 @@
package tk.antoine_roux.wiki.configuration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import tk.antoine_roux.wiki.utilitary.Constant;
@@ -17,4 +23,18 @@ public class WebConfiguration implements WebMvcRegistrations {
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(Constant.VERSION_PREFIX);
}
+
+ /**
+ * build default Spring boot {@link ObjectMapper}
+ * this bean avoid spring boot to auto detect {@link GitConfiguration#ObjectMapper(YAMLFactory)}
+ * as default {@link ObjectMapper}
+ *
+ * @param jackson2ObjectMapperBuilder
+ * @return
+ */
+ @Bean
+ @Primary
+ public ObjectMapper jackson2ObjectMapperBuilder(Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder) {
+ return jackson2ObjectMapperBuilder.build();
+ }
}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/GitlabCI.java b/src/main/java/tk/antoine_roux/wiki/model/internal/GitlabCI.java
new file mode 100644
index 0000000..04c4eb2
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/internal/GitlabCI.java
@@ -0,0 +1,46 @@
+package tk.antoine_roux.wiki.model.internal;
+
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import tk.antoine_roux.wiki.model.response.JobResponse;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class GitlabCI {
+ public String image;
+ @JsonProperty("before_script")
+ public List beforeScript = Collections.emptyList();
+ @JsonProperty("after_script")
+ public List afterScript = Collections.emptyList();
+ public Map jobs = Collections.emptyMap();
+
+ @JsonAnySetter
+ public void setJobs(String key, Job value) {
+ this.jobs.put(key, value);
+ }
+
+ public JobResponse buildJobResponse() {
+ return null;
+ }
+
+ public enum RuleEnum {
+ IF("if");
+
+ String content;
+
+ RuleEnum(String s) {
+ this.content = s;
+ }
+ }
+
+ private static class Job {
+ public String stage;
+ public String image;
+ public Map variables = Collections.emptyMap();
+ public List services = Collections.emptyList();
+ public Map rules = Collections.emptyMap();
+ public List script = Collections.emptyList();
+ }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/HookEvent.java b/src/main/java/tk/antoine_roux/wiki/model/internal/HookEvent.java
deleted file mode 100644
index 48f4740..0000000
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/HookEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package tk.antoine_roux.wiki.model.internal;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.time.ZonedDateTime;
-import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class HookEvent {
- public String secret;
- public String ref;
- public String before;
- public String after;
- @JsonProperty("compare_url")
- public String compareUrl;
- public List commits;
- @JsonProperty("head_commit")
- public String headCommit;
- public Repository repository;
- public User pusher;
- public User sender;
-
- AtomicInteger idIncrementer = new AtomicInteger();
-
- /**
- * convert {@link HookEvent} to {@link Job} if possible
- * else return and {@link Optional#empty()}
- */
- public Optional toJob() {
- Optional optJob;
-
- if (this.commits.isEmpty()) {
- optJob = Optional.empty();
- } else {
- // search for head commit or take first in event's list of commit
- Commit commit = this.commits.stream().filter(co -> co.id.equals(this.headCommit))
- .findFirst().orElse(this.commits.get(0));
-
- Job.Commit co = new Job.Commit(
- commit.author.email, commit.author.name, commit.timestamp,
- commit.id, commit.message, commit.id.substring(0, 8), commit.message
- );
-
- Job job = new Job(
- null, co, null, ZonedDateTime.now(), null,
- this.idIncrementer.getAndIncrement(), UUID.randomUUID().toString(), this.ref,
- null, "root", null, JobStatus.CREATED, false, this.pusher.toReducedUser()
- );
- optJob = Optional.of(job);
- }
-
- return optJob;
- }
-}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/Job.java b/src/main/java/tk/antoine_roux/wiki/model/internal/Job.java
deleted file mode 100644
index 7c2801b..0000000
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/Job.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package tk.antoine_roux.wiki.model.internal;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.time.ZonedDateTime;
-
-// ID int `json:"id"`
-// Token string `json:"token"`
-// AllowGitFetch bool `json:"allow_git_fetch"`
-// JobInfo JobInfo `json:"job_info"`
-// GitInfo GitInfo `json:"git_info"`
-// RunnerInfo RunnerInfo `json:"runner_info"`
-// Variables JobVariables `json:"variables"`
-// Steps Steps `json:"steps"`
-// Image Image `json:"image"`
-// Services Services `json:"services"`
-// Artifacts Artifacts `json:"artifacts"`
-// Cache Caches `json:"cache"`
-// Credentials []Credentials `json:"credentials"`
-// Dependencies Dependencies `json:"dependencies"`
-// Features GitlabFeatures `json:"features"`
-// Secrets Secrets `json:"secrets,omitempty"`
-
-public class Job {
- @JsonProperty("artifacts_file")
- public String artifactsFile;
- public Commit commit;
- public String coverage;
- @JsonProperty("created_at")
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssSSSXXX")
- public ZonedDateTime createdAt;
- @JsonProperty("finished_at")
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssSSSXXX")
- public ZonedDateTime finishedAt;
- public Integer id;
- public String name;
- public String ref;
- public Runner runner;
- public String stage;
- @JsonProperty("started_at")
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssSSSXXX")
- public ZonedDateTime startedAt;
- public JobStatus status;
- public boolean tag;
- public UserReduced user;
-
- public Job(
- String artifactsFile, Commit commit, String coverage, ZonedDateTime createdAt, ZonedDateTime finishedAt,
- Integer id, String name, String ref, Runner runner, String stage, ZonedDateTime startedAt, JobStatus status,
- boolean tag, UserReduced user
- ) {
- this.artifactsFile = artifactsFile;
- this.commit = commit;
- this.coverage = coverage;
- this.createdAt = createdAt;
- this.finishedAt = finishedAt;
- this.id = id;
- this.name = name;
- this.ref = ref;
- this.runner = runner;
- this.stage = stage;
- this.startedAt = startedAt;
- this.status = status;
- this.tag = tag;
- this.user = user;
- }
-
- public static class Commit {
- @JsonProperty("author_email")
- public String authorEmail;
- @JsonProperty("author_name")
- public String authorName;
- @JsonProperty("created_at")
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssSSSXXX")
- public ZonedDateTime createdAt;
- public String id;
- public String message;
- @JsonProperty("short_id")
- public String shortId;
- public String title;
-
- public Commit(String authorEmail, String authorName, ZonedDateTime createdAt, String id, String message, String shortId, String title) {
- this.authorEmail = authorEmail;
- this.authorName = authorName;
- this.createdAt = createdAt;
- this.id = id;
- this.message = message;
- this.shortId = shortId;
- this.title = title;
- }
- }
-}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/JobStatus.java b/src/main/java/tk/antoine_roux/wiki/model/internal/JobStatus.java
deleted file mode 100644
index ca99ddd..0000000
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/JobStatus.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package tk.antoine_roux.wiki.model.internal;
-
-/**
- * This enum represent all state a job could take during
- * his lifecycle
- */
-public enum JobStatus {
- CREATED,
- STARTED,
- STOPPED,
- FINISHED
-}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/request/AddRunner.java b/src/main/java/tk/antoine_roux/wiki/model/request/AddRunner.java
index b80c3a9..51bfe5f 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/request/AddRunner.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/AddRunner.java
@@ -1,6 +1,7 @@
package tk.antoine_roux.wiki.model.request;
import com.fasterxml.jackson.annotation.JsonProperty;
+import tk.antoine_roux.wiki.model.request.secondary.RunnerInfo;
import java.util.Arrays;
import java.util.List;
diff --git a/src/main/java/tk/antoine_roux/wiki/model/request/HookEvent.java b/src/main/java/tk/antoine_roux/wiki/model/request/HookEvent.java
new file mode 100644
index 0000000..9d8ea75
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/HookEvent.java
@@ -0,0 +1,55 @@
+package tk.antoine_roux.wiki.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import tk.antoine_roux.wiki.model.request.secondary.Commit;
+import tk.antoine_roux.wiki.model.request.secondary.Repository;
+import tk.antoine_roux.wiki.model.request.secondary.User;
+
+import java.util.List;
+
+public class HookEvent {
+ public String secret;
+ public String ref;
+ public String before;
+ public String after;
+ @JsonProperty("compare_url")
+ public String compareUrl;
+ public List commits;
+ @JsonProperty("head_commit")
+ public String headCommit;
+ public Repository repository;
+ public User pusher;
+ public User sender;
+
+// AtomicInteger idIncrementer = new AtomicInteger();
+//
+// /**
+// * convert {@link HookEvent} to {@link Job} if possible
+// * else return and {@link Optional#empty()}
+// */
+// public Optional toJob() {
+// Optional optJob;
+//
+// if (this.commits.isEmpty()) {
+// optJob = Optional.empty();
+// } else {
+// // search for head commit or take first in event's list of commit
+// Commit commit = this.commits.stream().filter(co -> co.id.equals(this.headCommit))
+// .findFirst().orElse(this.commits.get(0));
+//
+// Job.Commit co = new Job.Commit(
+// commit.author.email, commit.author.name, commit.timestamp,
+// commit.id, commit.message, commit.id.substring(0, 8), commit.message
+// );
+//
+// Job job = new Job(
+// null, co, null, ZonedDateTime.now(), null,
+// this.idIncrementer.getAndIncrement(), UUID.randomUUID().toString(), this.ref,
+// null, "root", null, JobStatus.CREATED, false, this.pusher.toReducedUser()
+// );
+// optJob = Optional.of(job);
+// }
+//
+// return optJob;
+// }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/request/JobRequest.java b/src/main/java/tk/antoine_roux/wiki/model/request/JobRequest.java
index d880009..01b7b1d 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/request/JobRequest.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/JobRequest.java
@@ -1,5 +1,7 @@
package tk.antoine_roux.wiki.model.request;
+import tk.antoine_roux.wiki.model.request.secondary.RunnerInfo;
+
/**
* Job Request compose from {@link RunnerInfo} and token field
*/
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/Commit.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/Commit.java
similarity index 76%
rename from src/main/java/tk/antoine_roux/wiki/model/internal/Commit.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/Commit.java
index 7f775c1..b2b1d52 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/Commit.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/Commit.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.internal;
+package tk.antoine_roux.wiki.model.request.secondary;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -13,7 +13,7 @@ public class Commit {
public UserReduced committer;
public String verification;
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
public ZonedDateTime timestamp;
public List added;
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/InternalTracker.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/InternalTracker.java
similarity index 88%
rename from src/main/java/tk/antoine_roux/wiki/model/internal/InternalTracker.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/InternalTracker.java
index 552983f..2d93f3d 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/InternalTracker.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/InternalTracker.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.internal;
+package tk.antoine_roux.wiki.model.request.secondary;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/Permission.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/Permission.java
similarity index 73%
rename from src/main/java/tk/antoine_roux/wiki/model/internal/Permission.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/Permission.java
index 1895119..c4825ac 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/Permission.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/Permission.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.internal;
+package tk.antoine_roux.wiki.model.request.secondary;
/**
* model about repository permission
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/Repository.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/Repository.java
similarity index 97%
rename from src/main/java/tk/antoine_roux/wiki/model/internal/Repository.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/Repository.java
index 2a665f1..b1f3a85 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/Repository.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/Repository.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.internal;
+package tk.antoine_roux.wiki.model.request.secondary;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/tk/antoine_roux/wiki/model/request/RunnerInfo.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/RunnerInfo.java
similarity index 94%
rename from src/main/java/tk/antoine_roux/wiki/model/request/RunnerInfo.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/RunnerInfo.java
index a4d1fe7..70210c3 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/request/RunnerInfo.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/RunnerInfo.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.request;
+package tk.antoine_roux.wiki.model.request.secondary;
import java.util.Map;
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/User.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/User.java
similarity index 92%
rename from src/main/java/tk/antoine_roux/wiki/model/internal/User.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/User.java
index dc62cc4..ad04d0b 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/User.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/User.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.internal;
+package tk.antoine_roux.wiki.model.request.secondary;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/tk/antoine_roux/wiki/model/internal/UserReduced.java b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/UserReduced.java
similarity index 85%
rename from src/main/java/tk/antoine_roux/wiki/model/internal/UserReduced.java
rename to src/main/java/tk/antoine_roux/wiki/model/request/secondary/UserReduced.java
index e28788e..9977400 100644
--- a/src/main/java/tk/antoine_roux/wiki/model/internal/UserReduced.java
+++ b/src/main/java/tk/antoine_roux/wiki/model/request/secondary/UserReduced.java
@@ -1,4 +1,4 @@
-package tk.antoine_roux.wiki.model.internal;
+package tk.antoine_roux.wiki.model.request.secondary;
/**
* Reduced user information
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/JobResponse.java b/src/main/java/tk/antoine_roux/wiki/model/response/JobResponse.java
new file mode 100644
index 0000000..033dc88
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/JobResponse.java
@@ -0,0 +1,33 @@
+package tk.antoine_roux.wiki.model.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import tk.antoine_roux.wiki.model.response.secondary.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * job format use to submit
+ * information to gitlab-runner
+ */
+public class JobResponse {
+ public Integer id;
+ public String token;
+ @JsonProperty("allow_git_fetch")
+ public boolean allowGitFetch;
+ @JsonProperty("job_info")
+ public JobInfo jobInfo;
+ @JsonProperty("git_info")
+ public GitInfo gitInfo;
+ public RunnerInfo runnerInfo;
+ public List variables;
+ public List steps;
+ public Image image;
+ public List services;
+ public List artifacts;
+ public List cache;
+ public List credentials;
+ public List dependencies;
+ public GitLabFeatures features;
+ public Map secrets;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Artifact.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Artifact.java
new file mode 100644
index 0000000..6b287ee
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Artifact.java
@@ -0,0 +1,19 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class Artifact {
+ public String name;
+ public boolean untracked;
+ public List paths;
+ public List exclude;
+ public String when;
+ @JsonProperty("artifact_type")
+ public String artifactType;
+ @JsonProperty("artifact_format")
+ public String artifactFormat;
+ @JsonProperty("expire_in")
+ public String expireIn;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Cache.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Cache.java
new file mode 100644
index 0000000..af508f1
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Cache.java
@@ -0,0 +1,10 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import java.util.List;
+
+public class Cache {
+ public String key;
+ public boolean untracked;
+ public String policy;
+ public List paths;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Credential.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Credential.java
new file mode 100644
index 0000000..f19a232
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Credential.java
@@ -0,0 +1,8 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+public class Credential {
+ public String type;
+ public String url;
+ public String username;
+ public String password;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Dependency.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Dependency.java
new file mode 100644
index 0000000..986b722
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Dependency.java
@@ -0,0 +1,16 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Dependency {
+ public int id;
+ public String token;
+ public String name;
+ @JsonProperty("artifacts_file")
+ public DependencyArtifactsFile artifactsFile;
+
+ public static class DependencyArtifactsFile {
+ public String filename;
+ public int size;
+ }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/GitInfo.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/GitInfo.java
new file mode 100644
index 0000000..c6a63ec
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/GitInfo.java
@@ -0,0 +1,16 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class GitInfo {
+ @JsonProperty("repo_url")
+ public String repoURL;
+ public String ref;
+ public String sha;
+ @JsonProperty("before_sha")
+ public String beforeSha;
+ @JsonProperty("ref_type")
+ public String refType;
+ public String[] refspecs;
+ public int depth;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/GitLabFeatures.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/GitLabFeatures.java
new file mode 100644
index 0000000..e84b280
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/GitLabFeatures.java
@@ -0,0 +1,8 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class GitLabFeatures {
+ @JsonProperty("trace_sections")
+ public boolean traceSections;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Image.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Image.java
new file mode 100644
index 0000000..1b567dd
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Image.java
@@ -0,0 +1,26 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import java.util.List;
+
+public class Image {
+ public String name;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public String alias;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public List command;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public List entrypoint;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public Port ports;
+
+ static class Port {
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public String name;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public int number;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public String protocol;
+ }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/JobInfo.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/JobInfo.java
new file mode 100644
index 0000000..5cdcf27
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/JobInfo.java
@@ -0,0 +1,14 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class JobInfo {
+ public String name;
+ public String stage;
+
+ @JsonProperty("project_id")
+ public String projectID;
+
+ @JsonProperty("project_name")
+ public String projectName;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/JobVariable.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/JobVariable.java
new file mode 100644
index 0000000..b1f0459
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/JobVariable.java
@@ -0,0 +1,15 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class JobVariable {
+ public String key;
+ public String value;
+ @JsonProperty("public")
+ public boolean isPublic;
+ @JsonProperty("-")
+ public boolean internal;
+ public boolean file;
+ public boolean masked;
+ public boolean raw;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/RunnerInfo.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/RunnerInfo.java
new file mode 100644
index 0000000..f21fbd0
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/RunnerInfo.java
@@ -0,0 +1,5 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+public class RunnerInfo {
+ public int timeout;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Secret.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Secret.java
new file mode 100644
index 0000000..d64d524
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Secret.java
@@ -0,0 +1,33 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import java.util.Map;
+
+public class Secret {
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public VaultSecret vault;
+
+ public static class VaultSecret {
+ public VaultServer server;
+ public VaultEngine engine;
+ public String path;
+ public String field;
+ }
+
+ public static class VaultServer {
+ public String url;
+ public VaultAuth auth;
+ }
+
+ public static class VaultAuth {
+ public String name;
+ public String path;
+ public Map data;
+ }
+
+ public static class VaultEngine {
+ public String name;
+ public String path;
+ }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Step.java b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Step.java
new file mode 100644
index 0000000..24103f3
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/model/response/secondary/Step.java
@@ -0,0 +1,14 @@
+package tk.antoine_roux.wiki.model.response.secondary;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+public class Step {
+ public String name;
+ public List script;
+ public int timeout;
+ public String when;
+ @JsonProperty("allow_failure")
+ public boolean allowFailure;
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/service/GitService.java b/src/main/java/tk/antoine_roux/wiki/service/GitService.java
new file mode 100644
index 0000000..05300cf
--- /dev/null
+++ b/src/main/java/tk/antoine_roux/wiki/service/GitService.java
@@ -0,0 +1,75 @@
+package tk.antoine_roux.wiki.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import tk.antoine_roux.wiki.model.internal.GitlabCI;
+import tk.antoine_roux.wiki.model.request.HookEvent;
+import tk.antoine_roux.wiki.model.request.secondary.Commit;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Optional;
+
+@Service
+public class GitService {
+
+ public static final String GITLAB_CI_FILE_PATH = ".gitlab-ci.yml";
+ private static final String GITLAB_RUNNER_CLONE_PREFIX = "gitlab-runner-clone";
+ public final UsernamePasswordCredentialsProvider credentialsProvider;
+ private final ObjectMapper objectMapper;
+
+ @Autowired
+ public GitService(UsernamePasswordCredentialsProvider credentialsProvider, @Qualifier("YAMLObjectMapper") ObjectMapper objectMapper) {
+ this.credentialsProvider = credentialsProvider;
+ this.objectMapper = objectMapper;
+ }
+
+ /**
+ * return .gitlab-ci.yml content for {@link HookEvent}
+ */
+ public Optional getYMLGitlabCI(HookEvent hookEvent) throws IOException, GitAPIException {
+ Optional optJob;
+ if (hookEvent.commits.isEmpty()) {
+ optJob = Optional.empty();
+ } else {
+ // search for head commit or take first in event's list of commit
+ Commit commit = hookEvent.commits.stream().filter(co -> co.id.equals(hookEvent.headCommit))
+ .findFirst().orElse(hookEvent.commits.get(0));
+
+ optJob = Optional.of(this.getGitlabCIContent(hookEvent.repository.cloneUrl, commit));
+ }
+ return optJob;
+ }
+
+ /**
+ * return .gitlab-ci.yml content for given commit into cloneUrl repository
+ */
+ private GitlabCI getGitlabCIContent(String cloneURL, Commit commit) throws IOException, GitAPIException {
+ Git call = Git.cloneRepository()
+ .setURI(cloneURL)
+ .setCredentialsProvider(this.credentialsProvider)
+ .setDirectory(Files.createTempDirectory(GITLAB_RUNNER_CLONE_PREFIX).toFile())
+ .call();
+
+ RevWalk revWalk = new RevWalk(call.getRepository());
+ RevCommit revCommit = revWalk.parseCommit(ObjectId.fromString(commit.id));
+
+ try (TreeWalk walk = TreeWalk.forPath(call.getRepository(), GITLAB_CI_FILE_PATH, revCommit.getTree())) {
+ if (walk != null) {
+ byte[] bytes = call.getRepository().open(walk.getObjectId(0)).getBytes();
+ return this.objectMapper.readValue(bytes, GitlabCI.class);
+ } else {
+ throw new IllegalArgumentException("No path found.");
+ }
+ }
+ }
+}
diff --git a/src/main/java/tk/antoine_roux/wiki/service/JobManager.java b/src/main/java/tk/antoine_roux/wiki/service/JobManager.java
index be19773..dd6f00b 100644
--- a/src/main/java/tk/antoine_roux/wiki/service/JobManager.java
+++ b/src/main/java/tk/antoine_roux/wiki/service/JobManager.java
@@ -1,9 +1,9 @@
package tk.antoine_roux.wiki.service;
import org.springframework.stereotype.Service;
-import tk.antoine_roux.wiki.model.internal.HookEvent;
-import tk.antoine_roux.wiki.model.internal.Job;
import tk.antoine_roux.wiki.model.request.JobRequest;
+import tk.antoine_roux.wiki.model.request.HookEvent;
+import tk.antoine_roux.wiki.model.response.JobResponse;
import java.util.Optional;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -12,16 +12,16 @@ import java.util.concurrent.ConcurrentLinkedQueue;
public class JobManager {
/**
- * concurrent list of {@link Job} fill by {@link tk.antoine_roux.wiki.ControllerHandlers#webhook(HookEvent)}
+ * concurrent list of {@link JobResponse} fill by {@link tk.antoine_roux.wiki.ControllerHandlers#webhook(HookEvent)}
* and pop by {@link tk.antoine_roux.wiki.ControllerHandlers#jobRequest(JobRequest)}
*/
- ConcurrentLinkedQueue jobQueue = new ConcurrentLinkedQueue<>();
+ ConcurrentLinkedQueue jobQueue = new ConcurrentLinkedQueue<>();
- public void stackJob(Job newJob) {
+ public void stackJob(JobResponse newJob) {
this.jobQueue.add(newJob);
}
- public Optional popJob(JobRequest jobRequest) {
+ public Optional popJob(JobRequest jobRequest) {
return Optional.ofNullable(this.jobQueue.poll());
}
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 2caf3e1..9d951cc 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,6 +1,7 @@
spring.main.banner-mode=off
spring.main.lazy-initialization=false
spring.output.ansi.enabled=ALWAYS
+spring.jackson.serialization.write-dates-as-timestamps=false
server.port=^application.port^
@@ -17,3 +18,6 @@ info.name=gitlab-runner-gateway
info.more.detail=This is a REST API use to gateway gitlab runner call to gitlab instance
management.endpoints.web.exposure.include=mappings
+
+gitlab-ci.username=
+gitlab-ci.password=