Command Palette

Search for a command to run...

Hectal
PHASE 3Intermediate ~14 min· topic 3 of 4

Topic 3.3

Credentials & Plugins

In one line

Jenkins' Credentials store keeps secrets out of a Jenkinsfile exactly the way GitHub Actions Secrets do — and its enormous plugin ecosystem is both Jenkins' biggest strength and its most common source of real operational headaches.

0/4 · 0%

Key ideas

  1. 01

    Jenkins' CREDENTIALS STORE (configured through its own UI, under 'Manage Jenkins' → 'Credentials') holds secrets — API tokens, SSH keys, username/password pairs — completely SEPARATELY from any Jenkinsfile, referenced by an ID rather than ever containing the real value directly in pipeline code, the exact same principle as GitHub Actions Secrets (Phase 2.2), just Jenkins' own specific mechanism for it.

  2. 02

    withCredentials([usernamePassword(credentialsId: 'my-cred-id', usernameVariable: 'USER', passwordVariable: 'PASS')]) { } injects a stored credential into environment variables for the DURATION of that specific block only — Jenkins automatically masks the actual values in console log output, exactly like GitHub's own automatic secret masking.

  3. 03

    A PLUGIN extends Jenkins with new functionality — literally thousands are available in the Plugin Manager, covering everything from source control integrations, to build tool support, to notification systems (Slack, email), to entirely new pipeline steps. Jenkins' plugin ecosystem is genuinely one of its biggest historical strengths: if a tool exists, there's very likely already a Jenkins plugin integrating with it.

  4. 04

    This same plugin ecosystem is also a genuinely common source of real operational pain — plugins can have compatibility issues with each other or with a specific Jenkins core version, and a Jenkins UPGRADE can sometimes break a plugin an entire team's pipelines depend on, requiring genuinely careful testing (often on a separate staging Jenkins instance) before upgrading a production Jenkins controller that many teams rely on.

  5. 05

    Plugins commonly add entirely new PIPELINE STEPS usable directly in a Jenkinsfile — archiveArtifacts (this phase's own earlier example) and junit (for publishing structured test results, directly analogous to Phase 1.2's JUnit XML reporting) are both plugin-provided steps, not part of Jenkins' own core — a genuinely important thing to know when a Jenkinsfile uses a step that doesn't work on a fresh Jenkins install missing that specific plugin.

  6. 06

    A genuinely important operational practice for any real Jenkins instance: keeping a documented, deliberately curated list of INSTALLED plugins and their specific versions (many teams manage this as actual configuration-as-code via the Jenkins Configuration as Code plugin, ironically enough) rather than installing plugins ad-hoc over time — an undocumented, organically-grown plugin set is a genuinely common source of 'why does this work on one Jenkins instance but not another' confusion.

Code & diagrams

credentials-usage.groovymarkdown

A stored credential, injected only for the duration of one block, never appearing in plain text anywhere.

pipeline {
    agent { label 'linux' }
    stages {
        stage('Deploy') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'deploy-registry-creds',
                    usernameVariable: 'REGISTRY_USER',
                    passwordVariable: 'REGISTRY_PASS'
                )]) {
                    sh '''
                        echo $REGISTRY_PASS | docker login -u $REGISTRY_USER --password-stdin
                        docker push my-registry/my-app:latest
                    '''
                }
                // REGISTRY_USER and REGISTRY_PASS are no longer available here —
                // scoped strictly to the withCredentials block above
            }
        }
    }
}
junit-reporting.groovymarkdown

A plugin-provided step (junit) publishing structured results, the same idea as Phase 1.2's JUnit XML reporting.

stage('Test') {
    steps {
        sh 'mvn test'
    }
    post {
        always {
            junit 'target/surefire-reports/*.xml'   // provided by the JUnit plugin
        }
    }
}

Explain it without notes

01

Why does withCredentials scope a credential's environment variables to just one specific block, rather than making them available for the entire pipeline once loaded?

02

Why can a Jenkins core upgrade genuinely break an existing pipeline, in a way that upgrading, say, a well-isolated application dependency typically wouldn't?

Practice

01

If you have access to a Jenkins instance, add a test credential to its Credentials store and reference it in a withCredentials block, confirming the actual value is masked in the console log.

02

Look at (or research) a genuinely popular Jenkins plugin (like the JUnit plugin or the Slack Notification plugin) and identify one specific pipeline step or feature it adds that isn't part of Jenkins' own bare core.

Trade-offs

  • ↔

    Jenkins' enormous plugin ecosystem gives it genuinely unmatched flexibility and integration breadth compared to more opinionated, single-vendor platforms — but that same breadth means a real Jenkins instance's actual behavior and reliability depends on the specific, curated combination of plugins installed, which is real, ongoing maintenance overhead a fully-hosted platform like GitHub Actions simply doesn't impose on its users at all.

Done when you can

  • I can use withCredentials to inject a stored credential scoped to just the steps that need it.

  • I understand that many common pipeline steps (archiveArtifacts, junit) come from plugins, not Jenkins' core.

  • I understand why plugin management is a genuine, ongoing operational responsibility for a self-hosted Jenkins instance.