Skip to content
Permalink
Browse files

[JENKINS-24626] Added permission check, help texts for DownstreamBuil…

…dSelector.
  • Loading branch information...
ikedam committed Sep 19, 2014
1 parent 1515de1 commit 7277e1d46b9f630b0caec62b2a6791f471bb203a
@@ -29,14 +29,17 @@
import jenkins.model.Jenkins;

import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;

import hudson.EnvVars;
import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Run;
import hudson.util.FormValidation;

/**
* Select a build which is a downstream of a specified build.
@@ -52,8 +55,8 @@
*/
@DataBoundConstructor
public DownstreamBuildSelector(String upstreamProjectName, String upstreamBuildNumber) {
this.upstreamProjectName = upstreamProjectName;
this.upstreamBuildNumber = upstreamBuildNumber;
this.upstreamProjectName = StringUtils.trim(upstreamProjectName);
this.upstreamBuildNumber = StringUtils.trim(upstreamBuildNumber);
}

/**
@@ -95,12 +98,12 @@ protected boolean isSelectable(Run<?, ?> run, EnvVars env) {
run.getParent(),
AbstractProject.class
);
if (upstreamProject == null) {
if (upstreamProject == null || !upstreamProject.hasPermission(Jenkins.READ)) {
LOGGER.warning(String.format("Upstream project '%s' is not found.", upstreamProject));
return false;
}
AbstractBuild<?,?> upstreamBuild = ((AbstractBuild<?,?>)run).getUpstreamRelationshipBuild(upstreamProject);
if (upstreamBuild == null) {
if (upstreamBuild == null || !upstreamBuild.hasPermission(Jenkins.READ)) {
LOGGER.fine(String.format("No upstream build of project '%s' is found for build %s-%s.", upstreamProject, run.getParent().getFullName(), run.getDisplayName()));
return false;
}
@@ -115,8 +118,8 @@ protected boolean isSelectable(Run<?, ?> run, EnvVars env) {
// Ignore. Nothing to do.
}

if (buildNumber.equals(upstreamBuild.getDisplayName())) {
// build name matches.
if (buildNumber.equals(upstreamBuild.getId()) || buildNumber.equals(upstreamBuild.getDisplayName())) {
// id or display name matches.
return true;
}

@@ -130,5 +133,110 @@ protected boolean isSelectable(Run<?, ?> run, EnvVars env) {
public String getDisplayName() {
return Messages.DownstreamBuildSelector_DisplayName();
}

/**
* @param str
* @return whether a value contains variable expressions.
*/
protected boolean containsVariable(String str) {
return !StringUtils.isBlank(str) && str.indexOf('$') >= 0;
}

/**
* Validates a form input to "Upstream Project Name"
*
* @return
*/
public FormValidation doCheckUpstreamProjectName(
@AncestorInPath AbstractProject<?,?> project,
@QueryParameter String upstreamProjectName
) {
upstreamProjectName = StringUtils.trim(upstreamProjectName);
if (StringUtils.isBlank(upstreamProjectName)) {
return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamProjectName_Required());
}

if (containsVariable(upstreamProjectName)) {
return FormValidation.ok();
}

AbstractProject<?,?> upstreamProject = Jenkins.getInstance().getItem(
upstreamProjectName, project, AbstractProject.class
);
if (upstreamProject == null || upstreamProject.hasPermission(Jenkins.READ)) {
return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamProjectName_NotFound());
}
return FormValidation.ok();
}

/**
* Validates a form input to "Upstream Build Number"
*
* @return
*/
public FormValidation doCheckUpstreamBuildNumber(
@AncestorInPath AbstractProject<?,?> project,
@QueryParameter String upstreamProjectName,
@QueryParameter String upstreamBuildNumber
) {
// This is useless in almost all cases as this is usually specified with variables.

upstreamProjectName = StringUtils.trim(upstreamProjectName);
upstreamBuildNumber = StringUtils.trim(upstreamBuildNumber);

if (StringUtils.isBlank(upstreamProjectName) || containsVariable(upstreamProjectName)) {
// skip validation
return FormValidation.ok();
}

if (StringUtils.isBlank(upstreamBuildNumber)) {
return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamBuildNumber_Required());
}

if (containsVariable(upstreamBuildNumber)) {
return FormValidation.ok();
}

AbstractProject<?,?> upstreamProject = Jenkins.getInstance().getItem(
upstreamProjectName, project, AbstractProject.class
);
if (upstreamProject == null || upstreamProject.hasPermission(Jenkins.READ)) {
return FormValidation.ok();
}

try {
int number = Integer.parseInt(upstreamBuildNumber);
AbstractBuild<?,?> upstreamBuild = upstreamProject.getBuildByNumber(number);
if (upstreamBuild != null && upstreamBuild.hasPermission(Jenkins.READ)) {
// build number matches.
return FormValidation.ok();
}
} catch (NumberFormatException e) {
// Ignore. Nothing to do.
}

{
AbstractBuild<?,?> upstreamBuild = upstreamProject.getBuild(upstreamBuildNumber);
if (upstreamBuild != null && upstreamBuild.hasPermission(Jenkins.READ)) {
// build id matches.
return FormValidation.ok();
}
}

{
for(
AbstractBuild<?,?> upstreamBuild = upstreamProject.getLastCompletedBuild();
upstreamBuild != null;
upstreamBuild = upstreamBuild.getPreviousCompletedBuild()
) {
if (upstreamBuild.getDisplayName().equals(upstreamBuildNumber)) {
// display name matches.
return FormValidation.ok();
}
}
}

return FormValidation.error(Messages.DownstreamBuildSelector_UpstreamBuildNumber_NotFound());
}
}
}
@@ -26,7 +26,7 @@ THE SOFTWARE.
<f:entry title="${%Upstream Project Name}" field="upstreamProjectName">
<f:textbox />
</f:entry>
<f:entry title="${%Upstream Project Number}" field="upstreamBuildNumber">
<f:entry title="${%Upstream Build Number}" field="upstreamBuildNumber">
<f:textbox />
</f:entry>
</j:jelly>
@@ -0,0 +1,24 @@
# The MIT License
#
# Copyright (c) 2014 IKEDA Yasuyuki
#
# 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.

Upstream\ Project\ Name=\u4e0a\u6d41\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u540d
Upstream\ Build\ Number=\u4e0a\u6d41\u306e\u30d3\u30eb\u30c9\u756a\u53f7
@@ -0,0 +1,5 @@
<div>
The number of the build to find its downstream build.
You can also specify display names.
You can use variable expressions.
</div>
@@ -0,0 +1,5 @@
<div>
下流ビルドを探すビルドのビルド番号を指定します。
表示名での指定も可能です。
変数を利用可能です。
</div>
@@ -0,0 +1,11 @@
<div>
<p>
Copy artifacts from a build that is a downstream of a build of the specified project.
You can use variable expressions.
</p>
<p>
Downstream builds are found using fingerprints of files.
That is, a build that is triggerd from a build isn't always considered downstream,
but you need to fingerprint files used in builds to let Jenkins track them.
</p>
</div>
@@ -0,0 +1,10 @@
<div>
<p>
指定したプロジェクトのビルドの下流ビルドから成果物をコピーします。
変数を使用できます。
</p>
<p>
下流ビルドはファイル指紋を使用して判定されます。
このため、単にビルドをトリガーしただけでは下流ビルドとはみなされず、ビルドで共通で使用したファイルの指紋を記録して Jenkins がファイルの利用状況を追跡できるようにする必要があることに注意してください。
</p>
</div>
@@ -25,3 +25,7 @@ WorkspaceSelector.DisplayName=Copy from WORKSPACE of latest completed build
CopyArtifactPermissionProperty.DisplayName=Permission to Copy Artifact
CopyArtifactPermissionProperty.MissingProject=Unable to find project: {0}
DownstreamBuildSelector.DisplayName=Downstream build of
DownstreamBuildSelector.UpstreamProjectName.Required=Required
DownstreamBuildSelector.UpstreamProjectName.NotFound=Not Found
DownstreamBuildSelector.UpstreamBuildNumber.Required=Required
DownstreamBuildSelector.UpstreamBuildNumber.NotFound=Not Found
@@ -18,4 +18,13 @@ BuildSelectorParameter.DisplayName=Copy Artifact\u7528\u30d3\u30eb\u30c9\u30bb\u
WorkspaceSelector.DisplayName=\u6700\u65b0\u306e\u5b8c\u4e86\u3057\u305f\u30d3\u30eb\u30c9\u306e\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u304b\u3089\u30b3\u30d4\u30fc
CopyArtifactPermissionProperty.DisplayName=\u6210\u679c\u7269\u306e\u30b3\u30d4\u30fc\u306e\u8a31\u53ef
CopyArtifactPermissionProperty.MissingProject=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093: {0}
DownstreamBuildSelector.DisplayName=\u6307\u5b9a\u30d3\u30eb\u30c9\u306e\u4e0b\u6d41\u30d3\u30eb\u30c9
#DownstreamBuildSelector.DisplayName=指定ビルドの下流ビルド
DownstreamBuildSelector.DisplayName=\u6307\u5b9a\u30d3\u30eb\u30c9\u306e\u4e0b\u6d41\u30d3\u30eb\u30c9
#DownstreamBuildSelector.UpstreamProjectName.Required=入力してください
DownstreamBuildSelector.UpstreamProjectName.Required=\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044
#DownstreamBuildSelector.UpstreamProjectName.NotFound=指定のプロジェクトが見つかりません
DownstreamBuildSelector.UpstreamProjectName.NotFound=\u6307\u5b9a\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
#DownstreamBuildSelector.UpstreamBuildNumber.Required=入力してください
DownstreamBuildSelector.UpstreamBuildNumber.Required=\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044
#DownstreamBuildSelector.UpstreamBuildNumber.NotFound=指定のビルドが見つかりません
DownstreamBuildSelector.UpstreamBuildNumber.NotFound=\u6307\u5b9a\u306e\u30d3\u30eb\u30c9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093

0 comments on commit 7277e1d

Please sign in to comment.
You can’t perform that action at this time.