Skip to content

Commit

Permalink
packaging: build rpm packages (#4632)
Browse files Browse the repository at this point in the history
Unfortunately, the new style rpm_rules (the ones that I find remotely
usable) do not appear to support cross-architecture packaging yet. So,
this is x86_64 only for now.

Fixes #4425

---------

Co-authored-by: FR4NK-W <wirzf@inf.ethz.ch>
  • Loading branch information
jiceatscion and FR4NK-W authored Oct 10, 2024
1 parent 7956be9 commit e6b0576
Show file tree
Hide file tree
Showing 9 changed files with 421 additions and 3 deletions.
6 changes: 5 additions & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ steps:
- exit_status: 255 # Forced agent shutdown
timeout_in_minutes: 10
- wait
- label: "Package :debian: :openwrt:"
- label: "Package :debian: :openwrt: :rpm:"
command: |
make dist-deb BFLAGS="--file_name_version=${SCION_VERSION}"
make dist-openwrt BFLAGS="--file_name_version=${SCION_VERSION}"
make dist-rpm BFLAGS="--file_name_version=${SCION_VERSION}"
artifact_paths:
- "installables/scion_*.tar.gz"
plugins:
Expand All @@ -42,6 +43,7 @@ steps:
tar -chaf scion_${SCION_VERSION}_deb_i386.tar.gz *_${SCION_VERSION}_i386.deb
tar -chaf scion_${SCION_VERSION}_deb_armel.tar.gz *_${SCION_VERSION}_armel.deb
tar -chaf scion_${SCION_VERSION}_openwrt_x86_64.tar.gz *_${SCION_VERSION}_x86_64.ipk
tar -chaf scion_${SCION_VERSION}_rpm_x86_64.tar.gz *_${SCION_VERSION}_x86_64.rpm
popd
ls installables
post-artifact: |
Expand All @@ -53,6 +55,8 @@ steps:
- <a href="artifact://installables/scion_${SCION_VERSION}_deb_armel.tar.gz">armel</a>
#### Packages :openwrt:
- <a href="artifact://installables/scion_${SCION_VERSION}_openwrt_x86_64.tar.gz">x86_64</a>
#### Packages :rpm:
- <a href="artifact://installables/scion_${SCION_VERSION}_rpm_x86_64.tar.gz">x86_64</a>
EOF
key: dist
retry: *automatic-retry
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ dist-openwrt-testing:
@ mkdir -p installables
@ cd installables ; ln -sfv ../bazel-out/*/bin/dist/*.ipk .

dist-rpm:
bazel build //dist:rpm_all $(BFLAGS)
@ # These artefacts have unique names but varied locations. Link them somewhere convenient.
@ mkdir -p installables
@ cd installables ; ln -sfv ../bazel-out/*/bin/dist/*.rpm .

# all: performs the code-generation steps and then builds; the generated code
# is git controlled, and therefore this is only necessary when changing the
# sources for the code generation.
Expand Down
9 changes: 9 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ oci_pull(
repository = "library/debian",
)

# Debian packaging
http_archive(
name = "rules_debian_packages",
sha256 = "0ae3b332f9d894e57693ce900769d2bd1b693e1f5ea1d9cdd82fa4479c93bcc8",
Expand All @@ -206,6 +207,14 @@ load("@tester_debian10_packages//:packages.bzl", tester_debian_packages_install_

tester_debian_packages_install_deps()

# RPM packaging
load("@rules_pkg//toolchains/rpm:rpmbuild_configure.bzl", "find_system_rpmbuild")

find_system_rpmbuild(
name = "rules_pkg_rpmbuild",
verbose = False,
)

# Buf CLI
http_archive(
name = "buf",
Expand Down
120 changes: 118 additions & 2 deletions dist/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
load(":package.bzl", "scion_pkg_deb")
load(":package.bzl", "scion_pkg_ipk")
load(":package.bzl", "scion_pkg_deb", "scion_pkg_ipk", "scion_pkg_rpm")
load(":platform.bzl", "multiplatform_filegroup")
load(":git_version.bzl", "git_version")

Expand All @@ -10,6 +9,10 @@ DEB_PLATFORMS = [
"@io_bazel_rules_go//go/toolchain:linux_arm",
]

RPM_PLATFORMS = [
"@io_bazel_rules_go//go/toolchain:linux_amd64",
]

# TODO(jice@scion.org):
# For now only a single openwrt platform can be in this list. If we allow several, they get
# built in parallel, which breaks on non-reentrant openwrt makefiles. For a single platform
Expand Down Expand Up @@ -221,3 +224,116 @@ multiplatform_filegroup(
target_platforms = OPENWRT_PLATFORMS,
visibility = ["//dist:__subpackages__"],
)

scion_pkg_rpm(
name = "router_rpm",
depends = [
"/sbin/adduser",
],
description = "SCION inter-domain network architecture border router",
executables = {
"//router/cmd/router:router": "scion-router",
},
package = "scion-router",
postinst = "rpm/scion.postinst",
systemds = ["systemd/scion-router@.service"],
version_file = ":git_version",
)

scion_pkg_rpm(
name = "control_rpm",
configs = [],
depends = [
"/sbin/adduser",
"scion-dispatcher",
],
description = "SCION inter-domain network architecture control service",
executables = {
"//control/cmd/control:control": "scion-control",
},
package = "scion-control",
systemds = ["systemd/scion-control@.service"],
version_file = ":git_version",
)

scion_pkg_rpm(
name = "dispatcher_rpm",
configs = ["conffiles/dispatcher.toml"],
depends = [
"/sbin/adduser",
],
description = "SCION dispatcher",
executables = {
"//dispatcher/cmd/dispatcher:dispatcher": "scion-dispatcher",
},
package = "scion-dispatcher",
postinst = "rpm/scion.postinst",
systemds = ["systemd/scion-dispatcher.service"],
version_file = ":git_version",
)

scion_pkg_rpm(
name = "daemon_rpm",
configs = ["conffiles/daemon.toml"],
depends = [
"/sbin/adduser",
],
description = "SCION daemon",
executables = {
"//daemon/cmd/daemon:daemon": "scion-daemon",
},
package = "scion-daemon",
postinst = "rpm/scion.postinst",
systemds = ["systemd/scion-daemon.service"],
version_file = ":git_version",
)

scion_pkg_rpm(
name = "gateway_rpm",
configs = [
"conffiles/gateway.json",
"conffiles/gateway.toml",
],
depends = [
"/sbin/adduser",
"scion-dispatcher",
"scion-daemon",
],
description = "SCION-IP Gateway",
executables = {
"//gateway/cmd/gateway:gateway": "scion-ip-gateway",
},
package = "scion-ip-gateway",
systemds = ["systemd/scion-ip-gateway.service"],
version_file = ":git_version",
)

scion_pkg_rpm(
name = "tools_rpm",
depends = [
"/sbin/adduser",
"scion-dispatcher",
"scion-daemon",
],
description = "SCION tools",
executables = {
"//scion/cmd/scion:scion": "scion",
"//scion-pki/cmd/scion-pki:scion-pki": "scion-pki",
},
package = "scion-tools",
version_file = ":git_version",
)

multiplatform_filegroup(
name = "rpm",
srcs = [
"control_rpm",
"daemon_rpm",
"dispatcher_rpm",
"gateway_rpm",
"router_rpm",
"tools_rpm",
],
target_platforms = RPM_PLATFORMS,
visibility = ["//dist:__subpackages__"],
)
102 changes: 102 additions & 0 deletions dist/package.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
load("@rules_pkg//pkg:pkg.bzl", "pkg_deb", "pkg_tar")
load("@rules_pkg//pkg:rpm.bzl", "pkg_rpm")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@rules_pkg//pkg:providers.bzl", "PackageVariablesInfo")
load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_files")

SCION_PKG_HOMEPAGE = "https://github.com/scionproto/scion"
SCION_PKG_MAINTAINER = "SCION Contributors"
Expand Down Expand Up @@ -30,6 +32,106 @@ name_elems = rule(
},
)

def scion_pkg_rpm(name, package, executables = {}, systemds = [], configs = [], **kwargs):
"""
The package content, the _data_ arg for the pkg_rpm rule, is assembled from:
- executables: Map Label (the executable) -> string, the basename of the executable in the package
Executables are installed to /usr/bin/
- systemds: List[string], the systemd unit files to be installed in /lib/systemd/system/
- configs: List[string], the configuration files to be installed in /etc/scion/
The values for the following pkg_rpm args are set to a default value:
- url
- license
- architecture, set based on the platform.
The caller needs to set:
- package: the name of the package (e.g. scion-router)
- description: one-liner
- version/version_file: One can use the label ":git_version"
and any of the optional control directives.
The version string gets edited to meet rpm requirements: dashes are replaced with ^.
"""

kwargs.setdefault("url", SCION_PKG_HOMEPAGE)
kwargs.setdefault("license", SCION_PKG_LICENSE)

if "architecture" not in kwargs:
kwargs["architecture"] = select({
"@platforms//cpu:x86_64": "x86_64",
"@platforms//cpu:x86_32": "i386",
"@platforms//cpu:aarch64": "arm64",
"@platforms//cpu:armv7": "armel",
"@platforms//cpu:s390x": "s390x",
# Note: some rules_go toolchains don't (currently) seem to map (cleanly) to @platforms//cpu.
# "@platforms//cpu:ppc": "ppc64",
# "@platforms//cpu:ppc64le": "ppc64le",
})

name_elems(
name = "package_file_naming_" + name,
file_name_version = "@@//:file_name_version",
architecture = kwargs["architecture"],
package = package,
)

# Note that our "executables" parameter is a dictionary label->file_name; exactly what pkg_files
# wants for its "renames" param.
pkg_files(name = "%s_configs" % name, prefix = "/etc/scion/", srcs = configs)
pkg_files(name = "%s_systemds" % name, prefix = "/lib/systemd/system/", srcs = systemds)
pkg_files(
name = "%s_execs" % name,
prefix = "/usr/bin/",
srcs = executables.keys(),
attributes = pkg_attributes(mode = "0755"),
renames = executables,
)

if kwargs.get("version_file"):
native.genrule(
name = "%s_version" % name,
srcs = [kwargs["version_file"]],
outs = ["%s_version_file" % name],
cmd = "sed 's/-/^/g' < $< > $@",
)
kwargs.pop("version_file")
elif kwargs.get("version"):
native.genrule(
name = "%s_version" % name,
srcs = [],
outs = ["%s_version_file" % name],
cmd = "echo \"%s\" | sed 's/-/^/g' > $@" % kwargs["version"],
)
kwargs.pop("version")

# Use the same attributes as scion_pkg_deb, in view of may-be simplifying BUILD.bazel later.
deps = kwargs.get("depends")
if deps:
kwargs.pop("depends")
else:
deps = []

post = kwargs.get("postinst")
if post:
kwargs.pop("postinst")

pkg_rpm(
name = name,
summary = kwargs["description"],
srcs = ["%s_configs" % name, "%s_systemds" % name, "%s_execs" % name],
target_compatible_with = ["@platforms//os:linux"],
package_file_name = "{package}_{file_name_version}_{architecture}.rpm",
package_variables = ":package_file_naming_" + name,
package_name = package,
release = "%autorelease",
version_file = ":%s_version" % name,
requires = deps,
post_scriptlet_file = post,
**kwargs
)

def scion_pkg_deb(name, executables = {}, systemds = [], configs = [], **kwargs):
"""
The package content, the _data_ arg for the pkg_deb rule, is assembled from:
Expand Down
13 changes: 13 additions & 0 deletions dist/rpm/scion.postinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash
set -e

# Create system user/group
groupadd --system -f scion
useradd --system --gid scion -M -s /sbin/nologin scion >& /dev/null || true

# Create configuration directory
mkdir /etc/scion/ >& /dev/null || true
mkdir /var/lib/scion/ >& /dev/null || true
chown scion:scion /etc/scion/ /var/lib/scion


16 changes: 16 additions & 0 deletions dist/test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,19 @@ sh_test(
"integration",
],
)

sh_test(
name = "rpm_test",
srcs = ["rpm_test.sh"],
data = [
"Dockerfile.rpm",
"//dist:rpm",
],
env = {
"SCION_RPM_PACKAGES": "$(locations //dist:rpm)",
},
tags = [
"exclusive",
"integration",
],
)
8 changes: 8 additions & 0 deletions dist/test/Dockerfile.rpm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM fedora:40

RUN dnf --assumeyes install systemd

ENV container docker

# Only "boot" a minimal system with journald and nothing else
CMD ["/usr/lib/systemd/systemd", "--unit", "systemd-journald.service"]
Loading

0 comments on commit e6b0576

Please sign in to comment.