Skip to content

Commit 4967aa7

Browse files
niklucasMarkEWaite
andauthored
Add nonStoredPassword symbol for Pipeline syntax (#102)
* Add nonStoredPassword Symbol value Jenkins Symbol Annotation: Official Guide: https://www.jenkins.io/doc/developer/extensibility/extension-points/#symbol Javadoc: https://javadoc.jenkins.io/jenkins/Symbol.html > The @symbol annotation allows Jenkins Pipeline DSL to reference extensions using a short, memorable name rather than the full class name. * Add DeclarativePipelineTest.java * Add scripted pipeline test * Update README * Use consistent white space * Add two Pipeline test dependencies * Format new tests with spotless * Remove unnecessary extra space --------- Co-authored-by: Mark Waite <[email protected]>
1 parent acb8bc9 commit 4967aa7

File tree

5 files changed

+152
-0
lines changed

5 files changed

+152
-0
lines changed

docs/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,37 @@ output:
5151

5252
![](docs/images/console-after.png)
5353

54+
# Pipeline Support
55+
56+
This plugin provides the `nonStoredPassword` parameter type for Jenkins pipelines, allowing you to define password parameters that are only provided at runtime and not stored in the job configuration. This is ideal for sensitive credentials that should not persist in your pipeline code.
57+
58+
**Declarative Pipeline Example:**
59+
```groovy
60+
pipeline {
61+
agent none
62+
parameters {
63+
nonStoredPassword(name: 'MY_PASSWORD', description: 'Database password')
64+
}
65+
stages {
66+
stage('Deploy') {
67+
steps {
68+
echo 'Using password parameter'
69+
}
70+
}
71+
}
72+
}
73+
```
74+
75+
**Scripted Pipeline Example:**
76+
```groovy
77+
node {
78+
properties([parameters([nonStoredPassword(name: 'API_KEY', description: 'API authentication key')])])
79+
stage('Build') {
80+
echo 'Using API key parameter'
81+
}
82+
}
83+
```
84+
5485
# User guide
5586

5687
First, go to Jenkins' main configuration screen (**Manage Jenkins** \>

pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@
9494
<artifactId>workflow-durable-task-step</artifactId>
9595
<scope>test</scope>
9696
</dependency>
97+
<dependency>
98+
<groupId>org.jenkins-ci.plugins</groupId>
99+
<artifactId>pipeline-stage-step</artifactId>
100+
<scope>test</scope>
101+
</dependency>
102+
<dependency>
103+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
104+
<artifactId>workflow-multibranch</artifactId>
105+
<scope>test</scope>
106+
</dependency>
97107
<dependency> <!-- StepConfigTester -->
98108
<groupId>org.jenkins-ci.plugins.workflow</groupId>
99109
<artifactId>workflow-step-api</artifactId>

src/main/java/com/michelin/cio/hudson/plugins/passwordparam/PasswordParameterDefinition.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import hudson.model.ParameterDefinition;
3333
import hudson.util.Secret;
3434
import org.jvnet.localizer.ResourceBundleHolder;
35+
import org.jenkinsci.Symbol;
3536

3637
public class PasswordParameterDefinition extends ParameterDefinition {
3738

@@ -68,6 +69,7 @@ public PasswordParameterValue createValue(StaplerRequest2 req, JSONObject formDa
6869
}
6970

7071
@Extension
72+
@Symbol("nonStoredPassword")
7173
public final static class ParameterDescriptorImpl extends ParameterDescriptor {
7274

7375
@Override
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.michelin.cio.hudson.plugins.passwordparam;
2+
3+
import hudson.model.ParametersAction;
4+
import hudson.util.Secret;
5+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
6+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
7+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.Test;
10+
import org.jvnet.hudson.test.JenkinsRule;
11+
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
12+
13+
@WithJenkins
14+
class DeclarativePipelineTest {
15+
16+
private static final String SCRIPT_WITH_NON_STORED_PASSWORD =
17+
"""
18+
pipeline {
19+
agent none
20+
parameters {
21+
nonStoredPassword(name: 'MY_PASSWORD', description: 'Test password parameter')
22+
}
23+
stages {
24+
stage('Test') {
25+
steps {
26+
echo 'Testing nonStoredPassword parameter'
27+
}
28+
}
29+
}
30+
}
31+
""";
32+
33+
private JenkinsRule j;
34+
35+
@BeforeEach
36+
void beforeEach(JenkinsRule j) throws Exception {
37+
this.j = j;
38+
}
39+
40+
@Test
41+
void test_nonStoredPassword_symbol_in_declarative_pipeline() throws Exception {
42+
WorkflowJob job = j.jenkins.createProject(WorkflowJob.class, "test-nonStoredPassword");
43+
job.setDefinition(new CpsFlowDefinition(SCRIPT_WITH_NON_STORED_PASSWORD, true));
44+
45+
// First run: defines the parameter for the job
46+
WorkflowRun run1 = job.scheduleBuild2(0).get();
47+
j.waitForCompletion(run1);
48+
j.assertBuildStatusSuccess(run1);
49+
50+
// Second run: accepts the parameter value
51+
PasswordParameterValue paramValue = new PasswordParameterValue(
52+
"MY_PASSWORD", Secret.fromString("testPassword123"), "Test password parameter");
53+
WorkflowRun run2 =
54+
job.scheduleBuild2(0, new ParametersAction(paramValue)).get();
55+
j.waitForCompletion(run2);
56+
j.assertBuildStatusSuccess(run2);
57+
}
58+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.michelin.cio.hudson.plugins.passwordparam;
2+
3+
import hudson.model.ParametersAction;
4+
import hudson.util.Secret;
5+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
6+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
7+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.Test;
10+
import org.jvnet.hudson.test.JenkinsRule;
11+
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
12+
13+
@WithJenkins
14+
class ScriptedPipelineTest {
15+
16+
private static final String SCRIPT_WITH_NON_STORED_PASSWORD =
17+
"""
18+
node {
19+
properties([parameters([nonStoredPassword(name: 'MY_PASSWORD', description: 'Test password parameter')])])
20+
stage('Test') {
21+
echo 'Testing nonStoredPassword parameter in a scripted pipeline'
22+
}
23+
}
24+
""";
25+
26+
private JenkinsRule j;
27+
28+
@BeforeEach
29+
void beforeEach(JenkinsRule j) throws Exception {
30+
this.j = j;
31+
}
32+
33+
@Test
34+
void test_nonStoredPassword_in_scripted_pipeline() throws Exception {
35+
WorkflowJob job = j.jenkins.createProject(WorkflowJob.class, "test-scripted-nonStoredPassword");
36+
job.setDefinition(new CpsFlowDefinition(SCRIPT_WITH_NON_STORED_PASSWORD, false));
37+
38+
// First run: defines the parameter for the job
39+
WorkflowRun run1 = job.scheduleBuild2(0).get();
40+
j.waitForCompletion(run1);
41+
j.assertBuildStatusSuccess(run1);
42+
43+
// Second run: accepts the parameter value
44+
PasswordParameterValue paramValue = new PasswordParameterValue(
45+
"MY_PASSWORD", Secret.fromString("testPassword123"), "Test password parameter");
46+
WorkflowRun run2 =
47+
job.scheduleBuild2(0, new ParametersAction(paramValue)).get();
48+
j.waitForCompletion(run2);
49+
j.assertBuildStatusSuccess(run2);
50+
}
51+
}

0 commit comments

Comments
 (0)