Skip to content
Snippets Groups Projects
Commit 0261dca9 authored by Gilles Filippini's avatar Gilles Filippini
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 54f04b41
No related branches found
No related tags found
No related merge requests found
...@@ -6,3 +6,4 @@ docker/Dockerfile ...@@ -6,3 +6,4 @@ docker/Dockerfile
docker-compose.yml docker-compose.yml
arm-build/ arm-build/
**/target/ **/target/
build/
# Runner tags:
# - podman: use 'podman' to build multiplatform images
stages: stages:
- schedule - schedule
- labels - labels
...@@ -40,7 +43,7 @@ check_labels: ...@@ -40,7 +43,7 @@ check_labels:
.env: .env:
image: paritytech/ci-linux:1.68.2-buster image: paritytech/ci-linux:1.68.2-buster
tags: tags:
- dind - podman
fmt_and_clippy: fmt_and_clippy:
extends: .env extends: .env
...@@ -58,95 +61,63 @@ fmt_and_clippy: ...@@ -58,95 +61,63 @@ fmt_and_clippy:
- cargo clippy -- -V - cargo clippy -- -V
- cargo clippy --all --tests -- -D warnings - cargo clippy --all --tests -- -D warnings
build_debug: .docker_build:
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
stage: build stage: build
script: script:
- cargo clean -p duniter - echo podman build --layers --tag "$IMAGE_NAME:$IMAGE_TAG" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
- cargo build --locked - podman build --layers --tag "$IMAGE_NAME:$IMAGE_TAG" -f docker/Dockerfile $PODMAN_BUILD_OPTIONS .
- mkdir build tags:
- mv target/debug/duniter build/duniter - podman
artifacts:
paths:
- build/
expire_in: 3 day
cache:
- key:
files:
- Cargo.lock
paths:
- target/debug
policy: push
build_debug_with_cache: .docker_deploy:
extends: .env 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: rules:
- changes:
- Cargo.lock
when: never
- if: $CI_COMMIT_TAG - if: $CI_COMMIT_TAG
when: never when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"' - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
- when: never - when: never
stage: build variables:
script: IMAGE_NAME: "duniter/duniter-v2s"
- cargo clean -p duniter IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
- cargo build --locked PODMAN_BUILD_OPTIONS: "--build-arg debug=1"
- 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
build_release: build_release:
extends: .env extends: .docker_build
rules: rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/" - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "master"'
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
- when: manual - when: manual
stage: build variables:
allow_failure: true IMAGE_NAME: "duniter/duniter-v2s"
script: IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
- cargo build --locked --release PODMAN_BUILD_OPTIONS: "--platform linux/amd64"
- mkdir build
- mv target/release/duniter build/duniter
artifacts:
paths:
- build/
expire_in: 3 day
tests_debug: test_debug:
extends: .env stage: tests
extends: .docker_build
rules: rules:
- if: $CI_COMMIT_REF_NAME =~ /^wip*$/ - if: $CI_COMMIT_REF_NAME =~ /^wip*$/
when: manual when: manual
...@@ -154,128 +125,83 @@ tests_debug: ...@@ -154,128 +125,83 @@ tests_debug:
when: never when: never
- if: '$CI_MERGE_REQUEST_ID || $CI_COMMIT_BRANCH == "master"' - if: '$CI_MERGE_REQUEST_ID || $CI_COMMIT_BRANCH == "master"'
- when: manual - when: manual
stage: tests
variables: variables:
DUNITER_BINARY_PATH: "../build/duniter" IMAGE_NAME: "duniter/duniter-v2s-test"
DUNITER_END2END_TESTS_SPAWN_NODE_TIMEOUT: "20" IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
script: PODMAN_BUILD_OPTIONS: "--target build --build-arg debug=1 --build-arg cucumber=1"
- 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
tests_release: test_release:
extends: .env stage: tests
extends: .docker_build
rules: rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/" - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never - when: never
stage: tests
variables: variables:
DUNITER_BINARY_PATH: "../build/duniter" IMAGE_NAME: "duniter/duniter-v2s-test"
DUNITER_END2END_TESTS_SPAWN_NODE_TIMEOUT: "20" IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
script: PODMAN_BUILD_OPTIONS: "--target build --build-arg cucumber=1"
- 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
.docker-build-app-image: deploy_docker_debug_sha:
stage: deploy stage: deploy
image: docker:18.06 extends: .docker_deploy_native
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
rules: rules:
- if: $CI_COMMIT_REF_NAME =~ /^wip*$/ - if: $CI_COMMIT_TAG
when: manual
- if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH == "master"'
when: never when: never
- when: manual - if: $CI_COMMIT_BRANCH == "master"
allow_failure: true
variables: variables:
DOCKERFILE_PATH: "docker/Dockerfile" IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "test-image-$CI_COMMIT_SHORT_SHA" IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA"
deploy_docker_debug_sha: deploy_docker_release_sha:
extends: .docker-build-app-image stage: deploy
extends: .docker_deploy_native
rules: rules:
- if: $CI_COMMIT_TAG - if: $CI_COMMIT_TAG
when: never when: never
- if: $CI_COMMIT_BRANCH == "master" - when: manual
variables: variables:
DOCKERFILE_PATH: "docker/Dockerfile" IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "debug-sha-$CI_COMMIT_SHORT_SHA" IMAGE_TAG: "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"
deploy_docker_release_sha: deploy_docker_release_sha_multiplatform:
extends: .docker-build-app-image stage: deploy
needs: ["deploy_docker_release_sha"]
extends: .docker_deploy_multiplatform
rules: rules:
- if: $CI_COMMIT_TAG - if: $CI_COMMIT_TAG
when: never when: never
- when: manual - when: manual
allow_failure: true
variables: variables:
DOCKERFILE_PATH: "docker/Dockerfile" IMAGE_NAME: "duniter/duniter-v2s"
IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA" IMAGE_TAG: "sha-$CI_COMMIT_SHORT_SHA"
dependencies:
- build_release_manual
deploy_docker_release_tag: deploy_docker_release_tag:
extends: .docker-build-app-image stage: deploy
extends: .docker_deploy_native
rules: rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/" - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never - when: never
variables: 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" 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: readme_docker_release_tag:
stage: deploy_readme stage: deploy_readme
needs: ["deploy_docker_release_tag"]
rules: rules:
- if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/" - if: "$CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v*/"
- when: never - when: never
...@@ -283,7 +209,7 @@ readme_docker_release_tag: ...@@ -283,7 +209,7 @@ readme_docker_release_tag:
name: chko/docker-pushrm name: chko/docker-pushrm
entrypoint: ["/bin/sh", "-c", "/docker-pushrm"] entrypoint: ["/bin/sh", "-c", "/docker-pushrm"]
variables: variables:
DOCKER_USER: "duniterteam" DOCKER_USER: duniterteam
DOCKER_PASS: "$DUNITERTEAM_PASSWD" DOCKER_PASS: "$DUNITERTEAM_PASSWD"
PUSHRM_SHORT: "Duniter v2 based on Substrate framework" PUSHRM_SHORT: "Duniter v2 based on Substrate framework"
PUSHRM_TARGET: "docker.io/duniter/duniter-v2s" PUSHRM_TARGET: "docker.io/duniter/duniter-v2s"
......
# Workaround for https://github.com/containers/buildah/issues/4742
FROM debian:bullseye-slim as target
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Build Stage # Build Stage
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Building for Debian buster because we need the binary to be compatible # When building for a foreign arch, use cross-compilation
# with the image paritytech/ci-linux:production (currently based on # https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/
# debian:buster-slim) used by the gitlab CI FROM --platform=$BUILDPLATFORM rust:1-bullseye as build
FROM rust:1-buster 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 WORKDIR /root
# Copy source tree # Copy source tree
COPY . . COPY . .
RUN test -x build/duniter || \ RUN apt-get update && \
( \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang cmake protobuf-compiler
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y clang cmake protobuf-compiler \
)
# build duniter # build duniter
ARG threads=1 ARG debug=0
RUN test -x build/duniter || \ RUN if [ "$debug" = 0 ]; then \
( \ echo "CARGO_OPTIONS=--release" >>/root/dynenv && \
cargo build --release -j $threads && \ echo "TARGET_FOLDER=release" >>/root/dynenv; \
mkdir -p build && \ else \
mv target/release/duniter build/ \ echo "TARGET_FOLDER=debug" >>/root/dynenv; \
) fi
# Create fake duniter-cucumber if is not exist # Configure cross-build environment if need be
# The goal is to avoid error later, this binary is optional RUN set -x && \
RUN test -x build/duniter-cucumber || \ if [ "$TARGETPLATFORM" != "$BUILDPLATFORM" ]; then \
( \ . /root/dynenv && \
mkdir -p build && \ apt install -y gcc-$DEBIAN_ARCH_TRIPLET binutils-$DEBIAN_ARCH_TRIPLET && \
touch build/duniter-cucumber \ 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 # Final Stage
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
FROM debian:buster-slim FROM target
LABEL maintainer="Gilles Filippini <gilles.filippini@pini.fr>" LABEL maintainer="Gilles Filippini <gilles.filippini@pini.fr>"
LABEL version="0.0.0" LABEL version="0.0.0"
...@@ -54,6 +86,5 @@ ENTRYPOINT ["docker-entrypoint"] ...@@ -54,6 +86,5 @@ ENTRYPOINT ["docker-entrypoint"]
USER duniter USER duniter
# Intall # Intall
COPY --from=build /root/build/duniter /usr/local/bin/duniter COPY --from=build /root/build /usr/local/bin/
COPY --from=build /root/build/duniter-cucumber /usr/local/bin/duniter-cucumber
COPY docker/docker-entrypoint /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