-
Notifications
You must be signed in to change notification settings - Fork 5
Building DEB packages with podman & pbuilder #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
06df6f3
0a1c5f2
676ac4d
11cc4de
0b2dd51
62748ff
aa0d915
97d5506
e26594f
29b258b
1f8b9b2
3165c10
70cb28a
7dec4dc
998546d
4ac7c0f
97581e7
3b02c92
0a84b1d
d39f047
164cc59
3122b37
a1ca046
0b62193
0e9ce56
f2339f8
71bcfdd
cb58e0a
8de62ed
6b56207
7b2aee8
775da7c
4bd0cbf
a99f00b
2a4a708
de2e49d
e14be75
8d0c175
8eb2766
6fb0482
a9ac637
7f4217c
d0a7907
79e1172
3073f73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# frozen_string_literal: true | ||
|
||
module Pgpm | ||
module Deb | ||
class Builder | ||
|
||
def initialize(spec) | ||
@spec = spec | ||
@image_name = "quay.io/qount25/pgpm-debian12" | ||
@container_name = "pgpm-debian12_build-#{Time.now.to_i}_#{rand(10000)}" | ||
end | ||
|
||
def build | ||
puts "build()" | ||
prepare | ||
generate_deb_src_files | ||
create_container | ||
run_pbuilder | ||
copy_build_from_container | ||
cleanup | ||
end | ||
|
||
private | ||
|
||
def prepare | ||
puts "Preparing build..." | ||
puts " Creating container dir structure..." | ||
@pgpm_dir = Dir.mktmpdir | ||
Dir.mkdir "#{@pgpm_dir}/source" | ||
Dir.mkdir "#{@pgpm_dir}/out" | ||
puts " Copying #{@spec.package.source.to_s} to #{@pgpm_dir}/source/" | ||
FileUtils.copy_entry @spec.package.source.to_s, "#{@pgpm_dir}/source/" | ||
end | ||
|
||
def create_container | ||
puts "Creating a podman container..." | ||
# Check if image exists | ||
system("podman image exists #{@image_name}") | ||
if $?.to_i > 0 # image doesn't exist -- pull image from a remote repository | ||
puts " Pulling image #{@image_name}..." | ||
system("podman pull quay.io/qount25/pgpm-debian12") | ||
else | ||
puts " Image #{@image_name} already exists! OK" | ||
end | ||
|
||
create_opts = " -v #{@pgpm_dir}:/root/pgpm" | ||
create_opts += ":z" if selinux_enabled? | ||
create_opts += " --privileged --annotation run.oci.keep_original_groups=1" | ||
create_opts += " --name #{@container_name} #{@image_name}" | ||
|
||
puts " Creating and starting container #{@container_name}" | ||
puts " podman run -dti #{create_opts}" | ||
system("podman run -dti #{create_opts}") | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
def generate_deb_src_files | ||
puts "Generating debian files..." | ||
Dir.mkdir "#{@pgpm_dir}/source/debian" | ||
[:changelog, :control, :copyright, :files, :rules].each do |f| | ||
puts " -> #{@pgpm_dir}/source/debian/#{f}" | ||
File.write "#{@pgpm_dir}/source/debian/#{f}", @spec.generate(f) | ||
end | ||
File.chmod 0740, "#{@pgpm_dir}/source/debian/rules" # rules file must be executable | ||
end | ||
|
||
def run_pbuilder | ||
puts "Building a .deb package with pbuilder..." | ||
cmd_pref = "podman exec -w /root/pgpm/source #{@container_name} " | ||
system("#{cmd_pref} dpkg-buildpackage --build=source") | ||
exit(1) if $?.to_i > 0 | ||
dsc_fn = "#{@spec.package.name}-#{@spec.package.version.to_s}_0-1.dsc" | ||
system("#{cmd_pref} fakeroot pbuilder build ../#{dsc_fn}") | ||
exit(1) if $?.to_i > 0 | ||
end | ||
|
||
def copy_build_from_container | ||
puts "Moving .deb file from podman container into current directory..." | ||
cmd_pref = "podman exec #{@container_name} " | ||
arch = "amd64" | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
deb_fn = "#{@spec.full_pkg_name}.deb" | ||
system("#{cmd_pref} mv /var/cache/pbuilder/result/#{deb_fn} /root/pgpm/out/") | ||
FileUtils.mv("#{@pgpm_dir}/out/#{deb_fn}", Dir.pwd) | ||
end | ||
|
||
def run_container_command(cmd) | ||
end | ||
|
||
def cleanup | ||
puts "Cleaning up..." | ||
|
||
# Stop and destroy podman container | ||
puts " Stopping podman container: #{@container_name}" | ||
system("podman stop #{@container_name}") | ||
puts " Destroying podman container: #{@container_name}" | ||
system("podman container rm #{@container_name}") | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Remove temporary files | ||
# | ||
# Make sure @pgpm_dir starts with "/tmp/" or we may accidentally | ||
# delete something everything! You can never be sure! | ||
if @pgpm_dir.start_with?("/tmp/") | ||
puts " Removing temporary files in #{@pgpm_dir}" | ||
FileUtils.rm_rf(@pgpm_dir) | ||
else | ||
puts "WARNING: will not remove temporary files, strange path: \"#{@pgpm_dir}\"" | ||
end | ||
end | ||
|
||
# Needed because SELinux requires :z suffix for mounted directories to | ||
# be accessible -- otherwise we get "Permission denied" when cd into a | ||
# mounted dir inside the container. | ||
def selinux_enabled? | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# This returns true or false by itself | ||
system("sestatus | grep 'SELinux status' | grep -o 'enabled'") | ||
end | ||
|
||
def safe_package_name | ||
@spec.package.name.gsub(%r{/}, "__") | ||
end | ||
|
||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# frozen_string_literal: true | ||
|
||
require "digest" | ||
require "open-uri" | ||
require "erb" | ||
|
||
module Pgpm | ||
module Deb | ||
class Spec | ||
attr_reader :package, :release, :postgres_version, :postgres_distribution | ||
|
||
def initialize(package) | ||
@package = package | ||
@release = 1 | ||
|
||
@postgres_distribution = Pgpm::Postgres::Distribution.in_scope | ||
end | ||
|
||
def sources | ||
@package.sources | ||
end | ||
|
||
def generate(template_name) | ||
fn = "#{__dir__}/templates/#{template_name}.erb" | ||
raise "No such template: #{fn}" unless File.exist?(fn) | ||
erb = ERB.new(File.read(fn)) | ||
erb.result(binding) | ||
end | ||
|
||
def deps | ||
["postgresql-#{postgres_version}"] | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
def build_deps | ||
[ | ||
"postgresql-#{postgres_version}", | ||
"build-essential", | ||
"postgresql-#{postgres_version}", | ||
"postgresql-server-dev-#{postgres_version}", | ||
"postgresql-common" | ||
] | ||
end | ||
|
||
def postgres_version | ||
17 | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
def source_version | ||
@package.version.to_s | ||
end | ||
|
||
def source_name | ||
@package.name | ||
end | ||
|
||
def full_pkg_name | ||
"#{@package.name}-#{@package.version.to_s}_0-1_#{arch}" | ||
end | ||
|
||
def deb_version | ||
"0.1.0" | ||
end | ||
|
||
def arch | ||
"amd64" | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
def description | ||
@package.description | ||
end | ||
|
||
# Whatever is returned from this method gets added to the "rules" file. | ||
def rules_amendments | ||
"#" | ||
end | ||
|
||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<%= source_name %>-<%= source_version %> (0-1) UNRELEASED; urgency=medium | ||
|
||
* Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP> | ||
|
||
-- PGPM Debian maintainer <[email protected]> Fri, 21 Feb 2025 21:08:08 +0000 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Source: <%= source_name %>-<%= source_version %> | ||
Section: libs | ||
Priority: optional | ||
Maintainer: PGPM Debian maintainer <[email protected]> | ||
qount25 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Rules-Requires-Root: no | ||
Build-Depends: debhelper-compat (= 13), <%= build_deps.join(", ") %> | ||
Standards-Version: 4.6.2 | ||
|
||
Package: <%= source_name %>-<%= source_version %> | ||
Depends: <%= deps.join(", ") %> | ||
Section: libdevel | ||
Architecture: <%= arch %> | ||
Description: <%= description %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some of this information should be extractable from the package. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what you mean. This line looks like some XML schema definition that should always be the same. No? |
||
Source: <url://example.com> | ||
Upstream-Name: <%= source_name %>-<%= source_version %> | ||
Upstream-Contact: <preferred name and address to reach the upstream project> | ||
|
||
Files: | ||
* | ||
Copyright: | ||
<years> <put author's name and email here> | ||
<years> <likewise for another author> | ||
License: <special license> | ||
<Put the license of the package here indented by 1 space> | ||
<This follows the format of Description: lines in control file> | ||
. | ||
<Including paragraphs> | ||
|
||
# If you want to use GPL v2 or later for the /debian/* files use | ||
# the following clauses, or change it to suit. Delete these two lines | ||
Files: | ||
debian/* | ||
Copyright: | ||
2025 PGPM Debian maintainer <[email protected]> | ||
License: GPL-2+ | ||
This package is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
. | ||
This package is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <https://www.gnu.org/licenses/> | ||
Comment: | ||
On Debian systems, the complete text of the GNU General | ||
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". | ||
|
||
# Please also look if there are files or directories which have a | ||
# different copyright/license attached and list them here. | ||
# Please avoid picking licenses with terms that are more restrictive than the | ||
# packaged work, as it may make Debian's contributions unacceptable upstream. | ||
# | ||
# If you need, there are some extra license texts available in two places: | ||
# /usr/share/debhelper/dh_make/licenses/ | ||
# /usr/share/common-licenses/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<%= source_name %>-<%= source_version %>_0-1_source.buildinfo libs optional |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/make -f | ||
|
||
# See debhelper(7) (uncomment to enable). | ||
# Output every command that modifies files on the build system. | ||
#export DH_VERBOSE = 1 | ||
|
||
|
||
# See FEATURE AREAS in dpkg-buildflags(1). | ||
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all | ||
|
||
# See ENVIRONMENT in dpkg-buildflags(1). | ||
# Package maintainers to append CFLAGS. | ||
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic | ||
# Package maintainers to append LDFLAGS. | ||
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed | ||
|
||
|
||
%: | ||
dh $@ | ||
|
||
<%= self.rules_amendments %> |
Uh oh!
There was an error while loading. Please reload this page.