Compare commits

...

2 Commits

Author SHA1 Message Date
Dustin c88b4c42e8 wip: ci: Add Jenkins build pipeline
infra/dch-autoprovision/pipeline/head This commit looks good Details
2025-08-14 08:35:08 -05:00
Dustin b02cd903fa Add RPM spec file 2025-08-14 08:12:05 -05:00
10 changed files with 293 additions and 0 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*.spec]
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab
indent_size = 4

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
dch-autoprovision-*.tar.gz
dch-autoprovision-*.rpm

38
Makefile Normal file
View File

@ -0,0 +1,38 @@
NAME = dch-autoprovision
VERSION = $(shell rpmspec -q --qf '%{VERSION}' $(NAME).spec)
RELEASE = $(shell rpmspec -q --qf '%{RELEASE}' $(NAME).spec)
ARCH = $(shell uname -m)
GIT_REV ?= HEAD
O ?= .
RPM = $(O)/$(NAME)-$(VERSION)-$(RELEASE).$(ARCH).rpm
SRPM = $(0)$/(NAME)-$(VERSION)-$(RELEASE).src.rpm
define rpmbuild
rpmbuild \
-D '_topdir $(shell realpath "$(O)")' \
-D '_builddir %_topdir' \
-D '_rpmdir %_topdir' \
-D '_sourcedir %_topdir' \
-D '_specdir %_topdir' \
-D '_srcrpmdir %_topdir' \
endef
rpm: $(O)/$(ARCH)/$(RPM)
sources: $(O)/$(NAME)-$(VERSION).tar.gz
srpm: $(O)/$(SRPM)
$(O)/$(NAME)-$(VERSION).tar.gz:
git archive --format=tar.gz --prefix $(NAME)-$(VERSION)/ $(GIT_REV) > $@
$(O)/$(ARCH)/$(RPM): $(O)/$(NAME)-$(VERSION).tar.gz
$(rpmbuild) -bb $(NAME).spec
$(O)/$(SRPM): $(O)/$(NAME)-$(VERSION).tar.gz
$(rpmbuild) -bs $(NAME).spec
.PHONY: rpm srpm

84
ci/Jenkinsfile vendored Normal file
View File

@ -0,0 +1,84 @@
pipeline {
agent none
stages {
stage('RPM') {
matrix {
axes {
axis {
name 'ARCH'
values 'amd64', 'arm64'
}
axis {
name 'FEDORA'
values '41', '42'
}
}
agent {
kubernetes {
yamlFile 'ci/podTemplate.yaml'
yamlMergeStrategy merge()
defaultContainer 'build'
nodeSelector "kubernetes.io/arch=${ARCH}"
containerTemplate {
name 'build'
image "registry.fedoraproject.org/fedora:${FEDORA}"
}
}
}
environment {
GNUPGHOME = "${env.WORKSPACE_TMP}/gnupg"
}
stages {
stage('Prepare') {
steps {
sh '. ci/prepare.sh'
}
}
stage('Build') {
steps {
sh '. ci/build.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 {
archiveArtifacts "f${FEDORA}/**/*.rpm"
}
}
}
stage('Publish') {
when {
branch 'master'
}
steps {
sshagent(['jenkins-repohost']) {
sh '. ci/publish.sh'
}
}
}
}
}
}
}
}

6
ci/build.sh Normal file
View File

@ -0,0 +1,6 @@
#!/bin/sh
install -o 1000 -g 1000 -d f${FEDORA}
setpriv --reuid 1000 --regid 1000 --keep-groups \
make O=f${FEDORA} srpm rpm

19
ci/podTemplate.yaml Normal file
View File

@ -0,0 +1,19 @@
spec:
containers:
- name: build
command: &sleep
- /bin/sh
- -c
- |
trap 'kill $!' TERM
sleep infinity &
wait
volumeMounts:
- mountPath: /etc/ssh/ssh_known_hosts
name: ssh-known-hosts
subPath: ssh_known_hosts
hostUsers: false
volumes:
- name: ssh-known-hosts
configMap:
name: ssh-known-hosts

16
ci/prepare.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
xargs dnf install -y <<EOF
git-core
make
openssh-clients
rpm-build
rpm-sign
rsync
systemd-rpm-macros
EOF
install -m u=rwx,go= -d "${GNUPGHOME}"
cat > "${GNUPGHOME}"/gpg-agent.conf <<EOF
allow-loopback-pinentry
EOF

30
ci/publish.sh Normal file
View File

@ -0,0 +1,30 @@
#!/bin/sh
ARCH="$(uname -m)"
REPO_HOST=jenkins@files.pyrocufflink.blue
REPO_PATH=/srv/www/repohost/repos/dch/fedora/$(rpm --eval %fedora)
ssh-add -l
ssh-add -L
mkdir -p "${WORKSPACE_TMP}/sync"
cd "${WORKSPACE_TMP}/sync"
ln "${WORKSPACE}/f${FEDORA}"/*.rpm .
ln "${WORKSPACE}/f${FEDORA}/${ARCH}"/*.rpm .
case "${ARCH}" in
x86_64)
# only include the SRPM once
include='*.rpm'
;;
*)
include="*.${ARCH}.rpm"
;;
esac
rsync -rtiO \
--chmod=ugo=rwX \
--include "${include}" \
--exclude '*' \
./ \
"${REPO_HOST}:${REPO_PATH}/"

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

@ -0,0 +1,11 @@
#!/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' \
f${FEDORA}/$(uname -m)/*.rpm \
3< "${RPM_GPG_KEY_PASSPHRASE}"

78
dch-autoprovision.spec Normal file
View File

@ -0,0 +1,78 @@
%global dch_libexecdir %{_libexecdir}/dch
%global dch_datadir %{_datarootdir}/dch
%define _debugsource_template %{nil}
Name: dch-autoprovision
Version: 1
Release: %autorelease
Summary: Automation for provisioning hosts on Dustin's infrastructure.
License: 0BSD
URL: https://git.pyrocufflink.net/infra/dch-autoprovision
Source0: %{name}-%{version}.tar.gz
BuildRequires: systemd-rpm-macros
Requires: /usr/bin/curl
%{systemd_requires}
%description
%{summary}.
%prep
%autosetup
%build
:
%install
%__install -m u=rwx,go=rx -d \
"${RPM_BUILD_ROOT}%{dch_libexecdir}"
%__install -m u=rwx,go=rx \
notify-online.sh \
"${RPM_BUILD_ROOT}%{dch_libexecdir}"/notify-online
mkdir -p "${RPM_BUILD_ROOT}%{_unitdir}"
%__install -m u=rw,go=r \
notify-online.service \
"${RPM_BUILD_ROOT}%{_unitdir}"
mkdir -p "${RPM_BUILD_ROOT}%{_presetdir}"
%__install -m u=rw,go=r \
notify-online.preset \
"${RPM_BUILD_ROOT}%{_presetdir}"
%__install -m u=rwx,go=rx -d \
"${RPM_BUILD_ROOT}%{dch_datadir}"
%__install -m u=rw,go=r \
host-provisioner.key \
"${RPM_BUILD_ROOT}%{dch_datadir}/"
%post
%systemd_post notify-online.service
%preun
%systemd_preun notify-online.service
%posttrans
if [ $1 -eq 1 ]; then
printf 'expiry-time=%s,restrict,pty %s\n' \
"$(date -d +1hour +%Y%m%d%H%M)" \
"$(cat %{dch_datadir}/host-provisioner.key)" \
>> /root/.ssh/authorized_keys
fi
%files
%{dch_libexecdir}
%{dch_datadir}
%{_unitdir}/*
%{_presetdir}/*
%changelog
%autochangelog