|
30 | 30 | import hudson.cli.handlers.GenericItemOptionHandler; |
31 | 31 | import hudson.model.Job; |
32 | 32 | import hudson.model.Run; |
| 33 | +import java.io.BufferedOutputStream; |
| 34 | +import java.io.ByteArrayOutputStream; |
| 35 | +import java.io.InputStream; |
| 36 | +import java.util.AbstractMap.SimpleEntry; |
| 37 | +import java.util.ArrayList; |
33 | 38 | import java.util.HashMap; |
34 | 39 | import java.util.Map; |
| 40 | +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; |
| 41 | +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; |
35 | 42 | import org.apache.commons.io.IOUtils; |
36 | | -import org.jenkinsci.plugins.workflow.cps.replay.Messages; |
37 | 43 | import org.kohsuke.args4j.Argument; |
38 | 44 | import org.kohsuke.args4j.CmdLineParser; |
39 | 45 | import org.kohsuke.args4j.Option; |
40 | 46 | import org.kohsuke.args4j.OptionDef; |
41 | 47 | import org.kohsuke.args4j.spi.Setter; |
42 | 48 |
|
| 49 | + |
43 | 50 | @Extension public class ReplayPipelineCommand extends CLICommand { |
44 | 51 |
|
45 | 52 | @Argument(required=true, index=0, metaVar="JOB", usage="Name of the job to replay.", handler=JobHandler.class) |
|
51 | 58 | @Option(name="-s", aliases="--script", metaVar="SCRIPT", usage="Name of script to edit, such as Script3, if not the main Jenkinsfile.") |
52 | 59 | public String script; |
53 | 60 |
|
| 61 | + @Option(name="-S", aliases="--scripts", usage="Pass tarball of override scripts to override build scripts on remote") |
| 62 | + private boolean scripts; |
| 63 | + |
54 | 64 | @Override public String getShortDescription() { |
55 | 65 | return Messages.ReplayCommand_shortDescription(); |
56 | 66 | } |
|
70 | 80 | if (!action.isEnabled()) { |
71 | 81 | throw new AbortException("Not authorized to replay builds of this job"); |
72 | 82 | } |
73 | | - String text = IOUtils.toString(stdin); |
74 | | - if (script != null) { |
75 | | - Map<String,String> replacementLoadedScripts = new HashMap<String,String>(action.getOriginalLoadedScripts()); |
76 | | - if (!replacementLoadedScripts.containsKey(script)) { |
77 | | - throw new AbortException("Unrecognized script name among " + replacementLoadedScripts.keySet()); |
| 83 | + if (scripts) { |
| 84 | + ArrayList<SimpleEntry<String,String>> replacementScripts = parseScripts(stdin); |
| 85 | + Map<String,String> replacementLoadedScripts = new HashMap<>(action.getOriginalLoadedScripts()); |
| 86 | + Boolean overrideJenkinsfile = false; |
| 87 | + String jenkinsfileContent = ""; |
| 88 | + |
| 89 | + for (SimpleEntry<String,String> pair : replacementScripts) { |
| 90 | + String scriptName = pair.getKey(); |
| 91 | + String scriptContent = pair.getValue(); |
| 92 | + |
| 93 | + if (scriptName.equals("Jenkinsfile")) { |
| 94 | + overrideJenkinsfile = true; |
| 95 | + jenkinsfileContent = scriptContent; |
| 96 | + } else { |
| 97 | + if (!replacementLoadedScripts.containsKey(scriptName)) { |
| 98 | + throw new AbortException("Unrecognized script name " + scriptName + " among " + replacementLoadedScripts.keySet()); |
| 99 | + } |
| 100 | + replacementLoadedScripts.put(scriptName, scriptContent); |
| 101 | + } |
78 | 102 | } |
79 | | - replacementLoadedScripts.put(script, text); |
80 | | - action.run(action.getOriginalScript(), replacementLoadedScripts); |
| 103 | + |
| 104 | + if (!overrideJenkinsfile) |
| 105 | + jenkinsfileContent = action.getOriginalScript(); |
| 106 | + |
| 107 | + action.run(jenkinsfileContent, replacementLoadedScripts); |
81 | 108 | } else { |
82 | | - action.run(text, action.getOriginalLoadedScripts()); |
| 109 | + String text = IOUtils.toString(stdin); |
| 110 | + if (script != null) { |
| 111 | + Map<String, String> replacementLoadedScripts = new HashMap<String, String>(action.getOriginalLoadedScripts()); |
| 112 | + if (!replacementLoadedScripts.containsKey(script)) { |
| 113 | + throw new AbortException("Unrecognized script name among " + replacementLoadedScripts.keySet()); |
| 114 | + } |
| 115 | + replacementLoadedScripts.put(script, text); |
| 116 | + action.run(action.getOriginalScript(), replacementLoadedScripts); |
| 117 | + } else { |
| 118 | + action.run(text, action.getOriginalLoadedScripts()); |
| 119 | + } |
83 | 120 | } |
84 | 121 | return 0; |
85 | 122 | } |
86 | 123 |
|
| 124 | + protected ArrayList<SimpleEntry<String,String>> parseScripts(InputStream tarInputStream) throws Exception { |
| 125 | + ArrayList<SimpleEntry<String, String>> list = new ArrayList<>(); |
| 126 | + |
| 127 | + try ( TarArchiveInputStream tarIn = new TarArchiveInputStream(tarInputStream) ) { |
| 128 | + TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); |
| 129 | + |
| 130 | + while (tarEntry != null) { |
| 131 | + String scriptName = tarEntry.getName(); |
| 132 | + |
| 133 | + int BUFFER_SIZE = 512; |
| 134 | + int count; |
| 135 | + byte data[] = new byte[BUFFER_SIZE]; |
| 136 | + |
| 137 | + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); |
| 138 | + BufferedOutputStream outStream = new BufferedOutputStream(byteStream, BUFFER_SIZE); |
| 139 | + while ((count = tarIn.read(data, 0, BUFFER_SIZE)) != -1) { |
| 140 | + outStream.write(data, 0, count); |
| 141 | + } |
| 142 | + outStream.flush(); |
| 143 | + String scriptContent = new String(byteStream.toByteArray()); |
| 144 | + |
| 145 | + SimpleEntry<String, String> entry = new SimpleEntry<>(scriptName, scriptContent); |
| 146 | + list.add(entry); |
| 147 | + |
| 148 | + tarEntry = tarIn.getNextTarEntry(); |
| 149 | + } |
| 150 | + } catch ( Exception e) { |
| 151 | + throw e; |
| 152 | + } |
| 153 | + |
| 154 | + return list; |
| 155 | + } |
| 156 | + |
87 | 157 | @SuppressWarnings("rawtypes") |
88 | 158 | public static class JobHandler extends GenericItemOptionHandler<Job> { |
89 | 159 |
|
|
0 commit comments