Nightly Package+
Goal
My goal is to have a single workflow for building and releasing nightly built packages that is straightforward conceptually and allows for more nightly package additions without heavy effort.
Package Structure
If a package is a nightly package, then it is required to have the following criteria:
1. It will have no sources checked into foreman-packaging
The project repo for the nightly package will be git checked out (locally or on jenkins) and the sources will be generated from that.
2. It will be based upon the version given in the project’s Github repo
If the version listed in the git repo is 0.14.0
, then the specfile for the nightly built package will be 0.14.0
. Conceptually this can be thought of as the goal we’re aiming for rather than a representation of the project as it stands today.
3. Nightly package specs will have a specific release field
The prerelease
macro will be used to signify a nightly package. Any package being built in a nightly fashion will have the following release field:
Release: %{?prerelease:0.}%{release}%{?prerelease}%{?dist}
The prerelease
macro is populated during obal nightly
, with .<timestamp>git<githhash>
. The timestamp is in the format YYYYMMDDHHMMSS
. The githash consists of the first seven characters in the commit hash.
an example:
rubygem-katello-3.9.0-0.6.20181201120000gitabcdef0.el7
Current Infrastructure
We have 9 nightly packages today.
$ koji list-targets \
| grep -E 'nightly-(nonscl-)?rhel7' \
| grep -v pulp \
| awk '{ print $1 }' \
| xargs -I '{}' koji list-tagged --latest --inherit {} \
| grep -E '[0-9]git' \
| awk '{print $1}'
foreman-installer-1.20.0-0.201808070324gitb4ef170.0.1.develop.el7
foreman-proxy-1.20.0-0.201808020010gita8f5b8e.0.1.develop.el7
foreman-selinux-1.20.0-0.201808060304gitfc6c210.0.1.develop.el7
foreman-1.20.0-0.201808061457git9f3477a.0.2.develop.el7
tfm-rubygem-hammer_cli-0.14.pre.develop-1.201807201904git0350ccb.el7
tfm-rubygem-hammer_cli_foreman-0.14.pre.develop-1.201808010919gitc3c8fa2.el7
katello-installer-base-3.9.0-0.201808062246gita2cd105.2.el7
tfm-rubygem-hammer_cli_katello-0.14.0-1.201808070939git54e9f0b.el7
tfm-rubygem-katello-3.9.0-0.201808061815git5820dc3.2.el7
Let’s take a closer look at each:
1. foreman-installer
packaging_trigger_installer_develop jenkins job: builds the source, archives it, then triggers RPM and deb build jobs.
release_nightly_build_deb jenkins job: exists to trigger another job
packaging_build_deb_coreproject jenkins job: does the building
release_nightly_build_rpm jenkins job: exists to trigger another job
packaging_build_rpm jenkins job: does the building
2. foreman-proxy
test_proxy_develop jenkins job: runs tests, builds the source, archives it, then triggers RPM and deb build jobs.
release_nightly_build_deb jenkins job: exists to trigger another job
packaging_build_deb_coreproject jenkins job: does the building
release_nightly_build_rpm jenkins job: exists to trigger another job
packaging_build_rpm jenkins job: does the building
3. foreman-selinux
packaging_trigger_selinux_develop: builds the source, archives it, then triggers RPM build job.
release_nightly_build_rpm jenkins job: exists to trigger another job
packaging_build_rpm jenkins job: does the building
4. foreman
test_develop jenkins job: runs tests, builds the source, archives it, then triggers RPM and deb build jobs.
release_nightly_build_deb jenkins job: exists to trigger another job
packaging_build_deb_coreproject jenkins job: does the building
release_nightly_build_rpm jenkins job: exists to trigger another job
packaging_build_rpm jenkins job: does the building
5. hammer-cli
test_hammer_cli jenkins jobs: runs tests, builds the source, archives it, then triggers RPM build job (no debian?).
release_nightly_build_rpm jenkins job: exists to trigger another job
packaging_build_rpm jenkins job: does the building
6. hammer-cli-foreman
test_hammer_cli_foreman jenkins job: runs tests, builds the source, archives it, then triggers RPM build job (no debian?).
release_nightly_build_rpm jenkins job: exists to trigger another job
packaging_build_rpm jenkins job: does the building
7. katello-installer
katello-installer-nightly-release jenkins workflow job: builds the source, archives it, triggers RPM build job.
packaging_build_rpm jenkins job: does the building
8. hammer-cli-katello
hammer-cli-katello-master-release jenkins workflow job: builds the source, archives it, then builds the RPM.
9.katello
katello-master-release jenkins workflow job: builds the source, archives it, then builds the RPM.
Bad Smells
- The parent jobs (beginning job for each chain) don’t all confirm to foreman-infra jenkins job naming conventions.
- Sometimes the source is generated and archived in a test job, other times in a release job.
- Groups of jobs that are always seen together
-
release_nightly_build_rpm
-->packaging_build_rpm
-
release_nightly_build_deb
-->packaging_build_deb_coreproject
-
- Multiple jobs chained together are harder to follow and debug since you have to chase down logs across jobs.
Proposal
Remedies
- Job Renaming
current name | proposed name |
---|---|
packaging_trigger_installer_develop | foreman-intaller-develop-release |
test_proxy_develop | foreman-proxy-develop-test --> foreman-proxy-develop-release |
packaging_trigger_selinux_develop | foreman-selinux-develop-release |
test_develop | foreman-develop-test --> foreman-develop-release |
test_hammer_cli | hammer-cli-master-test --> hammer-cli-master-release |
test_hammer_cli_foreman | hammer-cli-foreman-master-test --> hammer-cli-foreman-master-release |
katello-installer-nightly-release | katello-installer-master-release |
hammer-cli-katello-master-release | |
katello-master-release |
-
Reuse code via jenkins-job-builder rather than having multiple generic build jobs with lots of parameters chained together. This will allow us to cut down on the number of jobs and have one jenkins job per nightly package release, dropping the chained jobs anti pattern.
-
Use
obal
to build nightly packages based on a local checkout of the source repository rather than depending on archives stored on jenkins. We can still continue to archive the built source files. The source files will be archived in the-release
job for a given package.
Limitations & Complications
I can imagine a scenario where a *-nightly-release
job starts, then code is merged into the *
repo while the job is running. Since the job runs git checkout
in multiple places, is it possible that the code being tested could differ from the code that gets packaged into a source file?
The best solution I can come up with quickly is to disallow concurrent runs of the given jenkins job and
git checkout
based on a hash instead of a named pointer likemaster
ordevelop
. If we disable concurrent runs of jenkins jobs, do subsequent runs get queued or does jenkins drop them?
Completion Strategy
- Refactor obal and foreman-packaging to facility building of a nightly package both in jenkins or locally on a developer’s machine.
- Build a JJB groovy template and/or methods for releasing nightly deb packages to replace the
release_nightly_build_deb --> packaging_build_deb_coreproject
job chain. - Build a JJB groovy template and/or methods for releasing nightly RPM packages to replace the
release_nightly_build_rpm --> packaging_build_rpm
job chain. - Build a single JJB groovy template from both 2) and 3) for those nightly packages that build for both deb and RPM.
- Document how to become a nightly package and how does a nightly package do a standard release.
Questions
What will happen when I open a pull-request against foreman-packaging for a nightly package?
- Github hook will trigger
packaging_test_pull_request
andforeman-packaging-rpm-pr-test
as it does today.
1a.packaging_test_pull_request
does its usualdeb
thing.
1b.foreman-packaging-rpm-pr-test
will need to be updated to know how to build sources. this shouldn’t be difficult given that will be groovy methods that can be called. - Merge pull-request. This triggers
foreman-packaging-release
which builds the source (from the merged commit hash), then builds a new nightly RPM on Koji.
Please feel free to ask questions, comment, provide feedback.
If I don’t receive any strong disagreements regarding this proposal by 7 September, then I will assume people are okay with this plan and I will continue working on it. Thanks!