Skip to content

Commit

Permalink
it: move runtime-v2 github tests into runtime-v2 module (#1889)
Browse files Browse the repository at this point in the history
  • Loading branch information
brig authored and ibodrov committed Jul 30, 2020
1 parent 45007c4 commit 3e4cd57
Show file tree
Hide file tree
Showing 17 changed files with 325 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,38 @@

import com.walmartlabs.concord.common.IOUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.RefSpec;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermissions;

public final class GitUtils {

public static Path createBareRepository(Path data) throws Exception {
return createBareRepository(data, "initial message");
return createBareRepository(data, (Path)null);
}

public static Path createBareRepository(Path data, Path baseTmpDir) throws Exception {
return createBareRepository(data, "initial message", baseTmpDir);
}

public static Path createBareRepository(Path data, String commitMessage) throws Exception {
return createBareRepository(data, commitMessage, null);
}

public static Path createBareRepository(Path data, String commitMessage, Path baseTmpDir) throws Exception {
// init bare repository
Path tmp = createTempDir();
Path tmp = createTempDir(baseTmpDir);
Path repo = tmp.resolve("test");
Files.createDirectories(repo);

Git.init().setBare(true).setDirectory(repo.toFile()).call();

// clone the repository into a new directory
Path workdir = createTempDir();
Path workdir = createTempDir(baseTmpDir);
Git git = Git.cloneRepository()
.setDirectory(workdir.toFile())
.setURI("file://" + repo.toString())
Expand All @@ -60,8 +70,45 @@ public static Path createBareRepository(Path data, String commitMessage) throws
return repo;
}

protected static Path createTempDir() throws IOException {
Path tmpDir = Files.createTempDirectory("test");
public static void createNewBranch(Path bareRepo, String branch, Path src) throws Exception {
createNewBranch(bareRepo, branch, src, null);
}

public static void createNewBranch(Path bareRepo, String branch, Path src, Path baseTmpDir) throws Exception {
Path dir = createTempDir(baseTmpDir);

Git git = Git.cloneRepository()
.setDirectory(dir.toFile())
.setURI(bareRepo.toAbsolutePath().toString())
.call();

git.checkout()
.setCreateBranch(true)
.setName(branch)
.call();

IOUtils.copy(src, dir, StandardCopyOption.REPLACE_EXISTING);

git.add()
.addFilepattern(".")
.call();

git.commit()
.setMessage("adding files from " + src.getFileName())
.call();

git.push()
.setRefSpecs(new RefSpec(branch + ":" + branch))
.call();
}

protected static Path createTempDir(Path base) throws IOException {
Path tmpDir ;
if (base != null) {
tmpDir = Files.createTempDirectory(base, "test");
} else {
tmpDir = Files.createTempDirectory("test");
}
Files.setPosixFilePermissions(tmpDir, PosixFilePermissions.fromString("rwxr-xr-x"));
return tmpDir;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermissions;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

Expand All @@ -56,6 +60,17 @@ public static byte[] archive(URI uri, String depsDir) throws IOException {
return out.toByteArray();
}

public static String resourceToString(Class<?> klass, String resource) throws Exception {
URL url = klass.getResource(resource);

ByteArrayOutputStream out = new ByteArrayOutputStream();
try (InputStream in = url.openStream()) {
IOUtils.copy(in, out);
}

return new String(out.toByteArray());
}

public static Path createTempDir() throws IOException {
Path dir = IOUtils.createTempDir("test");
Files.setPosixFilePermissions(dir, PosixFilePermissions.fromString("rwxr-xr-x"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,25 @@
import ca.ibodrov.concord.testcontainers.junit4.ConcordRule;
import org.testcontainers.images.PullPolicy;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public final class ConcordConfiguration {

private static final Path sharedDir = Paths.get(System.getProperty("java.io.tmpdir")).resolve("concord-it");

static {
if (Files.notExists(sharedDir)) {
try {
Files.createDirectories(sharedDir);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

public static ConcordRule configure() {
ConcordRule concord = new ConcordRule()
.pathToRunnerV1(null)
Expand All @@ -35,6 +52,7 @@ public static ConcordRule configure() {
.pullPolicy(PullPolicy.defaultPolicy())
.streamServerLogs(true)
.streamAgentLogs(true)
.sharedContainerDir(sharedDir)
.useLocalMavenRepository(true);

boolean localMode = Boolean.parseBoolean(System.getProperty("it.local.mode"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package com.walmartlabs.concord.it.runtime.v2;

/*-
* *****
* Concord
* -----
* Copyright (C) 2017 - 2019 Walmart Inc.
* -----
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =====
*/

import ca.ibodrov.concord.testcontainers.ProcessListQuery;
import ca.ibodrov.concord.testcontainers.junit4.ConcordRule;
import com.google.common.collect.ImmutableMap;
import com.walmartlabs.concord.ApiClient;
import com.walmartlabs.concord.client.*;
import com.walmartlabs.concord.it.common.GitHubUtils;
import com.walmartlabs.concord.it.common.GitUtils;
import com.walmartlabs.concord.it.common.ITUtils;
import org.junit.ClassRule;
import org.junit.Test;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static com.walmartlabs.concord.it.common.ITUtils.randomString;
import static com.walmartlabs.concord.it.runtime.v2.ITConstants.DEFAULT_TEST_TIMEOUT;
import static org.junit.Assert.assertEquals;

public class GitHubTriggersV2IT {

@ClassRule
public static final ConcordRule concord = ConcordConfiguration.configure();

/**
* Test subscription to unknown repositories only:
* <pre>
* # project A
* # a default onPush trigger for the default branch
* triggers:
* - github:
* entryPoint: onPush
*
* # project G
* # accepts only specific commit authors
* triggers:
* - github:
* author: ".*xyz.*"
* entryPoint: onPush
* </pre>
*/
@Test(timeout = DEFAULT_TEST_TIMEOUT)
public void testFilterBySender() throws Exception {
String orgXName = "orgX_" + randomString();
concord.organizations().create(orgXName);

Path repo = initRepo("triggers/github/repos/v2/defaultTrigger");
String branch = "branch_" + randomString();
createNewBranch(repo, branch, "triggers/github/repos/v2/defaultTriggerWithSender");

// Project A
// master branch + a default trigger
String projectAName = "projectA_" + randomString();
String repoAName = "repoA_" + randomString();
Path projectARepo = initProjectAndRepo(orgXName, projectAName, repoAName, null, initRepo("triggers/github/repos/v2/defaultTrigger"));
refreshRepo(orgXName, projectAName, repoAName);

// Project G
// accepts only specific commit authors
String projectGName = "projectG_" + randomString();
String repoGName = "repoG_" + randomString();
Path projectBRepo = initProjectAndRepo(orgXName, projectGName, repoGName, null, initRepo("triggers/github/repos/v2/defaultTriggerWithSender"));
refreshRepo(orgXName, projectGName, repoGName);

// ---

sendEvent("triggers/github/events/direct_branch_push.json", "push",
"_FULL_REPO_NAME", toRepoName(projectARepo),
"_REF", "refs/heads/master",
"_USER_NAME", "aknowndude",
"_USER_LDAP_DN", "");

// A's triggers should be activated
ProcessEntry procA = waitForAProcess(orgXName, projectAName, "github");
expectNoProcesses(orgXName, projectGName, null);

// ---

sendEvent("triggers/github/events/direct_branch_push.json", "push",
"_FULL_REPO_NAME", toRepoName(projectBRepo),
"_REF", "refs/heads/master",
"_USER_NAME", "somecooldude",
"_USER_LDAP_DN", "");

// G's triggers should be activated
waitForAProcess(orgXName, projectGName, "github");

// no A's are expected
expectNoProcesses(orgXName, projectAName, procA);
}

@Test(timeout = DEFAULT_TEST_TIMEOUT)
public void testOnPushWithFullTriggerParams() throws Exception {
String orgXName = "orgX_" + randomString();
concord.organizations().create(orgXName);

// Project A
// master branch + a default trigger
String projectAName = "projectA_" + randomString();
String repoAName = "repoA_" + randomString();
initProjectAndRepo(orgXName, projectAName, repoAName, null, initRepo("triggers/github/repos/v2/allParamsTrigger"));
refreshRepo(orgXName, projectAName, repoAName);

// ---

sendEvent("triggers/github/events/direct_branch_push.json", "push",
"_FULL_REPO_NAME", "devtools/concord",
"_REF", "refs/heads/master",
"_USER_NAME", "vasia",
"_USER_LDAP_DN", "");

// A's trigger should be activated
waitForAProcess(orgXName, projectAName, "github");
}

private static Path initRepo(String resource) throws Exception {
Path src = Paths.get(GitHubTriggersV2IT.class.getResource(resource).toURI());
return GitUtils.createBareRepository(src, concord.sharedContainerDir());
}

private static void createNewBranch(Path bareRepo, String branch, String resource) throws Exception {
Path src = Paths.get(GitHubTriggersV2IT.class.getResource(resource).toURI());
GitUtils.createNewBranch(bareRepo, branch, src);
}

private static Path initProjectAndRepo(String orgName, String projectName, String repoName, String repoBranch, Path bareRepo) throws Exception {
// TODO: up concord test rule for projects with repository
ProjectsApi projectsApi = new ProjectsApi(apiClient());

RepositoryEntry repo = new RepositoryEntry()
.setBranch(repoBranch)
.setUrl(bareRepo.toAbsolutePath().toString());

projectsApi.createOrUpdate(orgName, new ProjectEntry()
.setName(projectName)
.setRawPayloadMode(ProjectEntry.RawPayloadModeEnum.EVERYONE)
.setRepositories(ImmutableMap.of(repoName, repo)));

return bareRepo;
}

private static void refreshRepo(String orgName, String projectName, String repoName) throws Exception {
RepositoriesApi repoApi = new RepositoriesApi(apiClient());
repoApi.refreshRepository(orgName, projectName, repoName, true);
}

private static void sendEvent(String resource, String event, String... params) throws Exception {
String payload = resourceToString(resource);
if (params != null) {
for (int i = 0; i < params.length; i += 2) {
String k = params[i];
String v = params[i + 1];
payload = payload.replaceAll(k, v);
}
}

ApiClient client = apiClient();
client.addDefaultHeader("X-Hub-Signature", "sha1=" + GitHubUtils.sign(payload));

GitHubEventsApi eventsApi = new GitHubEventsApi(client);
eventsApi.onEvent(payload, "abc", event);
}

private static String resourceToString(String resource) throws Exception {
return ITUtils.resourceToString(GitHubTriggersV2IT.class, resource);
}

private static String toRepoName(Path p) {
return p.getParent() .getFileName()+ "/" + p.getFileName();
}

private static ProcessEntry waitForAProcess(String orgName, String projectName, String initiator) throws Exception {
ProcessListQuery q = ProcessListQuery.builder()
.orgName(orgName)
.projectName(projectName)
.initiator(initiator)
.build();

while (!Thread.currentThread().isInterrupted()) {
List<ProcessEntry> l = concord.processes().list(q);
if (l.size() == 1 && isFinished(l.get(0).getStatus())) {
return l.get(0);
}

Thread.sleep(1000);
}

throw new RuntimeException("Process wait interrupted");
}

private static boolean isFinished(ProcessEntry.StatusEnum status) {
return status == ProcessEntry.StatusEnum.CANCELLED ||
status == ProcessEntry.StatusEnum.FAILED ||
status == ProcessEntry.StatusEnum.FINISHED ||
status == ProcessEntry.StatusEnum.TIMED_OUT;
}

private static void expectNoProcesses(String orgName, String projectName, ProcessEntry after) throws Exception {
ProcessListQuery q = ProcessListQuery.builder()
.orgName(orgName)
.projectName(projectName)
.afterCreatedAt(after != null ? after.getCreatedAt() : null)
.build();

List<ProcessEntry> l = concord.processes().list(q);
assertEquals(0, l.size());
}

private static ApiClient apiClient() {
return concord.apiClient();
}
}

0 comments on commit 3e4cd57

Please sign in to comment.