Skip to content
Snippets Groups Projects
Commit 1e21ea2e authored by Gilles Filippini's avatar Gilles Filippini Committed by pini
Browse files

ci: use podman gitlab-runner for multiarch builds

The build runs in two stages:
1. Cross compilation for target architecture on native arch image
2. Installation into target architecture image

Currently it requires a third stage to workaround an issue in podman/buildah:
https://github.com/containers/buildah/issues/4742

Configuring a gitlab-runner with podman:
1. Follow this documentation:
   https://docs.gitlab.com/runner/executors/docker.html#use-podman-to-run-docker-commands
2. Install the `crun` and `qemu-user-static` packages
parent dabb2c09
No related branches found
No related tags found
1 merge request!152ci: use podman gitlab-runner for multiarch builds
......@@ -6,3 +6,4 @@ docker/Dockerfile
docker-compose.yml
arm-build/
**/target/
build/
# Runner tags:
# - podman: use 'podman' to build multiplatform images
stages:
- schedule
- labels
......@@ -40,7 +43,7 @@ check_labels:
.env:
image: paritytech/ci-linux:1.68.2-buster
tags:
- dind
- podman
fmt_and_clippy:
extends: .env
......@@ -58,95 +61,63 @@ fmt_and_clippy:
- cargo clippy -- -V
- cargo clippy --all --tests -- -D warnings
build_debug:
extends: .env
rules:
- if: $CI_COMMIT_TAG
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
changes:
- Cargo.lock
- when: never
.docker_build:
stage: build
script:
- cargo clean -p duniter
- cargo build --locked
- mkdir build
- mv target/debug/duniter build/duniter
artifacts:
paths:
- build/
expire_in: 3 day
cache:
- key:
files:
- Cargo.lock
paths:
- target/debug
policy: push
- echo podman build --layers --tag "$IMAGE_NAME:$IMAGE_TAG" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
- podman build --layers --tag "$IMAGE_NAME:$IMAGE_TAG" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
tags:
- podman
build_debug_with_cache:
extends: .env
.docker_deploy:
stage: deploy
before_script:
- podman login -u "duniterteam" -p "$DUNITERTEAM_PASSWD" docker.io
tags:
- podman
.docker_deploy_native:
extends: .docker_deploy
script:
- podman push "localhost/$IMAGE_NAME:$IMAGE_TAG" "docker://docker.io/$IMAGE_NAME:$IMAGE_TAG"
.docker_deploy_multiplatform:
extends: .docker_deploy
script:
- podman manifest rm "$MANIFEST" 2>/dev/null || true
- podman build --layers --platform linux/amd64,linux/arm64 --manifest "$MANIFEST" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
- podman manifest push --all "$MANIFEST" "docker://docker.io/$IMAGE_NAME:$IMAGE_TAG"
after_script:
- podman manifest rm "$MANIFEST"
variables:
MANIFEST: "localhost/manifest-$IMAGE_NAME:$IMAGE_TAG"
build_debug:
extends: .docker_build
rules:
- changes:
- Cargo.lock
when: never
- if: $CI_COMMIT_TAG
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
- when: never
stage: build
script:
- cargo clean -p duniter
- cargo build --locked
- mkdir build
- mv target/debug/duniter build/duniter
artifacts:
paths:
- build/
expire_in: 3 day
cache:
- key:
files:
- Cargo.lock
paths:
- target/debug
policy: pull
variables:
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
PODMAN_BUILD_OPTIONS: "--build-arg debug=1"
build_release:
extends: .env
extends: .docker_build
rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never
stage: build
script:
- cargo build --locked --release
- mkdir build
- mv target/release/duniter build/duniter
artifacts:
paths:
- build/
expire_in: 3 day
build_release_manual:
extends: .env
rules:
- if: $CI_COMMIT_TAG
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
- when: manual
stage: build
allow_failure: true
script:
- cargo build --locked --release
- mkdir build
- mv target/release/duniter build/duniter
artifacts:
paths:
- build/
expire_in: 3 day
variables:
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
PODMAN_BUILD_OPTIONS: "--platform linux/amd64"
tests_debug:
extends: .env
test_debug:
stage: tests
extends: .docker_build
rules:
- if: $CI_COMMIT_REF_NAME =~ /^wip*$/
when: manual
......@@ -154,128 +125,83 @@ tests_debug:
when: never
- if: '$CI_MERGE_REQUEST_ID || $CI_COMMIT_BRANCH == "master"'
- when: manual
stage: tests
variables:
DUNITER_BINARY_PATH: "../build/duniter"
DUNITER_END2END_TESTS_SPAWN_NODE_TIMEOUT: "20"
script:
- cargo test --workspace --exclude duniter-end2end-tests --exclude duniter-live-tests
- cargo cucumber -i account_creation*
- cargo cucumber -i certification*
- cargo cucumber -i identity_creation*
- cargo cucumber -i monetary_mass*
- cargo cucumber -i oneshot_account*
- cargo cucumber -i transfer_all*
after_script:
- cd target/debug/deps/
- rm cucumber_tests-*.d
- mv cucumber_tests* ../../../build/duniter-cucumber
artifacts:
paths:
- build/
expire_in: 3 day
IMAGE_NAME: "duniter/duniter-v2s-test"
IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
PODMAN_BUILD_OPTIONS: "--target build --build-arg debug=1 --build-arg cucumber=1"
tests_release:
extends: .env
test_release:
stage: tests
extends: .docker_build
rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never
stage: tests
variables:
DUNITER_BINARY_PATH: "../build/duniter"
DUNITER_END2END_TESTS_SPAWN_NODE_TIMEOUT: "20"
script:
- cargo test --workspace --exclude duniter-end2end-tests --exclude duniter-live-tests
- cargo cucumber -i account_creation*
- cargo cucumber -i certification*
- cargo cucumber -i identity_creation*
- cargo cucumber -i monetary_mass*
- cargo cucumber -i oneshot_account*
- cargo cucumber -i transfer_all*
after_script:
- cd target/debug/deps/
- rm cucumber_tests-*.d
- mv cucumber_tests* ../../../build/duniter-cucumber
artifacts:
paths:
- build/
expire_in: 3 day
dependencies:
- build_release
IMAGE_NAME: "duniter/duniter-v2s-test"
IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
PODMAN_BUILD_OPTIONS: "--target build --build-arg cucumber=1"
.docker-build-app-image:
deploy_docker_debug_sha:
stage: deploy
image: docker:18.06
tags:
- docker
services:
- docker:dind
before_script:
- docker info
script:
- docker pull $CI_REGISTRY_IMAGE:$IMAGE_TAG || true
- docker build --cache-from $CI_REGISTRY_IMAGE:$IMAGE_TAG --pull -t "$CI_REGISTRY_IMAGE:$IMAGE_TAG" -f $DOCKERFILE_PATH .
- docker login -u "duniterteam" -p "$DUNITERTEAM_PASSWD"
- docker tag "$CI_REGISTRY_IMAGE:$IMAGE_TAG" "duniter/duniter-v2s:$IMAGE_TAG"
- docker push "duniter/duniter-v2s:$IMAGE_TAG"
deploy_docker_test_image:
extends: .docker-build-app-image
extends: .docker_deploy_native
rules:
- if: $CI_COMMIT_REF_NAME =~ /^wip*$/
when: manual
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH == "master"'
- if: $CI_COMMIT_TAG
when: never
- when: manual
allow_failure: true
- if: $CI_COMMIT_BRANCH == "master"
variables:
DOCKERFILE_PATH: "docker/Dockerfile"
IMAGE_TAG: "test-image-$CI_COMMIT_SHORT_SHA"
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
deploy_docker_debug_sha:
extends: .docker-build-app-image
deploy_docker_release_sha:
stage: deploy
extends: .docker_deploy_native
rules:
- if: $CI_COMMIT_TAG
when: never
- if: $CI_COMMIT_BRANCH == "master"
- when: manual
variables:
DOCKERFILE_PATH: "docker/Dockerfile"
IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
after_script:
- docker login -u "duniterteam" -p "$DUNITERTEAM_PASSWD"
- docker tag "duniter/duniter-v2s:$IMAGE_TAG" "duniter/duniter-v2s:debug-latest"
- docker push "duniter/duniter-v2s:debug-latest"
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
deploy_docker_release_sha:
extends: .docker-build-app-image
deploy_docker_release_sha_multiplatform:
stage: deploy
needs: ["deploy_docker_release_sha"]
extends: .docker_deploy_multiplatform
rules:
- if: $CI_COMMIT_TAG
when: never
- when: manual
allow_failure: true
variables:
DOCKERFILE_PATH: "docker/Dockerfile"
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
dependencies:
- build_release_manual
deploy_docker_release_tag:
extends: .docker-build-app-image
stage: deploy
extends: .docker_deploy_native
rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never
variables:
DOCKERFILE_PATH: "docker/Dockerfile"
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "$CI_COMMIT_TAG"
deploy_docker_release_tag_multiplatform:
stage: deploy
needs: ["deploy_docker_release_tag"]
extends: .docker_deploy_multiplatform
rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never
script:
- !reference [.docker_deploy_multiplatform, script]
- podman manifest push --all "$MANIFEST" "docker://docker.io/$IMAGE_NAME:latest"
variables:
IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "$CI_COMMIT_TAG"
after_script:
- docker login -u "duniterteam" -p "$DUNITERTEAM_PASSWD"
- docker tag "duniter/duniter-v2s:$IMAGE_TAG" "duniter/duniter-v2s:latest"
- docker push "duniter/duniter-v2s:latest"
dependencies:
- build_release
readme_docker_release_tag:
stage: deploy_readme
needs: ["deploy_docker_release_tag"]
rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never
......@@ -283,7 +209,7 @@ readme_docker_release_tag:
name: chko/docker-pushrm
entrypoint: ["/bin/sh", "-c", "/docker-pushrm"]
variables:
DOCKER_USER: "duniterteam"
DOCKER_USER: duniterteam
DOCKER_PASS: "$DUNITERTEAM_PASSWD"
PUSHRM_SHORT: "Duniter v2 based on Substrate framework"
PUSHRM_TARGET: "docker.io/duniter/duniter-v2s"
......
# Workaround for https://github.com/containers/buildah/issues/4742
FROM debian:bullseye-slim as target
# ------------------------------------------------------------------------------
# Build Stage
# ------------------------------------------------------------------------------
# Building for Debian buster because we need the binary to be compatible
# with the image paritytech/ci-linux:production (currently based on
# debian:buster-slim) used by the gitlab CI
FROM rust:1-buster as build
# When building for a foreign arch, use cross-compilation
# https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/
FROM --platform=$BUILDPLATFORM rust:1-bullseye as build
ARG BUILDPLATFORM
ARG TARGETPLATFORM
# We need the target arch triplet in both Debian and rust flavor
RUN echo "DEBIAN_ARCH_TRIPLET='$(dpkg-architecture -A${TARGETPLATFORM#linux/} -qDEB_TARGET_MULTIARCH)'" >>/root/dynenv
RUN . /root/dynenv && \
echo "RUST_ARCH_TRIPLET='$(echo "$DEBIAN_ARCH_TRIPLET" | sed -E 's/-linux-/-unknown&/')'" >>/root/dynenv
WORKDIR /root
# Copy source tree
COPY . .
RUN test -x build/duniter || \
( \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y clang cmake protobuf-compiler \
)
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y clang cmake protobuf-compiler
# build duniter
ARG threads=1
RUN test -x build/duniter || \
( \
cargo build --release -j $threads && \
mkdir -p build && \
mv target/release/duniter build/ \
)
# Create fake duniter-cucumber if is not exist
# The goal is to avoid error later, this binary is optional
RUN test -x build/duniter-cucumber || \
( \
mkdir -p build && \
touch build/duniter-cucumber \
)
ARG debug=0
RUN if [ "$debug" = 0 ]; then \
echo "CARGO_OPTIONS=--release" >>/root/dynenv && \
echo "TARGET_FOLDER=release" >>/root/dynenv; \
else \
echo "TARGET_FOLDER=debug" >>/root/dynenv; \
fi
# Configure cross-build environment if need be
RUN set -x && \
if [ "$TARGETPLATFORM" != "$BUILDPLATFORM" ]; then \
. /root/dynenv && \
apt install -y gcc-$DEBIAN_ARCH_TRIPLET binutils-$DEBIAN_ARCH_TRIPLET && \
rustup target add "$RUST_ARCH_TRIPLET" && \
: https://github.com/rust-lang/cargo/issues/4133 && \
echo "RUSTFLAGS='-C linker=$DEBIAN_ARCH_TRIPLET-gcc'; export RUSTFLAGS" >>/root/dynenv; \
fi
# Build
RUN set -x && \
cat /root/dynenv && \
. /root/dynenv && \
cargo build --locked $CARGO_OPTIONS --target "$RUST_ARCH_TRIPLET" && \
mkdir -p build && \
mv target/$RUST_ARCH_TRIPLET/$TARGET_FOLDER/duniter build/
# Run tests if requested, expted when cross-building
ARG cucumber=0
RUN if [ "$cucumber" != 0 ] && [ "$TARGETPLATFORM" = "$BUILDPLATFORM" ]; then \
cargo test --workspace --exclude duniter-end2end-tests --exclude duniter-live-tests && \
cargo cucumber -i account_creation* && \
cargo cucumber -i certification* && \
cargo cucumber -i identity_creation* && \
cargo cucumber -i monetary_mass* && \
cargo cucumber -i oneshot_account* && \
cargo cucumber -i transfer_all* && \
cd target/debug/deps/ && \
rm cucumber_tests-*.d && \
mv cucumber_tests* ../../../build/duniter-cucumber; \
fi
# ------------------------------------------------------------------------------
# Final Stage
# ------------------------------------------------------------------------------
FROM debian:buster-slim
FROM target
LABEL maintainer="Gilles Filippini <gilles.filippini@pini.fr>"
LABEL version="0.0.0"
......@@ -54,6 +86,5 @@ ENTRYPOINT ["docker-entrypoint"]
USER duniter
# Intall
COPY --from=build /root/build/duniter /usr/local/bin/duniter
COPY --from=build /root/build/duniter-cucumber /usr/local/bin/duniter-cucumber
COPY --from=build /root/build /usr/local/bin/
COPY docker/docker-entrypoint /usr/local/bin/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment