shell library for Debian package releases This is a bash library intended to be used in a CI/CD pipeline to make finding the next release number for a Debian package semi-automatic.  I figured out how to use a JSON file as a metadata store since the CI/CD pipeline I'm working with doesn't provide any metadata storage across jobs.

I'm basically happy with how this is working.  We've used it for a few weeks without finding any bugs yet.  I'm happy that it passes shellcheck, but I'd also like to have some linting for ensuring that the code is documented adequately.  I'm not sure if my use of jq makes this too hard to maintain or if it just that using jq like this is so new to me.

deblib.sh

#!/bin/bash

# TODO: generate $PKGJSON from Debian repo metadata
PKGJSON=/opt/org_foo/var/packaging/packaging.json

# deb-release-number
# ------------------
#
# Arguments:
# 1. (required) package name
# 2. (required) package version ("upstream" version)
# 3. (optional) architecture (defaults to amd64)
# 4. (optional) packager (defaults to 1org_foo)
#
# Testing:
# Test by running
#       bash deblib.sh debug
# or passing any argumenet in to activate the "verification" section below

function deb-release-number {
        # read arguments
        PKGNAME=${1?provide package name as first argument}
        PKGVER=${2?provide package version as second argument}
        PKGARCH=${3:-amd64}
        PACKAGER=${4-1org_foo}

        # find latest release of this package/version
        RELEASE=$(jq -r ".\"latest_version\".\"${PKGNAME}\".\"${PKGVER}\"" &lt;"$PKGJSON" )
        if [[ "$RELEASE" == "null" ]];
        then
                # start at 0 so the first release ends up being 1 after the increment below
                RELEASE=0
        fi
        ## echo RELEASE=$RELEASE

        # increment
        RELEASE=$(( RELEASE + 1 ))
        LONGPKGVER="${PKGVER}-${PACKAGER}-${RELEASE}" # seperated with dashes
        PKGFILENAME="${PKGNAME}_${LONGPKGVER}_${PKGARCH}.deb" # seperated with underscores
        echo "new release $RELEASE of $PKGNAME creates filename $PKGFILENAME"

        # backup
        cp "$PKGJSON" "${PKGJSON}.bak"

        # update release_version (into tmp file)
        jq ".\"latest_version\".\"${PKGNAME}\".\"${PKGVER}\" = \"${RELEASE}\"" &lt;"$PKGJSON" &gt;"${PKGJSON}.tmp"
        ## grep "$PKGVER" "${PKGJSON}.tmp"

        # update built_packages (out of tmp file into main file)
        jq ".\"built_packages\" += [\"${PKGFILENAME}\"]" &lt;"${PKGJSON}.tmp" &gt;"$PKGJSON"
        ## grep "$PKGNAME" "$PKGJSON"

        return $RELEASE
}

# verification
if [[ $# -gt 0 ]];
then
        deb-release-number librdkafka1 1.0.0
        deb-release-number foo 1.1.0 noarch
fi


Example

An example of usage:

source deblib.sh
deb-release-number 'foo-stuff' "${GIT_TAG#v}" 'amd64'
PKGRELEASE=$?
Some lints:


Uppercase names are by convention only for exported variables.
You can use getopt to parse parameters. This should make it easier to handle optional parameters, and also makes it easy to avoid positional parameters (which makes commands more self-documenting).
Use More Quotes™
I would guard against errors and accidents by using set -o errexit -o noclobber -o nounset -o pipefail at the top of the script.
returning anything other than an exit code is a problem. You function should instead output the value (and ensure other output goes to standard error). One issue is the semantics of conflating exit codes. The other is the lingering bug because exit codes wrap around after 255.
You can use mktemp --directory to create a temporary directory to store intermediate results. Even better would be to pass results in a pipeline to avoid any temporary files.