Skip to content

Add GitHub workflows for CI and packaging #5

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

Merged
merged 11 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: ci
on:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master
jobs:
test:
name: test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
rust: [1.84.0, stable]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install Rust
uses: hecrj/setup-rust-action@v2
with:
rust-version: ${{ matrix.rust }}
- if: matrix.rust == 'stable'
run: rustup component add clippy
- if: matrix.rust == 'stable'
run: cargo clippy -- -D warnings
- run: cargo build --verbose --locked
- run: cargo test --verbose
36 changes: 36 additions & 0 deletions .github/workflows/pkg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Packaging

on:
push:
branches:
- main
- master
tags:
- v*

# Triggering on PRs and arbitrary branch pushes is not enabled because most of the time only the CI build should be
# triggered, not the packaging build. In cases where you want to test changes to this workflow this trigger enables
# you to manually invoke this workflow on an arbitrary branch as needed.
workflow_dispatch:

jobs:
package:
# See: https://github.com/NLnetLabs/ploutos
uses: NLnetLabs/ploutos/.github/workflows/pkg-rust.yml@v7
secrets:
DOCKER_HUB_ID: ${{ vars.DOCKER_HUB_ID }}
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
with:
cross_build_args:
cross_max_wait_mins: 20

docker_org: nlnetlabs
docker_repo: rrdpit
docker_build_rules: pkg/rules/docker-images-to-build.yml
docker_sanity_check_command: rrdpit --version

package_build_rules: pkg/rules/packages-to-build.yml
package_test_rules: pkg/rules/packages-to-test.yml
package_test_scripts_path: pkg/test-scripts/test-<package>.sh

deb_extra_build_packages: libssl-dev
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,46 @@ hex = "^0.3"
ring = "^0.17"
uuid = { version = "^0.7", features = ["v4"] }
xml-rs = "0.8.25"

# ------------------------------------------------------------------------------
# START DEBIAN PACKAGING
#
# Configurations for the cargo-deb cargo plugin which builds Debian packages in
# target/debian/ when invoked with: cargo deb.
#
# TODO:
# - Build packages with GH Actions
# - Add man page?
# - Add changelog
#
# NOTE:
# - There is a single binary only (no daemon yet)

[package.metadata.deb]
name = "rrdpit"
priority = "optional"
section = "net"
extended-description-file = "pkg/debian/description.txt"
license-file = ["LICENSE", "0"]
depends = ""
maintainer-scripts = "pkg/debian/"
changelog = "target/debian/changelog" # this will be generated by the pkg workflow
copyright = "Copyright (c) 2025, NLnet Labs. All rights reserved."
assets = [["target/release/rrdpit", "/usr/bin/rrdpit", "755"]]

# List target variants
[package.metadata.deb.variants.ubuntu-focal]

[package.metadata.deb.variants.ubuntu-jammy]

[package.metadata.deb.variants.ubuntu-noble]

[package.metadata.deb.variants.debian-buster]

[package.metadata.deb.variants.debian-bullseye]

[package.metadata.deb.variants.debian-bookworm]

# END DEBIAN PACKAGING
# ------------------------------------------------------------------------------

172 changes: 172 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# This is a multi-stage Dockerfile, with a selectable first stage. With this
# approach we get:
#
# 1. Separation of dependencies needed to build our app in the 'build' stage
# and those needed to run our app in the 'final' stage, as we don't want
# the build-time dependencies to be included in the final Docker image.
#
# 2. Support for either building our app for the architecture of the base
# image using MODE=build (the default) or for externally built app
# binaries (e.g. cross-compiled) using MODE=copy.
#
# In total there are four stages consisting of:
# - Two possible first stages: 'build' or 'copy'.
# - A special 'source' stage which selects either 'build' or 'copy' as the
# source of binaries to be used by ...
# - The 'final' stage.


###
### ARG DEFINITIONS ###########################################################
###

# This section defines arguments that can be overriden on the command line
# when invoking `docker build` using the argument form:
#
# `--build-arg <ARGNAME>=<ARGVALUE>`.

# MODE
# ====
# Supported values: build (default), copy
#
# By default this Dockerfile will build our app from sources. If the sources
# have already been (cross) compiled by some external process and you wish to
# use the resulting binaries from that process, then:
#
# 1. Create a directory on the host called 'dockerbin/$TARGETPLATFORM'
# containing the already compiled app binaries (where $TARGETPLATFORM
# is a special variable set by Docker BuiltKit).
# 2. Supply arguments `--build-arg MODE=copy` to `docker build`.
ARG MODE=build


# BASE_IMG
# ========
#
# Only used when MODE=build.
ARG BASE_IMG=alpine:3.21


# CARGO_ARGS
# ==========
#
# Only used when MODE=build.
#
# This ARG can be used to control the features enabled when compiling the app
# or other compilation settings as necessary.
ARG CARGO_ARGS


###
### BUILD STAGES ##############################################################
###


# -----------------------------------------------------------------------------
# Docker stage: build
# -----------------------------------------------------------------------------
#
# Builds our app binaries from sources.
FROM ${BASE_IMG} AS build
ARG CARGO_ARGS

RUN apk add --no-cache rust cargo openssl-dev

WORKDIR /tmp/build
COPY . .

# `CARGO_HTTP_MULTIPLEXING` forces Cargo to use HTTP/1.1 without pipelining
# instead of HTTP/2 with multiplexing. This seems to help with various
# "spurious network error" warnings when Cargo attempts to fetch from crates.io
# when building this image on Docker Hub and GitHub Actions build machines.
#
# `cargo install` is used instead of `cargo build` because it places just the
# binaries we need into a predictable output directory. We can't control this
# with arguments to cargo build as `--out-dir` is unstable and contentious and
# `--target-dir` still requires us to know which profile and target the
# binaries were built for. By using `cargo install` we can also avoid needing
# to hard-code the set of binary names to copy so that if we add or remove
# built binaries in future this will "just work". Note that `--root /tmp/out`
# actually causes the binaries to be placed in `/tmp/out/bin/`. `cargo install`
# will create the output directory for us.
RUN CARGO_HTTP_MULTIPLEXING=false cargo install \
--locked \
--path . \
--root /tmp/out/ \
${CARGO_ARGS}


# -----------------------------------------------------------------------------
# Docker stage: copy
# -----------------------------------------------------------------------------
# Only used when MODE=copy.
#
# Copy binaries from the host directory 'dockerbin/$TARGETPLATFORM' directory
# into this build stage to the same predictable location that binaries would be
# in if MODE were 'build'.
#
# Requires that `docker build` be invoked with variable `DOCKER_BUILDKIT=1` set
# in the environment. This is necessary so that Docker will skip the unused
# 'build' stage and so that the magic $TARGETPLATFORM ARG will be set for us.
FROM ${BASE_IMG} AS copy
ARG TARGETPLATFORM
ONBUILD COPY dockerbin/$TARGETPLATFORM /tmp/out/bin/


# -----------------------------------------------------------------------------
# Docker stage: source
# -----------------------------------------------------------------------------
# This is a "magic" build stage that "labels" a chosen prior build stage as the
# one that the build stage after this one should copy application binaries
# from. It also causes the ONBUILD COPY command from the 'copy' stage to be run
# if needed. Finally, we ensure binaries have the executable flag set because
# when copied in from outside they may not have the flag set, especially if
# they were uploaded as a GH actions artifact then downloaded again which
# causes file permissions to be lost.
# See: https://github.com/actions/upload-artifact#permission-loss
FROM ${MODE} AS source
RUN chmod a+x /tmp/out/bin/*


# -----------------------------------------------------------------------------
# Docker stage: final
# -----------------------------------------------------------------------------
# Create an image containing just the binaries, configs & scripts needed to run
# our app, and not the things needed to build it.
#
# The previous build stage from which binaries are copied is controlled by the
# MODE ARG (see above).
FROM ${BASE_IMG} AS final

# Copy binaries from the 'source' build stage into the image we are building
COPY --from=source /tmp/out/bin/* /usr/local/bin/

# Build variables for uid and guid of user to run container
ARG RUN_USER=rrdpit
ARG RUN_USER_UID=1012
ARG RUN_USER_GID=1012

# Install required runtime dependencies
RUN apk add --no-cache bash libgcc openssl tini tzdata util-linux

# Create the user and group to run the application as
RUN addgroup -g ${RUN_USER_GID} ${RUN_USER} && \
adduser -D -u ${RUN_USER_UID} -G ${RUN_USER} ${RUN_USER}

# Create the data directories and create a volume for them
VOLUME /data
RUN mkdir -p /data/source /data/target && \
chown -R ${RUN_USER_UID}:${RUN_USER_GID} /data

# Install a Docker entrypoint script that will be executed when the container
# runs
COPY docker/entrypoint.sh /opt/
RUN chown ${RUN_USER}: /opt/entrypoint.sh

# Switch to our applications user
USER ${RUN_USER}

# Use Tini to ensure that our application responds to CTRL-C when run in the
# foreground without the Docker argument "--init" (which is actually another
# way of activating Tini, but cannot be enabled from inside the Docker image).
ENTRYPOINT ["/sbin/tini", "--", "/opt/entrypoint.sh"]
15 changes: 15 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# run rrdpit with variable interpolation
set -e
DATA="${DATA:-/data}"
SOURCE_DIR="${SOURCE_DIR:-$DATA/source}"
TARGET_DIR="${TARGET_DIR:-$DATA/target}"
RSYNC_URI="${RSYNC_URI:-rsync://example.org/test/}"
HTTPS_URI="${HTTPS_URI:-https://example.org/}"

exec /usr/local/bin/rrdpit \
--source ${SOURCE_DIR} \
--target ${TARGET_DIR} \
--rsync ${RSYNC_URI} \
--https ${HTTPS_URI} \
"$@"
7 changes: 7 additions & 0 deletions pkg/debian/description.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"rrdpit" is a small little tool that can be pointed at a directory on your
system, and produce RPKI RRDP (RFC 8182) notification, snapshot, and
delta files. You will need to use an http server of your preferred
flavour to deliver these files to the world.

Read more here:
https://github.com/NLnetLabs/rrdpit/
18 changes: 18 additions & 0 deletions pkg/debian/postinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh
set -e

KRILL_HOME="/var/lib/rrdpit/"
KRILL_USER="rrdpit"

create_user() {
if id ${KRILL_USER} > /dev/null 2>&1; then return; fi
adduser --system --home "${KRILL_HOME}" --group ${KRILL_USER}
}

case "$1" in
configure)
create_user
;;
esac

#DEBHELPER#
21 changes: 21 additions & 0 deletions pkg/rules/docker-images-to-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# See: https://github.com/NLnetLabs/ploutos/blob/main/docs/docker_packaging.md#docker-build-rules
---
include:
- platform: 'linux/amd64'
shortname: 'amd64'
mode: 'build'

- platform: 'linux/arm/v6'
shortname: 'armv6'
crosstarget: 'arm-unknown-linux-musleabihf'
mode: 'copy'

- platform: 'linux/arm/v7'
shortname: 'armv7'
crosstarget: 'armv7-unknown-linux-musleabihf'
mode: 'copy'

- platform: 'linux/arm64'
shortname: 'arm64'
crosstarget: 'aarch64-unknown-linux-musl'
mode: 'copy'
Loading