Skip to content

Commit e95ddb0

Browse files
committed
Create docker build GHA
1 parent 1bd30b0 commit e95ddb0

3 files changed

Lines changed: 136 additions & 40 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: Docker Build
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag_latest:
7+
description: 'Tag as latest'
8+
required: true
9+
type: choice
10+
options:
11+
- 'true'
12+
- 'false'
13+
default: 'false'
14+
push:
15+
# temp disable branch filter for testing
16+
#branches: [main]
17+
paths:
18+
- 'docker/**'
19+
- 'scripts/setup_*.sh'
20+
- 'src/holosoma_inference/docker/Dockerfile'
21+
- 'src/holosoma_retargeting/docker/Dockerfile'
22+
23+
permissions:
24+
contents: read
25+
26+
env:
27+
ECR_REPO: 982423663241.dkr.ecr.us-west-2.amazonaws.com
28+
29+
jobs:
30+
build:
31+
strategy:
32+
fail-fast: false # continue on one build failing
33+
matrix:
34+
include:
35+
# CPU-buildable images
36+
- environment: inference
37+
dockerfile: 'src/holosoma_inference/docker/Dockerfile'
38+
runner_prefix: 'codebuild-holosoma-cpu-build'
39+
- environment: retargeting
40+
dockerfile: 'src/holosoma_retargeting/docker/Dockerfile'
41+
runner_prefix: 'codebuild-holosoma-cpu-build'
42+
# GPU-required images (setup scripts build/link against CUDA/IsaacSim)
43+
- environment: holosoma
44+
dockerfile: 'docker/Dockerfile'
45+
runner_prefix: 'codebuild-holosoma-a10g-x1-gpu-build'
46+
- environment: isaacgym
47+
dockerfile: 'docker/isaacgym.Dockerfile'
48+
runner_prefix: 'codebuild-holosoma-a10g-x1-gpu-build'
49+
- environment: isaacsim
50+
dockerfile: 'docker/isaacsim.Dockerfile'
51+
runner_prefix: 'codebuild-holosoma-a10g-x1-gpu-build'
52+
- environment: mujoco
53+
dockerfile: 'docker/mujoco.Dockerfile'
54+
runner_prefix: 'codebuild-holosoma-a10g-x1-gpu-build'
55+
#TODO: add mujoco warp
56+
name: Build ${{ matrix.environment }} Docker Image
57+
continue-on-error: true
58+
runs-on: ${{ matrix.runner_prefix }}-${{ github.run_id }}-${{ github.run_attempt }}
59+
steps:
60+
- name: Checkout code
61+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
62+
63+
- name: Generate Image name and path
64+
id: name
65+
# image name should be `holosoma` or `holsoma-${environment}`
66+
run: |
67+
IMAGE_NAME="${{ case(matrix.environment == 'holosoma', '', 'holosoma-') }}${{ matrix.environment }}"
68+
IMAGE_PATH="${{ env.ECR_REPO }}/${IMAGE_NAME}"
69+
echo "image_path=${IMAGE_PATH}" >> "$GITHUB_OUTPUT"
70+
71+
# might be unnecessary
72+
- name: Set up Docker Buildx
73+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
74+
75+
- name: Generate image tags
76+
id: tags
77+
run: |
78+
tags="${{ steps.name.outputs.image_path }}:$(date -u +%Y_%m%d_%H%M)"
79+
if [[ "${{ inputs.tag_latest || 'false' }}" == "true" ]]; then
80+
tags="$tags,${{ steps.name.outputs.image_path }}:latest"
81+
fi
82+
echo "tags=$tags" >> "$GITHUB_OUTPUT"
83+
84+
- name: Build and push Docker image
85+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
86+
with:
87+
context: .
88+
file: "${{ matrix.dockerfile }}"
89+
push: true
90+
tags: "${{ steps.tags.outputs.tags }}"
91+
cache-from: type=registry,ref=${{ steps.name.outputs.image_path }}:buildcache
92+
cache-to: type=registry,ref=${{ steps.name.outputs.image_path }}:buildcache,mode=max
93+
94+
- name: Summary
95+
run: |
96+
echo "## Docker Build Summary" >> "$GITHUB_STEP_SUMMARY"
97+
echo "- **Tags:** \`${{ steps.tags.outputs.tags }}\`" >> "$GITHUB_STEP_SUMMARY"

docker/build_and_push.sh

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Usage:
66
# bash docker/build_and_push.sh # build & push all images
77
# bash docker/build_and_push.sh mujoco retarget # only matching images
8-
# bash docker/build_and_push.sh --no-push # build only, skip push
8+
# bash docker/build_and_push.sh --latest # also tag and push as :latest
99
# bash docker/build_and_push.sh --dry-run # print commands, do nothing
1010
#
1111
# Environment variables:
@@ -34,13 +34,13 @@ IMAGES=(
3434
)
3535

3636
# ── Parse flags ──────────────────────────────────────────────────────
37-
NO_PUSH=false
37+
TAG_LATEST=false
3838
DRY_RUN=false
3939
FILTERS=()
4040

4141
for arg in "$@"; do
4242
case "$arg" in
43-
--no-push) NO_PUSH=true ;;
43+
--latest) TAG_LATEST=true ;;
4444
--dry-run) DRY_RUN=true ;;
4545
--help|-h)
4646
sed -n '2,/^$/{ s/^# \?//; p }' "$0"
@@ -81,32 +81,30 @@ for cmd in docker; do
8181
fi
8282
done
8383

84-
if ! $NO_PUSH && ! $DRY_RUN; then
84+
if ! $DRY_RUN; then
8585
if ! command -v aws &>/dev/null; then
8686
echo "Error: aws CLI is not installed (required for push)" >&2; exit 1
8787
fi
8888
fi
8989

9090
# ── ECR authentication ──────────────────────────────────────────────
91-
if ! $NO_PUSH; then
92-
echo "==> Configuring ECR credential helper for ${ECR_REPO}"
93-
if ! $DRY_RUN; then
94-
# Ensure docker config dir exists
95-
mkdir -p ~/.docker
96-
97-
# Add ecr-login credential helper for our registry if not already present
98-
if [ ! -f ~/.docker/config.json ]; then
99-
echo '{}' > ~/.docker/config.json
100-
fi
91+
echo "==> Configuring ECR credential helper for ${ECR_REPO}"
92+
if ! $DRY_RUN; then
93+
# Ensure docker config dir exists
94+
mkdir -p ~/.docker
95+
96+
# Add ecr-login credential helper for our registry if not already present
97+
if [ ! -f ~/.docker/config.json ]; then
98+
echo '{}' > ~/.docker/config.json
99+
fi
101100

102-
if ! jq -e ".credHelpers[\"${ECR_REPO}\"]" ~/.docker/config.json &>/dev/null; then
103-
tmp=$(mktemp)
104-
jq --arg repo "$ECR_REPO" '.credHelpers[$repo] = "ecr-login"' ~/.docker/config.json > "$tmp" \
105-
&& mv "$tmp" ~/.docker/config.json
106-
echo " Added ecr-login credential helper for ${ECR_REPO}"
107-
else
108-
echo " ECR credential helper already configured"
109-
fi
101+
if ! jq -e ".credHelpers[\"${ECR_REPO}\"]" ~/.docker/config.json &>/dev/null; then
102+
tmp=$(mktemp)
103+
jq --arg repo "$ECR_REPO" '.credHelpers[$repo] = "ecr-login"' ~/.docker/config.json > "$tmp" \
104+
&& mv "$tmp" ~/.docker/config.json
105+
echo " Added ecr-login credential helper for ${ECR_REPO}"
106+
else
107+
echo " ECR credential helper already configured"
110108
fi
111109
fi
112110

@@ -125,30 +123,31 @@ for entry in "${IMAGES[@]}"; do
125123
echo ""
126124
echo "==> Building ${image_name} from ${dockerfile}"
127125

128-
# tags: date tag + latest
129-
tags=(-t "${full_image}:latest" -t "${full_image}:${TAG}")
126+
# tags: always date tag, optionally latest
127+
tags=(-t "${full_image}:${TAG}")
128+
if $TAG_LATEST; then
129+
tags+=(-t "${full_image}:latest")
130+
fi
130131

131132
if run env DOCKER_BUILDKIT=1 docker build "${tags[@]}" -f "${dockerfile}" "${ROOT_REPO}"; then
132133
echo " Built: ${image_name}"
133134

134-
if ! $NO_PUSH; then
135-
echo " Pushing ${image_name}..."
136-
push_ok=true
135+
echo " Pushing ${image_name}..."
136+
push_ok=true
137+
if ! run docker push "${full_image}:${TAG}"; then
138+
push_ok=false
139+
fi
140+
if $TAG_LATEST; then
137141
if ! run docker push "${full_image}:latest"; then
138142
push_ok=false
139143
fi
140-
if ! run docker push "${full_image}:${TAG}"; then
141-
push_ok=false
142-
fi
144+
fi
143145

144-
if $push_ok; then
145-
SUCCEEDED+=("$image_name")
146-
else
147-
echo " FAILED to push: ${image_name}" >&2
148-
FAILED+=("$image_name")
149-
fi
150-
else
146+
if $push_ok; then
151147
SUCCEEDED+=("$image_name")
148+
else
149+
echo " FAILED to push: ${image_name}" >&2
150+
FAILED+=("$image_name")
152151
fi
153152
else
154153
echo " FAILED to build: ${image_name}" >&2
@@ -196,6 +195,6 @@ if [[ ${#SUCCEEDED[@]} -eq 0 ]] && [[ ${#FAILED[@]} -eq 0 ]]; then
196195
exit 1
197196
fi
198197
echo " Tag: ${TAG}"
199-
$NO_PUSH && echo " (push skipped — --no-push)"
198+
$TAG_LATEST && echo " (also tagged as :latest)"
200199
$DRY_RUN && echo " (dry run — nothing was executed)"
201200
echo " Done."

src/holosoma_inference/holosoma_inference/utils/network.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"""Network interface auto-detection for robot communication."""
22

3-
import os
3+
from pathlib import Path
44

55
_SKIP_PREFIXES = ("lo", "wl", "docker", "br-", "veth", "virbr", "vnet", "tun", "tap")
66

77

88
def detect_robot_interface() -> str:
99
"""Return the name of the single wired NIC that is operationally UP."""
10-
for ifname in sorted(os.listdir("/sys/class/net/")):
10+
for ifname in sorted(Path("/sys/class/net/").iterdir()):
1111
if any(ifname.startswith(p) for p in _SKIP_PREFIXES):
1212
continue
1313
try:

0 commit comments

Comments
 (0)