Add Dockerfiles, Makefile for testing against isolated environment

This commit adds a Dockerfile for PHP 5.6.x and PHP 7.1.x versions, allowing for tests, package
builds etc. to run against an isolated, controlled environment. PHP is currently built as a shared
library, in the future we may build as a static library to allow bundling with Go applications.

Also included is a Makefile, containing targets for common operations, such as testing, building
packages etc. Two undocumented targets related to Docker are included, `docker-image` and
`docker-test`. Moving these as documented targets is a future task.
This commit is contained in:
Alex Palaistras 2017-10-06 12:39:05 +01:00
parent 0232656e7d
commit 549d883bbc
4 changed files with 271 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.build
*.deb
*.tar.xz
*.out

60
Dockerfile.php5 Normal file
View File

@ -0,0 +1,60 @@
FROM debian:stable-slim
ENV PHP_VERSION="5.6.31"
ENV PHP_URL="https://secure.php.net/get/php-${PHP_VERSION}.tar.xz/from/this/mirror" PHP_ASC_URL="https://secure.php.net/get/php-${PHP_VERSION}.tar.xz.asc/from/this/mirror"
ENV PHP_BASE_DIR="/tmp/php"
ENV PHP_SRC_DIR="${PHP_BASE_DIR}/src"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="${PHP_CFLAGS}"
ENV GPG_KEYS="0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3"
ENV PHP_SHA256="c464af61240a9b7729fabe0314cdbdd5a000a4f0c9bd201f89f8628732fe4ae4"
ENV FETCH_DEPS="ca-certificates wget dirmngr gnupg2"
RUN set -xe && \
apt-get update && apt-get install -y --no-install-recommends ${FETCH_DEPS} && \
mkdir -p ${PHP_BASE_DIR} && cd ${PHP_BASE_DIR} && \
wget -O php.tar.xz ${PHP_URL} && \
echo "${PHP_SHA256} *php.tar.xz" | sha256sum -c - && \
wget -O php.tar.xz.asc "${PHP_ASC_URL}" && \
export GNUPGHOME="$(mktemp -d)" && \
for key in ${GPG_KEYS}; do gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; done && \
gpg --batch --verify php.tar.xz.asc php.tar.xz && \
rm -Rf ${GNUPGHOME} && \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false ${FETCH_DEPS}
ENV BUILD_DEPS="build-essential file libpcre3-dev dpkg-dev libcurl4-openssl-dev libedit-dev libsqlite3-dev libssl1.0-dev libxml2-dev zlib1g-dev"
RUN set -xe && \
apt-get update && apt-get install -y --no-install-recommends ${BUILD_DEPS} && \
export CFLAGS="${PHP_CFLAGS}" CPPFLAGS="${PHP_CPPFLAGS}" LDFLAGS="${PHP_LDFLAGS}" && \
arch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" && multiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)" && \
if [ ! -d /usr/include/curl ]; \
then ln -sT "/usr/include/$multiarch/curl" /usr/local/include/curl; \
fi && \
mkdir -p ${PHP_SRC_DIR} && cd ${PHP_SRC_DIR} && \
tar -xJf ${PHP_BASE_DIR}/php.tar.xz -C . --strip-components=1 && \
./configure \
--prefix=/usr --build="$arch" \
--with-libdir="lib/$multiarch" \
--with-pcre-regex=/usr \
--disable-cgi --disable-fpm \
--enable-embed --enable-ftp --enable-mbstring \
--with-curl --with-libedit --with-openssl --with-zlib \
&& \
make -j "$(nproc)" && \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false ${BUILD_DEPS}
ENV RUNTIME_DEPS="build-essential git golang curl libedit2 libssl1.0 libxml2"
ENV SOURCE_REPO="github.com/deuill/go-php"
RUN set -xe && \
apt-get update && apt-get install -y --no-install-recommends ${RUNTIME_DEPS} && \
cd ${PHP_SRC_DIR} && make -j "$(nproc)" PHP_SAPI=embed install-sapi install-headers && \
cd / && rm -Rf ${PHP_BASE_DIR} ${PHP_SRC_DIR}
ENTRYPOINT ["/bin/sh", "-c"]

60
Dockerfile.php7 Normal file
View File

@ -0,0 +1,60 @@
FROM debian:stable-slim
ENV PHP_VERSION="7.1.10"
ENV PHP_URL="https://secure.php.net/get/php-${PHP_VERSION}.tar.xz/from/this/mirror" PHP_ASC_URL="https://secure.php.net/get/php-${PHP_VERSION}.tar.xz.asc/from/this/mirror"
ENV PHP_BASE_DIR="/tmp/php"
ENV PHP_SRC_DIR="${PHP_BASE_DIR}/src"
ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
ENV PHP_CPPFLAGS="${PHP_CFLAGS}"
ENV GPG_KEYS="A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E"
ENV PHP_SHA256="2b8efa771a2ead0bb3ae67b530ca505b5b286adc873cca9ce97a6e1d6815c50b"
ENV FETCH_DEPS="ca-certificates wget dirmngr gnupg2"
RUN set -xe && \
apt-get update && apt-get install -y --no-install-recommends ${FETCH_DEPS} && \
mkdir -p ${PHP_BASE_DIR} && cd ${PHP_BASE_DIR} && \
wget -O php.tar.xz ${PHP_URL} && \
echo "${PHP_SHA256} *php.tar.xz" | sha256sum -c - && \
wget -O php.tar.xz.asc "${PHP_ASC_URL}" && \
export GNUPGHOME="$(mktemp -d)" && \
for key in ${GPG_KEYS}; do gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; done && \
gpg --batch --verify php.tar.xz.asc php.tar.xz && \
rm -Rf ${GNUPGHOME} && \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false ${FETCH_DEPS}
ENV BUILD_DEPS="build-essential file libpcre3-dev dpkg-dev libcurl4-openssl-dev libedit-dev libsqlite3-dev libssl-dev libxml2-dev zlib1g-dev"
RUN set -xe && \
apt-get update && apt-get install -y --no-install-recommends ${BUILD_DEPS} && \
export CFLAGS="${PHP_CFLAGS}" CPPFLAGS="${PHP_CPPFLAGS}" LDFLAGS="${PHP_LDFLAGS}" && \
arch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" && multiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)" && \
if [ ! -d /usr/include/curl ]; \
then ln -sT "/usr/include/$multiarch/curl" /usr/local/include/curl; \
fi && \
mkdir -p ${PHP_SRC_DIR} && cd ${PHP_SRC_DIR} && \
tar -xJf ${PHP_BASE_DIR}/php.tar.xz -C . --strip-components=1 && \
./configure \
--prefix=/usr --build="$arch" \
--with-libdir="lib/$multiarch" \
--with-pcre-regex=/usr \
--disable-cgi --disable-fpm \
--enable-embed --enable-ftp --enable-mbstring \
--with-curl --with-libedit --with-openssl --with-zlib \
&& \
make -j "$(nproc)" && \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false ${BUILD_DEPS}
ENV RUNTIME_DEPS="build-essential git golang curl libedit2 libssl1.1 libxml2"
ENV SOURCE_REPO="github.com/deuill/go-php"
RUN set -xe && \
apt-get update && apt-get install -y --no-install-recommends ${RUNTIME_DEPS} && \
cd ${PHP_SRC_DIR} && make -j "$(nproc)" PHP_SAPI=embed install-sapi install-headers && \
cd / && rm -Rf ${PHP_BASE_DIR} ${PHP_SRC_DIR}
ENTRYPOINT ["/bin/sh", "-c"]

147
Makefile Normal file
View File

@ -0,0 +1,147 @@
# Package options.
NAME := go-php
DESCRIPTION := PHP bindings for the Go programming language
IMPORT_PATH := github.com/deuill/$(NAME)
VERSION := $(shell git describe --tags --always --dirty="-dev")
DATE := $(shell date '+%Y-%m-%d-%H%M UTC')
# Build options.
BUILD_OPTIONS := -ldflags='-X "main.Version=$(VERSION)" -X "main.BuildTime=$(DATE)"'
PACKAGE_FORMAT := tar.xz
PHP_VERSION := php7
GO := go
# Install options.
PREFIX := /usr
# Default Makefile options.
VERBOSE :=
## Default action. Build binary distribution.
all: $(NAME)
$(NAME): .build/env/GOPATH/.ok
@echo "Building '$(NAME)'..."
$Q $(GO) install $(if $(VERBOSE),-v) $(BUILD_OPTIONS) $(IMPORT_PATH)
## Print internal package list.
list: .build/env/GOPATH/.ok
@echo $(PACKAGES)
## Install binary distribution to directory, accepts DESTDIR argument.
install: $(NAME)
@echo "Installing '$(NAME)'..."
$Q mkdir -p $(DESTDIR)/etc/$(NAME)
$Q cp -a dist/conf/. $(DESTDIR)/etc/$(NAME)
$Q install -Dm 0755 .build/env/GOPATH/bin/$(NAME) $(DESTDIR)$(PREFIX)/bin/$(NAME)
## Run test for all local packages or specified PACKAGE.
test: .build/env/GOPATH/.ok
@echo "Running tests for '$(NAME)'..."
$Q $(GO) test -race $(if $(VERBOSE),-v) -tags $(PHP_VERSION) $(if $(PACKAGE),$(PACKAGE),$(PACKAGES))
@echo "Running 'vet' for '$(NAME)'..."
$Q $(GO) vet $(if $(VERBOSE),-v) -tags $(PHP_VERSION) $(if $(PACKAGE),$(PACKAGE),$(PACKAGES))
## Create test coverage report for all local packages or specified PACKAGE.
cover: .build/env/GOPATH/.ok
@echo "Creating code coverage report for '$(NAME)'..."
$Q rm -Rf .build/tmp && mkdir -p .build/tmp
$Q for pkg in $(if $(PACKAGE),$(PACKAGE),$(PACKAGES)); do \
name=`echo $$pkg.cover | tr '/' '.'`; \
imports=`go list -f '{{ join .Imports " " }}' $$pkg`; \
coverpkg=`echo "$$imports $(PACKAGES)" | tr ' ' '\n' | sort | uniq -d | tr '\n' ','`; \
$(GO) test $(if $(VERBOSE),-v) -tags $(PHP_VERSION) -coverpkg $$coverpkg$$pkg -coverprofile .build/tmp/$$name $$pkg; done
$Q awk "$$COVERAGE_MERGE" .build/tmp/*.cover > .build/tmp/cover.merged
$Q $(GO) tool cover -html .build/tmp/cover.merged -o .build/tmp/coverage.html
@echo "Coverage report written to '.build/tmp/coverage.html'"
@echo "Total coverage for '$(NAME)':"
$Q $(GO) tool cover -func .build/tmp/cover.merged
## Package binary distribution to file, accepts PACKAGE_FORMAT argument.
package: clean $(NAME)_$(VERSION).$(PACKAGE_FORMAT)
## Remove temporary files and packages required for build.
clean:
@echo "Cleaning '$(NAME)'..."
$Q $(GO) clean
$Q rm -Rf .build
## Show usage information for this Makefile.
help:
@printf "$(BOLD)$(DESCRIPTION)$(RESET)\n\n"
@printf "This Makefile contains tasks for processing auxiliary actions, such as\n"
@printf "building binaries, packages, or running tests against the test suite.\n\n"
@printf "$(UNDERLINE)Available Tasks$(RESET)\n\n"
@awk -F \
':|##' '/^##/ {c=$$2; getline; printf "$(BLUE)%10s$(RESET) %s\n", $$1, c}' \
$(MAKEFILE_LIST)
@printf "\n"
.PHONY: $(NAME) all install package test cover clean
.DEFAULT:
$Q $(MAKE) -s -f $(MAKEFILE) help
docker-image:
$Q docker build -t "$(NAME):$(PHP_VERSION)" -f Dockerfile.$(PHP_VERSION) .
docker-test: docker-image
$Q docker run --rm \
-e GOPATH="/tmp/go" \
-v "$(CURDIR):/tmp/go/src/$(IMPORT_PATH)" $(NAME):$(PHP_VERSION) \
"make -C /tmp/go/src/$(IMPORT_PATH) test VERBOSE=$(VERBOSE) PHP_VERSION=$(PHP_VERSION)"
$(NAME)_$(VERSION).tar.xz: .build/dist/.ok
@echo "Building 'tar' package for '$(NAME)'..."
$Q fakeroot -- tar -cJf $(NAME)_$(VERSION).tar.xz -C .build/dist .
$(NAME)_$(VERSION).deb: .build/dist/.ok
@echo "Building 'deb' package for '$(NAME)'..."
$Q fakeroot -- fpm -f -s dir -t deb \
-n $(NAME) -v $(VERSION) -p $(NAME)_$(VERSION).deb \
-C .build/dist
.build/dist/.ok:
$Q mkdir -p .build/dist && touch $@
$Q $(MAKE) -s -f $(MAKEFILE) DESTDIR=".build/dist" install
.build/env/GOPATH/.ok:
$Q mkdir -p "$(dir .build/env/GOPATH/src/$(IMPORT_PATH))" && touch $@
$Q ln -s ../../../../../.. ".build/env/GOPATH/src/$(IMPORT_PATH)"
MAKEFILE := $(lastword $(MAKEFILE_LIST))
Q := $(if $(VERBOSE),,@)
PACKAGES = $(shell ( \
cd $(CURDIR)/.build/env/GOPATH/src/$(IMPORT_PATH) && \
GOPATH=$(CURDIR)/.build/env/GOPATH go list ./... | grep -v "vendor" \
))
export GOPATH := $(CURDIR)/.build/env/GOPATH
BOLD = \033[1m
UNDERLINE = \033[4m
BLUE = \033[36m
RESET = \033[0m
define COVERAGE_MERGE
/^mode: (set|count|atomic)/ {
if ($$2 == "set") mode = "set"
next
}
/^mode: / {
printf "Unknown mode '%s' in %s, line %d", $$2, FILENAME, FNR | "cat >&2"
exit 1
}
{
val = $$NF; $$NF = ""
blocks[$$0] += val
}
END {
printf "mode: %s\n", (mode == "set") ? "set" : "count"
for (b in blocks) {
printf "%s%d\n", b, (mode == "set" && blocks[b] > 1) ? 1 : blocks[b]
}
}
endef
export COVERAGE_MERGE