aboutsummaryrefslogtreecommitdiffstats
path: root/ci
diff options
context:
space:
mode:
authorGilles Chehade <gilles@poolp.org>2020-04-30 02:06:46 +0200
committerGilles Chehade <gilles@poolp.org>2020-04-30 02:06:46 +0200
commitd4180f85d53f7381da9fcc7257cf61d0b29497a0 (patch)
tree928f5541f702f22aec334cd7262d611821ff44cf /ci
parentMerge remote-tracking branch 'portable/native' (diff)
downloadOpenSMTPD-d4180f85d53f7381da9fcc7257cf61d0b29497a0.tar.xz
OpenSMTPD-d4180f85d53f7381da9fcc7257cf61d0b29497a0.zip
merge histories
Diffstat (limited to 'ci')
-rw-r--r--ci/COVERITY.MD5SUM1
-rw-r--r--ci/README.md83
-rw-r--r--ci/docker/Dockerfile.alpine50
-rw-r--r--ci/docker/Dockerfile.archlinux62
-rw-r--r--ci/docker/Dockerfile.ubuntu52
-rw-r--r--ci/docker/Dockerfile.ubuntu-gcc1054
-rwxr-xr-xci/scripts/clang_scan.sh60
-rwxr-xr-xci/scripts/coverity_scan.sh77
-rwxr-xr-xci/scripts/generate_certs.sh33
-rw-r--r--ci/scripts/imports/badge.sh72
-rw-r--r--ci/scripts/ssl.conf23
11 files changed, 567 insertions, 0 deletions
diff --git a/ci/COVERITY.MD5SUM b/ci/COVERITY.MD5SUM
new file mode 100644
index 00000000..67b8a2de
--- /dev/null
+++ b/ci/COVERITY.MD5SUM
@@ -0,0 +1 @@
+d0d7d7df9d6609e578f85096a755fb8f ./cov-analysis-linux64.tgz
diff --git a/ci/README.md b/ci/README.md
new file mode 100644
index 00000000..2eee08f1
--- /dev/null
+++ b/ci/README.md
@@ -0,0 +1,83 @@
+# Continuous Integration
+
+This directory contains CI/CD related scripts and resources
+
+CI/CD process leverages GitHub Actions as a primary automation platform since
+up to 20 parallel workflows are available for opensource projects.
+
+On high level we have multiple dimensions to test:
+
+ - OS Distribution
+ - TLS library implementation: libress, openssl
+ - libc implementations: glibc, musl
+ - compiler: gcc, clang (not yet tested)
+
+Within this matrix build tests, static code analysis, functional and
+integration tests are planned. Currently only build tests and static code
+analysis exist. Help is much needed with developing functional and integration
+tests.
+
+## Directory strucuture
+
+- [docker](#dockerfiles) dockerfiles for various distributions
+- [scripts](#scripts) useful scripts for ci/cd automation
+
+
+## Design Considerations
+
+- Keep workflow yaml files and execution logic as separate as possible.
+ Reference ci scripts from workflow files to allow running same tests
+ locally, without depending on github.
+
+
+
+# Dockerfiles
+
+Dockerfiles in [docker](docker/) directory can be used for developing and
+testing OpenSMTPD. These dockerfiles are intended to be used for dev/test
+cycle ONLY and ARE NOT intended to be a delivery mechanism for end users and
+should not be published on external resouces like DockerHub. Dockerfiles in
+this folder can be used as a reference for package maintainers of various
+distributions.
+
+
+## Usage
+
+OpenSMTPD provides a set of dockerfiles for getting started with development
+quickly locally or with GitHub's Actions.
+
+For each distribution there is a separate dockerfile with a distro name
+suffixed. E.g. `Dockerfile.alpine` is a dockerfile that builds OpenSMTPD in
+Alpine Linux environment.
+
+To build:
+
+ docker build -f docker/Dockerfile.alpine -t opensmtpd-alpine
+
+
+All configuration files that are in `/etc/mail` are taken from `etc/` directory.
+
+
+To run the container that you've just built run:
+
+ docker run --name smtpd_server -p 25:25 opensmtpd-alpine
+
+
+
+# Scripts
+
+Scripts to automate ci/cd actions:
+
+- [coverity_scan](scripts/coverity_scan.sh) - runs coverity scan and submits
+ the rusult to Coverity. See script contents for usage instructions.
+
+- [generate_certs](scripts/generate_certs.sh) - convenient script to quickly
+ generate some TLS certificates. Useful for testing.
+
+# Historical reference
+
+[Initial design discusstion](https://github.com/OpenSMTPD/OpenSMTPD/issues/947)
+
+
+
+
diff --git a/ci/docker/Dockerfile.alpine b/ci/docker/Dockerfile.alpine
new file mode 100644
index 00000000..2c7c66fc
--- /dev/null
+++ b/ci/docker/Dockerfile.alpine
@@ -0,0 +1,50 @@
+FROM alpine:3.11 as build
+
+# creates /opensmtpd dir and makes all following commands to run in it
+# https://docs.docker.com/engine/reference/builder/#workdir
+WORKDIR /opensmtpd
+
+# install necessary packages
+RUN apk add --no-cache \
+ autoconf \
+ automake \
+ bison \
+ ca-certificates \
+ fts-dev \
+ gcc \
+ fts \
+ libevent-dev \
+ libtool \
+ libtool \
+ linux-pam-dev \
+ make \
+ musl-dev \
+ libressl \
+ libressl-dev \
+ zlib-dev
+
+# create users and directories
+# note: alpine uses busybox and useradd is not available there
+# also long flags are not available too, so sorry for the
+RUN mkdir -p /var/lib/opensmtpd/empty \
+ && adduser _smtpd -h /var/lib/opensmtpd/empty/ -D -H -s /bin/false \
+ && adduser _smtpq -h /var/lib/opensmtpd/empty/ -D -H -s /bin/false \
+ && mkdir -p /var/spool/smtpd \
+ && mkdir -p /var/mail \
+ && mkdir -p /etc/mail \
+ && chmod 711 /var/spool/smtpd
+
+# Copy contentes of the repo inside the container
+# https://docs.docker.com/engine/reference/builder/#copy
+COPY . /opensmtpd
+
+# build opensmtpd
+RUN ./bootstrap \
+ && ./configure \
+ --with-gnu-ld \
+ --sysconfdir=/etc/mail \
+ --with-auth-pam \
+ && make \
+ && make install \
+ && cp etc/aliases /etc/mail/aliases
+
diff --git a/ci/docker/Dockerfile.archlinux b/ci/docker/Dockerfile.archlinux
new file mode 100644
index 00000000..dcd46684
--- /dev/null
+++ b/ci/docker/Dockerfile.archlinux
@@ -0,0 +1,62 @@
+FROM archlinux
+
+# Allow container to expose ports at runtime, if necessary
+# https://docs.docker.com/engine/reference/#expose
+EXPOSE 25
+EXPOSE 465
+EXPOSE 587
+
+# creates /opensmtpd dir and makes all following commands to run in it
+# https://docs.docker.com/engine/reference/builder/#workdir
+WORKDIR /opensmtpd
+
+# install necessary packages
+RUN pacman -Suy --noconfirm \
+ base \
+ make \
+ m4 \
+ grep \
+ gcc \
+ automake \
+ autoconf \
+ libtool \
+ bison \
+ gettext \
+ libevent \
+ libressl \
+ pam \
+ zlib
+
+
+# create users and directories
+RUN mkdir -p /var/lib/opensmtpd/empty \
+ && useradd _smtpd \
+ --home-dir /var/lib/opensmtpd/empty \
+ --no-create-home \
+ --shell /bin/false \
+ && useradd _smtpq \
+ --home-dir /var/lib/opensmtpd/empty \
+ --no-create-home \
+ --shell /bin/false \
+ && mkdir -p /var/spool/smtpd \
+ && mkdir -p /var/mail \
+ && mkdir -p /etc/mail \
+ && chmod 711 /var/spool/smtpd
+
+
+# Copy contentes of the repo inside the container
+# https://docs.docker.com/engine/reference/builder/#copy
+COPY . /opensmtpd
+
+
+# build opensmtpd
+RUN ./bootstrap \
+ && ./configure --with-gnu-ld \
+ --sysconfdir=/etc/mail \
+ --with-cflags='-I/usr/include/libressl -L/usr/lib/libressl -Wl,-rpath=/usr/lib/libressl' \
+ --with-path-empty=/var/lib/opensmtpd/empty \
+ --with-auth-pam \
+ && make \
+ && make install \
+ && cp etc/aliases /etc/mail/aliases
+
diff --git a/ci/docker/Dockerfile.ubuntu b/ci/docker/Dockerfile.ubuntu
new file mode 100644
index 00000000..6626033d
--- /dev/null
+++ b/ci/docker/Dockerfile.ubuntu
@@ -0,0 +1,52 @@
+FROM ubuntu:latest
+
+# Allow container to expose ports at runtime, if necessary
+# https://docs.docker.com/engine/reference/#expose
+EXPOSE 25
+EXPOSE 465
+EXPOSE 587
+
+# creates /opensmtpd dir and makes all following commands to run in it
+# https://docs.docker.com/engine/reference/builder/#workdir
+WORKDIR /opensmtpd
+
+# install necessary packages
+RUN apt update \
+ && apt install -y --no-install-recommends \
+ autoconf \
+ automake \
+ bison \
+ build-essential \
+ libevent-dev \
+ libssl-dev \
+ libtool \
+ libpam0g-dev \
+ zlib1g-dev
+
+# create users and directories
+RUN mkdir -p /var/lib/opensmtpd/empty \
+ && useradd _smtpd \
+ --home-dir /var/lib/opensmtpd/empty \
+ --no-create-home \
+ --shell /bin/false \
+ && useradd _smtpq \
+ --home-dir /var/lib/opensmtpd/empty \
+ --no-create-home \
+ --shell /bin/false \
+ && mkdir -p /var/spool/smtpd \
+ && mkdir -p /var/mail \
+ && mkdir -p /etc/mail \
+ && chmod 711 /var/spool/smtpd
+
+# Copy contentes of the repo inside the container
+# https://docs.docker.com/engine/reference/builder/#copy
+COPY . /opensmtpd
+
+RUN ./bootstrap \
+ && ./configure \
+ --with-gnu-ld \
+ --sysconfdir=/etc/mail \
+ --with-auth-pam \
+ && make \
+ && make install \
+ && cp etc/aliases /etc/mail/aliases
diff --git a/ci/docker/Dockerfile.ubuntu-gcc10 b/ci/docker/Dockerfile.ubuntu-gcc10
new file mode 100644
index 00000000..2ebbdf58
--- /dev/null
+++ b/ci/docker/Dockerfile.ubuntu-gcc10
@@ -0,0 +1,54 @@
+FROM ubuntu:latest
+
+# Allow container to expose ports at runtime, if necessary
+# https://docs.docker.com/engine/reference/#expose
+EXPOSE 25
+EXPOSE 465
+EXPOSE 587
+
+# creates /opensmtpd dir and makes all following commands to run in it
+# https://docs.docker.com/engine/reference/builder/#workdir
+WORKDIR /opensmtpd
+
+# install necessary packages
+RUN apt update \
+ && apt install -y --no-install-recommends \
+ autoconf \
+ automake \
+ bison \
+ build-essential \
+ libevent-dev \
+ libssl-dev \
+ libtool \
+ libpam0g-dev \
+ zlib1g-dev \
+ gcc-10
+
+# create users and directories
+RUN mkdir -p /var/lib/opensmtpd/empty \
+ && useradd _smtpd \
+ --home-dir /var/lib/opensmtpd/empty \
+ --no-create-home \
+ --shell /bin/false \
+ && useradd _smtpq \
+ --home-dir /var/lib/opensmtpd/empty \
+ --no-create-home \
+ --shell /bin/false \
+ && mkdir -p /var/spool/smtpd \
+ && mkdir -p /var/mail \
+ && mkdir -p /etc/mail \
+ && chmod 711 /var/spool/smtpd
+
+# Copy contentes of the repo inside the container
+# https://docs.docker.com/engine/reference/builder/#copy
+COPY . /opensmtpd
+
+RUN export CC=gcc-10 CXX=g++-10
+RUN ./bootstrap \
+ && ./configure \
+ --with-gnu-ld \
+ --sysconfdir=/etc/mail \
+ --with-auth-pam \
+ && make \
+ && make install \
+ && cp etc/aliases /etc/mail/aliases
diff --git a/ci/scripts/clang_scan.sh b/ci/scripts/clang_scan.sh
new file mode 100755
index 00000000..714d55a7
--- /dev/null
+++ b/ci/scripts/clang_scan.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+set -eu
+
+# Unconditionally go to the root level of the git repo.
+# If you invoke it from outside of the repo go to
+# the script location first
+cd "$(dirname "$0")"
+cd "$(git rev-parse --show-toplevel)"
+
+# Clang Scan script
+#
+# USAGE:
+# - clang must be installed
+# - make sure you have clean repository,
+# e.g. git clean -ffdx
+# - if you want to download github badge set CLANG_SCAN_BADGE_REQUIRED variable
+# - Run script from anywhere inside the repository
+# ./ci/scripts/clang_scan.sh
+# or
+# CLANG_SCAN_BADGE_REQUIRED=1 ./ci/scripts/clang_scan.sh
+#
+
+if ! type scan-build > /dev/null; then
+ echo "clang scan-build is missing"
+ exit 1
+fi
+
+# Unconditionally go to the root level of the git repo.
+# If you invoke it from outside of the repo go to
+# the script location first
+cd "$(dirname "$0")"
+# This moves us to the root of the repo
+cd "$(git rev-parse --show-toplevel)"
+
+# Get short SHA of the HEAD
+sha=$(git rev-parse --short HEAD)
+
+results_dir=${CLANG_SCAN_RESULTS_DIR:-clang-report}
+mkdir -p "$results_dir"
+
+# Build with scan-build
+./bootstrap
+./configure
+scan-build -o "$results_dir" \
+ --keep-empty \
+ --html-title="OpenSMTPD $sha" make
+
+
+set -x
+# conditionally generate badge
+if [ -z "${CLANG_SCAN_BADGE_REQUIRED:-}" ]; then
+ echo "Skipping badge generation"
+else
+ echo "Generating badge"
+ . ci/scripts/imports/badge.sh
+ cd "$results_dir"
+ cd "$( find . -type d | sort | tail -n1 )"
+ issues_nr="$( find . -name "report-*" | wc -l)"
+ download_badge "$issues_nr" "clang analysis" "$(pwd)" 30
+fi
diff --git a/ci/scripts/coverity_scan.sh b/ci/scripts/coverity_scan.sh
new file mode 100755
index 00000000..ab302767
--- /dev/null
+++ b/ci/scripts/coverity_scan.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+set -eu
+
+# Coverity Scan script
+# Steps closely follow official documentation https://scan.coverity.com/download
+#
+# USAGE: provide coverity project token as 'token' environment variable and run
+# token=abcdedf ./ci/scripts/coverity_scan.sh
+#
+# Or uncomment this line and put token here. But do not commit this to git.
+# token=""
+project_name="OpenSMTPD%2FOpenSMTPD"
+cov_analysis_url="https://scan.coverity.com/download/cxx/linux64"
+maintainer="ihor@antonovs.family"
+
+# Unconditionally go to the root level of the git repo.
+# If you invoke it from outside of the repo go to
+# the script location first
+cd "$(dirname "$0")"
+# This moves us to the root of the repo
+cd "$(git rev-parse --show-toplevel)"
+
+# Get short SHA of the HEAD
+sha=$(git rev-parse --short HEAD)
+
+# Download Coverity Build Tool if absent
+set +x
+# shellcheck disable=SC2154
+md5sum -c ./ci/COVERITY.MD5SUM || wget $cov_analysis_url \
+ --post-data "token=$token&project=$project_name" \
+ -O cov-analysis-linux64.tgz
+set -x
+
+#Check MD5
+md5sum -c ./ci/COVERITY.MD5SUM
+
+# Extract Coverty Scan Tool
+rm -rf ./cov-analysis-linux64
+mkdir -p cov-analysis-linux64
+tar xzf cov-analysis-linux64.tgz --strip 1 -C cov-analysis-linux64
+
+# export PATH=$(pwd)/cov-analysis-linux64/bin:$PATH
+
+# Build with cov-build
+./bootstrap
+./configure
+cov-analysis-linux64/bin/cov-build --dir cov-int make
+
+# Compress the rusults
+tar czvf opensmtpd.tgz cov-int
+
+
+# Submit the result to Coverity Scan
+# Some parts are shamelessly taken from:
+# https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh
+set +x
+response=$(curl \
+ --silent \
+ --write-out "\n%{http_code}\n" \
+ --form token="$token" \
+ --form email="$maintainer" \
+ --form file=@opensmtpd.tgz \
+ --form version="portable-$sha" \
+ --form description="daily scan" \
+ "https://scan.coverity.com/builds?project=$project_name")
+set -x
+
+status_code=$(echo "$response" | sed -n '$p')
+
+if [ "$status_code" != "200" ]; then
+ text=$(echo "$response" | sed '$d')
+ echo -e "Coverity Scan upload failed: $text"
+ exit 1
+fi
+
+
+
diff --git a/ci/scripts/generate_certs.sh b/ci/scripts/generate_certs.sh
new file mode 100755
index 00000000..a9249c1e
--- /dev/null
+++ b/ci/scripts/generate_certs.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Generate self-signed SSL certs
+# Usage: ./generate_certs.sh
+
+days=3560 # 10 years
+config="$(dirname "$0")/ssl.conf"
+cert="open.smtpd.cert"
+key="open.smtpd.key"
+csr="open.smtpd.csr"
+
+# Key + CSR generation:
+openssl req \
+ -new \
+ -x509 \
+ -newkey rsa:2048 \
+ -sha256 \
+ -nodes \
+ -keyout $key \
+ -out $csr \
+ -days $days \
+ -config "$config"
+
+# Certificate generation:
+openssl req \
+ -new \
+ -x509 \
+ -newkey rsa:2048 \
+ -days $days \
+ -nodes \
+ -config "$config" \
+ -keyout $key \
+ -out $cert
diff --git a/ci/scripts/imports/badge.sh b/ci/scripts/imports/badge.sh
new file mode 100644
index 00000000..d6cf0b3a
--- /dev/null
+++ b/ci/scripts/imports/badge.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# Copyright 2019 Neovim Project Contributors (https://neovim.io/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Helper functions for getting badges.
+
+# Get code quality color.
+# ${1}: Amount of bugs actually found.
+# ${2}: Maximum number of bugs above which color will be red. Defaults to 20.
+# ${3}: Maximum number of bugs above which color will be yellow. Defaults to
+# $1 / 2.
+# Output: 24-bit hexadecimal representation of the color (xxxxxx).
+get_code_quality_color() {
+ bugs=$1 ; shift # shift will fail if there is no argument
+ max_bugs=${1:-20}
+ yellow_threshold=${2:-$(( max_bugs / 2 ))}
+
+ red=255
+ green=255
+ blue=0
+
+ bugs=$(( bugs < max_bugs ? bugs : max_bugs))
+ if test $bugs -ge "$yellow_threshold" ; then
+ green=$(( 255 - 255 * (bugs - yellow_threshold) / yellow_threshold ))
+ else
+ red=$(( 255 * bugs / yellow_threshold ))
+ fi
+
+ printf "%02x%02x%02x" $red $green $blue
+}
+
+# Get code quality badge.
+# ${1}: Amount of bugs actually found.
+# ${2}: Badge text.
+# ${3}: Directory where to save badge to.
+# ${3}: Maximum number of bugs above which color will be red. Defaults to 20.
+# ${4}: Maximum number of bugs above which color will be yellow. Defaults to
+# $1 / 2.
+# Output: 24-bit hexadecimal representation of the color (xxxxxx).
+download_badge() {
+ bugs=$1 ; shift
+ badge_text="$1" ; shift
+ reports_dir="$1" ; shift
+ max_bugs=${1:-20}
+ yellow_threshold=${2:-$(( max_bugs / 2 ))}
+
+ code_quality_color="$(
+ get_code_quality_color $bugs $max_bugs $yellow_threshold)"
+ badge="${badge_text}-${bugs}-${code_quality_color}"
+
+ rm -f "$reports_dir/badge.svg"
+
+ response="$(
+ curl --tlsv1 "https://img.shields.io/badge/${badge}.svg" \
+ -o"$reports_dir/badge.svg" 2>&1)"
+
+ if ! grep -F 'xmlns="http://www.w3.org/2000/svg"' "$reports_dir/badge.svg" ; then
+ echo "Failed to download badge to $reports_dir: $response"
+ rm -f "$reports_dir/badge.svg"
+ fi
+}
diff --git a/ci/scripts/ssl.conf b/ci/scripts/ssl.conf
new file mode 100644
index 00000000..eddfb7f8
--- /dev/null
+++ b/ci/scripts/ssl.conf
@@ -0,0 +1,23 @@
+[req]
+default_bits = 2048
+prompt = no
+default_md = sha256
+x509_extensions = v3_req
+distinguished_name = dn
+
+
+# Puffy the pufferfish
+# https://en.wikipedia.org/wiki/Tetraodontidae
+[dn]
+C = AZ
+ST = Chordata
+L = Actinopterygii_Tetraodontiformes
+O = Tetraodontoidei_Tetraodontidae
+CN = Puffy
+
+[v3_req]
+subjectAltName = @alt_names
+
+[alt_names]
+DNS.1 = puffy.bsd
+DNS.2 = puffy.mail