RFC: splitting SCL and non-SCL RPMs that currently live in the same folder

Ohai,

currently when we package Ruby gems, they all end up as rubugem-foo in foreman-packaging. This makes it very hard to see whether a specific gem has to be built for the system ruby, or for our SCL (or both). The only way to know where a package belongs is to look at tito.props and read all the tags and whitelists there.

I would like to propose to be more explicit here, and call the packages that go inside the SCL tfm-rubygem-foo in the packaging repo (they are called like this inside Koji anyways). However this also means that we end up with duplicated data in the case where a gem has to be built for both Rubies.

FWIW, that’s how we’ve been handling downstream packaging for some time now, and it’s really convenient :slight_smile:

Pros

  1. easy mapping from Koji to packaging folder
  2. no guessing which ruby a gem belongs so
  3. easier automation of building because of the above

Cons

  1. slightly duplicated data
  2. will require updating all copies for changes

I’m not against it per se, but until we have more automated tools to do version bumps I think the additional overhead for packages that are built in both is too much and too error prone since we have no automated reviewing tools to notice we need to bump both packages.

Compare it to the change to drop the use of tags. Previously we didn’t need to write changelogs at the cost of a bit more (scripted) work and a more verbose git log. Now we need more manual work. Cherry picks are more work because we changed the workflow. For now I still consider dropping tags a net loss in productivity and I’m afraid this change will end up in the same way.

If the desire is to know where a package is built, why not start with a package2tags script instead until we fix the other issues.

How many packages are actually built in both places?

It’s not that much:

>>> nonscl = c.get('foreman-nightly-nonscl-rhel7', 'whitelist').split()
>>> scl = c.get('foreman-nightly-rhel7', 'whitelist').split()
>>> set(scl).intersection(nonscl)
set(['rubygem-hashie', 'rubygem-bundler_ext', 'rubygem-highline', 'rubygem-little-plugger', 'rubygem-logging', 'rubygem-passenger', 'rubygem-clamp', 'rubygem-apipie-bindings', 'rubygem-powerbar', 'rubygem-multi_json', 'rubygem-oauth'])

>>> nonscl = c.get('foreman-plugins-nightly-nonscl-rhel7', 'whitelist').split()
>>> scl = c.get('foreman-plugins-nightly-rhel7', 'whitelist').split()
>>> set(scl).intersection(nonscl)
set(['rubygem-faraday_middleware'])

In that case, I think it’d be OK especially since these are not revved very often. Not to mention, our SCL ruby is progressing further than the installer Ruby and we may need to rev them separately.

I get a slightly different list:

#!/usr/bin/env python3

from collections import defaultdict
from configparser import ConfigParser

parser = ConfigParser()
with open('tito.props') as fp:
    parser.readfp(fp)

packages = defaultdict(list)

for tag, section in parser.items():
    for package in section.get('whitelist', '').split():
        packages[package].append(tag)

for package, tags in sorted(packages.items()):
    if len(tags) > 1:
        print('{}: {}'.format(package, ', '.join(tags)))

Results into:

katello-host-tools: katello-nightly-rhel5, katello-nightly-rhel6, katello-nightly-fedora26, katello-nightly-fedora25
katello-repos: katello-nightly-rhel5, katello-nightly-rhel6, katello-nightly-rhel7, katello-nightly-fedora26, katello-nightly-fedora25
rubygem-apipie-bindings: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-bundler_ext: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-clamp: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-concurrent-ruby: foreman-nightly-nonscl-rhel7, foreman-plugins-nightly-rhel7
rubygem-faraday: foreman-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-faraday_middleware: foreman-plugins-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-hashie: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-highline: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-jenkins_api_client: katello-nightly-rhel7, katello-thirdparty-rhel7
rubygem-little-plugger: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-logging: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-mixlib-shellout: katello-nightly-rhel7, katello-thirdparty-rhel7
rubygem-multi_json: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-mysql2: foreman-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-oauth: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-passenger: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-powerbar: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-robotex: katello-nightly-rhel7, katello-nightly-rhel7
rubygem-terminal-table: katello-nightly-rhel7, katello-thirdparty-rhel7

There are non-SCL only:

katello-host-tools: katello-nightly-rhel5, katello-nightly-rhel6, katello-nightly-fedora26, katello-nightly-fedora25
katello-repos: katello-nightly-rhel5, katello-nightly-rhel6, katello-nightly-rhel7, katello-nightly-fedora26, katello-nightly-fedora25

Some of whats below here are I think no longer used outside the SCL. We have not hard pruned in a while and this is a good opportunity to do so.

SCL only:
rubygem-jenkins_api_client: katello-nightly-rhel7, katello-thirdparty-rhel7
rubygem-mixlib-shellout: katello-nightly-rhel7, katello-thirdparty-rhel7
rubygem-robotex: katello-nightly-rhel7, katello-nightly-rhel7
rubygem-terminal-table: katello-nightly-rhel7, katello-thirdparty-rhel7

Unknown
rubygem-apipie-bindings: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-bundler_ext: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-clamp: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-concurrent-ruby: foreman-nightly-nonscl-rhel7, foreman-plugins-nightly-rhel7
rubygem-faraday: foreman-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-faraday_middleware: foreman-plugins-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-hashie: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-highline: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-little-plugger: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-logging: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-multi_json: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-mysql2: foreman-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-oauth: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-passenger: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-powerbar: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7

Using repoquery --whatrequires I think we can clean up:

  • rubygem-apipie-bindings
  • rubygem-jenkins_api_client
  • rubygem-mixlib-shellout
  • rubygem-robotex
  • rubygem-terminal-table
  • tfm-rubygem-jenkins_api_client
  • tfm-rubygem-mixlib-shellout
  • tfm-rubygem-terminal-table

Not sure about jenkins_api_client, mixlib-shellout and terminal-table since that’s listed in katello and I might be missing something.

https://github.com/theforeman/foreman-packaging/pull/2277

Another thing that we could do to limit the burden of duplicated pkgs is to use symlinks instead of full copies. That will obviously blow up as soon as we need different spec files for SCL and non-SCL versions (but I don’t foresee that anytime soon).
Another contra symlinks is: the current Jenkins code will not detect that it needs to rebuild two packages.

False, we already have one case with tfm-rubygem-rest-client

https://github.com/theforeman/foreman-packaging/tree/rpm/develop/packages/foreman/tfm-rubygem-rest-client

But I don’t see a non-SCL version of rest-client in the repo? Anyways, after thinking a bit more, I think symlinks are not a good solution, as this would hinder automated builds (they would not show up in a git diff)

Yes, the not showing up in git diff makes them impractical. You could work around it, but then the symlinks don’t really add anything.

so, re-running @ekohl’s script, after the cleanup PR was merged, we end up with:

katello-host-tools: katello-nightly-rhel5, katello-nightly-rhel6, katello-nightly-fedora26, katello-nightly-fedora25
katello-repos: katello-nightly-rhel5, katello-nightly-rhel6, katello-nightly-rhel7, katello-nightly-fedora26, katello-nightly-fedora25
rubygem-bundler_ext: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-clamp: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-concurrent-ruby: foreman-nightly-nonscl-rhel7, foreman-plugins-nightly-rhel7
rubygem-faraday: foreman-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-faraday_middleware: foreman-plugins-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-hashie: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-highline: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-little-plugger: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-logging: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-multi_json: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-mysql2: foreman-nightly-rhel7, foreman-plugins-nightly-nonscl-rhel7
rubygem-oauth: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-passenger: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7
rubygem-powerbar: foreman-nightly-nonscl-rhel7, foreman-nightly-rhel7

k-h-t and k-repos are “special” and not inside the SCL anyways, so let’s look at the rest:

  • rubygem-bundler_ext: required by foreman (SCL), foreman-proxy (nonSCL), smart_proxy_dynflow_core (nonSCL)
  • rubygem-clamp: required by foreman_maintain (nonSCL), hammer_cli (SCL), kafo (nonSCL)
  • rubygem-concurrent-ruby: required by foreman-proxy (nonSCL), dynflow (SCL)
  • rubygem-faraday: required by rubygem-infoblox (nonSCL) and multiple SCL packages
  • rubygem-faraday_middleware: required by rubygem-infoblox (nonSCL) and multiple SCL packages
  • rubygem-hashie: only required by powerbar (built for SCL and nonSCL)
  • rubygem-highline: required by foreman_maintain (nonSCL), hammer_cli (SCL), kafo (nonSCL)
  • rubygem-little-plugger: only required by rubygem-logging (built for SCL and nonSCL)
  • rubygem-logging: required by foreman (SCL), hammer_cli (SCL), kafo (nonSCL)
  • rubygem-multi_json: required by multiple SCL and nonSCL packages
  • rubygem-mysql2: required by foreman (SCL) and smart_proxy_dns_powerdns (nonSCL)
  • rubygem-oauth: required by foreman (SCL), apipie-bindings (SCL), foreman_api (nonSCL), katello (SCL), runcible (SCL)
  • rubygem-passenger: only SCL version is used, for nonSCL we end up with the version from EPEL on installs as that is newer
  • rubygem-powerbar: required by hammer_cli_foreman_tasks (SCL) and kafo (nonSCL)

so we probably can drop passenger, but that’s it

I think we can drop the foreman_api package altogether since it’s deprecated. The last update was in 2015 and I’m not even sure it supports the v2 API (nightly dropped v1).

https://github.com/theforeman/foreman-packaging/pull/2298