Skip to content

Commit

Permalink
Merge pull request #5 from jonesbusy/bugfix/copy
Browse files Browse the repository at this point in the history
Fix stash copy bug and implement test for it
  • Loading branch information
jonesbusy committed Mar 22, 2024
2 parents aa00148 + 8ee5d1d commit aa504f5
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,23 @@ public void copyAllArtifactsAndStashes(@NonNull Run<?, ?> to, @NonNull TaskListe
}
ArtifactoryArtifactManager artifactoryArtifactManager = (ArtifactoryArtifactManager) artifactManager;
try {
listener.getLogger().println(String.format("Copy {0} artifacts and {1} stashes from {2} to {3}"));
String stashedPath = getFilePath("stashes");
String artifactPath = getFilePath("artifacts");
String toStashedPath = artifactoryArtifactManager.getFilePath("stashes");
String toArtifactPath = artifactoryArtifactManager.getFilePath("artifacts");
LOGGER.debug(String.format("Copying artifacts from %s to %s", artifactPath, toArtifactPath));
LOGGER.debug(String.format("Copying stashes from %s to %s", stashedPath, toStashedPath));
ArtifactoryClient client = buildArtifactoryClient();
client.copy(stashedPath, toStashedPath);
client.copy(artifactPath, toArtifactPath);
if (client.isFolder(artifactPath)) {
LOGGER.debug(String.format("Copying artifacts from %s to %s", artifactPath, toArtifactPath));
listener.getLogger()
.println(String.format("Copying artifacts from %s to %s", artifactPath, toArtifactPath));
client.copy(stashedPath, toStashedPath);
}
if (client.isFolder(stashedPath)) {
listener.getLogger()
.println(String.format("Copying stashes from %s to %s", stashedPath, toStashedPath));
LOGGER.debug(String.format("Copying stashes from %s to %s", stashedPath, toStashedPath));

Check warning on line 175 in src/main/java/io/jenkins/plugins/artifactory_artifacts/ArtifactoryArtifactManager.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 166-175 are not covered by tests
client.copy(artifactPath, toArtifactPath);
}
} catch (Exception e) {
listener.getLogger()
.printf("Failed to copy artifact and stashes on Artifactory Storage. Details %s%n", e.getMessage());
Expand Down Expand Up @@ -284,6 +291,10 @@ public Unstash(ArtifactoryClient client, String path, TaskListener listener) thr
public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
try (InputStream is = client.downloadArtifact(path)) {
new FilePath(f).untarFrom(is, FilePath.TarCompression.GZIP);
} catch (Exception e) {
LOGGER.error("Unable to unstash file", e);
listener.getLogger().println(String.format("Unable to unstash file: %s", e.getMessage()));
return null;
} finally {
listener.getLogger().flush();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void shouldDeleteArtifactWhenDeletingJob(JenkinsRule jenkinsRule, WireMoc
StandardCharsets.UTF_8);

// Setup wiremock stubs
setupWireMockStubs(pipelineName, wmRuntimeInfo, "", "artifact.txt");
setupWireMockStubs(pipelineName, wmRuntimeInfo, "", "artifact.txt", "stash.tgz");

// Query job folder
String folderPath = "/api/storage/my-generic-repo/" + pipelineName;
Expand Down Expand Up @@ -85,7 +85,7 @@ public void shouldDeleteArtifactWhenDeletingBuild(JenkinsRule jenkinsRule, WireM
StandardCharsets.UTF_8);

// Setup wiremock stubs
setupWireMockStubs(pipelineName, wmRuntimeInfo, "", "artifact.txt");
setupWireMockStubs(pipelineName, wmRuntimeInfo, "", "artifact.txt", "stash.tgz");

// Query build folder
String folderPath = "/api/storage/my-generic-repo/" + pipelineName + "/1";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected ArtifactoryGenericArtifactConfig configureConfig(
* @param wmRuntimeInfo the WireMock runtime info
*/
protected void setupWireMockStubs(
final String jobName, WireMockRuntimeInfo wmRuntimeInfo, String prefix, String artifact) {
final String jobName, WireMockRuntimeInfo wmRuntimeInfo, String prefix, String artifact, String stash) {
// WireMock stub
WireMock wireMock = wmRuntimeInfo.getWireMock();

Expand All @@ -48,7 +48,8 @@ protected void setupWireMockStubs(
.willReturn(WireMock.okJson("{}")));

// Define the base URL
String basePath = "/api/storage/my-generic-repo/" + prefix + jobName + "/1/artifacts";
String artifactBasePath = "/api/storage/my-generic-repo/" + prefix + jobName + "/1/artifacts";
String stashBasePath = "/my-generic-repo/" + prefix + jobName + "/1/stashes";

// JSON response for folder with children
String artifactsResponse = "{"
Expand All @@ -58,9 +59,22 @@ protected void setupWireMockStubs(
+ "\"lastModified\": \"2024-03-17T13:20:19.836Z\","
+ "\"lastUpdated\": \"2024-03-17T13:20:19.836Z\","
+ "\"modifiedBy\": \"admin\","
+ "\"path\": \"" + basePath + "\","
+ "\"path\": \"" + artifactBasePath + "\","
+ "\"repo\": \"my-generic-repo\","
+ "\"uri\": \"http://localhost:" + wmRuntimeInfo.getHttpPort() + "/artifactory" + basePath + "\""
+ "\"uri\": \"http://localhost:" + wmRuntimeInfo.getHttpPort() + "/artifactory" + artifactBasePath
+ "\""
+ "}";
String stashesResponse = "{"
+ "\"children\": [{\"folder\": false, \"uri\": \"/" + artifact + "\"}],"
+ "\"created\": \"2024-03-17T13:20:19.836Z\","
+ "\"createdBy\": \"admin\","
+ "\"lastModified\": \"2024-03-17T13:20:19.836Z\","
+ "\"lastUpdated\": \"2024-03-17T13:20:19.836Z\","
+ "\"modifiedBy\": \"admin\","
+ "\"path\": \"" + stashBasePath + "\","
+ "\"repo\": \"my-generic-repo\","
+ "\"uri\": \"http://localhost:" + wmRuntimeInfo.getHttpPort() + "/artifactory" + stashBasePath
+ "\""
+ "}";

// JSON response for single artifact
Expand All @@ -70,9 +84,9 @@ protected void setupWireMockStubs(
+ "\"lastModified\": \"2024-03-17T13:20:19.836Z\","
+ "\"lastUpdated\": \"2024-03-17T13:20:19.836Z\","
+ "\"modifiedBy\": \"admin\","
+ "\"path\": \"" + basePath + "/" + artifact + "\","
+ "\"path\": \"" + artifactBasePath + "/" + artifact + "\","
+ "\"repo\": \"my-generic-repo\","
+ "\"uri\": \"http://localhost:" + wmRuntimeInfo.getHttpPort() + "/artifactory" + basePath + "/"
+ "\"uri\": \"http://localhost:" + wmRuntimeInfo.getHttpPort() + "/artifactory" + artifactBasePath + "/"
+ artifact + "\""
+ "}";

Expand All @@ -81,10 +95,14 @@ protected void setupWireMockStubs(
+ "\", \"repo\": \"my-generic-repo\", \"path\": \"" + prefix + "/" + jobName + "/1/artifacts\"}]}";

// Register GET requests
wireMock.register(
WireMock.get(WireMock.urlEqualTo(basePath + "/")).willReturn(WireMock.okJson(artifactsResponse)));
wireMock.register(WireMock.get(WireMock.urlEqualTo(basePath + "/" + artifact))
wireMock.register(WireMock.get(WireMock.urlEqualTo(artifactBasePath + "/"))
.willReturn(WireMock.okJson(artifactsResponse)));
wireMock.register(WireMock.get(WireMock.urlEqualTo(artifactBasePath + "/" + artifact))
.willReturn(WireMock.okJson(artifactResponse)));
wireMock.register(
WireMock.get(WireMock.urlEqualTo(stashBasePath + "/")).willReturn(WireMock.okJson(stashesResponse)));
wireMock.register(WireMock.get(WireMock.urlEqualTo(stashBasePath + "/" + stash))
.willReturn(WireMock.ok().withBodyFile(stash).withHeader("Content-Type", "application/gzip")));

// Register POST request
wireMock.register(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import org.apache.commons.io.IOUtils;
import org.htmlunit.html.HtmlAnchor;
import org.htmlunit.html.HtmlPage;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
Expand All @@ -33,7 +35,7 @@ public void testPipelineWithPrefix(JenkinsRule jenkinsRule, WireMockRuntimeInfo
StandardCharsets.UTF_8);

// Setup wiremock stubs
setupWireMockStubs(pipelineName, wmRuntimeInfo, "jenkins/", "artifact.txt");
setupWireMockStubs(pipelineName, wmRuntimeInfo, "jenkins/", "artifact.txt", "stash.tgz");

// Run job
WorkflowJob workflowJob = jenkinsRule.createProject(WorkflowJob.class, pipelineName);
Expand All @@ -59,7 +61,7 @@ public void testPipelineWithoutPrefix(JenkinsRule jenkinsRule, WireMockRuntimeIn
StandardCharsets.UTF_8);

// Setup wiremock stubs
setupWireMockStubs(pipelineName, wmRuntimeInfo, "", "artifact.txt");
setupWireMockStubs(pipelineName, wmRuntimeInfo, "", "artifact.txt", "stash.tgz");

// Run job
WorkflowJob workflowJob = jenkinsRule.createProject(WorkflowJob.class, pipelineName);
Expand Down Expand Up @@ -88,7 +90,7 @@ public void testPipelineOnAgentWithPrefix(JenkinsRule jenkinsRule, WireMockRunti
DumbSlave s = jenkinsRule.createSlave(Label.get("agent"));

// Setup wiremock stubs
setupWireMockStubs(pipelineName, wmRuntimeInfo, "jenkins/", "artifact.txt");
setupWireMockStubs(pipelineName, wmRuntimeInfo, "jenkins/", "artifact.txt", "stash.tgz");

// Run job
WorkflowJob workflowJob = jenkinsRule.createProject(WorkflowJob.class, pipelineName);
Expand All @@ -102,4 +104,38 @@ public void testPipelineOnAgentWithPrefix(JenkinsRule jenkinsRule, WireMockRunti
// Check 1 artifact
assertThat(run1.getArtifacts(), hasSize(1));
}

@Test
public void testReplay(JenkinsRule jenkinsRule, WireMockRuntimeInfo wmRuntimeInfo) throws Exception {

final String pipelineName = "testReplay";

configureConfig(jenkinsRule, wmRuntimeInfo, "jenkins/");
String pipeline = IOUtils.toString(
Objects.requireNonNull(PipelineTest.class.getResourceAsStream("/pipelines/replay.groovy")),
StandardCharsets.UTF_8);

// Setup wiremock stubs
setupWireMockStubs(pipelineName, wmRuntimeInfo, "jenkins/", "artifact.txt", "stash.tgz");

// Run job
WorkflowJob workflowJob = jenkinsRule.createProject(WorkflowJob.class, pipelineName);
workflowJob.setDefinition(new CpsFlowDefinition(pipeline, true));
WorkflowRun run1 = Objects.requireNonNull(workflowJob.scheduleBuild2(0)).waitForStart();
jenkinsRule.waitForCompletion(run1);

// Print pipeline logs
System.out.println(run1.getLog());

// Job success
assertThat(run1.getResult(), equalTo(hudson.model.Result.SUCCESS));

// Perform replay of the pipline
HtmlPage buildPage = jenkinsRule.createWebClient().goTo("job/testReplay/1");
final HtmlAnchor replayLink = buildPage.getAnchorByText("Replay");
final HtmlPage replayPage = replayLink.click();
// HtmlSelect stageSelect = replayPage.getFirstByXPath("//select[@name='Result']");
// final HtmlOption resultOption = stageSelect.getOptionByText("Result");
// stageSelect.setSelectedAttribute(resultOption, true);
}
}
Binary file added src/test/resources/__files/stash.tgz
Binary file not shown.
32 changes: 32 additions & 0 deletions src/test/resources/pipelines/replay.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//file:noinspection GrPackage
pipeline {
agent none
options {
preserveStashes()
}
stages {
stage('Agent 1') {
agent {
label 'built-in'
}
steps {
script {
if (isUnix()) {
sh 'mkdir target && echo "Hello" > target/foo.txt'
} else {
bat 'mkdir target && echo "Hello" > target/foo.txt'
}
}
stash(name: 'stash', includes: 'target/**')
}
}
stage('Result') {
agent {
label 'built-in'
}
steps {
unstash(name: 'stash')
}
}
}
}

0 comments on commit aa504f5

Please sign in to comment.