Hello Fedora people!
I would like to offer a solution for dynamic changelog and release generation and potentially more.
Intro ------
The solution employs a new type of macros, which can be placed into an rpm spec file and afterward parsed by preproc utility (https://pagure.io/rpkg-util/blob/master/f/preproc/preproc) which executes the macros (by using bash interpreter) and replaces the occurrences of the macros in the original file with standard output of those macros.
The main use of those macros is intended to be reading git metadata and using it to automatically generate rpm fields like Name, Release, or %changelog but the macros are, in the end, a turing-complete tool so they can be potentially used to do more than that (if desired).
The tags for those macros are {{{ and }}} and a header of an example spec file could then look like this:
Name: {{{ git_dir_name }}} Version: 1.18 Summary: Remove old packages from rpm-md repository Release: {{{ git_dir_release_branched }}}
The `git_dir_name` and `git_dir_release_branched` keywords are bash functions that already implement some logic for automatic generation of package name (from git repository name) and release (from commit and tag history), respectively. There is also `git_dir_changelog` macro to generate a changelog from content of annotated tags.
This proposal, however, is not about usage of those particular macro functions (this can be discussed later as well as the usage of annotated tags in particular) but only about usage of the new macro class {{{ ... }}} recognized by the preproc utility.
The reason why we need this new macro class and we couldn't rely just on shell expansion already offered by rpm is that %(…) (the shell expansion rpm tag) gets carried over verbatim into the spec file which is stored inside a built source rpm. If the code in such tag relied on git metadata it would work only when the srpm is originally built from dist-git sources but later when the source rpm gets rebuilt (e.g. internally in mock), the code would fail because at that point, the git metadata is already missing (they are not included in srpms).
Therefore we need a new type of macros in a spec file that, when evaluated, are replaced with their stdout before the spec file is used to build an srpm.
Implementation ---------------------
I have some packages in reviews and ready for a review to provide the building stones. These are:
https://bugzilla.redhat.com/show_bug.cgi?id=1809644 (preproc - the preprocessor) https://bugzilla.redhat.com/show_bug.cgi?id=1811432 (rpkg-macros - basic set of macros that can be used by packagers) https://bugzilla.redhat.com/show_bug.cgi?id=1811432 (preproc-rpmspec - simple tool that makes it easier to invoke preproc on a spec file with the rpkg-macros included)
These packages are functional from fedora-rawhide down to epel-6.
Only preproc is essential for this proposal but I would like to, at the same time, also provide some basic starting set of macros that packagers can easily try and comment on. Either we can stick with those macros, tweak them, or provide an entirely different set of macros that uses a different logic.
Next, I was looking into koji code and found out that no changes should be actually needed there to support this. The changes, in my opinion, should be placed into mock here, just before the start of srpm build: https://github.com/rpm-software-management/mock/blob/5c08f5b74/mock/py/mockb... together with adding three new configuration options:
config_opts['rpkg_preprocessing'] = True # by default False config_opts['rpkg_preprocessing_requires'] = ["preproc-rpmspec"] config_opts['rpkg_preprocessing_cmd'] = '/usr/bin/preproc-rpmspec %(source_spec)s --output %(target_spec)s'
The first one `rpkg_preprocessing` tells us if the feature should be enabled or not (by default, it will be probably False in mock). The second one tells us what package should be installed into the chroot before the start of srpm build to provide the preprocessing functionality. And the third one is a concrete invocation of a preprocessing command.
The logic in mock (at the corresponding place) should go as follows:
if rpkg_preprocessing is enabled; then if rpkg.conf file is present in git toplevel directory; then if the rpkg.conf file contains `preprocess_spec = True` directive under [rpkg] section; then install `rpkg_preprocessing_requires` into the chroot run the preprocessing command as specified by the config
And these changes in mock (apart from the above packages being brought into Fedora and EPEL) are the only changes that need to be done for the solution to already work in Fedora (and EPEL).
I scanned master branches of all packages in Fedora dist-git and none of them contains rpkg.conf file in the git top-level directory so there should be no conflict there (i can do the checks on other branches too but at this point, I am already quite certain that 'rpkg.conf' is a non-conflicting filename).
I have run all spec files from master through preproc and all of them came out unchanged except two: python-dns-lexicon.spec - uses {{{ }}} in comments python-suds.spec - uses {{{ }}} in changelog at one place
All the other packages are just left untouched after the preproc run (by the way, that wouldn't be the case for {{, }} tags if used - there are many more conflicts there).
Those two packages would need to escape the {{{ }}} tags to keep using them if they wanted to also start using the preprocessing functionality by placing rpkg.conf file into dist-git repo with the following content: [rpkg] preprocess_spec = True
I already have this working on my machine so now it is a matter of opening a PR and polishing the code. Basically, I tested it on a dist-git repo (on prunerepo package, specifically) where I added rpkg.conf with the above content and used some preproc macros in the spec file and I was able to successfully build an srpm with a preprocessed spec file by invoking:
mock --buildsrpm --spec prunerepo.spec --sources .
This is pretty much what koji does when building from SCM (it just adds more switches to the above command).
Implementation continued -----------------------------------
The next thing that needs to be adjusted is the mass-rebuild script (https://pagure.io/releng/blob/master/f/scripts/mass-rebuild.py) and rpmdev-bumpspec (https://github.com/rsrchboy/rpmdevtools/blob/master/rpmdev-bumpspec), however also here the changes should be quite minimal.
My plan is to tweak rpmdev-bumpspec to return a dedicated exit code when it encounters:
Release: {{{ ... }}}
and not to do any changes on release or changelog then with the assumption that the macros will do it themselves. The mass rebuild script when being given this exit code will not error out but instead continue by adding a new commit (https://pagure.io/releng/blob/682804c8/f/scripts/mass-rebuild.py#_162) and building as usual.
This is not a 100% percent solution because one could e.g. do this in a spec file:
{{{{ echo "Release: $(git_dir_release_branched)" }}} in which case regular expression checking e.g. for "Release: {{{" wouldn't work. It might be therefore better to check for the rpkg.conf file and check if it contains `preprocess_spec = True` in the [rpkg] section.
In either case, we can make this work by communicating with packagers the following: "You are free to use preproc macros but if a new commit lands, the Release field needs to change based on that". That's also the behavior of `git_dir_release` and `git_dir_release_branched` macros included in rpkg-macros library.
Implementation continued continued ------------------------------------------------
If the mock changes arrive to koji builders, you will be already able to play around with the macros and I recommend using the latest version of rpkg-utility (https://copr.fedorainfracloud.org/coprs/clime/rpkg-util/) that can interpret the macros client-side and tell you exactly what the koji builders produce before you push.
Anyway, I would like to get proper support for this in fedpkg. I think we could immediately start supporting this on the level of the rpkg library (https://pagure.io/rpkg) so that the other dist-git clients get this functionality as well (in opt-in manner).
This is not a difficult task - i have already done the support in rpkg-util so I (or maybe someone else) will just open a pull request which should port the code from rpkg-util to the rpkg library.
Implementation finished? ---------------------------------
Is there anything else I should think about or some other scripts in infra that should be adjusted?
About the approach -------------------------- - the preproc macros (together with rpkg-macros) are already supported in Copr when you use SCM method with rpkg srpm build method - the approach is generic in the sense that it makes it very easy to start generating other parts of spec files from git (or possibly other) content: e.g. VCS field, Source field by packing the whole dist-git repo content into a tarball, and %prep field - it depends on what community and packaging committee decide is acceptable - the approach gives packagers the same freedom they have with rpm macros. While there can be some preconfigured macros, everybody can roll out their own variants or entirely new macros - the approach is suitable to implement "Git is the single source of truth" paradigm at least with respect to the basic package information like Release, Version or Changelog. - the approach needs very little changes in our tooling - it produces the same results locally which will be produced by build system for a given commit - guys from "Ideas and proposal for removing changelog and release fields from spec file" are currently trying something else which involves build system and, from my POV, magic spec file manipulations but I still hope we can find a common language at some point and finally start cooperating
Thanks clime
This would break processing with ‘rpmspec’?
Rich.
On Mon, 9 Mar 2020 at 22:45, Richard W.M. Jones rjones@redhat.com wrote:
This would break processing with ‘rpmspec’?
With just rpmspec, yes. The preproc-rpmspec tool can become a wrapper around rpmspec aliased prerpmspec essentially doing the preprocessing, then immediately passing the result to rpmspec for further processing. Similarly with spectool, wrapper prespectool can be provided.
Best Regards! clime
Rich.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/ _______________________________________________ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org
On Mon, Mar 09, 2020 at 11:36:33PM +0100, clime wrote:
On Mon, 9 Mar 2020 at 22:45, Richard W.M. Jones rjones@redhat.com wrote:
This would break processing with ‘rpmspec’?
With just rpmspec, yes. The preproc-rpmspec tool can become a wrapper around rpmspec aliased prerpmspec essentially doing the preprocessing, then immediately passing the result to rpmspec for further processing. Similarly with spectool, wrapper prespectool can be provided.
Also this would break fedpkg local, fedpkg srpm, rpmbuild, any process which creates an SRPM, and arbitrary scripts that we run over spec files?
If so, it seems like a bad idea to me.
Rich.
On Wed, 11 Mar 2020 at 11:24, Richard W.M. Jones rjones@redhat.com wrote:
On Mon, Mar 09, 2020 at 11:36:33PM +0100, clime wrote:
On Mon, 9 Mar 2020 at 22:45, Richard W.M. Jones rjones@redhat.com wrote:
This would break processing with ‘rpmspec’?
With just rpmspec, yes. The preproc-rpmspec tool can become a wrapper around rpmspec aliased prerpmspec essentially doing the preprocessing, then immediately passing the result to rpmspec for further processing. Similarly with spectool, wrapper prespectool can be provided.
Also this would break fedpkg local, fedpkg srpm, rpmbuild, any process which creates an SRPM, and arbitrary scripts that we run over spec files?
Hey Richard!
fedpkg local and fedpkg srpm support can be added.
rpmbuild needs to get a preprocessed spec already. This can be assured by having support in a higher layer (i.e. in mock).
Manually on command line, you would first run:
$ preproc-rpmspec <in-spec> -o <out-spec>
and then
$ rpmbuild -bs <out-spec>
if you wanted to do the operation manually.
I don't think that we would call somewhere in infra rpmbuild directly. It is either wrapped in mock or in fedpkg so adding support to these places should be sufficient.
Ad. "arbitrary scripts that we run over spec file". Do you mean in infrastructure or somewhere else? I am aware of the mass rebuild script and rpmdev-bumpspec that need to be tweaked. Would you know about any other infra scripts that need to be adjusted?
Or do you mean packager custom scripts that one would use to make his/her packaging job easier and that work directly on spec file? If someone has such a strong local tooling, probably this proposal wouldn't work for him/her. But this is opt-in only so everyone is free to use what works the best.
In other words, I would need to know what are those arbitrary scripts.
Also, if the majority of packagers like to use rpmbuild directly when doing local builds, then my proposal wouldn't probably work but I assumed it's not the case. But even there we can offer prerpmbuild wrapper over rpmbuild which will do preprocessing and build in one go to make it easier. There, it's not super pleasant because you will have suddenly two commands (one which runs preprocessing first and one which doesn't) but on the level of fedpkg and mock, the commands stay exactly the same.
clime
If so, it seems like a bad idea to me.
Rich.
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org _______________________________________________ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org
On Wed, 2020-03-11 at 12:21 +0100, clime wrote:
rpmbuild needs to get a preprocessed spec already.
Hmm, what do you mean with that? The spec files we currently have in dist-git can be built directly with rpmbuild, you just need to tell rpmbuild that the sources are in the same directory, e.g.:
--- 8< --- nils@gibraltar:~/dist-git/fedora/rpms/dcraw (master)> rpmbuild --define "%_sourcedir $PWD" -ba --clean dcraw.spec setting SOURCE_DATE_EPOCH=1563926400 Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.PTKY48 + umask 022 + cd /home/nils/rpmbuild/BUILD + cd /home/nils/rpmbuild/BUILD + rm -rf dcraw + /usr/bin/gzip -dc /home/nils/dist-git/fedora/rpms/dcraw/dcraw-9.28.0.tar.gz [... skip build messages ...] Wrote: /home/nils/rpmbuild/SRPMS/dcraw-9.28.0-6.fc31.src.rpm Wrote: /home/nils/rpmbuild/RPMS/x86_64/dcraw-debugsource-9.28.0-6.fc31.x86_64.rpm Wrote: /home/nils/rpmbuild/RPMS/x86_64/dcraw-9.28.0-6.fc31.x86_64.rpm Wrote: /home/nils/rpmbuild/RPMS/x86_64/dcraw-debuginfo-9.28.0-6.fc31.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.qq02g8 + umask 022 + cd /home/nils/rpmbuild/BUILD + cd dcraw + /usr/bin/rm -rf /home/nils/rpmbuild/BUILDROOT/dcraw-9.28.0-6.fc31.x86_64 + RPM_EC=0 ++ jobs -p + exit 0 Executing(--clean): /bin/sh -e /var/tmp/rpm-tmp.x7fCS6 + umask 022 + cd /home/nils/rpmbuild/BUILD + rm -rf dcraw + RPM_EC=0 ++ jobs -p + exit 0 nils@gibraltar:~/dist-git/fedora/rpms/dcraw (master)> --- >8 ---
That aside, the main thing I don't like in your proposal is that the files would still be called '*.spec', but with the additional macros they wouldn't be RPM spec files anymore. Files which are to be preprocessed, should be distinguishable from the preprocessed version by a different extension, e.g.:
- something.c --> cpp --> something.i - Makefile.am --> automake --> Makefile.in --> configure --> Makefile - sendmail.mc -> /etc/mail/make (m4) -> sendmail.cf
Nils
Hello nils!
On Wed, 11 Mar 2020 at 16:07, Nils Philippsen nils@redhat.com wrote:
On Wed, 2020-03-11 at 12:21 +0100, clime wrote:
rpmbuild needs to get a preprocessed spec already.
Hmm, what do you mean with that?
I mean, in this proposal, rpmbuild would need to get an already preprocessed spec file on input to work correctly in case the original spec file contains the new macros. I.e. you need to call some other command first (preproc-rpmspec) to get a spec file which is valid by rpm standard.
The spec files we currently have in dist-git can be built directly with rpmbuild, you just need to tell rpmbuild that the sources are in the same directory, e.g.:
--- 8< --- nils@gibraltar:~/dist-git/fedora/rpms/dcraw (master)> rpmbuild --define "%_sourcedir $PWD" -ba --clean dcraw.spec
Yes, this wouldn't be possible in my proposal iff the spec file contained the new non-rpm syntax. But `fedpkg local` would work or `mock --buildsrpm --spec dcraw.spec --sources .` would work and some tiny wrapper over rpmbuild (e.g. prerpmbuild as mentioned earlier) can be also provided to give users more low-level experience.
setting SOURCE_DATE_EPOCH=1563926400 Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.PTKY48
- umask 022
- cd /home/nils/rpmbuild/BUILD
- cd /home/nils/rpmbuild/BUILD
- rm -rf dcraw
- /usr/bin/gzip -dc /home/nils/dist-git/fedora/rpms/dcraw/dcraw-9.28.0.tar.gz
[... skip build messages ...] Wrote: /home/nils/rpmbuild/SRPMS/dcraw-9.28.0-6.fc31.src.rpm Wrote: /home/nils/rpmbuild/RPMS/x86_64/dcraw-debugsource-9.28.0-6.fc31.x86_64.rpm Wrote: /home/nils/rpmbuild/RPMS/x86_64/dcraw-9.28.0-6.fc31.x86_64.rpm Wrote: /home/nils/rpmbuild/RPMS/x86_64/dcraw-debuginfo-9.28.0-6.fc31.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.qq02g8
- umask 022
- cd /home/nils/rpmbuild/BUILD
- cd dcraw
- /usr/bin/rm -rf /home/nils/rpmbuild/BUILDROOT/dcraw-9.28.0-6.fc31.x86_64
- RPM_EC=0
++ jobs -p
- exit 0
Executing(--clean): /bin/sh -e /var/tmp/rpm-tmp.x7fCS6
- umask 022
- cd /home/nils/rpmbuild/BUILD
- rm -rf dcraw
- RPM_EC=0
++ jobs -p
- exit 0
nils@gibraltar:~/dist-git/fedora/rpms/dcraw (master)> --- >8 ---
That aside, the main thing I don't like in your proposal is that the files would still be called '*.spec', but with the additional macros they wouldn't be RPM spec files anymore. Files which are to be preprocessed, should be distinguishable from the preprocessed version by a different extension, e.g.:
- something.c --> cpp --> something.i
- Makefile.am --> automake --> Makefile.in --> configure --> Makefile
- sendmail.mc -> /etc/mail/make (m4) -> sendmail.cf
I understand this and currently, I give my template spec files .spec.rpkg extension (e.g. https://pagure.io/rpkg-util/blob/master/f/rpkg-util.spec.rpkg). But at the same time, I think that calling the file just somepkg.spec would provide a better user experience.
Mainly, I wouldn't like very much to break *.spec glob that people might use. I think what is more important is that the glob finds at least something even if it is not necessarily a pure rpm spec file.
I can tell you my related personal experience...I used to do web development and at some point, I was seeing all those extensions like .dhtml, .phtml, .html.j2, etc. used for template files. A few years later, however, I started to see a backward trend - some frameworks began to use again just .html even when speaking about dynamic html files. While I was surprised by this initially, in the end, I found it much easier to work with because usually, one just wants to open a template file (when the problem appears to be in a template) and what is the templating language in use is not that important until a file is opened.
Best regards! clime
Nils
Nils Philippsen "Those who would give up Essential Liberty to Software Engineer purchase a little Temporary Safety, deserve neither Red Hat Liberty nor Safety." -- Benjamin Franklin, 1759 PGP fingerprint: D0C1 1576 CDA6 5B6E BBAE 95B2 7D53 7FCA E9F6 395D old: C4A8 9474 5C4C ADE3 2B8F 656D 47D8 9B65 6951 3011 _______________________________________________ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org
Le lundi 09 mars 2020 à 00:26 +0100, clime a écrit :
Hi,
the code would fail because at that point, the git metadata is already missing (they are not included in srpms).
Can’t storage of built-time information in srpms be fixed instead of adding a whole new overlay over existing tools, that ties building to Fedora infra?
There are lots of practical applications of being able to record build time info in srpms (for example, I’ve been asked to record the buildroot state one way or another, and, IIRC, samba called rpm in its scripts for the same reason).
Modules went the overlay route, it was not their best decision.
Regards
On Thu, 30 Apr 2020 at 20:40, Nicolas Mailhot via devel devel@lists.fedoraproject.org wrote:
Le lundi 09 mars 2020 à 00:26 +0100, clime a écrit :
Hi,
the code would fail because at that point, the git metadata is already missing (they are not included in srpms).
Can’t storage of built-time information in srpms be fixed instead of adding a whole new overlay over existing tools, that ties building to Fedora infra?
There are lots of practical applications of being able to record build time info in srpms (for example, I’ve been asked to record the buildroot state one way or another, and, IIRC, samba called rpm in its scripts for the same reason).
It took me a while to realize you don't mean BUILDTIME header info but state of build environment that affects build of srpms :).
Anyway, maybe? I think this might be more handy for rpms rather than for srpms. In most cases, srpms are only source carriers?
If this should be the way for dynamic changelog/release, you would still first need something that translates relevant git metadata into something which rpm can work with. I don't think rpm should do it on its own as it would become tied to git or any other future scm.
Can you elaborate on what samba did? I would like to know because it sounded interesting.
---
I don't think this proposal ties it to Fedora-Infra. Anyone using either mock or rpkg-based tool should be able to use it according to this proposal.
Modules went the overlay route, it was not their best decision.
I don't think it is a proof that overlay-based solution are wrong though.
By the way, modularity, in my opinion, would be great if it produced rpms (created by mixing/overlaying rpms from built modulemd) instead of yum sub-repos. That way we wouldn't need to duplicate things like Obsoletes or Requires on another layer and it would get a proper binary format for distribution.
Regards
-- Nicolas Mailhot _______________________________________________ devel mailing list -- devel@lists.fedoraproject.org To unsubscribe send an email to devel-leave@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org
devel@lists.stg.fedoraproject.org