Skip to content

Commit

Permalink
[JENKINS-40906] The missing configuration UI
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenc committed Jan 19, 2017
1 parent 068add4 commit c818d7d
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 0 deletions.
Expand Up @@ -32,16 +32,20 @@
import hudson.model.Descriptor;
import hudson.model.TaskListener;
import hudson.scm.SCM;
import hudson.util.FormValidation;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadObserver;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMSource;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution;
Expand All @@ -50,6 +54,8 @@
import org.jenkinsci.plugins.workflow.steps.StepExecution;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;

/**
* Resolves an {@link SCM} from a {@link SCMSource} using a priority list of target branch names.
Expand Down Expand Up @@ -175,6 +181,39 @@ public String getFunctionName() {
public String getDisplayName() {
return "Resolves an SCM from an SCM Source and a list of candidate target branch names";
}

@Override
public Step newInstance(@javax.annotation.CheckForNull StaplerRequest req, @Nonnull JSONObject formData)
throws FormException {
// roll our own because we want the groovy api to be easier than the jelly form binding would have us
JSONObject src = formData.getJSONObject("source");
src.put("id", "_");
SCMSource source = req.bindJSON(SCMSource.class, src);
List<String> targets = new ArrayList<>();
Object t = formData.get("targets");
if (t instanceof JSONObject) {
JSONObject o = (JSONObject) t;
targets.add(o.getString("target"));
} else if (t instanceof JSONArray) {
JSONArray a = (JSONArray) t;
for (int i = 0; i < a.size(); i++) {
JSONObject o = a.getJSONObject(i);
targets.add(o.getString("target"));
}
}
ResolveScmStep step = new ResolveScmStep(source, targets);
if (formData.optBoolean("ignoreErrors", false)) {
step.setIgnoreErrors(true);
}
return step;
}

public FormValidation doCheckTarget(@QueryParameter String value) {
if (StringUtils.isNotBlank(value)) {
return FormValidation.ok();
}
return FormValidation.error("You must supply a target branch name to resolve");
}
}

/**
Expand Down
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License
Copyright 2017 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:dropdownDescriptorSelector field="source" title="${%Source}"/>
<f:entry field="targets" title="${%Targets}">
<f:repeatable name="${targets}" var="targets"
items="${instance.targets}" minimum="1" add="${%Add target}">
<table width="100%">
<tr>
<td width="80%">
<f:textbox name="target"/>
</td>
<td width="auto">
<f:repeatableDeleteButton/>
</td>
</tr>
</table>
</f:repeatable>
</f:entry>
<f:entry field="ignoreErrors" title="${%Ignore Errors}">
<f:checkbox />
</f:entry>
</j:jelly>
@@ -0,0 +1,26 @@
<!--
The MIT License
Copyright 2017 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<div>
When selected, the step will return <code>null</code> in the event that no matching branch can be resolved.
</div>
@@ -0,0 +1,26 @@
<!--
The MIT License
Copyright 2017 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<div>
The source repository from which to resolve the target branches.
</div>
@@ -0,0 +1,26 @@
<!--
The MIT License
Copyright 2017 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<div>
The branch names to try and resolve from the source, in order of preference.
</div>
@@ -0,0 +1,51 @@
<!--
The MIT License
Copyright 2017 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<div>
When you have a multi-branch pipeline that checks out other sibling repositories, you may want to check out the
matching branch from that sibling repository (assuming it exists) but fall back to the main branch if there is no
matching branch.
<p>
This step lets you create a branch in the primary repository and then when you need downstream / upstream changes in
the sibling repository you can just create a matching branch and it will be resolved automatically.
For example:
<pre>// checkout the main source
dir('main'){
// this will checkout the source repository that is driving the multi-branch pipeline
checkout scm
}
// now checkout the tests
dir('tests'){
// this will check if there is a branch with the same name as the current branch in
// https://example.com/example.git and use that for the checkout, but if there is no
// branch with the same name it will fall back to the master branch
checkout resolveScm(source: git('https://example.com/example.git'), targets: [env.BRANCH_NAME,'master']
}
// rest of pipeline
</pre>
<p>
The return value is the resolved SCM instance (or <code>null</code> if ignoring errors).
Where the SCM implementation supports it, the SCM instance will be pinned to the current head revision of
the resolved branch. This can be useful if, for example, you want to check out the resolved branch on
multiple nodes because all the nodes will get the same revision.
</div>

0 comments on commit c818d7d

Please sign in to comment.