Introduced in Jenkins 2.171 (weekly) / 2.176.1 (LTS), this library is provided as a way for plugins to use the new multiline secrets UI component until plugins can safely depend on requiring Jenkins 2.176.1 at minimum. See also Storing Secrets in Jenkins for more information about how secrets are used.
Add a dependency in your plugin:
<dependency>
<groupId>io.jenkins.temp.jelly</groupId>
<artifactId>multiline-secrets-ui</artifactId>
<version>1.0</version>
</dependency>
This component binds to fields or values of type hudson.util.Secret
.
Thus, the most common way this can be used would be with getters and setters/constructors with that type.
For example:
public class ModelObject {
private final Secret secretFieldName;
@DataBoundConstructor
public ModelObject(Secret secretFieldName) {
this.secretFieldName = secretFieldName;
}
public Secret getSecretFieldName() {
return secretFieldName;
}
}
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:s="/io/jenkins/temp/jelly">
<f:entry title="Some Secret" field="secretFieldName">
<s:secretTextarea/>
</f:entry>
</j:jelly>
Using inline namespaces:
<jelly xmlns="jelly:core">
<entry xmlns="/lib/form" title="Some Secret" field="secretFieldName">
<secretTextarea xmlns="/io/jenkins/temp/jelly"/>
</entry>
</jelly>
def f = namespace('/lib/form')
def s = namespace('/io/jenkins/temp/jelly')
f.entry(title: 'Some Secret', field: 'secretFieldName') {
s.secretTextarea()
}
Using inline namespaces:
namespace('/lib/form').entry(title: 'Some Secret', field: 'secretFieldName') {
namespace('/io/jenkins/temp/jelly').secretTextarea()
}
In order to update an existing model that isn't already using Secret
, we can simply change the underlying field types to Secret
and allow XML unmarshalling to automatically convert existing strings into secrets.
For example, suppose we have an existing model:
public class LegacyModel {
private final String value;
@DataBoundConstructor
public LegacyModel(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
This can be migrated like so:
public class LegacyModel {
private final Secret value;
@DataBoundConstructor
public LegacyModel(String value) {
this.value = Secret.fromString(value);
}
public String getValue() {
return Secret.toString(value);
}
public Secret getValueSecret() {
return value;
}
}
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:s="/io/jenkins/temp/jelly">
<f:entry title="Some Secret" field="value">
<s:secretTextarea value="${instance.valueSecret}"/>
</f:entry>
</j:jelly>
def f = namespace('/lib/form')
def s = namespace('/io/jenkins/temp/jelly')
f.entry(title: 'Some Secret', field: 'value') {
s.secretTextarea(value: instance.valueSecret)
}
Starting in Jenkins 2.171 and 2.176.1, this component was integrated into Jenkins. To migrate to the Jenkins version of this component:
- Remove usages of the
/io/jenkins/temp/jelly
namespace in Jelly and Groovy views. - Change usage of the
secretTextarea
element to use the/lib/form
namespace as with other form controls.
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:s="/io/jenkins/temp/jelly">
<f:entry title="Some Secret" field="secretFieldName">
<s:secretTextarea/>
</f:entry>
</j:jelly>
becomes
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry title="Some Secret" field="secretFieldName">
<f:secretTextarea/>
</f:entry>
</j:jelly>
Similarly,
def f = namespace('/lib/form')
def s = namespace('/io/jenkins/temp/jelly')
f.entry(title: 'Some Secret', field: 'secretFieldName') {
s.secretTextarea()
}
becomes
def f = namespace('/lib/form')
f.entry(title: 'Some Secret', field: 'secretFieldName') {
f.secretTextarea()
}