Parameters and when Conditions

Scenario: An arbitrary environment string typo creates an unintended deployment target.

Parameters are a form, and forms need validation

A Jenkins job with parameters is, functionally, a public form that anyone with Build permission can submit - and just like any web form, it needs to validate its inputs, because someone (or some automated caller) will eventually submit something you didn't expect.

Analogy: Think of a parameterized Jenkins job like an online order form for a pizza delivery. A dropdown menu for "size" (small/medium/large) prevents someone from typing "seventeen" into a free-text box - but it doesn't prevent someone from choosing "large" and typing "999999" into a separate free-text "quantity" field, or leaving the "delivery address" field completely blank because it was optional and nobody thought to require it. A well-designed order form validates every field, not just the ones that happen to be dropdowns - and a well-designed Jenkins pipeline needs to do exactly the same thing with its params.

Choice parameters (dropdowns) genuinely reduce mistakes for the common path, but they don't replace real validation logic inside the Pipeline itself - especially for anything triggered by an API call rather than a human clicking through the UI.

Pipeline example

pipeline { agent any; parameters { choice(name: 'TARGET', choices: ['dev','staging']) }; stages { stage('Deploy') { when { expression { params.TARGET == 'staging' } }; steps { echo 'deploy' } } } }

Parameters are a public job interface

Declarative Pipeline offers string, text, boolean, choice, and password parameter types natively, with community plugins adding more. Pipeline code reads typed values through the params object, while environment-variable exports of those same values get stringified (a boolean true becomes the literal text "true", for instance). A choice list reduces mistakes for a human clicking through the UI, but it cannot replace real validation at every possible trigger path - an API caller or an upstream job invoking build job: ... with parameters can pass any string value, dropdown or not. Reject unknown environment names, malformed artifact digests, unsafe file paths, and contradictory parameter combinations before allocating a costly or privileged agent to do any real work - validating early avoids wasting resources and avoids partially executing something that should have been rejected outright.

when conditions decide what actually runs

The Declarative when block supports conditions like branch, tag, changeRequest, environment, expression, allOf, anyOf, and not. Setting beforeAgent true lets Jenkins evaluate a supported condition before provisioning that stage's agent at all, saving real resources when the condition would skip the stage anyway. An expression block must return a genuine boolean - and here's a subtle trap: the Groovy string "false" is truthy in a boolean context (any non-empty string is truthy in Groovy), so a careless expression comparing against a string can unexpectedly evaluate as "true" and enable a deployment stage that was supposed to be skipped. Keep required release policy checks independent of values a caller fully controls, so a malformed or malicious input can't accidentally satisfy a security-relevant condition.

[Pipeline] { (Deploy)
[Pipeline] // Stage "Deploy" skipped due to when conditional
[Pipeline] }

This is exactly what a correctly-skipped stage looks like in the log - notice it's explicitly recorded as skipped-by-condition, not silently absent, which is important for anyone auditing the build later to understand why deployment didn't happen.

Make skipped-or-run decisions explainable, not string-matched

Prefer immutable artifact digests and a genuinely constrained set of target choices over arbitrary free-text branch names or hostnames as parameter values - a digest can't typo its way into pointing at the wrong thing the way a hand-typed hostname can. Parameter defaults should be conservative (fail toward the safer option), since API and scheduled callers frequently omit optional values entirely and will get whatever default you configured. Note a genuinely confusing Jenkins quirk: changes to a job's declared parameters inside the Jenkinsfile itself sometimes require one initial run before the job's own UI form actually reflects the new parameter list - so don't be surprised if a brand-new parameter doesn't show up in the "Build with Parameters" screen until after the very first build that introduces it.

A pitfall: a typo that silently created the wrong deployment target

Test with missing input, extra whitespace, differing case (Staging vs staging), stale cached values, an unauthorized caller attempting the API path directly, a Replay attempt, and deliberately invalid parameter combinations - not just the happy path a human would type into the UI. Record which non-secret parameters were actually accepted for a given build, and why a particular condition caused a stage to be skipped, so a future investigator doesn't have to guess. The real-world incident this all defends against: a caller (human or automated) passes an almost-correct environment name with a typo or unexpected casing, and because no stage actually validated it strictly, the pipeline creates a brand-new, unintended deployment target that nobody meant to create - a safe interface fails closed, rejecting the ambiguous input entirely, before any side effect happens, rather than optimistically guessing what the caller "probably meant."

Goal: Practice the concrete behavior in jenkins-parameterized-deploy. Learn sections have no Jenkins terminal; the Jenkins lab opens the real shared service in a new full-screen tab inside your private folder.