-
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 19 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,120 @@ | ||
# frozen_string_literal: true | ||
|
||
module Pgpm | ||
module Deb | ||
class Builder | ||
|
||
def initialize(spec) | ||
@spec = spec | ||
@container_name = "pgpm-debian_build-#{Time.now.to_i}_#{rand(10000)}" | ||
end | ||
|
||
def build | ||
prepare | ||
generate_deb_src_files | ||
pull_image | ||
run_build | ||
copy_build_from_container | ||
cleanup | ||
end | ||
|
||
private | ||
|
||
# Depends on postgres version and arch | ||
def image_name | ||
"quay.io/qount25/pgpm-debian-pg#{@spec.package.postgres_major_version}-#{@spec.arch}" | ||
end | ||
|
||
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 pull_image | ||
puts "Checking if podman image exists..." | ||
# 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 " No. Pulling image #{image_name}..." | ||
system("podman pull #{image_name}") | ||
else | ||
puts " Yes, image #{image_name} already exists! OK" | ||
end | ||
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_build | ||
# podman run options | ||
create_opts = " -v #{@pgpm_dir}:/root/pgpm" | ||
create_opts += ":z" if selinux_enabled? | ||
create_opts += " --privileged" | ||
create_opts += " --name #{@container_name} #{image_name}" | ||
|
||
dsc_fn = "#{@spec.package.name}-#{@spec.package.version.to_s}_0-1.dsc" | ||
deb_fn = "#{@spec.full_pkg_name}.deb" | ||
|
||
# commands to run | ||
cmds = " /bin/bash -c 'cd /root/pgpm/source" | ||
cmds += " && dpkg-buildpackage --build=source -d" # -d flag helps with dependencies error | ||
cmds += " && fakeroot pbuilder build ../#{dsc_fn}" | ||
cmds += " && mv /var/cache/pbuilder/result/#{deb_fn} /root/pgpm/out/'" | ||
|
||
puts " Creating and starting container #{@container_name} & running pbuilder" | ||
puts "podman run -it #{create_opts} #{cmds}" | ||
system("podman run -it #{create_opts} #{cmds}") | ||
exit(1) if $?.to_i > 0 | ||
end | ||
|
||
def copy_build_from_container | ||
puts "Moving .deb file from podman container into current directory..." | ||
deb_fn = "#{@spec.full_pkg_name}.deb" | ||
FileUtils.mv("#{@pgpm_dir}/out/#{deb_fn}", Dir.pwd) | ||
end | ||
|
||
def cleanup | ||
puts "Cleaning up..." | ||
|
||
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,52 @@ | ||
# 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) | ||
@postgres_distribution = Pgpm::Postgres::Distribution.in_scope | ||
@package = package | ||
@package.postgres_major_version = @postgres_distribution.version.split(".")[0] | ||
@package.os = "debian" | ||
@release = 1 | ||
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 source_version | ||
@package.version.to_s | ||
end | ||
|
||
def full_pkg_name | ||
"#{@package.name}-#{@package.version.to_s}_0-1_#{arch}" | ||
end | ||
|
||
def arch | ||
# https://memgraph.com/blog/ship-it-on-arm64-or-is-it-aarch64 | ||
# Debian suffixes are "amd64" and "arm64". Here we translate: | ||
case Pgpm::Arch.in_scope.name | ||
when "amd64", "x86_64" | ||
"amd64" | ||
when "aarch64", "arm64" | ||
"arm64" | ||
end | ||
end | ||
|
||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<%= self.package.name %>-<%= source_version %> (0-1) UNRELEASED; urgency=medium | ||
|
||
* Version <%= source_version %> package release. | ||
|
||
-- PGPM Debian maintainer <[email protected]> <%= Time.now.to_s %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Source: <%= self.package.name %>-<%= source_version %> | ||
Description: <%= self.package.description %> | ||
Section: libs | ||
Priority: optional | ||
Maintainer: PGPM Debian maintainer <[email protected]> | ||
Rules-Requires-Root: no | ||
Build-Depends: debhelper-compat (= 13), <%= self.package.build_dependencies.join(", ") %> | ||
Standards-Version: 4.6.2 | ||
|
||
Package: <%= self.package.name %>-<%= source_version %> | ||
Depends: <%= self.package.dependencies.join(", ") %> | ||
Section: libdevel | ||
Architecture: <%= arch %> | ||
Description: <%= self.package.description %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
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: <%= self.package.name %>-<%= self.package.name %> | ||
Upstream-Contact: <preferred name and address to reach the upstream project> | ||
|
||
Files: | ||
* | ||
Copyright: | ||
<%= self.package.license %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<%= self.package.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.package.build_info[:rules] %> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
|
||
require "rbconfig" | ||
|
||
module Pgpm | ||
module OS | ||
class Debian < Pgpm::OS::Linux | ||
def self.auto_detect | ||
# TODO: distinguish between flavors of Debian | ||
Debian12.new | ||
end | ||
|
||
def self.name | ||
"debian" | ||
end | ||
|
||
def mock_config; end | ||
end | ||
|
||
class Debian12 < Pgpm::OS::Debian | ||
def self.name | ||
"debian-12" | ||
end | ||
|
||
def self.builder | ||
Pgpm::Debian::Builder | ||
end | ||
|
||
def mock_config | ||
"debian-12-#{Pgpm::Arch.in_scope.name}+pgdg" | ||
end | ||
|
||
end | ||
end | ||
end |
Uh oh!
There was an error while loading. Please reload this page.