Building a Perl Module in OBS


Introduction

The Open Build Service is used to build all packages for the SUSE operating system family. It can also be used to build other package formats.

In this post I want to show you how you can setup a project to build your perl module(s) in OBS. Some parts might not be that intuitive, so I documented everything with screenshots.

In my next post I will show how you can setup your package to automatically build on pull requests.

In another post, I want to show how we at SUSE actually fetch and update a large list of perl modules automatically in our devel:languages:perl repo. Your perl module might already be in the list!

Prerequisites

First you should create an account here. This is not covered in this post, but should be easy enough :)

Note that the OBS website has two layouts. For smaller screens, there is a horizontal bar at the bottom. Otherwise there will be a vertical bar on the left.

I used the small layout in my screenshots.

You need git and osc.

The source of your module should be in GitHub. OBS also supports other SCMs, but for this post I used GitHub.

Many of the GUI actions I show are also available in the osc command line tool.

Create a project and package

First, go to your home project.

Go to the navigation item “Your Home Project”. It should be empty so far.

The URL would look like https://build.opensuse.org/project/show/home:yourusername.

OBS - Home Project

Then go to “Subprojects” and click on “Create Subproject” under “Actions”.

OBS - Create subproject

Chose a name for your perl modules project and click “Accept”. I used home:tinita:perlmodules.

OBS - Create subproject

In your new project, you can now click on “Create Package”.

OBS - Subproject

In my example I’m using my perl module YAML::PP.

The naming convention for perl modules in SUSE is to prefix it with perl-, so I use perl-YAML-PP. Click on “Create”.

OBS - Create package

You should see an empty package now.

OBS - Created package

Now you can select repositories it should be built on. Here I used openSUSE Leap 15.5 and 15.6 plus openSUSE Tumbleweed.

For that go back to the project home:user:perlmodules. You can’t add repositories for a package.

In the project click on “Repositories” and “Add from a Distribution”.

OBS - Select repositories

Add files to your package

To add files to it, I switch to the command line.

For working with OBS projects on the command line, you need to install the tool osc. It’s available on many Linux distributions.

First I’m checking out the perl-YAML-PP package.

~% mkdir osc
~% cd osc
~/osc% osc co home:tinita:perlmodules/perl-YAML-PP
A    home:tinita:perlmodules
A    home:tinita:perlmodules/perl-YAML-PP
At revision None.
~/osc% cd home:tinita:perlmodules/perl-YAML-PP
~/osc/home:tinita:perlmodules/perl-YAML-PP%

To let OBS fetch the source code automatically from GitHub, I need to create a _service file. For demo purposes I created a temporary repository https://github.com/perlpunk/gpw2024-demo to hold a copy of the YAML::PP source:

~/osc/home:tinita:perlmodules/perl-YAML-PP% cat _service
<services>
  <service name="obs_scm">
    <param name="url">https://github.com/perlpunk/gpw2024-demo</param>
    <param name="revision">main</param>
    <param name="versionprefix">3.14</param>
    <param name="versionformat">%ct.%h</param>
    <param name="scm">git</param>
    <param name="changesgenerate">enable</param>
    <param name="changesauthor">tina.mueller@suse.com</param>
    <param name="filename">perl-YAML-PP</param>
  </service>
  <service name="set_version"/>
  <service name="tar" mode="buildtime"/>
  <service name="recompress" mode="buildtime">
    <param name="compression">xz</param>
    <param name="file">*.tar</param>
  </service>
</services>

Now I need a .spec file so that rpm can build a package:

~/osc/home:tinita:perlmodules/perl-YAML-PP% cat perl-YAML-PP.spec
Name:           perl-YAML-PP
Version:        3.14
Release:        0
License:        Artistic-1.0 OR GPL-1.0-or-later
Summary:        YAML 1.2 Processor
# Generated by _service
Source0:        %{name}-%{version}.tar.xz
BuildArch:      noarch
BuildRequires:  perl
BuildRequires:  perl-macros
BuildRequires:  perl(Module::Load)
BuildRequires:  perl(Test::More) >= 0.98
BuildRequires:  perl(Test::Warn)
Requires:       perl(Module::Load)
%{perl_requires}

%description
YAML::PP is a modular YAML processor.
...

%prep
%autosetup  -n %{name}-%{version}

%build
perl Makefile.PL INSTALLDIRS=vendor
%make_build

%check
make test

%install
%perl_make_install
%perl_process_packlist
%perl_gen_filelist

%files -f %{name}.files
%doc Changes CONTRIBUTING.md examples Makefile.dev README.md

Note that I used an arbitrary version 3.14 here. How to automatically retrieve a version from your sources is not covered here. But for the purposes of checking that the module successfully builds a static version is fine.

Now I commit my newly added files:

~/osc/home:tinita:perlmodules/perl-YAML-PP% osc st
?    _service
?    perl-YAML-PP.spec

~/osc/home:tinita:perlmodules/perl-YAML-PP% osc add _service perl-YAML-PP.spec
A    _service
A    perl-YAML-PP.spec

~/osc/home:tinita:perlmodules/perl-YAML-PP% osc ci -m "Add spec and _service"
Sending    _service
Sending    perl-YAML-PP.spec
Transmitting file data ..
Committed revision 1.
Waiting for server side source service run
........................................................
At revision 1.

Looking at the project in OBS, I can see the _service and the .spec file, but additionally some generated files:

OBS - Package - First commit

And it already started to build!

OBS - Package - First commit - build status

Automatically build new commits

It’s possible to click on “Trigger Services” to fetch sources and rebuild, but that can be automated.

For that I need to create an OBS Service Token and a GitHub Webhook.

First I create the token. On your homepage, go to “Manage your tokens”.

OBS - Home - Actions

Click on “Create Token”.

OBS - Tokens

The token type is service. Choose a description so that you can find that token easily when you later have more tokens.

Add the perl modules project, in my case home:tinita:perlmodules and the package name perl-YAML-PP and click “Create”.

OBS - Create Service Token

You will see a Token Id and a secret (marked red in the screenshot). Note down both.

OBS - Created Service Token

Now go to the Settings of your GitHub project and go to Webhooks.

GitHub - Webhooks

Add a webhook. The payload URL should be https://build.opensuse.org/trigger/webhook?id=$ID.

The Content type should be application/json.

Add the secret.

Click on “Add webhook”.

GitHub - Add OBS Webhook

You should see a message that the webhook was created successfully.

GitHub - Created OBS Webhook

In the OBS project, you should see that the service was triggered already by the first Webhook ping.

OBS - Package - Service Triggered

Now with every commit to the main branch the OBS project should be rebuilt.

It’s also possible to be notified of build failures for projects. Look at the “Watchlist” and “Notifications” items in the top navigation.

You can download the generated rpm package under “Download package”.

I hope that was helpful.

In the next post I will show how to build the module on every pull request.