Skip to content

Commit b68f8d6

Browse files
committed
deb workflow added
1 parent 2a61d87 commit b68f8d6

2 files changed

Lines changed: 295 additions & 0 deletions

File tree

scripts/create-deb-deploy.sh

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
#!/usr/bin/env bash
2+
3+
if [ -z "${BASH_VERSION:-}" ]; then
4+
echo "ERROR: run this script with bash"
5+
exit 1
6+
fi
7+
8+
set -euo pipefail
9+
10+
# -----------------------------------------------------------------------------
11+
# Build + package script (deployment CI on runner host)
12+
# Produces: dls2_<version>_amd64.deb at repo root.
13+
# -----------------------------------------------------------------------------
14+
15+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16+
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
17+
ART_DIR="${ROOT_DIR}/deb_pipeline_artifacts"
18+
BUILD_LOG="${ART_DIR}/build.log"
19+
20+
VERSION="${VERSION_OVERRIDE:-0.0.0-local}"
21+
DEB_CONTROL_VERSION="$(echo "${VERSION}" | sed -E 's/^[^0-9]*//')"
22+
if [[ -z "${DEB_CONTROL_VERSION}" ]]; then
23+
echo "ERROR: VERSION '${VERSION}' cannot be converted to a Debian control version"
24+
exit 1
25+
fi
26+
27+
PACKAGE_NAME="${PACKAGE_NAME:-dls2}"
28+
MAINTAINER="${DEB_MAINTAINER:-Michele Pestarino <michele.pestarino@iit.it>}"
29+
PACKAGE_DESCRIPTION="${DEB_DESCRIPTION:-DLS2 runtime package}"
30+
DEB_DEPENDS="${DEB_DEPENDS:-python3, python3-psutil, libyaml-cpp0.8, libtinyxml2-10, libgtk-3-0, libcairo2, libglib2.0-0, libboost-filesystem1.83.0, libconsole-bridge1.0, libcap2-bin}"
31+
32+
DEB_NAME="${PACKAGE_NAME}_${VERSION}_amd64.deb"
33+
DEB_PATH="${ROOT_DIR}/${DEB_NAME}"
34+
JOBS="${JOBS:-4}"
35+
LIVE_BUILD_OUTPUT="${LIVE_BUILD_OUTPUT:-0}"
36+
BUILD_VERBOSE="${BUILD_VERBOSE:-0}"
37+
CLEAN_BUILD="${CLEAN_BUILD:-0}"
38+
CMAKE_ARGS="${CMAKE_ARGS:-}"
39+
BUILD_ARGS="${BUILD_ARGS:--j${JOBS}}"
40+
41+
DEPLOY_FLAGS=(
42+
DLS_DEPLOY_gazebo_sim
43+
DLS_DEPLOY_pid_controller
44+
DLS_DEPLOY_periodic_generator
45+
DLS_DEPLOY_foot_traj_generator
46+
DLS_DEPLOY_gait_timer
47+
DLS_DEPLOY_terrain_estimator
48+
DLS_DEPLOY_trunk_controller
49+
DLS_DEPLOY_dls_keyboard
50+
DLS_DEPLOY_dls_gamepad
51+
)
52+
53+
CMAKE_DEPLOY_ARGS=()
54+
for flag in "${DEPLOY_FLAGS[@]}"; do
55+
value="${!flag:-ON}"
56+
CMAKE_DEPLOY_ARGS+=("-D${flag}=${value}")
57+
done
58+
59+
mkdir -p "${ART_DIR}"
60+
rm -f "${DEB_PATH}" "${ART_DIR}/pkg_files.txt" "${BUILD_LOG}"
61+
62+
run_pipeline() {
63+
local build_dir="${ROOT_DIR}/build"
64+
local stage_dir="${ROOT_DIR}/.deb_stage"
65+
66+
cleanup_stage() {
67+
rm -rf "${stage_dir}" "${ROOT_DIR}/stage"
68+
}
69+
trap cleanup_stage EXIT
70+
71+
if [[ "${CLEAN_BUILD}" == "1" ]]; then
72+
rm -rf "${build_dir}"
73+
fi
74+
rm -rf "${stage_dir}"
75+
76+
# shellcheck disable=SC2206
77+
local cmake_user_args=(${CMAKE_ARGS})
78+
# shellcheck disable=SC2206
79+
local build_user_args=(${BUILD_ARGS})
80+
81+
cmake -S "${ROOT_DIR}" -B "${build_dir}" -DCMAKE_BUILD_TYPE=Release \
82+
"${CMAKE_DEPLOY_ARGS[@]}" \
83+
"${cmake_user_args[@]}"
84+
85+
if [[ "${BUILD_VERBOSE}" == "1" ]]; then
86+
cmake --build "${build_dir}" -- "${build_user_args[@]}" --verbose
87+
else
88+
cmake --build "${build_dir}" -- "${build_user_args[@]}"
89+
fi
90+
91+
# Expected setcap warnings during staged install are tolerated.
92+
DESTDIR="${stage_dir}" cmake --install "${build_dir}" || true
93+
94+
# Ensure robot description assets are packaged when available.
95+
if [[ -d "${ROOT_DIR}/robots/aliengo/aliengo-description" ]]; then
96+
mkdir -p "${stage_dir}/usr/include/aliengo_description"
97+
for dir in gazebo launch meshes robcogen robots rviz urdfs yarf foxglove default_postures kinematics; do
98+
if [[ -d "${ROOT_DIR}/robots/aliengo/aliengo-description/${dir}" ]]; then
99+
cp -a "${ROOT_DIR}/robots/aliengo/aliengo-description/${dir}" "${stage_dir}/usr/include/aliengo_description/"
100+
fi
101+
done
102+
fi
103+
104+
strip "${stage_dir}/usr/bin/dls2/dynamic_legged_systems_framework" || true
105+
strip "${stage_dir}/usr/bin/dls2/child_process_launcher" || true
106+
strip "${stage_dir}/usr/lib/librobotlib.so" || true
107+
108+
copy_into_stage() {
109+
local src="$1"
110+
local dst="${stage_dir}${src}"
111+
[[ -f "${src}" ]] || return 0
112+
mkdir -p "$(dirname "${dst}")"
113+
if [[ -L "${src}" ]]; then
114+
cp -a --no-dereference "${src}" "${dst}"
115+
local resolved
116+
resolved="$(readlink -f "${src}" || true)"
117+
if [[ -n "${resolved}" && "${resolved}" != "${src}" && -f "${resolved}" ]]; then
118+
copy_into_stage "${resolved}"
119+
fi
120+
else
121+
cp -a "${src}" "${dst}"
122+
fi
123+
}
124+
125+
copy_ldd_closure() {
126+
local target="$1"
127+
[[ -e "${target}" ]] || return 0
128+
(ldd "${target}" 2>/dev/null || true) \
129+
| awk '
130+
/=> \// {print $3}
131+
/^\// {print $1}
132+
' \
133+
| sort -u \
134+
| while IFS= read -r lib; do
135+
[[ -f "${lib}" ]] || continue
136+
case "$(basename "${lib}")" in
137+
libfastdds.so*|libfastcdr.so*|libfastdds_statistics_backend.so*|libpinocchio*.so*|libcoal.so*)
138+
continue
139+
;;
140+
liburdfdom_model.so*|liburdfdom_model_state.so*|liburdfdom_sensor.so*|liburdfdom_world.so*)
141+
continue
142+
;;
143+
libgz-math*.so*|libgz-utils*.so*)
144+
continue
145+
;;
146+
esac
147+
case "${lib}" in
148+
/usr/local/lib/*)
149+
copy_into_stage "${lib}"
150+
;;
151+
*)
152+
# Avoid bundling core distro libs from /lib and /usr/lib.
153+
;;
154+
esac
155+
done
156+
}
157+
158+
for p in /usr/local/lib/liburdfdom*.so*; do
159+
for f in $p; do
160+
[[ -e "${f}" ]] || continue
161+
copy_into_stage "${f}"
162+
done
163+
done
164+
165+
if [[ -d "${stage_dir}/usr/lib/dls2" ]]; then
166+
while IFS= read -r sofile; do
167+
copy_ldd_closure "${sofile}"
168+
done < <(find "${stage_dir}/usr/lib/dls2" -type f -name '*.so*' | sort -u)
169+
fi
170+
if [[ -d "${stage_dir}/usr/bin/dls2" ]]; then
171+
while IFS= read -r exe; do
172+
copy_ldd_closure "${exe}"
173+
done < <(find "${stage_dir}/usr/bin/dls2" -type f -perm -111 | sort -u)
174+
fi
175+
if [[ -x "${stage_dir}/usr/bin/dls" ]]; then
176+
copy_ldd_closure "${stage_dir}/usr/bin/dls"
177+
fi
178+
179+
# Patch launcher script:
180+
# - prioritize packaged runtime paths
181+
# - make FastDDS cleanup best-effort
182+
if [[ -f "${stage_dir}/usr/bin/dls" ]]; then
183+
awk '
184+
NR == 1 {
185+
print
186+
print "export LD_LIBRARY_PATH=\"/opt/ros/jazzy/lib/x86_64-linux-gnu:/usr/local/lib:/usr/lib:${LD_LIBRARY_PATH:-}\""
187+
next
188+
}
189+
/fastdds shm clean/ {
190+
print "command -v fastdds >/dev/null 2>&1 && fastdds shm clean > /dev/null 2>/dev/null || true"
191+
print
192+
next
193+
}
194+
{ print }
195+
' "${stage_dir}/usr/bin/dls" > "${stage_dir}/usr/bin/dls.tmp"
196+
mv "${stage_dir}/usr/bin/dls.tmp" "${stage_dir}/usr/bin/dls"
197+
chmod +x "${stage_dir}/usr/bin/dls"
198+
fi
199+
200+
mkdir -p "${stage_dir}/etc/profile.d" "${stage_dir}/DEBIAN"
201+
cat > "${stage_dir}/etc/profile.d/dls2.sh" << "EOPROFILE"
202+
#!/bin/sh
203+
export GZ_SIM_RESOURCE_PATH="/usr/local/share/dls-gazebo/worlds"
204+
export DLS_SERVERS_PATH="/usr/include/dls2/util/messaging/servers.yaml"
205+
export DLS_SAFETY_LAYER_PATH="/usr/include/dls2/supervisor/data/safety_layer.yaml"
206+
export DLS_SCHEDULER_PATH="/usr/include/dls2/schedulers"
207+
EOPROFILE
208+
chmod +x "${stage_dir}/etc/profile.d/dls2.sh"
209+
210+
cat > "${stage_dir}/DEBIAN/control" << EOCONTROL
211+
Package: ${PACKAGE_NAME}
212+
Version: ${DEB_CONTROL_VERSION}
213+
Section: base
214+
Priority: optional
215+
Architecture: amd64
216+
Maintainer: ${MAINTAINER}
217+
Depends: ${DEB_DEPENDS}
218+
Description: ${PACKAGE_DESCRIPTION}
219+
EOCONTROL
220+
221+
cat > "${stage_dir}/DEBIAN/postinst" << 'EOPOSTINST'
222+
#!/bin/sh
223+
set -e
224+
225+
if command -v setcap >/dev/null 2>&1; then
226+
setcap cap_sys_nice=eip /usr/bin/dls2/dynamic_legged_systems_framework || true
227+
setcap cap_sys_nice=eip /usr/bin/dls2/child_process_launcher || true
228+
fi
229+
230+
if command -v ldconfig >/dev/null 2>&1; then
231+
ldconfig || true
232+
fi
233+
234+
exit 0
235+
EOPOSTINST
236+
chmod 0755 "${stage_dir}/DEBIAN/postinst"
237+
238+
dpkg-deb --build "${stage_dir}" "${DEB_NAME}"
239+
240+
dpkg-deb -c "${DEB_NAME}" \
241+
| awk '
242+
$1 !~ /^d/ {
243+
for (i = 1; i <= NF; i++) {
244+
if ($i ~ /^\.\//) {
245+
print $i
246+
break
247+
}
248+
}
249+
}
250+
' \
251+
| sed -E 's#^\./#/#; s#/$##; s#//+#/#g' \
252+
| sort -u > "${ART_DIR}/pkg_files.txt"
253+
}
254+
255+
echo "[build] building and packaging on host in ${ROOT_DIR}"
256+
if [[ "${LIVE_BUILD_OUTPUT}" == "1" ]]; then
257+
if ! run_pipeline 2>&1 | tee "${BUILD_LOG}"; then
258+
echo "ERROR: build/package failed. See ${BUILD_LOG}"
259+
tail -n 120 "${BUILD_LOG}" || true
260+
exit 1
261+
fi
262+
else
263+
if ! run_pipeline > "${BUILD_LOG}" 2>&1; then
264+
echo "ERROR: build/package failed. See ${BUILD_LOG}"
265+
tail -n 120 "${BUILD_LOG}" || true
266+
exit 1
267+
fi
268+
fi
269+
270+
if [[ ! -f "${DEB_PATH}" ]]; then
271+
echo "ERROR: .deb not created at ${DEB_PATH}"
272+
echo "See ${BUILD_LOG}"
273+
tail -n 120 "${BUILD_LOG}" || true
274+
exit 1
275+
fi
276+
277+
echo "[build] OK: ${DEB_PATH}"
278+
echo "${DEB_PATH}"

workflows/create-release-deb.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Create Release and .deb Files Project
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
- 'v*.*.*-rc*'
8+
9+
env:
10+
GNUTLS_CPUID_OVERRIDE: 0x1
11+
12+
jobs:
13+
create-release-ci-cd:
14+
uses: iit-DLSLab/cicd_tools/.github/workflows/create-release-deb.yml@main
15+
with:
16+
package-name: "dls2"
17+
deb-script-path: "scripts/create-deb-deploy.sh"

0 commit comments

Comments
 (0)