<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Selma Guedidi</title>
    <description>The latest articles on Forem by Selma Guedidi (@selmaguedidi).</description>
    <link>https://forem.com/selmaguedidi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1170049%2F558ceeb3-6337-4248-85c3-b29f68a3bb44.png</url>
      <title>Forem: Selma Guedidi</title>
      <link>https://forem.com/selmaguedidi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/selmaguedidi"/>
    <language>en</language>
    <item>
      <title>Publishing Your Java Library to Maven Central</title>
      <dc:creator>Selma Guedidi</dc:creator>
      <pubDate>Sun, 05 Oct 2025 18:37:55 +0000</pubDate>
      <link>https://forem.com/selmaguedidi/publishing-your-java-library-to-maven-central-15in</link>
      <guid>https://forem.com/selmaguedidi/publishing-your-java-library-to-maven-central-15in</guid>
      <description>&lt;h2&gt;
  
  
  Why Maven Central Matters
&lt;/h2&gt;

&lt;p&gt;You've built an amazing Java library. It solves real problems, the code is clean, and you're ready to share it with the world. But there's one crucial step between your local repository and global adoption: publishing to Maven Central.&lt;/p&gt;

&lt;p&gt;Maven Central isn't just another package repository: it's the canonical repository for Java and JVM libraries. With over 10 million artifacts and billions of downloads monthly, it's where the entire Java ecosystem comes to find dependencies. When your library is on Maven Central, developers can add it to their projects with a single dependency declaration. No custom repositories, no manual downloads, no friction.&lt;/p&gt;

&lt;p&gt;In this guide, I'll walk you through the entire process of publishing to Maven Central, from initial setup to your first release. Whether you're publishing your first library or your tenth, this guide will help you navigate the journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create Your Sonatype Account&lt;/strong&gt;&lt;br&gt;
Maven Central is operated by Sonatype, and they've recently modernized the onboarding process. You'll need to create an account on their new platform.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://central.sonatype.com" rel="noopener noreferrer"&gt;https://central.sonatype.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click "Sign up" (you can use GitHub, Google, or email)&lt;/li&gt;
&lt;li&gt;Verify your email address if using email registration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Claim Your Namespace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Namespace ownership is fundamental to publishing on Maven Central. Your namespace (groupId) serves as the unique identifier for all your published artifacts, and you must demonstrate legitimate ownership before you can publish. The Central Portal offers two primary verification methods, each suited to different use cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method 1: DNS-Based Verification (For Domain Owners)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you own or maintain a registered domain name, you can leverage the Domain Name System in reversed format for your namespace. This approach mirrors Java's package naming convention and provides the most flexibility for organizational publishing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How It Works:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The namespace uses your domain name in reverse order, allowing you to create as many subsections as needed for organizational purposes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Examples:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain: example.com → Namespace: com.example&lt;/li&gt;
&lt;li&gt;Domain: subdomain.example.com → Namespace: com.example&lt;/li&gt;
&lt;li&gt;Domain: my-domain.com → Namespace: com.my-domain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once verified, you can utilize any groupId starting with your reversed domain and extend it with additional subsections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;com.example.domain&lt;/li&gt;
&lt;li&gt;com.example.test&lt;/li&gt;
&lt;li&gt;com.example.utilities.logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Important Considerations:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Exact Reversal: The groupId must reverse the domain name exactly as it appears, preserving hyphens and special characters even if they would produce invalid Java package names. This is acceptable and expected, your Java package names need not match your groupId.&lt;br&gt;
Ownership Requirement: You must have control over the domain to add DNS verification records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verification Process:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to "Namespaces" in the left sidebar&lt;/li&gt;
&lt;li&gt;Click "Add Namespace"&lt;/li&gt;
&lt;li&gt;Enter your reversed domain namespace (e.g., com.example)&lt;/li&gt;
&lt;li&gt;Select "DNS Verification" as your verification method&lt;/li&gt;
&lt;li&gt;Copy the provided TXT record from the portal&lt;/li&gt;
&lt;li&gt;Add this TXT record to your domain's DNS configuration&lt;/li&gt;
&lt;li&gt;Return to the portal and click "Verify Namespace"&lt;/li&gt;
&lt;li&gt;Verification typically completes within minutes once DNS propagates&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Method 2: Code Hosting Service Verification (Personal Namespace)
&lt;/h3&gt;

&lt;p&gt;For individual developers and open-source projects hosted on popular code hosting platforms, Maven Central provides a streamlined verification process using your platform identity. This method is ideal for personal libraries and projects without a custom domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supported Platforms:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code Hosting Service&lt;/th&gt;
&lt;th&gt;Username Pattern&lt;/th&gt;
&lt;th&gt;Example Namespace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;myusername&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;io.github.myusername&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitLab&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;myusername&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;io.gitlab.myusername&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gitee&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;myusername&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;io.gitee.myusername&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bitbucket&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;myusername&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;io.bitbucket.myusername&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The namespace format follows the pattern &lt;code&gt;io.{platform}.{username}&lt;/code&gt;, where the username matches your account on the respective platform. This creates a globally unique namespace tied to your platform identity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verification Process:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to "Namespaces"&lt;/li&gt;
&lt;li&gt;Click "Add Namespace"&lt;/li&gt;
&lt;li&gt;Enter your platform-based namespace (e.g., &lt;code&gt;io.github.myusername&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Select your code hosting service as the verification method&lt;/li&gt;
&lt;li&gt;The portal will prompt you to create a temporary public repository with a specific verification name &lt;/li&gt;
&lt;li&gt;Create the repository on your platform with the exact name provided&lt;/li&gt;
&lt;li&gt;Return to the portal and click "Verify Namespace"&lt;/li&gt;
&lt;li&gt;Verification is typically instant once the repository is detected&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Step 3: Generate GPG Keys
&lt;/h2&gt;

&lt;p&gt;Maven Central enforces a strict security requirement: all published artifacts must be cryptographically signed using GPG (GNU Privacy Guard). This digital signature ensures artifact integrity and authenticity, protecting the entire Java ecosystem from tampering and unauthorized modifications.&lt;/p&gt;
&lt;h3&gt;
  
  
  3.1 Installing GPG
&lt;/h3&gt;

&lt;p&gt;Before generating keys, you need to ensure GPG is installed on your system.&lt;/p&gt;
&lt;h4&gt;
  
  
  For macOS
&lt;/h4&gt;

&lt;p&gt;Using Homebrew (recommended):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using MacPorts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;port &lt;span class="nb"&gt;install &lt;/span&gt;gnupg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  For Linux
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Debian/Ubuntu:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fedora/RHEL/CentOS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;gnupg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Arch Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  For Windows
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Using Gpg4win (Recommended)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download Gpg4win from &lt;a href="https://gpg4win.org/download.html" rel="noopener noreferrer"&gt;https://gpg4win.org/download.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run the installer and follow the installation wizard&lt;/li&gt;
&lt;li&gt;Add GPG to your PATH if not done automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Using Chocolatey&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;choco &lt;span class="nb"&gt;install &lt;/span&gt;gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option 3: Using Windows Subsystem for Linux (WSL)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installation (in Command Prompt or PowerShell):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.2 Generating Your Key Pair
&lt;/h3&gt;

&lt;p&gt;Once GPG is installed, generate a new key pair for signing your artifacts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--gen-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the interactive prompts to configure your key:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key type&lt;/strong&gt;: Choose RSA and RSA (default)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key size&lt;/strong&gt;: Use 2048 bits or higher (4096 recommended)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiration&lt;/strong&gt;: Set to 2-3 years (recommended) or no expiration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real name&lt;/strong&gt;: Your name or organization name&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email address&lt;/strong&gt;: A professional email you control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comment&lt;/strong&gt;: Optional (e.g., "Maven Central Signing Key")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passphrase&lt;/strong&gt;: Create a strong passphrase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Critical&lt;/strong&gt;: Your passphrase will be required for every release. Store it securely in a password manager—you cannot recover it if lost, and you'll need it throughout your publishing workflow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Listing Your Keys
&lt;/h4&gt;

&lt;p&gt;After generation, verify your keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--list-keys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub   rsa4096 2025-10-05 [SC] [expires: 2027-10-05]
      1234567890ABCDEF1234567890ABCDEF12345678
uid           [ultimate] John Doe (Maven Central Signing Key) &amp;lt;john.doe@example.com&amp;gt;
sub   rsa4096 2025-10-05 [E] [expires: 2027-10-05]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The long hexadecimal string is your &lt;strong&gt;key ID&lt;/strong&gt;. You can also use the last 8 characters as a short key ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Publishing Your Public Key
&lt;/h3&gt;

&lt;p&gt;For Maven Central to verify your signatures, your public key must be published to a public key server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using the full key ID&lt;/span&gt;
gpg &lt;span class="nt"&gt;--keyserver&lt;/span&gt; keys.openpgp.org &lt;span class="nt"&gt;--send-keys&lt;/span&gt; 1234567890ABCDEF1234567890ABCDEF12345678

&lt;span class="c"&gt;# Or using the short key ID (last 8 characters)&lt;/span&gt;
gpg &lt;span class="nt"&gt;--keyserver&lt;/span&gt; keys.openpgp.org &lt;span class="nt"&gt;--send-keys&lt;/span&gt; 12345678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: It may take a few minutes for your key to propagate across key server networks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verifying Key Publication
&lt;/h4&gt;

&lt;p&gt;Confirm your key is publicly accessible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpg &lt;span class="nt"&gt;--keyserver&lt;/span&gt; keys.openpgp.org &lt;span class="nt"&gt;--recv-keys&lt;/span&gt; YOUR_KEY_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpg: key YOUR_KEY_ID: "John Doe (Maven Central Signing Key) &amp;lt;john.doe@example.com&amp;gt;" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Next Steps
&lt;/h4&gt;

&lt;p&gt;With your GPG keys generated, published, and backed up, you're ready to configure your build tool to automatically sign artifacts during the publishing process. Your key ID and passphrase will be required in the build configuration covered in Step 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Configure Your Build Tool
&lt;/h2&gt;

&lt;p&gt;Configuring Maven for publishing to Maven Central requires understanding two distinct deployment workflows: &lt;strong&gt;release versions&lt;/strong&gt; and &lt;strong&gt;snapshot versions&lt;/strong&gt;. Each serves a different purpose in the development lifecycle and has different requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Release vs Snapshot Versions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Release Versions&lt;/strong&gt; (e.g., &lt;code&gt;1.0.0&lt;/code&gt;, &lt;code&gt;2.3.1&lt;/code&gt;, &lt;code&gt;1.5.0-beta1&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutable and permanent once published&lt;/li&gt;
&lt;li&gt;Require complete metadata, including developers, SCM, and license information&lt;/li&gt;
&lt;li&gt;Undergo full validation before publication&lt;/li&gt;
&lt;li&gt;Intended for production use and stable APIs&lt;/li&gt;
&lt;li&gt;Cannot be overwritten or deleted after publication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Snapshot Versions&lt;/strong&gt; (e.g., &lt;code&gt;1.0.0-SNAPSHOT&lt;/code&gt;, &lt;code&gt;2.3.1-SNAPSHOT&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mutable and can be republished with the same version&lt;/li&gt;
&lt;li&gt;Require minimal metadata validation&lt;/li&gt;
&lt;li&gt;Used for development, testing, and continuous integration&lt;/li&gt;
&lt;li&gt;Not indexed in Maven Central search&lt;/li&gt;
&lt;li&gt;Must be explicitly enabled in your namespace configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Generating Authentication Tokens
&lt;/h3&gt;

&lt;p&gt;Before configuring your build, you need to generate authentication tokens from the Central Portal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to &lt;a href="https://central.sonatype.com" rel="noopener noreferrer"&gt;https://central.sonatype.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click on your account name in the top right corner&lt;/li&gt;
&lt;li&gt;Select "View User Tokens" from the dropdown&lt;/li&gt;
&lt;li&gt;Click "Generate User Token"&lt;/li&gt;
&lt;li&gt;The portal will display your username and password token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save these immediately&lt;/strong&gt;—the password token is only shown once&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: These tokens are not your Sonatype login credentials. They are specifically generated for programmatic publishing and should be treated as API keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling Snapshot Publishing (Optional)
&lt;/h3&gt;

&lt;p&gt;If you plan to publish snapshot versions, you must enable this feature in your namespace:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to &lt;a href="https://central.sonatype.com" rel="noopener noreferrer"&gt;https://central.sonatype.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to "Namespaces"&lt;/li&gt;
&lt;li&gt;Select your verified namespace&lt;/li&gt;
&lt;li&gt;Click on its "dropdown menu"&lt;/li&gt;
&lt;li&gt;Click on "Enable Snapshots"&lt;/li&gt;
&lt;li&gt;Save the configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without this setting enabled, snapshot deployments will fail with an authorization error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk9p6k8d0je01afovlia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk9p6k8d0je01afovlia.png" alt="Namespaces with snapshots enabled" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuration for Release Versions
&lt;/h2&gt;

&lt;p&gt;Release versions require comprehensive metadata and validation. This configuration ensures your artifacts meet all Maven Central requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maven POM Configuration
&lt;/h3&gt;

&lt;p&gt;Add the following to your &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;project&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.yourusername&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;your-library&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;packaging&amp;gt;&lt;/span&gt;jar&lt;span class="nt"&gt;&amp;lt;/packaging&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Your Library Name&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;A comprehensive description of your library's purpose and functionality&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://github.com/yourusername/your-library&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;licenses&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;license&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Apache License, Version 2.0&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://www.apache.org/licenses/LICENSE-2.0.txt&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;distribution&amp;gt;&lt;/span&gt;repo&lt;span class="nt"&gt;&amp;lt;/distribution&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/license&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/licenses&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;developers&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;developer&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;yourusername&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Your Full Name&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;email&amp;gt;&lt;/span&gt;your.email@example.com&lt;span class="nt"&gt;&amp;lt;/email&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;organization&amp;gt;&lt;/span&gt;Your Organization&lt;span class="nt"&gt;&amp;lt;/organization&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;organizationUrl&amp;gt;&lt;/span&gt;https://yoursite.com&lt;span class="nt"&gt;&amp;lt;/organizationUrl&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/developer&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/developers&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;scm&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&amp;gt;&lt;/span&gt;scm:git:git://github.com/yourusername/your-library.git&lt;span class="nt"&gt;&amp;lt;/connection&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;developerConnection&amp;gt;&lt;/span&gt;scm:git:ssh://github.com:yourusername/your-library.git&lt;span class="nt"&gt;&amp;lt;/developerConnection&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://github.com/yourusername/your-library/tree/main&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tag&amp;gt;&lt;/span&gt;HEAD&lt;span class="nt"&gt;&amp;lt;/tag&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/scm&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- Central Publishing Plugin --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.sonatype.central&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;central-publishing-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.9.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;extensions&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/extensions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;publishingServerId&amp;gt;&lt;/span&gt;central&lt;span class="nt"&gt;&amp;lt;/publishingServerId&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;autoPublish&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/autoPublish&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;waitUntil&amp;gt;&lt;/span&gt;published&lt;span class="nt"&gt;&amp;lt;/waitUntil&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;

            &lt;span class="c"&gt;&amp;lt;!-- GPG Signing Plugin --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-gpg-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;sign-artifacts&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;verify&lt;span class="nt"&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;sign&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Retrieves passphrase from settings.xml --&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;passphraseServerId&amp;gt;&lt;/span&gt;gpg.passphrase&lt;span class="nt"&gt;&amp;lt;/passphraseServerId&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Required for gpg2 to avoid GUI prompts --&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;gpgArguments&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--pinentry-mode&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;loopback&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/gpgArguments&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Ensure correct GPG binary is used --&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;executable&amp;gt;&lt;/span&gt;gpg&lt;span class="nt"&gt;&amp;lt;/executable&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;

            &lt;span class="c"&gt;&amp;lt;!-- Source Attachment Plugin --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-source-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.3.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;attach-sources&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;jar-no-fork&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;

            &lt;span class="c"&gt;&amp;lt;!-- Javadoc Generation Plugin --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-javadoc-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.6.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;attach-javadocs&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;jar&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Optional: Configure Javadoc strictness --&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;doclint&amp;gt;&lt;/span&gt;none&lt;span class="nt"&gt;&amp;lt;/doclint&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;quiet&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/quiet&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plugin Explanations
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Central Publishing Maven Plugin
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.sonatype.central&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;central-publishing-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.9.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the modern publishing plugin that replaces the legacy Nexus staging plugin. It handles the entire deployment workflow to Maven Central.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Configuration Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;publishingServerId&lt;/code&gt;: References the server credentials in &lt;code&gt;settings.xml&lt;/code&gt; (must be &lt;code&gt;central&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;autoPublish&lt;/code&gt;: When &lt;code&gt;true&lt;/code&gt;, automatically publishes after successful validation. When &lt;code&gt;false&lt;/code&gt;, requires manual approval in the Central Portal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;waitUntil&lt;/code&gt;: Controls deployment behavior

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;uploaded&lt;/code&gt;: Waits until artifacts are uploaded&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;validated&lt;/code&gt;: Waits until validation completes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;published&lt;/code&gt;: Waits until artifacts are fully published to Maven Central (recommended)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Maven GPG Plugin
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-gpg-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Signs all project artifacts (JAR, sources, javadoc, POM) with your GPG key during the verify phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Configuration Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;passphraseServerId&lt;/code&gt;: References the GPG passphrase stored in &lt;code&gt;settings.xml&lt;/code&gt;, avoiding hardcoded credentials&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpgArguments&lt;/code&gt;: Configures GPG behavior

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--pinentry-mode loopback&lt;/code&gt;: Essential for non-interactive environments (CI/CD) and gpg2, prevents GUI password prompts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;executable&lt;/code&gt;: Specifies the GPG binary path. Use &lt;code&gt;gpg2&lt;/code&gt; if you have both versions installed&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Maven Source Plugin
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-source-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.3.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generates a JAR file containing your source code. Maven Central mandates source JARs for all releases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jar-no-fork&lt;/code&gt;: Creates the source JAR without forking a new Maven lifecycle, improving build performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Maven Javadoc Plugin
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-javadoc-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.6.3&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generates comprehensive API documentation and packages it as a JAR. Maven Central requires Javadoc JARs for all releases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;doclint&lt;/code&gt;: Set to &lt;code&gt;none&lt;/code&gt; to disable strict Javadoc validation (useful if you have legacy code with incomplete docs)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;quiet&lt;/code&gt;: Reduces console output during generation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Maven Settings Configuration
&lt;/h3&gt;

&lt;p&gt;Add the following to your &lt;code&gt;~/.m2/settings.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;servers&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Central Portal Authentication --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;server&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;central&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;username&amp;gt;&lt;/span&gt;YOUR_GENERATED_TOKEN_USERNAME&lt;span class="nt"&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&lt;/span&gt;YOUR_GENERATED_TOKEN_PASSWORD&lt;span class="nt"&gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/server&amp;gt;&lt;/span&gt;

        &lt;span class="c"&gt;&amp;lt;!-- GPG Passphrase --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;server&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;gpg.passphrase&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;passphrase&amp;gt;&lt;/span&gt;YOUR_GPG_PASSPHRASE&lt;span class="nt"&gt;&amp;lt;/passphrase&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/server&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/servers&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploying a Release
&lt;/h3&gt;

&lt;p&gt;Execute the deployment with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clean previous build artifacts&lt;/li&gt;
&lt;li&gt;Compile your code&lt;/li&gt;
&lt;li&gt;Run tests&lt;/li&gt;
&lt;li&gt;Generate source and Javadoc JARs&lt;/li&gt;
&lt;li&gt;Sign all artifacts with GPG&lt;/li&gt;
&lt;li&gt;Upload to Maven Central&lt;/li&gt;
&lt;li&gt;Validate the deployment&lt;/li&gt;
&lt;li&gt;Automatically publish (if &lt;code&gt;autoPublish&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Verification&lt;/strong&gt;: Monitor the deployment at &lt;a href="https://central.sonatype.com/publishing/deployments" rel="noopener noreferrer"&gt;https://central.sonatype.com/publishing/deployments&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuration for Snapshot Versions
&lt;/h2&gt;

&lt;p&gt;Snapshot versions are designed for rapid iteration during development. They have relaxed validation requirements and can be republished multiple times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maven POM Configuration for Snapshots
&lt;/h3&gt;

&lt;p&gt;Snapshots require minimal metadata compared to releases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;project&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.yourusername&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;your-library&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;packaging&amp;gt;&lt;/span&gt;jar&lt;span class="nt"&gt;&amp;lt;/packaging&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Minimal required metadata for snapshots --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Your Library Name&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Development snapshot of Your Library&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://github.com/yourusername/your-library&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- Central Publishing Plugin (same as releases) --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.sonatype.central&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;central-publishing-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.9.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;extensions&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/extensions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;publishingServerId&amp;gt;&lt;/span&gt;central&lt;span class="nt"&gt;&amp;lt;/publishingServerId&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;autoPublish&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/autoPublish&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;

            &lt;span class="c"&gt;&amp;lt;!-- GPG Signing (same as releases) --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-gpg-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;sign-artifacts&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;verify&lt;span class="nt"&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;sign&lt;span class="nt"&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;passphraseServerId&amp;gt;&lt;/span&gt;gpg.passphrase&lt;span class="nt"&gt;&amp;lt;/passphraseServerId&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;gpgArguments&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;--pinentry-mode&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;loopback&lt;span class="nt"&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/gpgArguments&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;executable&amp;gt;&lt;/span&gt;gpg&lt;span class="nt"&gt;&amp;lt;/executable&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;

            &lt;span class="c"&gt;&amp;lt;!-- Source and Javadoc plugins are optional for snapshots --&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- Include them if you want consistent artifact structure --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Differences for Snapshots
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Relaxed Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;&amp;lt;developers&amp;gt;&lt;/code&gt; section required&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;&amp;lt;scm&amp;gt;&lt;/code&gt; section required&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;&amp;lt;licenses&amp;gt;&lt;/code&gt; section required (though recommended)&lt;/li&gt;
&lt;li&gt;Source and Javadoc JARs are optional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Version Format:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must end with &lt;code&gt;-SNAPSHOT&lt;/code&gt; (e.g., &lt;code&gt;1.0.0-SNAPSHOT&lt;/code&gt;, &lt;code&gt;2.1.0-SNAPSHOT&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Can be republished multiple times without changing the version number&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Publication Behavior:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not indexed in Maven Central search&lt;/li&gt;
&lt;li&gt;Available immediately after upload&lt;/li&gt;
&lt;li&gt;Stored in a separate snapshot repository&lt;/li&gt;
&lt;li&gt;Automatically cleaned up after a retention period&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deploying a Snapshot
&lt;/h3&gt;

&lt;p&gt;Deploy snapshots using the same command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn clean deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maven automatically detects the &lt;code&gt;-SNAPSHOT&lt;/code&gt; suffix and routes the deployment to the snapshot repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consuming Published Snapshots
&lt;/h3&gt;

&lt;p&gt;To use snapshots published by others (or your own), configure your project's &lt;code&gt;pom.xml&lt;/code&gt; or &lt;code&gt;settings.xml&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  In Your Project's POM
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;repositories&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;repository&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;central-portal-snapshots&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Central Portal Snapshots&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://central.sonatype.com/repository/maven-snapshots/&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;snapshots&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;enabled&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/enabled&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;updatePolicy&amp;gt;&lt;/span&gt;always&lt;span class="nt"&gt;&amp;lt;/updatePolicy&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/snapshots&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;releases&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;enabled&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/enabled&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/releases&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/repository&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/repositories&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  In Your Settings.xml (Global Configuration)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;profiles&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;central-snapshots&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;repositories&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;repository&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;central-portal-snapshots&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Central Portal Snapshots&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://central.sonatype.com/repository/maven-snapshots/&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;snapshots&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;enabled&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/enabled&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;updatePolicy&amp;gt;&lt;/span&gt;always&lt;span class="nt"&gt;&amp;lt;/updatePolicy&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/snapshots&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/repository&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/repositories&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/profiles&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;activeProfiles&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;activeProfile&amp;gt;&lt;/span&gt;central-snapshots&lt;span class="nt"&gt;&amp;lt;/activeProfile&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/activeProfiles&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuration Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;updatePolicy&lt;/code&gt;: Controls how often Maven checks for snapshot updates

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;always&lt;/code&gt;: Check on every build (recommended for active development)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;daily&lt;/code&gt;: Check once per day (default)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;interval:X&lt;/code&gt;: Check every X minutes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;never&lt;/code&gt;: Never check for updates&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;For more detailed information and the latest updates, refer to the official Sonatype documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Central Portal Documentation&lt;/strong&gt;: &lt;a href="https://central.sonatype.org/register/central-portal/" rel="noopener noreferrer"&gt;https://central.sonatype.org/register/central-portal/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publishing Guide&lt;/strong&gt;: &lt;a href="https://central.sonatype.org/publish/publish-guide/" rel="noopener noreferrer"&gt;https://central.sonatype.org/publish/publish-guide/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maven Configuration&lt;/strong&gt;: &lt;a href="https://central.sonatype.org/publish/publish-maven/" rel="noopener noreferrer"&gt;https://central.sonatype.org/publish/publish-maven/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The official documentation provides comprehensive coverage of edge cases, advanced configurations, and troubleshooting scenarios that may not be covered in this guide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Sonatype recently migrated from the old JIRA-based system to the new Central Portal at central.sonatype.com. If you find older tutorials mentioning JIRA tickets and issues.sonatype.org, that process is now deprecated. This guide reflects the current, streamlined process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions or issues?&lt;/strong&gt; Drop a comment below, and I'll do my best to help!&lt;/p&gt;

</description>
      <category>java</category>
      <category>maven</category>
    </item>
    <item>
      <title>Understanding GitHub Webhooks: Leveraging Reverse Proxy with Ngrok for Local Development</title>
      <dc:creator>Selma Guedidi</dc:creator>
      <pubDate>Thu, 25 Jul 2024 00:10:33 +0000</pubDate>
      <link>https://forem.com/selmaguedidi/understanding-github-webhooks-leveraging-reverse-proxy-with-ngrok-for-local-development-2k7n</link>
      <guid>https://forem.com/selmaguedidi/understanding-github-webhooks-leveraging-reverse-proxy-with-ngrok-for-local-development-2k7n</guid>
      <description>&lt;p&gt;Webhooks are a powerful and flexible way for applications to communicate with each other in real-time. They are a crucial feature for developers who want to automate workflows and integrate with other services. In this blog post, we will explore what GitHub webhooks are, why we use them, and how to leverage a reverse proxy like &lt;em&gt;Ngrok&lt;/em&gt; to trigger events on a local development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are GitHub Webhooks?
&lt;/h2&gt;

&lt;p&gt;Webhooks allow you to subscribe to specific events occurring within a software system and automatically receive detailed data delivered to your server in real-time whenever those events take place. &lt;/p&gt;

&lt;p&gt;When you create a webhook, you specify a URL and subscribe to specific events that occur within your GitHub repository. These events can range from code pushes and pull requests to issues and comments. Whenever an event that your webhook is subscribed to occurs, GitHub sends an HTTP POST request with detailed data about the event to the URL you specified.&lt;/p&gt;

&lt;p&gt;The webhook's payload URL is the endpoint that will receive these HTTP requests. Your server must be set up to listen for webhook deliveries at this URL. When it receives a request, it can parse the event data and take appropriate actions. This allows for a wide variety of automated workflows, such as triggering CI/CD pipelines, sending notifications, or updating external systems with the latest repository information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Workflow of GitHub Webhooks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event Subscription:&lt;/strong&gt; When configuring a webhook, you choose which events your webhook should listen for. These could include events like push, pull_request, issues, release, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event Trigger:&lt;/strong&gt; When one of the subscribed events occurs in the repository, GitHub prepares an HTTP POST request with a payload containing details about the event. For example, a push event payload includes information about the commits, the branch involved, and the repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTTP Request to Payload URL:&lt;/strong&gt; GitHub sends the HTTP POST request to the specified payload URL. This request includes the payload data as JSON, providing all the necessary details about the event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Processing:&lt;/strong&gt; Your server, which is set up to handle requests at the payload URL, receives the webhook request. It then processes the payload data to determine what action to take. For instance, it might trigger a Jenkins build, post a message to a Slack channel, or update a database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Response to GitHub:&lt;/strong&gt; After processing the event, your server responds to GitHub with an HTTP status code. A &lt;code&gt;2xx&lt;/code&gt; status code indicates that the request was successfully received and processed. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu63vh6dbs2nsinlo1awi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu63vh6dbs2nsinlo1awi.png" alt="Webhook process" width="800" height="1094"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Ngrok as a Reverse Proxy
&lt;/h2&gt;

&lt;p&gt;In a local development environment, your server might not be accessible from the internet, making it difficult to test webhooks that require a publicly accessible endpoint. This is where Ngrok comes in handy. Ngrok is a tool that creates a secure tunnel to your local server, providing a public URL that GitHub can send webhooks to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Ngrok Works?
&lt;/h2&gt;

&lt;p&gt;Ngrok establishes a secure connection between your local machine and a publicly accessible URL, effectively exposing your local server to the internet. Here’s a detailed breakdown of the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an account in &lt;a href="//www.ngrok.com"&gt;ngrok.com&lt;/a&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahxqgmtxzzdtt51hzio4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahxqgmtxzzdtt51hzio4.png" alt="Ngrok website" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Follow given instructions to install ngrok and add authtoken:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaowqxpa1ho8y3xik570.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaowqxpa1ho8y3xik570.png" alt="instructions to install ngrok and add token" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Setting Up Ngrok to Trigger a Simple CI/CD Pipeline in Jenkins
&lt;/h2&gt;

&lt;p&gt;Let's walk through an example of setting up Ngrok to expose a local Jenkins server and configure a GitHub webhook to trigger a simple CI/CD pipeline when code is pushed to a repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Ensure Jenkins is Running&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this example, let's assume that your Jenkins server is already installed and running on port &lt;code&gt;8080&lt;/code&gt;. If Jenkins is running correctly, you should be able to access it in your browser at &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Install Github plugin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To allow Jenkins to be triggered by GitHub webhooks, you need to install the GitHub plugin:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;"Manage Jenkins” -&amp;gt; “Plugins”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Install the &lt;strong&gt;GitHub Plugin&lt;/strong&gt; and restart Jenkins if required.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4o9v3g2ilsba8zo9x1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4o9v3g2ilsba8zo9x1d.png" alt="GitHub Plugin" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Create a Jenkins Job&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click on “New Item,” enter a name for your job, select “Freestyle project,” and click “OK.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add git repository and specify branch(s)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the “GitHub hook trigger for GITScm polling” option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure your job. For simplicity, you might just echo a message in the Build section.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjl5vcq9jh9lm0w0kiflr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjl5vcq9jh9lm0w0kiflr.png" alt="Repository" width="800" height="464"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fein4zm48u6i28baxwja8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fein4zm48u6i28baxwja8.png" alt="Jenkins Job" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Start Ngrok&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open a terminal and start Ngrok to create a secure tunnel to your local Jenkins server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok http 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ngrok will provide a public URL, such as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw9jzq80nnsiwgvsqry3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw9jzq80nnsiwgvsqry3.png" alt="Ngrok url" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Configure GitHub Webhook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your GitHub repository, configure a webhook to send events to your Jenkins server through the Ngrok URL:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to your GitHub repository and go to “Settings” -&amp;gt; “Webhooks”&lt;/li&gt;
&lt;li&gt;Click “Add webhook”&lt;/li&gt;
&lt;li&gt;In the “Payload URL” field, enter the Ngrok URL followed by &lt;code&gt;/github-webhook/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click “Add webhook” to save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfgoma276l2bl1o5s1ir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfgoma276l2bl1o5s1ir.png" alt="github Webhook" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If your Jenkins server denies anonymous user access, you need to include authentication credentials in the webhook URL to avoid a 401 Unauthorized error. The URL format should be &lt;code&gt;https://user:password@PUBLIC_URL/github-webhook/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Test the Setup&lt;/strong&gt;&lt;br&gt;
To test the webhook setup, push a change to your GitHub repository. This should trigger the webhook and send a request to your Jenkins server via the Ngrok tunnel. Jenkins will then trigger the configured job.&lt;/p&gt;

&lt;p&gt;You can verify this by checking the Jenkins job console output. You should see the echo message "Build triggered by GitHub webhook," indicating that the webhook successfully triggered the CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftldzg99mz34lgdcyfvdc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftldzg99mz34lgdcyfvdc.png" alt="Console log" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;GitHub webhooks enable real-time automation by notifying external services about repository events. Testing these integrations locally can be challenging due to accessibility constraints. Ngrok simplifies this by creating a secure tunnel to your local server, allowing you to test webhook configurations as if they were exposed on the internet.&lt;/p&gt;

&lt;p&gt;In our example, we demonstrated how to use Ngrok to trigger a Jenkins CI/CD pipeline from GitHub events. This setup allows for seamless testing of webhooks in a local environment, ensuring your integrations work as expected before deployment. Overall, leveraging GitHub webhooks with Ngrok enhances development efficiency and reliability.&lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>jenkins</category>
      <category>ngrok</category>
      <category>devops</category>
    </item>
    <item>
      <title>A dive into Jenkins Configuration as Code (JCasC)</title>
      <dc:creator>Selma Guedidi</dc:creator>
      <pubDate>Mon, 22 Jul 2024 19:05:06 +0000</pubDate>
      <link>https://forem.com/selmaguedidi/a-dive-into-jenkins-configuration-as-code-jcasc-4dj0</link>
      <guid>https://forem.com/selmaguedidi/a-dive-into-jenkins-configuration-as-code-jcasc-4dj0</guid>
      <description>&lt;p&gt;In today's fast-paced DevOps world, automation is key to maintaining efficiency and consistency across development, testing, and deployment processes. Jenkins, a popular open-source automation server, offers a powerful feature called Jenkins Configuration as Code (JCasC). This allows you to manage your Jenkins configurations in a human-readable and declarative manner using YAML files, ensuring your setup is consistent, reproducible, and version-controlled.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll explore the benefits of JCasC and walk through a sample use case to get you started.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Jenkins Configuration as Code (JCasC)?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Jenkins Configuration as Code (JCasC) allows you to define and configure Jenkins instances using YAML files. This means you can describe all aspects of your Jenkins setup —from global configurations to job definitions— in a version-controlled repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Dockerfile
&lt;/h2&gt;

&lt;p&gt;The Dockerfile provided below sets up Jenkins with the necessary plugins and configurations using JCasC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM jenkins/jenkins:lts-jdk17

# Install Jenkins plugins
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN jenkins-plugin-cli --plugin-file /usr/share/jenkins/ref/plugins.txt

# Disable the setup wizard as we will set up Jenkins as code
ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false"

# Copy the Configuration as Code (CasC) YAML file into the image
COPY jenkins-casc.yaml /var/jenkins_home/casc_configs/jenkins.yaml

# Tell the Jenkins Configuration as Code plugin where to find the YAML file
ENV CASC_JENKINS_CONFIG="/var/jenkins_home/casc_configs/jenkins.yaml"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this Dockerfile, we start with the &lt;code&gt;jenkins/jenkins:lts-jdk17&lt;/code&gt; image, ensuring we have a stable Jenkins version with &lt;code&gt;JDK 17&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;jenkins-plugin-cli&lt;/code&gt; is a command-line tool that installs Jenkins plugins specified in &lt;code&gt;plugins.txt&lt;/code&gt;, streamlining the setup of necessary plugins. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;JAVA_OPTS&lt;/code&gt; environment variable disables the Jenkins setup wizard since we are configuring Jenkins using JCasC. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;COPY&lt;/code&gt; commands include the required &lt;code&gt;plugins.txt&lt;/code&gt; and &lt;code&gt;jenkins-casc.yaml&lt;/code&gt; files into the Docker image. &lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;CASC_JENKINS_CONFIG&lt;/code&gt; environment variable points Jenkins to the location of the JCasC YAML file, allowing it to automatically apply the specified configurations at startup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specifying Plugins
&lt;/h2&gt;

&lt;p&gt;To ensure Jenkins has the necessary plugins for its operations, create a &lt;code&gt;plugins.txt&lt;/code&gt; file. This file lists the required plugins and their versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git:5.0.0
workflow-aggregator:600.vb_57cdd26fdd7
configuration-as-code:1810.v9b_c30a_249a_4c
matrix-auth:3.2.2
job-dsl:1.87
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each line in &lt;code&gt;plugins.txt&lt;/code&gt; specifies a plugin. You can include the version after a colon (e.g., &lt;code&gt;git:5.0.0&lt;/code&gt;) to ensure a specific version is installed. If you omit the version (e.g., &lt;code&gt;git&lt;/code&gt;), the latest version of the plugin will be installed when the image is built. Specifying versions can help maintain consistency across different environments by ensuring the same plugin versions are used.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;matrix-auth&lt;/code&gt; plugin is useful for managing access control in Jenkins environments where multiple users or teams interact with Jenkins. We'll need it later when we set up users and assign them different roles based on their responsibilities.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;code&gt;job-dsl Plugin&lt;/code&gt; adds support for defining Jenkins jobs using Groovy DSL scripts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;configuration-as-code&lt;/code&gt; plugin is essential for JCasC to function. It enables Jenkins to read the YAML configuration file and apply the specified settings automatically. &lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Jenkins with JCasC
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;jenkins-casc.yaml&lt;/code&gt; file to configure Jenkins. In this blog, we will define user authentication, tool installations, and a sample job. Here’s a comprehensive example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jenkins:
  systemMessage: "Jenkins configured automatically by Jenkins Configuration as Code plugin"

  # Security Realm for user authentication
  securityRealm:
    local:
      allowsSignup: false
      users:
        - id: "admin"
          password: "admin"

        - id: "developer"
          password: "developer"

        - id: "viewer"
          password: "viewer"


  # Authorization Strategy
  authorizationStrategy:
    projectMatrix:
      entries:
        - user:
            name: admin
            permissions:
              - Overall/Administer
        - user:
            name: developer
            permissions:
              - Overall/Read
              - Job/Build
        - user:
            name: viewer
            permissions:
              - Overall/Read



# Tool Configuration
tool:
  git:
    installations:
      - name: "Default"
        home: "/usr/bin/git"
  maven:
    installations:
      - name: maven3
        properties:
          - installSource:
              installers:
                - maven:
                    id: "3.8.4"

# Sample Job Configuration
jobs:
  - script: &amp;gt;
      pipelineJob('example-pipeline-job') {
      definition {
        cps {
            script('''
                pipeline {
                    agent any
                    stages {
                        stage('Build') {
                            steps {
                                echo 'Building...'
                            }
                        }
                        stage('Test') {
                            steps {
                                echo 'Testing...'
                            }
                        }
                        stage('Deploy') {
                            steps {
                                echo 'Deploying...'
                            }
                        }
                    }
                }
            ''')
            }
          }
        } 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;User authentication is defined in the &lt;code&gt;securityRealm&lt;/code&gt; section, where local user authentication is configured, and self-signup is disabled for security. Three users are predefined: &lt;code&gt;admin&lt;/code&gt;, with full administrative access; &lt;code&gt;developer&lt;/code&gt;, with read and build permissions; and &lt;code&gt;viewer&lt;/code&gt;, with read-only access. This setup ensures appropriate access levels based on user roles.&lt;/p&gt;

&lt;p&gt;Authorization is handled by the Project-based Matrix Authorization Strategy in the authorizationStrategy section. This strategy provides granular control over user permissions, giving the &lt;code&gt;admin&lt;/code&gt; full control with &lt;code&gt;(Overall/Administer)&lt;/code&gt;, while both the &lt;code&gt;developer&lt;/code&gt; and &lt;code&gt;viewer&lt;/code&gt; have read access to the overall Jenkins instance &lt;code&gt;(Overall/Read)&lt;/code&gt;, with the &lt;code&gt;developer&lt;/code&gt; also having the ability to build jobs &lt;code&gt;(Job/Build)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tool section Specifies the configuration for tools that Jenkins will use, in our case: git and Maven. The git tool is set up with a default installation path, and Maven is installed ensuring that these tools are readily available for use in jobs.&lt;/p&gt;

&lt;p&gt;The jobs section defines a sample pipeline job using a script block. &lt;/p&gt;

&lt;h2&gt;
  
  
  Build and Run the Docker Container
&lt;/h2&gt;

&lt;p&gt;Now, we'll build and run our Docker container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build the Docker image
docker build -t jenkins-jcasc .

# Run the Docker container
docker run --name jenkins -p 8080:8080  jenkins-jcasc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the container is running, you can access Jenkins at &lt;code&gt;http://localhost:8080&lt;/code&gt; and log in using one of the user credentials created earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F080xbfokj6msv8xilwtg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F080xbfokj6msv8xilwtg.png" alt="Login page" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can notice the system message we defined earlier and the sample pipeline.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzaor78wyqupqbghvl606.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzaor78wyqupqbghvl606.png" alt="Admin dashboard" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the code used for this blog in the following repository: &lt;a href="https://github.com/SelmaGuedidi/JCasC" rel="noopener noreferrer"&gt;https://github.com/SelmaGuedidi/JCasC&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;For further information on Jenkins Configuration as Code (JCasC), you can consult these sources:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Configuration-as-code plugin documentation:&lt;/em&gt; &lt;a href="https://plugins.jenkins.io/configuration-as-code/" rel="noopener noreferrer"&gt;https://plugins.jenkins.io/configuration-as-code/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;demos:&lt;/em&gt; &lt;a href="https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos" rel="noopener noreferrer"&gt;https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Jenkins Configuration as Code simplifies the management of Jenkins configurations, making your CI/CD pipeline more robust and easier to maintain. By leveraging Docker and JCasC, you can quickly set up consistent Jenkins environments that are easy to reproduce and update.&lt;/p&gt;

&lt;p&gt;Try out JCasC in your projects and experience the benefits of a streamlined, automated Jenkins setup. Happy automating!&lt;/p&gt;

</description>
      <category>jenkins</category>
      <category>docker</category>
      <category>devops</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
