Jenkins build parameterized with a choice of versi

2019-04-13 17:34发布

问题:

Is there a Jenkins plugin that can do a group-artifact-version (GAV) search of my Nexus repo and list the results? I would like the results to be available on a parameterized build as a choice (a dropdown).

回答1:

I added a groovy script to a Dynamic Choice Parameter (See Jenkins Plugins)

Some hurdles were:

  1. Our Nexus server issues a basic authentication challenge so I couldn't simply use a groovy "http://blah".toURL().text
  2. I didn't want to load in missing groovy jars like httpbuilder so I simply used the Java URLConnection class and the encoded user:pass as a header.
  3. Used REST api to Nexus to get versions, but had to distinguish between release and snapshots. I added group based authentication so that only developers had access to the snapshots.
  4. GAV sort is not a straight forward. There is a better way to GAV sort (using org.apache.maven.artifact.versioning.ComparableVersion) but I have not implemented it yet so for now, I'm simply sorting so the smaller strings line up first.
import hudson.model.*
import jenkins.model.*

def versions=[ ]
def snapshots=[ ]

// The artifactName could be passed in from another parameter (eg. Extended Choice Parameter) linked to this 'dynamic choice' parameter.
def address = "https://xyzcompany.com/nexus/service/local/lucene/search?r=releases&g=com.xyzcompany&a=artifactName&c=features&p=xml"
def urlInfo = address.toURL()

// Consider using tokenstring technique instead of basic auth if pro version of Nexus.
def authString = "user:pass"; // replace 'user' with username, 'pass' with password.  
def authStr="Basic " + authString.bytes.encodeBase64().toString()

// Using URLConnection instead of HTTPBuilder et al.
def connection = urlInfo.openConnection()
connection.setRequestProperty( "Authorization" , authStr)

def xml="${connection.content.text}"
def root = new XmlParser().parseText( xml )
root.data.artifact.each {
 if (it.artifactHits.artifactHit.repositoryId.text() == "releases")
      versions.add("${it.version.text()}");
 else
    snapshots.add("${it.version.text()}");
}

// There is a better way to GAV sort (using org.apache.maven.artifact.versioning.ComparableVersion) but I have not implemented it yet so for now, I'm simply sorting so the smaller strings line up first.
versions.sort { -it.size() }
Collections.reverse(versions)

// Only certain users should be able to see the SNAPSHOT versions
def userid = User.current().id
def auths = Jenkins.instance.securityRealm.loadUserByUsername(userid).authorities.collect{a -> a.authority}
if (["OffShoreDevGroup", "DevGroup"].intersect(auths))
{
  snapshots.sort { -it.size() }
  Collections.reverse(snapshots)
  versions+=snapshots
}

versions.add(" "); // My build uses a blank version string to simply report what is already deployed to the container.
return versions;


回答2:

No need for custom Ruby scripts. There is now a dedicated plugin which does what you require: Maven Metadata Plugin for Jenkins CI server

Just mark "Parameterized Build" and "Add Parameter" of type "List Maven artifact versions":

  • Name MY_SNAPSHOT_JAR
  • Repository Base URL (this one is tricky) http://localhost/nexus/service/local/repositories/snapshots/content

Then add a shell command to wget/scp/etc, you can use the following variables resolved by plugin:

wget "$MY_SNAPSHOT_JAR_ARTIFACT_URL"
echo    "$MY_SNAPSHOT_JAR_VERSION" - the version you selected in the dropdown or that was selected as part of an automated build
echo    "$MY_SNAPSHOT_JAR_ARTIFACT_URL" - the full URL to the actual artifact selected. You can use something like "wget" to download that artifact and do something with it.
echo    "$MY_SNAPSHOT_JAR_GROUP_ID" - echoes back your configuration
echo    "$MY_SNAPSHOT_JAR_ARTIFACT_ID" - echoes back your configuration
echo    "$MY_SNAPSHOT_JAR_CLASSIFIER" - echoes back your configuration
echo    "$MY_SNAPSHOT_JAR_PACKAGING" - echoes back your configuration

Unfortunately you cannot ask about snapshot and release in the same dropdown list. A possible workaround is to add another parameter for MY_RELEASE_JAR (thus another dropdown list, somewhat confusing for a user). Another workaround is to have a separate job for release deployment.