Answers: <p>A common approach is to define your pipelines <a href="https://www.jenkins.io/doc/book/pipeline/getting-started/#defining-a-pipeline-in-scm" rel="nofollow noreferrer">as code</a>. That way they will always be up-to-date with the code they build, and much easier to maintain.</p>
  <p>You will end up with a <a href="https://www.jenkins.io/doc/book/pipeline/jenkinsfile/" rel="nofollow noreferrer">Jenkinsfile</a> in your repository that represents your pipeline along with all the parameters, steps, agent requirements, environment variables, triggers, and other elements.</p>
  <p>There are several built-in types of parameters, with many others are available as plugins.</p>
  <p>The <code>choices</code> parameter would look like this, with the first element of the list being the default value:</p>
  <pre class="lang-java prettyprint-override"><code>parameters 
      {
          choice name: 'ENVIRONMENT', 
              choices: [
                  'sandbox', 
                  'staging',
                  'production',
                  'feature',
                  'devops'
              ],
              description: 'The environment to deploy the application to'
      }
  </code></pre>
  <p>If you want to use a single Jenkinsfile for multiple jobs, you can either do the same but manually checkout the desired repository in the first stage, or explore the abilities provided by <a href="https://www.jenkins.io/doc/book/pipeline/shared-libraries/" rel="nofollow noreferrer">shared libraries</a>. Both options have an obvious drawback - if the application code requires changes to the pipeline, you will have to make them in the pipeline repository first. And to apply them gradually (e.g. modify the apps one by one if required), you will need to maintain two or more pipeline versions simultaneously and make sure they always work correctly.</p>
  <p>Note that unlike other CI servers, Jenkins is unable to automatically pick up the pipeline parameters changes until the start of the next build, so you may need to implement some workaround for that, i.e. adding a <code>stage</code> that aborts the build if some dummy parameter value is changed.</p>
  
Answers: CC BY-SA 4.0
Answers: 2023-12-24T03:01:46.037Z
Answers: Thanks. I normally do it this way, but in this case someone else has created this jobs already and I just want to "modify" that part, and not "change" them with Jenkinsfiles.
Answers: Chris F
Answers: CC BY-SA 4.0
Answers: 2023-12-24T03:16:26.593Z
Answers: Oh, I see. But there is no way to bulk edit the jobs. There is a thing called [JobDSL](https://www.jenkins.io/doc/pipeline/steps/job-dsl/), that allows to generate (and re-generate) the jobs from the source, but it also comes with a number of consequences. The most DevOpsy turn you can make then is set up and force the RBAC via JCasC and prohibit editing the jobs via UI.
Answers: Alexander Pletnev
Answers: CC BY-SA 4.0
Answers: 2023-12-24T02:05:32.123Z
Answers: 2023-12-24T02:05:32.123Z
Answers: Alexander Pletnev
Answers: <ul>
  <li>The answer before advised to use <strong>Jenkinsfile</strong> for better source control and it is <strong>usually</strong> the best way to do.</li>
  <li>For people not interested to go that way, the non-straight-forward way is to use some scripting logic using <strong>Jenkins REST API or Jenkins CLI</strong> wrapped with <strong>Python or Bash</strong>.</li>
  </ul>
  <h3>1 - Python + Jenkins REST API</h3>
  <pre><code>import requests
  from requests.auth import HTTPBasicAuth
  import xml.etree.ElementTree as ET
  
  # Jenkins details
  jenkins_url = 'http://localhost:8000'
  job_name = 'your-job-name'
  username = 'your-username'
  api_token = 'your-api-token'
  
  # Step 1: Get the current job configuration
  response = requests.get(f'{jenkins_url}/job/{job_name}/config.xml', auth=HTTPBasicAuth(username, api_token))
  if response.status_code != 200:
      print('Failed to fetch job configuration')
      exit(1)
  
  config_xml = response.text
  
  # Step 2: Modify the job configuration
  root = ET.fromstring(config_xml)
  for parameter in root.findall(&quot;.//hudson.model.ChoiceParameterDefinition&quot;):
      name = parameter.find('name').text
      if name == 'ENVIRONMENT':
          choices = parameter.find('choices').find('a')
          choices.text += '\nfeature'
  
  # Convert the modified XML tree back to a string
  modified_config_xml = ET.tostring(root, encoding='unicode')
  
  # Step 3: Update the job configuration
  headers = {'Content-Type': 'application/xml'}
  response = requests.post(f'{jenkins_url}/job/{job_name}/config.xml', data=modified_config_xml, headers=headers, auth=HTTPBasicAuth(username, api_token))
  
  if response.status_code == 200:
      print('Job updated successfully')
  else:
      print('Failed to update job')
  
  </code></pre>
  <h3>2 - Bash + Jenkins CLI</h3>
  <pre><code>#!/bin/bash
  
  # Download the Jenkins CLI jar file
  wget http://localhost:8000/jnlpJars/jenkins-cli.jar
  
  # Get the current job configuration
  java -jar jenkins-cli.jar -s http://localhost:8000/ get-job your-job-name &gt; config.xml
  
  # Add &quot;feature-devops&quot; to the choices for the 'ENVIRONMENT' parameter
  sed -i '/&lt;name&gt;ENVIRONMENT&lt;\/name&gt;/!b;n;/&lt;choices&gt;/!b;n;s/&lt;string&gt;production&lt;\/string&gt;/&lt;string&gt;production&lt;\/string&gt;\n&lt;string&gt;feature&lt;\/string&gt;/' config.xml
  
  # Update the job configuration
  java -jar jenkins-cli.jar -s http://localhost:8000/ update-job your-job-name &lt; config.xml
  
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2024-08-16T17:15:20.240Z
Answers: 2024-08-16T17:15:20.240Z
Answers: YassineLbk
Body: <p>We set up a Jenkins job in multiple folders that has the following &quot;Choice Parameter&quot; property.
  <a href="https://i.sstatic.net/GHrB8.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/GHrB8.png" alt="enter image description here" /></a></p>
  <p>How can I modify the property programmatically to add more choices? For example, I want to add a <code>feature</code> and <code>devops</code> choice. I know I can just got to each individual job and add them, but that's just not DevOpsy. Thanks!</p>
  
Tags: <jenkins><jenkins-pipeline><groovy>
Title: How to modify a Jenkins pipeline job's property programmatically?
UserDisplayName: Chris F
ThreadText: # How to modify a Jenkins pipeline job's property programmatically?
  
  (Asked by: username_0 on 2023-12-19)
  
  We set up a Jenkins job in multiple folders that has the following "Choice Parameter" property.
  [![enter image description here](https://i.sstatic.net/GHrB8.png)](https://i.sstatic.net/GHrB8.png)
  
  How can I modify the property programmatically to add more choices? For example, I want to add a `feature` and `devops` choice. I know I can just got to each individual job and add them, but that's just not DevOpsy. Thanks!
  
  **Tags:** jenkins, jenkins-pipeline, groovy
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2023-12-24. Score: 0
  
  A common approach is to define your pipelines [as code](https://www.jenkins.io/doc/book/pipeline/getting-started/#defining-a-pipeline-in-scm). That way they will always be up-to-date with the code they build, and much easier to maintain.
  
  You will end up with a [Jenkinsfile](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/) in your repository that represents your pipeline along with all the parameters, steps, agent requirements, environment variables, triggers, and other elements.
  
  There are several built-in types of parameters, with many others are available as plugins.
  
  The `choices` parameter would look like this, with the first element of the list being the default value:
  
  ```java
  parameters 
      {
          choice name: 'ENVIRONMENT', 
              choices: [
                  'sandbox', 
                  'staging',
                  'production',
                  'feature',
                  'devops'
              ],
              description: 'The environment to deploy the application to'
      }
  
  ```
  
  If you want to use a single Jenkinsfile for multiple jobs, you can either do the same but manually checkout the desired repository in the first stage, or explore the abilities provided by [shared libraries](https://www.jenkins.io/doc/book/pipeline/shared-libraries/). Both options have an obvious drawback - if the application code requires changes to the pipeline, you will have to make them in the pipeline repository first. And to apply them gradually (e.g. modify the apps one by one if required), you will need to maintain two or more pipeline versions simultaneously and make sure they always work correctly.
  
  Note that unlike other CI servers, Jenkins is unable to automatically pick up the pipeline parameters changes until the start of the next build, so you may need to implement some workaround for that, i.e. adding a `stage` that aborts the build if some dummy parameter value is changed.
  
  > **Comments:**
  > **username_0**: Thanks. I normally do it this way, but in this case someone else has created this jobs already and I just want to "modify" that part, and not "change" them with Jenkinsfiles.  
  > **username_1**: Oh, I see. But there is no way to bulk edit the jobs. There is a thing called [JobDSL](https://www.jenkins.io/doc/pipeline/steps/job-dsl/), that allows to generate (and re-generate) the jobs from the source, but it also comes with a number of consequences. The most DevOpsy turn you can make then is set up and force the RBAC via JCasC and prohibit editing the jobs via UI.  
  
  ---
  
  ### Answer by username_2 on 2024-08-16. Score: 0
  
  * The answer before advised to use **Jenkinsfile** for better source control and it is **usually** the best way to do.
  * For people not interested to go that way, the non-straight-forward way is to use some scripting logic using **Jenkins REST API or Jenkins CLI** wrapped with **Python or Bash**.
  
  ### 1 - Python + Jenkins REST API
  
  ```
  import requests
  from requests.auth import HTTPBasicAuth
  import xml.etree.ElementTree as ET
  
  # Jenkins details
  jenkins_url = 'http://localhost:8000'
  job_name = 'your-job-name'
  username = 'your-username'
  api_token = 'your-api-token'
  
  # Step 1: Get the current job configuration
  response = requests.get(f'{jenkins_url}/job/{job_name}/config.xml', auth=HTTPBasicAuth(username, api_token))
  if response.status_code != 200:
      print('Failed to fetch job configuration')
      exit(1)
  
  config_xml = response.text
  
  # Step 2: Modify the job configuration
  root = ET.fromstring(config_xml)
  for parameter in root.findall(".//hudson.model.ChoiceParameterDefinition"):
      name = parameter.find('name').text
      if name == 'ENVIRONMENT':
          choices = parameter.find('choices').find('a')
          choices.text += '\nfeature'
  
  # Convert the modified XML tree back to a string
  modified_config_xml = ET.tostring(root, encoding='unicode')
  
  # Step 3: Update the job configuration
  headers = {'Content-Type': 'application/xml'}
  response = requests.post(f'{jenkins_url}/job/{job_name}/config.xml', data=modified_config_xml, headers=headers, auth=HTTPBasicAuth(username, api_token))
  
  if response.status_code == 200:
      print('Job updated successfully')
  else:
      print('Failed to update job')
  
  ```
  
  ### 2 - Bash + Jenkins CLI
  
  ```
  #!/bin/bash
  
  # Download the Jenkins CLI jar file
  wget http://localhost:8000/jnlpJars/jenkins-cli.jar
  
  # Get the current job configuration
  java -jar jenkins-cli.jar -s http://localhost:8000/ get-job your-job-name > config.xml
  
  # Add "feature-devops" to the choices for the 'ENVIRONMENT' parameter
  sed -i '/<name>ENVIRONMENT<\/name>/!b;n;/<choices>/!b;n;s/<string>production<\/string>/<string>production<\/string>\n<string>feature<\/string>/' config.xml
  
  # Update the job configuration
  java -jar jenkins-cli.jar -s http://localhost:8000/ update-job your-job-name < config.xml
  
  ```
  
  
  ---
  
  