ci: Add Jenkins pipeline
dustin/sshca/pipeline/head There was a failure building this commit Details

The CI pipeline builds both the SSHCA server and client CLI.  The server
is published as an OCI image, while the latter uses RPMs.  Since
multiple RPMs with the same version cannot exist in the same repository,
and since RPM versions cannot be arbitrarily set after they have been
built, the RPMs are only published when building the *master* branch.
Server container images are published from every branch, as each image
is tagged with the branch name and build number.
Dustin 2023-11-08 19:15:01 -06:00
parent 4610e9df33
commit 2243e9e41d
10 changed files with 217 additions and 0 deletions

109
ci/Jenkinsfile vendored Normal file
View File

@ -0,0 +1,109 @@
pipeline {
agent none
stages {
stage('SSHCA') {
parallel {
stage('Server') {
agent {
kubernetes {
yamlFile 'ci/serverPodTemplate.yaml'
yamlMergeStrategy merge()
defaultContainer 'buildah'
}
}
stages {
stage('Build - Server') {
steps {
sh '. ci/build-server.sh'
}
}
stage('Publish - Server') {
steps {
withEnv([
"REGISTRY_AUTH_FILE=${env.WORKSPACE_TMP}/auth.json"
]) {
withCredentials([usernamePassword(
credentialsId: 'jenkins-packages',
usernameVariable: 'BUILDAH_USERNAME',
passwordVariable: 'BUILDAH_PASSWORD',
)]) {
sh """
buildah login \
--username \${BUILDAH_USERNAME} \
--password \${BUILDAH_PASSWORD} \
git.pyrocufflink.net
"""
}
sh '. ci/publish-server.sh'
}
}
}
}
}
stage('CLI') {
agent {
kubernetes {
yamlFile 'ci/clientPodTemplate.yaml'
yamlMergeStrategy merge()
defaultContainer 'fedora'
}
}
environment {
GNUPGHOME = "${env.WORKSPACE_TMP}/gnupg"
}
stages {
stage('Prepare - CLI') {
steps {
sh '. ci/prepare-client.sh'
}
}
stage('Build - CLI') {
steps {
sh '. ci/build-client.sh'
script {
if (env.BRANCH_NAME == 'master') {
withCredentials([
file(
credentialsId: 'rpm-gpg-key',
variable: 'RPM_GPG_PRIVATE_KEY',
),
file(
credentialsId: 'rpm-gpg-key-passphrase',
variable: 'RPM_GPG_KEY_PASSPHRASE',
),
]) {
sh '. ci/sign-rpms.sh'
}
}
}
}
post {
success {
dir('cli') {
archiveArtifacts '*.rpm'
}
}
}
}
stage('Publish - CLI') {
when {
branch 'master'
}
steps {
sshagent(['jenkins-repohost']) {
sh '. ci/publish-client.sh'
}
}
}
}
}
}
}
}
}

4
ci/build-client.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/sh
cd cli
make rpm

5
ci/build-server.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/sh
. ci/common.sh
buildah build -t "${IMAGE_NAME}:${TAG}" server

View File

@ -0,0 +1,9 @@
spec:
containers:
- name: fedora
image: registry.fedoraproject.org/fedora:38
command:
- cat
stdin: true
tty: true
hostUsers: false

13
ci/common.sh Normal file
View File

@ -0,0 +1,13 @@
escape_name() {
echo "$1" \
| tr A-Z a-z \
| sed -e 's/[^a-zA-Z0-9._-]/-/g' -e 's/^[.-]/_/'
}
REGISTRY_URL=git.pyrocufflink.net
NAMESPACE=containerimages
NAME="${JOB_NAME#*/}"
NAME=$(escape_name "${NAME%/*}")
TAG=$(escape_name "${BRANCH_NAME}")
IMAGE_NAME="${REGISTRY_URL}/${NAMESPACE}/${NAME}"

21
ci/prepare-client.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/sh
dnf install -y \
--setopt install_weak_deps=0 \
cargo \
cargo-rpm-macros \
make \
openssh-clients \
openssl-devel \
rpm-build \
rpm-sign \
rsync \
rust \
systemd-rpm-macros \
tar \
--
install -m u=rwx,go= -d "${GNUPGHOME}"
cat > "${GNUPGHOME}"/gpg-agent.conf <<EOF
allow-loopback-pinentry
EOF

14
ci/publish-client.sh Normal file
View File

@ -0,0 +1,14 @@
#!/bin/sh
REPO_HOST=jenkins@files.pyrocufflink.blue
REPO_PATH=/srv/www/repohost/repos/dch/fedora/$(rpm --eval %fedora)
ssh-add -l
ssh-add -L
rsync -rtiO \
--chmod=ugo=rwX \
--include '*.rpm' \
--exclude '*' \
cli/ \
"${REPO_HOST}:${REPO_PATH}/"

11
ci/publish-server.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/sh
. ci/common.sh
buildah push "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${TAG}-${BUILD_NUMBER}"
buildah push "${IMAGE_NAME}:${TAG}"
case "${BRANCH_NAME}" in
master|main)
buildah push "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:latest"
;;
esac

19
ci/serverPodTemplate.yaml Normal file
View File

@ -0,0 +1,19 @@
spec:
containers:
- name: buildah
image: quay.io/containers/buildah:v1
command:
- cat
stdin: true
tty: true
securityContext:
capabilities:
add:
- SYS_ADMIN
- MKNOD
- SYS_CHROOT
- SETFCAP
resources:
limits:
github.com/fuse: 1
hostUsers: false

12
ci/sign-rpms.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/sh
gpg2 --pinentry-mode loopback --passphrase-fd 0 \
--import "${RPM_GPG_PRIVATE_KEY}" \
< "${RPM_GPG_KEY_PASSPHRASE}"
rpmsign --addsign \
-D '_gpg_name jenkins@pyrocufflink.net' \
-D '_gpg_sign_cmd_extra_args --pinentry-mode loopback --passphrase-fd 3' \
cli/*.rpm \
3< "${RPM_GPG_KEY_PASSPHRASE}"