matrix-id.lisp#
SBCL Common Lisp reference module. Load before compiling your system to embed
org.cispec.* attribution strings in the compiled image. The strings are
defined as defconstant forms and survive save-lisp-and-die dumps.
Source#
;;;; SPDX-License-Identifier: BSD-2-Clause
;;;;
;;;; matrix-id.lisp — org.cispec Change Item attribution module
;;;; Canonical source: https://cispec.org/spec/matrix-id.lisp
;;;; Spec version: 1.0
;;;;
;;;; Embeds org.cispec.* attribution strings into a compiled SBCL image
;;;; as defconstant forms. Strings survive save-lisp-and-die dumps and
;;;; are present in the compiled fasl.
;;;;
;;;; Usage: load before compiling your system, or add to your .asd file
;;;; as a component with :depends-on ("matrix-id").
;;;;
;;;; Required parameters — set via environment or redefine before loading:
;;;; CISPEC_ORGANIZATION
;;;; CISPEC_ORGUNIT
;;;; CISPEC_APPLICATION
;;;; CISPEC_VERSION
(defpackage #:org.cispec.matrix-id
(:use #:cl)
(:export
#:+organization+
#:+orgunit+
#:+owner+
#:+oid+
#:+duns+
#:+customer+
#:+costcenter+
#:+application+
#:+role+
#:+version+
#:+environment+
#:+specversion+
#:label-set
#:verify-required))
(in-package #:org.cispec.matrix-id)
;;; ----------------------------------------------------------------
;;; Helper — read from environment with fallback
;;; ----------------------------------------------------------------
(defun env-or (var default)
"Return the value of environment variable VAR, or DEFAULT if unset or empty."
(let ((val (uiop:getenv var)))
(if (and val (plusp (length val))) val default)))
;;; ----------------------------------------------------------------
;;; Required attribution constants
;;; ----------------------------------------------------------------
(defconstant +organization+
(env-or "CISPEC_ORGANIZATION" "")
"org.cispec.organization — owning organisation slug.")
(defconstant +orgunit+
(env-or "CISPEC_ORGUNIT" "")
"org.cispec.orgunit — organisational unit slug.")
(defconstant +application+
(env-or "CISPEC_APPLICATION" "")
"org.cispec.application — application or service name.")
(defconstant +version+
(env-or "CISPEC_VERSION" "")
"org.cispec.version — semver 2.0 version string.")
;;; ----------------------------------------------------------------
;;; Optional attribution constants
;;; ----------------------------------------------------------------
(defconstant +owner+
(env-or "CISPEC_OWNER" "")
"org.cispec.owner — identity contact (key fingerprint or handle).")
(defconstant +oid+
(env-or "CISPEC_OID" "iso.org.dod.internet.42387")
"org.cispec.oid — IANA OID arc.")
(defconstant +duns+
(env-or "CISPEC_DUNS" "")
"org.cispec.duns — D&B DUNS in OID notation.")
(defconstant +customer+
(env-or "CISPEC_CUSTOMER" "")
"org.cispec.customer — customer identifier.")
(defconstant +costcenter+
(env-or "CISPEC_COSTCENTER" "")
"org.cispec.costcenter — cost centre identifier.")
(defconstant +role+
(env-or "CISPEC_ROLE" "")
"org.cispec.role — functional role slug.")
(defconstant +environment+
(env-or "CISPEC_ENVIRONMENT" "")
"org.cispec.environment — deployment environment slug.")
(defconstant +specversion+
"1.0"
"org.cispec spec version this module implements.")
;;; ----------------------------------------------------------------
;;; Label set — returns an alist of all non-empty key/value pairs
;;; ----------------------------------------------------------------
(defun label-set ()
"Return an alist of (key . value) pairs for all non-empty org.cispec labels."
(remove-if (lambda (pair) (string= "" (cdr pair)))
(list (cons "org.cispec.organization" +organization+)
(cons "org.cispec.orgunit" +orgunit+)
(cons "org.cispec.application" +application+)
(cons "org.cispec.version" +version+)
(cons "org.cispec.owner" +owner+)
(cons "org.cispec.oid" +oid+)
(cons "org.cispec.duns" +duns+)
(cons "org.cispec.customer" +customer+)
(cons "org.cispec.costcenter" +costcenter+)
(cons "org.cispec.role" +role+)
(cons "org.cispec.environment" +environment+)
(cons "org.cispec.specversion" +specversion+))))
;;; ----------------------------------------------------------------
;;; Verify required keys are populated
;;; ----------------------------------------------------------------
(defun verify-required ()
"Signal an error if any required org.cispec key is empty.
Call at load time to catch misconfigured builds early."
(let ((required '((+organization+ . "org.cispec.organization")
(+orgunit+ . "org.cispec.orgunit")
(+application+ . "org.cispec.application")
(+version+ . "org.cispec.version"))))
(dolist (pair required)
(when (string= "" (symbol-value (car pair)))
(error "org.cispec: required label ~A is empty; ~
set environment variable ~:*~A before loading."
(cdr pair)))))
t)Usage in an ASDF system#
Add matrix-id as a dependency in your .asd file:
(asdf:defsystem "my-system"
:depends-on ("org.cispec.matrix-id")
:components ((:file "main")))Call (org.cispec.matrix-id:verify-required) early in your build script
or entry-point to catch missing attribution before shipping.
Printing the label set#
(dolist (pair (org.cispec.matrix-id:label-set))
(format t "~A=~A~%" (car pair) (cdr pair)))Output (example):
org.cispec.organization=daplanet
org.cispec.orgunit=dps
org.cispec.application=my-tool
org.cispec.version=1.0.0
org.cispec.oid=iso.org.dod.internet.42387
org.cispec.specversion=1.0Licence#
BSD-2-Clause. SPDX-License-Identifier: BSD-2-Clause.
Canonical source: https://cispec.org/spec/matrix-id.lisp