Skip to content

Commit

Permalink
Add multi-arch building of the msgs
Browse files Browse the repository at this point in the history
  • Loading branch information
mehmetkillioglu committed Jul 12, 2024
1 parent f7349f8 commit e03747a
Show file tree
Hide file tree
Showing 5 changed files with 293 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
################################################################################
# Repo

.circleci/
.github/
.vscode/
.dockerignore
.gitignore
**Dockerfile
**.Dockerfile
Dockerfile.**
Dockerfile
bin
build_deb.sh
103 changes: 103 additions & 0 deletions .github/workflows/fognav-msgs-docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Build and Push Docker Image, upload artifact

on:
push:
pull_request:

jobs:
build-and-push:
runs-on: ubuntu-latest

outputs:
short_git_sha: ${{ steps.vars.outputs.SHORT_GIT_SHA }}
short_git_version_string: ${{ steps.vars.outputs.SHORT_GIT_VERSION_STRING }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set short git commit SHA
id: vars
run: |
calculatedSha=$(git rev-parse --short ${{ github.sha }})
calculatedGitVersionString=$(git log --date=format:%Y%m%d --pretty=~git%cd.%h -n 1)
echo "SHORT_GIT_SHA=$calculatedSha" >> $GITHUB_OUTPUT
echo "SHORT_GIT_VERSION_STRING=$calculatedGitVersionString" >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: amd64,arm64

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

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Container metadata for runtime base image
id: meta # referenced from later step
uses: docker/metadata-action@v5
with:
images: ghcr.io/tiiuae/tii-fognav-msgs
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{raw}}
type=sha
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
- name: Build and push runtime base image
uses: docker/build-push-action@v5
with:
push: true
context: .
file: ./Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
build-args: |
PACKAGE_NAME=fognav-msgs
GIT_RUN_NUMBER=${{ github.run_number }}
GIT_COMMIT_HASH=${{ github.sha }}
GIT_VERSION_STRING=${{ steps.vars.outputs.SHORT_GIT_VERSION_STRING }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# Needed because we have to create a manifest list in the next job.
provenance: mode=min

- name: Create container and copy deb packages
run: |
platforms=("amd64" "arm64")
for platform in "${platforms[@]}"; do
docker create -ti --name "fognav-msgs-build-temp-$platform" --platform=linux/$platform $(echo "${{ steps.meta.outputs.tags }}" | head -1) bash
docker cp "fognav-msgs-build-temp-$platform:/output_dir/." ./output_dir
docker rm "fognav-msgs-build-temp-$platform"
done
- name: Upload .deb packages as artifact
uses: actions/upload-artifact@v4
with:
name: deb-packages
path: ./output_dir/*.deb

jobs:
upload-to-digitalocean:
runs-on: ubuntu-latest
needs: build-and-push
# if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
steps:
- name: Download .deb package artifact
uses: actions/download-artifact@v4
with:
name: deb-packages

- name: Upload to digitalocean
run: |
echo "Placeholder"
ls -la ./deb-packages
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build/
msg/idl.cc
bin
30 changes: 30 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM ros:humble-ros-base as builder
ARG GIT_RUN_NUMBER
ARG GIT_COMMIT_HASH
ARG GIT_VERSION_STRING

RUN echo $GIT_RUN_NUMBER
RUN echo $GIT_COMMIT_HASH
RUN echo $GIT_VERSION_STRING

RUN apt-get update -y && apt-get install -y --no-install-recommends \
curl \
python3-bloom \
dh-make \
libboost-dev \
ros-${ROS_DISTRO}-geographic-msgs \
&& rm -rf /var/lib/apt/lists/*

COPY . /main_ws/src/

# this:
# 1) builds the application
# 2) packages the application as .deb in /main_ws/
WORKDIR /main_ws/src
RUN /main_ws/src/package.sh -b $GIT_RUN_NUMBER -g $GIT_COMMIT_HASH -v $GIT_VERSION_STRING

RUN mkdir -p /output_dir && cp /main_ws/*.deb /output_dir/

FROM alpine:edge
COPY --from=builder /output_dir/*.deb /output_dir/
CMD ["sh"]
143 changes: 143 additions & 0 deletions package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/bin/bash

set -eo pipefail

usage() {
echo "
Usage: $(basename "$0") [-h] [-b nbr] [-d dist]
-- Generate debian package from fog_sw module.
Params:
-h Show help text.
-b Build number. This will be tha last digit of version string (x.x.N).
-d Distribution string in debian changelog.
-g Git commit hash.
-v Git version string
-o Output dir
"
exit 0
}

check_arg() {
if [ "$(echo $1 | cut -c1)" = "-" ]; then
return 1
else
return 0
fi
}

error_arg() {
echo "$0: option requires an argument -- $1"
usage
}

# this should refer to the repo's root dir.
# this used some clever tricks before, but now using just assumption that this is invoked from repo root.
mod_dir="$(pwd)"
build_nbr=0
distr=""
version=""
git_commit_hash=""
git_version_string=""
output_dir="build_output/"

while getopts "hb:d:g:v:o:" opt
do
case $opt in
h)
usage
;;
b)
check_arg $OPTARG && build_nbr=$OPTARG || error_arg $opt
;;
d)
check_arg $OPTARG && distr=$OPTARG || error_arg $opt
;;
g)
check_arg $OPTARG && git_commit_hash=$OPTARG || error_arg $opt
;;
v)
check_arg $OPTARG && git_version_string=$OPTARG || error_arg $opt
;;
o)
check_arg $OPTARG && output_dir=$OPTARG || error_arg $opt
;;
\?)
usage
;;
esac
done

if [[ "$git_commit_hash" == "0" || -z "$git_commit_hash" ]]; then
git_commit_hash="$(git rev-parse HEAD)"
fi
if [[ "$git_version_string" == "0" || -z "$git_version_string" ]]; then
git_version_string="$(git log --date=format:%Y%m%d --pretty=~git%cd.%h -n 1)"
fi

## Remove trailing '/' mark in module dir, if exists
mod_dir=$(echo $mod_dir | sed 's/\/$//')

## Debug prints
echo
echo "[INFO] mod_dir: ${mod_dir}."
echo "[INFO] build_nbr: ${build_nbr}."
echo "[INFO] distr: ${distr}."
echo "[INFO] git_commit_hash: ${git_commit_hash}."
echo "[INFO] git_version_string: ${git_version_string}."

cd $mod_dir

## Generate package
echo "[INFO] Creating deb package..."
### ROS2 Packaging

### Create version string
version=$(grep "<version>" package.xml | sed 's/[^>]*>\([^<"]*\).*/\1/')

echo "[INFO] Version: ${version}."

if [ -e ${mod_dir}/ros2_ws ]; then
# From fog-sw repo.
source ${mod_dir}/ros2_ws/install/setup.bash
fi
if [ -e ${mod_dir}/deps_ws ]; then
source ${mod_dir}/deps_ws/install/setup.bash
fi

# Speed up builds.
# In addition to the following environmental variable,
# --parallel flag is needed in "fakeroot debian/rules binary" call.
export DEB_BUILD_OPTIONS="parallel=`nproc`"

# generates makefile at debian/rules, which is used to invoke the actual build.
bloom-generate rosdebian --os-name ubuntu --os-version jammy --ros-distro ${ROS_DISTRO} --place-template-files

sed -i "s/@(DebianInc)@(Distribution)/@(DebianInc)/" debian/changelog.em

# modify the distribution in the template and ignore warnings from sed and not stop the script.
[ ! "$distr" = "" ] && sed -i "s/@(Distribution)/${distr}/" debian/changelog.em || :

bloom-generate rosdebian --os-name ubuntu --os-version jammy --ros-distro ${ROS_DISTRO} --process-template-files -i ${build_nbr}${git_version_string}

sed -i 's/^\tdh_shlibdeps.*/& --dpkg-shlibdeps-params=--ignore-missing-info/g' debian/rules

sed -i "s/\=\([0-9]*\.[0-9]*\.[0-9]*\*\)//g" debian/control

debian/rules clean

# the actual build process magic.
# internally it calls debhelper with something like "$ dh binary --parallel -v --buildsystem=cmake --builddirectory=.obj-x86_64-linux-gnu"
# debhelper uses cmake to run the build, and after it wrap it in a .deb package.
debian/rules "binary --parallel"

mkdir -p "$output_dir"

echo "[INFO] Move debian packages."
cp ${mod_dir}/../*.deb "$output_dir"
# Some components do not produce ddeb packages.
if ls ${mod_dir}/../*.ddeb 1> /dev/null 2>&1; then
cp ${mod_dir}/../*.ddeb "$output_dir"
fi

echo "[INFO] Done."
exit 0

0 comments on commit e03747a

Please sign in to comment.