Adguardhome/docker/ci.Dockerfile
Maksim Kazantsev fc30c3ddfc
Some checks are pending
Build and test QA artifacts / Build (push) Waiting to run
Build and test QA artifacts / TestE2E (push) Blocked by required conditions
Mirror / mirror (push) Waiting to run
Lint and test workflow (private) / TestFrontend (push) Waiting to run
Lint and test workflow (private) / LintAndTestJobDocker (push) Waiting to run
Lint and test workflow (private) / LintAndTestJobMacOS (push) Waiting to run
Lint and test workflow (private) / LintAndTestJobWindows (push) Waiting to run
Test and snapshot workflow / ESLint (push) Waiting to run
Test and snapshot workflow / TestJob (macos-latest) (push) Waiting to run
Test and snapshot workflow / TestJob (ubuntu-latest) (push) Waiting to run
Test and snapshot workflow / TestJob (windows-latest) (push) Waiting to run
Test and snapshot workflow / BuildSnapshot (push) Blocked by required conditions
ADG-12585 Upd all
2026-10-15 18:29:27 +03:00

244 lines
7 KiB
Docker

# syntax=docker/dockerfile:1
# This comment is used to simplify checking local copies of the Dockerfile.
# Bump this number every time a significant change is made to this Dockerfile.
#
# AdGuard-Project-Version: 14
# Dockerfile guidelines:
#
# 1. Make sure that Docker correctly caches layers, on a second build attempt it
# must not run lint / test second time when it's not required.
#
# 2. Use BuildKit to improve the build performance (--mount=type=cache, etc).
#
# 3. Prefer using ARG instead of ENV when appropriate, as ARG does not create a
# layer in the final image. However, be careful with what you use ARG for.
# Also, prefer to give ARGs sensible default values.
#
# 4. Use --output and the export stage if you need to get any output on the host
# machine.
#
# NOTE: Only use --output with FROM scratch.
#
# 5. Use .dockerignore to prevent unnecessary files from being sent to the
# Docker daemon, which can invalidate the cache.
#
# 6. Add a CACHE_BUSTER argument to stages to be able to rerun the stages if
# needed. Keep it in sync with the files in .github/workflows/.
ARG BASE_IMAGE=adguard/go-builder:1.27.2--1
# The dependencies stage is needed to install packages and tool dependencies.
# This is also where binaries like osslsigncode, which may be required for tests
# in some projects, must be installed.
#
# Use fake BRANCH and REVISION values to both prevent git calls and also not
# ruin the caching with ARGs.
#
# NOTE: Only ADD the files required to install the dependencies.
FROM "$BASE_IMAGE" AS dependencies
ADD Makefile go.mod go.sum /app/
ADD scripts /app/scripts
WORKDIR /app
RUN \
--mount=type=cache,id=gocache,target=/root/.cache/go-build \
--mount=type=cache,id=gopath,target=/go \
<<-'EOF'
set -e -f -o 'pipefail' -u -x
make \
BRANCH='master' \
REVISION='0000000000000000000000000000000000000000' \
VERBOSE=1 \
go-env \
go-deps \
;
EOF
# The linter stage is separated from the tester stage to make catching test
# failures easier.
#
# Use fake BRANCH and REVISION values to both prevent git calls and also not
# ruin the caching with ARGs. IGNORE_NON_REPRODUCIBLE is set to 1 to make this
# stage reproducible even when linters that query external sources fail.
#
# NOTE: go-deps is necessary to download the modules of the linter tool
# dependencies, so that the "go: downloading" messages are not treated as linter
# output by the "run_linter -e" checks in ./scripts/make/go-lint.sh. This may
# happen in CI, where builds may receive a fresh cache mount.
FROM dependencies AS linter
ADD . /app
WORKDIR /app
RUN \
--mount=type=cache,id=gocache,target=/root/.cache/go-build \
--mount=type=cache,id=gopath,target=/go \
<<-'EOF'
set -e -f -o 'pipefail' -u -x
export GOMAXPROCS=2
make \
BRANCH='master' \
IGNORE_NON_REPRODUCIBLE='1' \
REVISION='0000000000000000000000000000000000000000' \
VERBOSE=1 \
go-deps \
go-lint \
md-lint \
sh-lint \
txt-lint \
;
EOF
# The test stage. TEST_REPORTS_DIR is set to create JUnit reports for the
# tester-exporter stage; run with --build-arg TEST_REPORTS_DIR='' if you don't
# need them on your machine.
#
# Use fake BRANCH and REVISION values to both prevent git calls and also not
# ruin the caching with ARGs.
#
# To run the tests:
#
# docker build --target tester -t 'app' .
#
# Projects that have go-bench and/or go-fuzz targets should add them here as
# well.
FROM linter AS tester
ARG CACHE_BUSTER=0
ARG TEST_REPORTS_DIR=/test-reports
RUN \
--mount=type=cache,id=gocache,target=/root/.cache/go-build \
--mount=type=cache,id=gopath,target=/go \
<<-'EOF'
set -e -f -o 'pipefail' -u -x
export GOMAXPROCS=2
make \
BRANCH='master' \
REVISION='0000000000000000000000000000000000000000' \
TEST_REPORTS_DIR="$TEST_REPORTS_DIR" \
VERBOSE=1 \
go-test \
;
exit_code="$(cat "${TEST_REPORTS_DIR}/test-exit-code.txt")"
readonly exit_code
make \
BRANCH='master' \
REVISION='0000000000000000000000000000000000000000' \
VERBOSE=1 \
go-fuzz \
go-bench \
;
exit "$exit_code"
EOF
# tester-exporter exports the test result to the host machine so that it could
# parse and analyze it. This stage should only used in a CI.
#
# It the file test-report.xml, which contains test results in the JUnit format.
#
# Run the following command to export the test result:
#
# docker build \
# --output . \
# --progress plain \
# --target tester-exporter \
# .
FROM scratch AS tester-exporter
ARG CACHE_BUSTER=0
ARG TEST_REPORTS_DIR=/test-reports
COPY --from=tester "$TEST_REPORTS_DIR" "$TEST_REPORTS_DIR"
# The builder stage is used to build release artifacts. It imports GPG keys and
# runs the build-release target. Real BRANCH and REVISION must be used here.
FROM dependencies AS builder
ARG ARCH=""
ARG BRANCH=master
ARG CACHE_BUSTER=0
ARG CHANNEL=development
ARG DIST_DIR="dist"
ARG OS=""
ARG REVISION=0000000000000000000000000000000000000000
ARG SIGN=0
ARG SOURCE_DATE_EPOCH=0
ARG VERSION=""
ADD . /app
WORKDIR /app
RUN \
--mount=type=cache,id=gocache,target=/root/.cache/go-build \
--mount=type=cache,id=gopath,target=/go \
--mount=type=secret,id=GPG_KEY_PASSPHRASE,env=GPG_KEY_PASSPHRASE \
--mount=type=secret,id=GPG_SECRET_KEY,env=GPG_SECRET_KEY \
<<-'EOF'
set -e -f -o 'pipefail' -u -x
# Import GPG key if provided.
if [ "${GPG_SECRET_KEY:-}" != '' ]; then
echo "$GPG_SECRET_KEY" | awk '{ gsub(/\\n/, "\n"); print; }' | gpg --import --batch --yes
fi
make \
ARCH="${ARCH}" \
BRANCH="${BRANCH}" \
CHANNEL="${CHANNEL}" \
DIST_DIR="${DIST_DIR}" \
FRONTEND_PREBUILT=1 \
GPG_KEY_PASSPHRASE="${GPG_KEY_PASSPHRASE}" \
OS="${OS}" \
PARALLELISM=1 \
REVISION="${REVISION}" \
SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \
SIGN="${SIGN}" \
VERBOSE=2 \
VERSION="${VERSION}" \
build-release \
;
EOF
# builder-exporter exports the build artifacts to the host machine so that they
# could be published. This stage should only be used in a CI.
FROM scratch AS builder-exporter
ARG CACHE_BUSTER=0
ARG DIST_DIR="dist"
COPY --from=builder /app/${DIST_DIR} /${DIST_DIR}
# The packer stage is used to pack the built and signed artifacts into archives.
#
# Use fake BRANCH and REVISION values to both prevent git calls and also not
# ruin the caching with ARGs.
#
# ARCH, OS, and SOURCE_DATE_EPOCH are not passed to pack-release, but they are
# declared here on purpose: they define the artifacts produced by the build
# stages, so changing them must invalidate this stage's cache as well.
FROM dependencies AS packer
ARG ARCH=""
ARG BRANCH=master
ARG CACHE_BUSTER=0
ARG CHANNEL=development
ARG DIST_DIR="dist"
ARG OS=""
ARG REVISION=0000000000000000000000000000000000000000
ARG SOURCE_DATE_EPOCH=0
ARG VERSION=""
ADD . /app
WORKDIR /app
RUN <<-'EOF'
set -e -f -o 'pipefail' -u -x
make \
BRANCH="${BRANCH}" \
CHANNEL="${CHANNEL}" \
DIST_DIR="${DIST_DIR}" \
REVISION="${REVISION}" \
VERBOSE=2 \
VERSION="${VERSION}" \
pack-release \
;
EOF
# packer-exporter exports the packed artifacts to the host machine so that they
# could be published. This stage should only be used in a CI.
FROM scratch AS packer-exporter
ARG CACHE_BUSTER=0
ARG DIST_DIR="dist"
COPY --from=packer /app/${DIST_DIR} /${DIST_DIR}