Codenotary Trustcenter Blog

A Jenkins shared library to execute commands with vcn, our CLI tool - Codenotary

Written by @marco | Jul 20, 2022 5:16:12 PM

Learn how to reuse code in continuous integration pipelines with our digital assets attestation tool

If you need to use the same piece of code in many different pipelines, a Jenkins shared library is a good approach. After importing it, you will have access to its methods, which is a convenient way of avoiding repetition and improving scalability and maintainability.

Here at Codenotary we recently wrote a shared library with simple methods for some commands of our command line interface (CLI) tool, vcn, which we can then use on other pipelines in a very intuitive manner:

package lib

public class VCN implements Serializable {
    def context

    public VCN(def context) {
        this.context = context
    }

    def execute(String command, String... arguments) {
        arguments = arguments.join(" ")
        context.echo context.sh(returnStdout: true, script: "./vcn ${command} ${arguments}").trim()
    }

    def authenticate(String... arguments) {
        execute("authenticate", arguments)
    }

    def bom(String... arguments) {
        execute("bom", arguments)
    }

    def inspect(String... arguments) {
        execute("inspect", arguments)
    }

    def list(String... arguments) {
        execute("list", arguments)
    }

    def login(String... arguments) {
        execute("login", arguments)
    }

    def logout(String... arguments) {
        execute("logout", arguments)
    }

    def notarize(String... arguments) {
        execute("notarize", arguments)
    }

    def serve(String... arguments) {
        execute("serve", arguments)
    }

    def unsupport(String... arguments) {
        execute("unsupport", arguments)
    }

    def untrust(String... arguments) {
        execute("untrust", arguments)
    }
}

As you can see, the shared library exposes a class that models the vcn tool. When initialized, the class instance receives the Jenkins context, which allows it to execute the commands on the pipeline that called it. All methods representing the commands just receive any amount of String parameters and pass them, with the command name, to the execute method. The execute method then just joins the parameters received and calls vcn in a shell – with the command passed and the joined parameters.

This is an example Jenkins pipeline script that could make use of this shared library:

@Library('jenkins-libs@vcn') _

import lib.VCN


node('debian') {
    try {
	def vcn = new VCN(this)

	stage('Checkout vcn') {
	    checkout scm
	    }

	stage('Build vcn') {
	    sh "make"
	}

	stage("Login") {
	    String arguments = "--lc-host ${LC_HOST} --lc-skip-tls-verify --lc-port 443"
	    vcn.login(arguments)
	}

	stage("Notarize vcn") {
            String arguments = '"*.py"'
            vcn.notarize(arguments)
	}

	stage("Authenticate vcn") {
	    String arguments = 'vcn --output=""'
		vcn.authenticate(arguments)
	}

	} finally {
	    stage('Cleanup') {
	    step([$class: 'WsCleanup'])
	    deleteDir()
	}
    }
}

The pipeline would work like this:

This is just a simple example to show the power of a Jenkins shared library. It can be certainly improved and extended to accommodate more robust needs required by a production environment.

You can try it yourself by starting a Codenotary Trustcenter trial: