diff --git a/README.md b/README.md index 853c132..c29180f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,29 @@ Because permission management can be difficult, this plugin assumes you have created an AWS CodeBuild project with the necessary IAM roles for the job types that you will be running. The project can have any configuration; all settings will be overridden by the plugin to provide a build using source -provided by the Jenkins host. +provided by the Jenkins host. However, it does expect you to have your own +custom `buildspec.yaml` file when creating the project. At runtime on building +your project, the plugin will override the buildspec and replace the following +variables that it expects to connect with the codebuilder jenkins slaves to build +the project. These variables are: + +- `{CODEBUILD_JENKINS_URL}}` +- `{{CODEBUILD_COMPUTER_JNLP_MAC}}` +- `{{CODEBUILD_NODE_DISPLAY_NAME}}` + + A sample buildspec might look like the following: + +```yaml +version: 0.2 +phases: + pre_build: + commands: + - which dockerd-entrypoint.sh >/dev/null && dockerd-entrypoint.sh || exit 0 + build: + commands: + - jenkins-agent -noreconnect -workDir "$CODEBUILD_SRC_DIR" -url "{{CODEBUILD_JENKINS_URL}}" "{{CODEBUILD_COMPUTER_JNLP_MAC}}" "{{CODEBUILD_NODE_DISPLAY_NAME}}" + - exit 0 +``` Once a project is created, you can configure the cloud in Jenkins by adding a new cloud and configuring the plugin in `Manage Jenkins > Configure System`. @@ -56,9 +78,12 @@ aws codebuild create-project \ --service-role jenkins-default \ --artifacts type=NO_ARTIFACTS \ --environment type=LINUX_CONTAINER,image=aws/codebuild/docker:18.09.0,computeType=BUILD_GENERAL1_SMALL \ - --source $'type=NO_SOURCE,buildspec=version:0.2\nphases:\n build:\n commands:\n - exit 1' + --source $'type=NO_SOURCE,buildspec=version: 0.2\nphases:\n pre_build:\n commands:\n - which dockerd-entrypoint.sh >/dev/null && dockerd-entrypoint.sh || exit 0\n build:\n commands:\n - jenkins-agent -noreconnect -workDir "$CODEBUILD_SRC_DIR" -url "{{CODEBUILD_JENKINS_URL}}" "{{CODEBUILD_COMPUTER_JNLP_MAC}}" "{{CODEBUILD_NODE_DISPLAY_NAME}}"\n - exit 0\n' ``` + + + #### Configuring the Plugin In `Manage Jenkins > Configure System` you will find a drop-down to "Add a New diff --git a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java index be856db..34c534c 100644 --- a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java +++ b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java @@ -8,6 +8,8 @@ import com.amazonaws.services.codebuild.model.SourceType; import com.amazonaws.services.codebuild.model.StartBuildRequest; import com.amazonaws.services.codebuild.model.StartBuildResult; +import com.amazonaws.services.codebuild.model.BatchGetProjectsRequest; +import com.amazonaws.services.codebuild.model.BatchGetProjectsResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,8 +66,13 @@ public void launch(@Nonnull SlaveComputer computer, @Nonnull TaskListener listen LOGGER.info("[CodeBuilder]: Launching {} with {}", computer, listener); CodeBuilderComputer cbcpu = (CodeBuilderComputer) computer; + + BatchGetProjectsResult projects = cloud.getClient().batchGetProjects( + new BatchGetProjectsRequest().withNames(cloud.getProjectName()) + ); + String existingBuildSpec = projects.getProjects().get(0).getSource().getBuildspec(); StartBuildRequest req = new StartBuildRequest().withProjectName(cloud.getProjectName()) - .withSourceTypeOverride(SourceType.NO_SOURCE).withBuildspecOverride(buildspec(computer)) + .withSourceTypeOverride(SourceType.NO_SOURCE).withBuildspecOverride(buildspec(existingBuildSpec, computer)) .withImageOverride(cloud.getJnlpImage()).withPrivilegedModeOverride(true) .withComputeTypeOverride(cloud.getComputeType()); @@ -108,23 +115,18 @@ public void beforeDisconnect(@Nonnull SlaveComputer computer, @Nonnull StreamTas } } - private String buildspec(@Nonnull SlaveComputer computer) { + private String buildspec(String existingBuildSpec, @Nonnull SlaveComputer computer) { Node n = computer.getNode(); if (n == null) { return ""; } - String cmd = String.format("jenkins-agent -noreconnect -workDir \"$CODEBUILD_SRC_DIR\" -url \"%s\" \"%s\" \"%s\"", - cloud.getJenkinsUrl(), computer.getJnlpMac(), n.getDisplayName()); - StringBuilder builder = new StringBuilder(); - builder.append("version: 0.2\n"); - builder.append("phases:\n"); - builder.append(" pre_build:\n"); - builder.append(" commands:\n"); - builder.append(" - which dockerd-entrypoint.sh >/dev/null && dockerd-entrypoint.sh || exit 0\n"); - builder.append(" build:\n"); - builder.append(" commands:\n"); - builder.append(" - " + cmd + " || exit 0\n"); - - return builder.toString(); + + // Reformat the buildspec with the variables: + // {{CODEBUILD_JENKINS_URL}}, {{CODEBUILD_COMPUTER_JNLP_MAC}} and {{CODEBUILD_NODE_DISPLAY_NAME}} + String newBuildSpec = existingBuildSpec + .replace("{{CODEBUILD_JENKINS_URL}}", cloud.getJenkinsUrl()) + .replace("{{CODEBUILD_COMPUTER_JNLP_MAC}}", computer.getJnlpMac()) + .replace("{{CODEBUILD_NODE_DISPLAY_NAME}}", n.getDisplayName()); + return newBuildSpec; } } diff --git a/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java b/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java index 2717834..a2c59e7 100644 --- a/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java +++ b/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java @@ -13,7 +13,7 @@ public class CodeBuilderCloudTest { @Test public void initializes_correctly() throws InterruptedException { - CodeBuilderCloud cloud = new CodeBuilderCloud(null, "project", null, null); + CodeBuilderCloud cloud = new CodeBuilderCloud(null, "project", null, "local"); assertEquals("project", cloud.getProjectName()); assertEquals("codebuilder_0", cloud.getDisplayName()); assertNotNull(cloud.getClient());