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."); } } } }