Skip to content
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
51 changes: 44 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
name: Main

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

Expand All @@ -11,38 +14,72 @@ env:
BUILD_PLATFORMS: linux/amd64,linux/arm64

jobs:
test-image:
name: Test image (${{ matrix.platform }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
goss_asset: goss-linux-amd64
- platform: linux/arm64
goss_asset: goss-linux-arm64
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up QEMU
uses: docker/setup-qemu-action@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Install dgoss
run: |
curl -fsSL https://github.com/goss-org/goss/releases/download/v0.4.9/${{ matrix.goss_asset }} -o /usr/local/bin/goss
curl -fsSL https://github.com/goss-org/goss/releases/download/v0.4.9/dgoss -o /usr/local/bin/dgoss
chmod +x /usr/local/bin/goss /usr/local/bin/dgoss

- name: Build and test image
run: make test BUILD_EXTRA_ARGS="--platform ${{ matrix.platform }}" TEST_PLATFORM=${{ matrix.platform }}

build-and-push-image:
name: Build and push image
if: startsWith(github.ref, 'refs/tags/v')
needs: test-image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v6

- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v4

- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Log in to the Container registry
uses: docker/login-action@v1
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
uses: docker/metadata-action@v6
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
Expand All @@ -53,7 +90,7 @@ jobs:
type=match,pattern=v(.*),group=1

- name: Build and push Docker image
uses: docker/build-push-action@v2
uses: docker/build-push-action@v7
with:
context: .
push: true
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Changed

- Updated the packaged `imapfilter` version to `2.8.2`, pinned the Docker base image to Alpine `3`, removed stale explicit OpenSSL and unused network-tool package installs, and relied on the `imapfilter` package to pull its runtime dependencies from Alpine `edge/testing`.
- Added a `dgoss`-based container validation suite and CI job so pull requests can require a stable image test status check before merge.
- Extended CI container validation to run against both `amd64` and `arm64`, while keeping local `make test` behavior aligned with the host architecture by default.
- Fixed local `dgoss` execution on Apple Silicon by using a Linux `arm64` `goss` binary for container-side validation instead of the macOS host binary.

## [2026-05-18]

### Added
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:latest
FROM alpine:3

ARG IMAPFILTER_CONFIG=/config
ARG IMAPFILTER_LOGS=/logs
Expand All @@ -17,8 +17,8 @@ RUN set -xe \
&& apk update \
&& apk upgrade \
&& apk add --no-cache \
libcrypto1.1 libssl1.1 moreutils bash wget curl \
&& apk add --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ \
moreutils bash \
&& apk add --no-cache --repository https://dl-cdn.alpinelinux.org/alpine/edge/testing/ \
imapfilter \
&& apk del --progress --purge \
&& rm -rf /var/cache/apk/*
Expand Down
2 changes: 1 addition & 1 deletion IMAPFILTER_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.7.5
2.8.2
31 changes: 30 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
IMAGE := imapfilter
# override with: make BUILD_CMD=podman
BUILD_CMD ?= docker
DGOSS_CMD ?= dgoss
BUILD_EXTRA_ARGS ?=
TEST_PLATFORM ?=
DGOSS_GOSS_PATH ?=
CONFIG_DIR ?=$(shell pwd)/config
LOG_DIR ?=
_DOCKER_ENV := -e IMAPFILTER_DRY_RUN=yes -e IMAPFILTER_VERBOSE=yes -e IMAPFILTER_CONFIG_DIR=/config $(DOCKER_ENV)
_EXTRA_DOCKER_PARAMS := $(EXTRA_DOCKER_PARAMS)
_DGOSS_ENV :=
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)

ifneq ($(LOG_DIR),)
_EXTRA_DOCKER_PARAMS := $(_EXTRA_DOCKER_PARAMS) -v $(LOG_DIR):/logs
_DOCKER_ENV := $(_DOCKER_ENV) -e IMAPFILTER_LOG_DIR=/logs
endif

ifneq ($(TEST_PLATFORM),)
_DGOSS_ENV := DOCKER_DEFAULT_PLATFORM=$(TEST_PLATFORM)
endif

ifeq ($(DGOSS_GOSS_PATH),)
ifeq ($(UNAME_S),Darwin)
ifeq ($(UNAME_M),arm64)
DGOSS_GOSS_PATH := /Users/sandipb/bin/goss-linux-arm64
endif
endif
endif

DOCKER_RUN_PARAMS := -ti --rm --init $(_EXTRA_DOCKER_PARAMS)

.PHONY: build
build:
$(BUILD_CMD) build -t local/${IMAGE} .
$(BUILD_CMD) build $(BUILD_EXTRA_ARGS) -t local/${IMAGE} .

.PHONY: test
test: build
@command -v $(DGOSS_CMD) >/dev/null 2>&1 || { echo "$(DGOSS_CMD) is required"; exit 1; }
@tmp_dir=$$(mktemp -d /tmp/imapfilter-goss.XXXXXX); \
trap 'rm -rf "$$tmp_dir"' EXIT; \
cp $(CURDIR)/goss.yaml "$$tmp_dir/goss.yaml"; \
printf 'imapfilter_version: %s\n' "$$(cat IMAPFILTER_VERSION)" > "$$tmp_dir/vars.yaml"; \
$(_DGOSS_ENV) GOSS_FILES_PATH="$$tmp_dir" GOSS_VARS="vars.yaml" \
GOSS_PATH="$(DGOSS_GOSS_PATH)" $(DGOSS_CMD) run --rm --entrypoint sh local/${IMAGE} -c "sleep 30"

## Update the base imapfilter version file
.PHONY: update-version
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ The `Makefile` uses Docker by default. To use Podman or another compatible comma
$ make BUILD_CMD=podman build
```

The image is built on Alpine `3` and installs `imapfilter` from Alpine `edge/testing`, because `imapfilter` is not currently available in the stable Alpine repositories.

Run the container validation suite with `dgoss`:

```shell-session
$ make test
```

This requires `dgoss` to be installed locally and validates that the container contains the expected tooling, reports the version tracked in `IMAPFILTER_VERSION`, and can invoke `imapfilter` through the packaged entrypoint.

On macOS, `dgoss` needs a Linux `goss` binary because it copies `goss` into the test container and executes it there. The `Makefile` defaults to `/Users/sandipb/bin/goss-linux-arm64` on Apple Silicon. Override `DGOSS_GOSS_PATH` if your local setup uses a different location or architecture.

By default, `make test` validates the image for the local Docker host architecture. To exercise a specific Docker platform explicitly, pass `TEST_PLATFORM`, for example:

```shell-session
$ make test BUILD_EXTRA_ARGS="--platform linux/arm64" TEST_PLATFORM=linux/arm64
```

Run the local image against a config directory:

```shell-session
Expand Down
25 changes: 25 additions & 0 deletions goss.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
command:
bash-present:
exec: bash --version
exit-status: 0

ts-present:
exec: sh -lc 'command -v ts'
exit-status: 0

imapfilter-version:
exec: "sh -lc 'test \"$(/usr/bin/imapfilter -V 2>&1 | awk '\\''{print $2}'\\'')\" = \"{{ .Vars.imapfilter_version }}\"'"
exit-status: 0

entrypoint-version:
exec: sh -lc 'IMAPFILTER_EXTRA_ARGS=-V /entrypoint.sh 2>&1'
exit-status: 0
stdout:
- "Running: /usr/bin/imapfilter -V"
- "IMAPFilter {{ .Vars.imapfilter_version }}"

file:
/entrypoint.sh:
exists: true
/usr/bin/imapfilter:
exists: true