-
-
Notifications
You must be signed in to change notification settings - Fork 34
Use in automatic RPM building
Automatically build RPMs for project releases on GitHub.
You want to create a system that automatically builds new RPM packages, against a given GitHub repository.
Simply declaring Version:
obtained from lastversion
and checking if it's newer than previously built is not sufficient to make the auto-build system future-proof.
You need to also consider that the Source0
URL structure becomes different if the upstream decides to tag a new release in an unusual way. This happens more often than you can't imagine. Release URLs are git tags dependent!
Source tarball URLs on GitHub are always git tag-specific, that is the key component of a release source tarball's URL is the git tag and only that. Standard structure:
https://github.com/author/name/archive/tag/name-tag.tar.gz
This is the default format used by lastversion
also when you use --source
.
lastversion
makes sure that the URL you get contains a stable, well-formatted version inside it. But it's still important to understand that the varying component of URLs in between different releases on GitHub, will always be a git tag.
Example, lastversion https://github.com/apache/incubator-pagespeed-ngx
:
https://github.com/apache/incubator-pagespeed-ngx/archive/v1.13.35.2-stable/incubator-pagespeed-ngx-v1.13.35.2-stable.tar.gz
Here, v1.13.35.2-stable
is the release tag.
Say, you had in your spec, to make it clean and pretty:
Version: 1.13.35.2
URL: https://github.com/apache/incubator-pagespeed-ngx
Source0: %{url}/archive/v%{version}-stable.tar.gz#/incubator-pagespeed-ngx-%{version}-stable
Then you're auto-updating Version:
with the help of lastversion
. It will work most of the time. But any time a project's author decides on a different release tag format (e.g. v1.2.3
becomes release-1.2.3
), you will have broken automatic builds.
Another specific is in the way release tarballs are extracted. For the following link:
I'm talking about the continuous automatic build of newer versions, as they are released.
Say, we want to build new releases of lorem/ipsum
from GitHub.
Take an existing .spec
where the version is hardcoded, convert it to a template, e.g. rename to .j2
.
Then the essential change is change hardcoded Version:
and and URL to template variables, like so:
Name: ipsum Version: {{ version }} URL: https://github.com/lorem/ipsum Source0: %{url}/archive/{{ spec_tag }}/%{upstream_name}-{{ spec_tag }}.tar.gz ... %prep %autosetup -n %{name}-%{version} ...
Because release URLs are dependent on tags, we must template them.
lastversion
will pass them to the template
This is optional, but you may need to get some extra info aside from the version to make be passed to spec template, e.g. ipsum.yml
:
repo: lorem/ipsum
description: |
What a great package it is!
coupled with these lines added to the template:
%description
{{ description }}
lastversion --format json lorem/ipsum | jinja2 --format=json ipsum.j2 --strict - > ipsum.spec
or, if you using the .yml
file:
lastversion --format json /path/to/ipsum.yml | jinja2 --format=json ipsum.j2 --strict - > ipsum.spec
The result is a .spec
file containing the latest release version and correct URL for it!
How does this work?
-
lastversion
fetches information about the latest release as a json, this includes release's fields:-
spec_tag
which is specifically prepared for .spec. The value would be, e.g.v%{version}
orfoo-%{version
}, etc. -
version
- the well-formatted version number, e.g.1.0.1
-
- we piped this data to
jinja2
and specify the template file and the output file,ipsum.spec
.
If you use .yml
file, then lastversion
takes repo:
value inside it, and uses as REPO
argument.
Then any other keys from there are passed for templating.
Our generated .spec file is clean and ready to build:
Name: ipsum Version: 1.0.1 URL: https://github.com/lorem/ipsum Source0: %{url}/archive/v%{version}/%{name}-v%{version}.tar.gz ... %prep %autosetup -n %{name}-%{version} ...
Now time to build stuff! :-)
Next time, they release a new version but this time with v1.14.0.0
tag (no stable
) and the clean spec has to be:
Version: 1.14.0.0
Source0: https://github.com/apache/incubator-pagespeed-ngx/archive/v%{version}.tar.gz#/incubator-pagespeed-ngx-%{version}
See how Source0
had to be different?
So you if you want to keep your spec files clean with Version:
parametrized and having it reliable, you need to pass both tag and version to "something" that generates your spec file, or replace both.
Basically, you have to always have the release tag included in your SourceX
tag URL somehow just because GitHub source URLs have to include the tag always.
How I solve it have a jinja template for spec, and then have:
%global upstream_version {{ version }}
%global upstream_name incubator-pagespeed-ngx
URL: https://github.com/apache/incubator-pagespeed-ngx
Source0: %{url}/archive/{{ spec_tag }}/%{upstream_name}-{{ spec_tag }}.tar.gz
....
%autosetup -n %{upstream_name}-{{ spec_tag_no_v }}
Where spec_tag
is what I get from running lastversion --format json REPO | jq -r .spec_tag
and spec_tag_no_v
is just the same with leading v
stripped (because of how GitHub packages are).
lastversion --format json apache/incubator-pagespeed-ngx | jq -r .spec_tag
In that case, lastversion
says it's v%{upstream_version}-stable
.
So the generated spec file is "human-friendly":
%global upstream_version 1.13.35.2
%global upstream_name incubator-pagespeed-ngx
URL: https://github.com/apache/incubator-pagespeed-ngx
Source0: %{url}/archive/v%{upstream_version}-stable/%{upstream_name}-v%{upstream_version}-stable.tar.gz
....
%autosetup -n %{upstream_name}-%{upstream_version}-stable
The v%{version}
maybe would make more sense for most users maybe, but I am building modules for NGINX, so I mostly have things like:
Version: %{main_version}.%{upstream_version}
So the spec_tag
returned by lastversion
is the key point to the reliability, considering the human inconsistency when they file releases... I haven't documented it elsewhere because not sure if there is a better way to return the tag info for consuming in spec files.