Skip to content

Commit 7e261d1

Browse files
fix: align mirrored images with chart configuration
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
1 parent 112d357 commit 7e261d1

1 file changed

Lines changed: 110 additions & 70 deletions

File tree

Lines changed: 110 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
11
#!/usr/bin/env bash
22
# mirror_langsmith_images.sh
3-
# Pull each image, retag it, and push to a destination registry.
4-
#
5-
# Ensure that you have logged into the destination registry if credentials are required.
6-
#
7-
# Default mode: retag as <REGISTRY>/<original-repo>:<tag>
8-
# Marketplace mode (--dest-repo): retag as <REGISTRY>/<dest-repo>:<image-name>-<tag>
9-
#
10-
# Examples:
11-
# ./mirror_langsmith_images.sh --registry myregistry --version 0.10.66 --platform linux/arm64
12-
# ./mirror_langsmith_images.sh --registry myregistry --version 0.16.0 --include-sandboxes --platform linux/amd64
13-
# ./mirror_langsmith_images.sh --registry 709825985650.dkr.ecr.us-east-1.amazonaws.com \
14-
# --dest-repo langchain/langchain-repository --version 0.10.67 --platform linux/amd64 --dry-run
3+
# Mirror the images configured by the LangSmith chart to a destination registry.
154

165
set -euo pipefail
176

18-
# Default version
19-
DEFAULT_VERSION="0.13.9"
20-
DEFAULT_OPERATOR_VERSION="0.1.37"
7+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
VALUES_FILE="${SCRIPT_DIR}/../values.yaml"
9+
CHART_FILE="${SCRIPT_DIR}/../Chart.yaml"
10+
CONSOLIDATED_VERSION="0.16.21"
2111

22-
###############################################################################
23-
# CLI parsing
24-
###############################################################################
2512
REGISTRY=""
2613
VERSION=""
2714
OPERATOR_VERSION=""
@@ -32,15 +19,15 @@ INCLUDE_SANDBOXES=false
3219

3320
usage() {
3421
cat <<EOF
35-
Usage: $0 --registry <registry-prefix> [--dest-repo <repo>] [--version <version>] [--platform linux/arm64] [--include-sandboxes] [--dry-run]
36-
37-
--registry Mandatory. Destination registry (e.g. myregistry or 12345678.dkr.ecr.us-east-1.amazonaws.com)
38-
--dest-repo Single destination repo (e.g. langchain/langchain_repository). Tags become <image-name>-<version>.
39-
--version Version to use for LangSmith images (default: $DEFAULT_VERSION)
40-
--operator-version Version for langgraph-operator (default: $DEFAULT_OPERATOR_VERSION)
41-
--platform Architecture to pull (default: linux/amd64)
42-
--include-sandboxes Also mirror sandbox runtime images. Requires --platform linux/amd64.
43-
--dry-run Only print the docker commands
22+
Usage: $0 --registry <registry-prefix> [--dest-repo <repo>] [--version <version>] [--operator-version <version>] [--platform linux/arm64] [--include-sandboxes] [--dry-run]
23+
24+
--registry Mandatory. Destination registry (e.g. myregistry or 12345678.dkr.ecr.us-east-1.amazonaws.com)
25+
--dest-repo Single destination repo (e.g. langchain/langchain_repository). Tags become <image-name>-<version>.
26+
--version Override the tag for LangSmith application images
27+
--operator-version Override the tag for langgraph-operator
28+
--platform Architecture to pull (default: linux/amd64)
29+
--include-sandboxes Also mirror sandbox runtime images. Requires --platform linux/amd64.
30+
--dry-run Only print the docker commands
4431
EOF
4532
exit 1
4633
}
@@ -59,51 +46,109 @@ while [[ $# -gt 0 ]]; do
5946
done
6047

6148
[[ -z $REGISTRY ]] && { echo "ERROR: --registry is required"; usage; }
49+
[[ -f $VALUES_FILE ]] || { echo "ERROR: values.yaml not found at ${VALUES_FILE}" >&2; exit 1; }
50+
[[ -f $CHART_FILE ]] || { echo "ERROR: Chart.yaml not found at ${CHART_FILE}" >&2; exit 1; }
6251

63-
# Use provided version or default
64-
VERSION="${VERSION:-$DEFAULT_VERSION}"
65-
OPERATOR_VERSION="${OPERATOR_VERSION:-$DEFAULT_OPERATOR_VERSION}"
66-
67-
# Build images array with the specified version
68-
IMAGES=(
69-
"docker.io/langchain/langsmith-ace-backend:${VERSION}"
70-
"docker.io/langchain/langsmith-backend:${VERSION}"
71-
"docker.io/langchain/langsmith-insights-engine:${VERSION}"
72-
"docker.io/langchain/langsmith-frontend:${VERSION}"
73-
"docker.io/langchain/hosted-langserve-backend:${VERSION}"
74-
"docker.io/langchain/langgraph-operator:${OPERATOR_VERSION}"
75-
"docker.io/langchain/langsmith-go-backend:${VERSION}"
76-
"docker.io/langchain/langsmith-playground:${VERSION}"
77-
"docker.io/langchain/agent-builder-tool-server:${VERSION}"
78-
"docker.io/langchain/agent-builder-trigger-server:${VERSION}"
79-
"docker.io/langchain/agent-builder-deep-agent:${VERSION}"
80-
"docker.io/postgres:15.15"
81-
"docker.io/redis:8"
82-
"docker.io/clickhouse/clickhouse-server:25.12"
83-
)
84-
85-
if $INCLUDE_SANDBOXES; then
86-
if [[ "$PLATFORM" != "linux/amd64" ]]; then
87-
echo "ERROR: --include-sandboxes requires --platform linux/amd64 because sandbox runtime images are only published for amd64." >&2
88-
exit 1
52+
if $INCLUDE_SANDBOXES && [[ $PLATFORM != "linux/amd64" ]]; then
53+
echo "ERROR: --include-sandboxes requires --platform linux/amd64 because sandbox runtime images are only published for amd64." >&2
54+
exit 1
55+
fi
56+
57+
CHART_APP_VERSION=""
58+
while IFS= read -r line; do
59+
if [[ $line =~ ^appVersion:[[:space:]]*\"?([^\"[:space:]#]+) ]]; then
60+
CHART_APP_VERSION="${BASH_REMATCH[1]}"
61+
break
8962
fi
63+
done < "$CHART_FILE"
64+
65+
[[ -n $CHART_APP_VERSION ]] || { echo "ERROR: appVersion not found in ${CHART_FILE}" >&2; exit 1; }
66+
67+
version_before() {
68+
local version=$1
69+
local minimum=$2
70+
local version_major version_minor version_patch
71+
local minimum_major minimum_minor minimum_patch
72+
73+
[[ $version =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+) ]] || return 1
74+
version_major=${BASH_REMATCH[1]}
75+
version_minor=${BASH_REMATCH[2]}
76+
version_patch=${BASH_REMATCH[3]}
77+
[[ $minimum =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+) ]]
78+
minimum_major=${BASH_REMATCH[1]}
79+
minimum_minor=${BASH_REMATCH[2]}
80+
minimum_patch=${BASH_REMATCH[3]}
81+
82+
(( 10#$version_major < 10#$minimum_major )) && return 0
83+
(( 10#$version_major > 10#$minimum_major )) && return 1
84+
(( 10#$version_minor < 10#$minimum_minor )) && return 0
85+
(( 10#$version_minor > 10#$minimum_minor )) && return 1
86+
(( 10#$version_patch < 10#$minimum_patch ))
87+
}
88+
89+
IMAGES=()
9090

91-
IMAGES+=(
92-
"docker.io/langchain/sandbox-host:${VERSION}"
93-
)
91+
add_image() {
92+
IMAGES+=("${1}:${2}")
93+
}
94+
95+
in_images=false
96+
image_key=""
97+
current_repo=""
98+
while IFS= read -r line; do
99+
if [[ $line == "images:" ]]; then
100+
in_images=true
101+
continue
102+
fi
103+
$in_images || continue
104+
[[ $line =~ ^[^[:space:]#] ]] && break
105+
106+
if [[ $line =~ ^[[:space:]]{2}([[:alnum:]_]+Image):[[:space:]]*$ ]]; then
107+
image_key="${BASH_REMATCH[1]}"
108+
current_repo=""
109+
elif [[ -n $image_key && $line =~ ^[[:space:]]{4}repository:[[:space:]]*\"([^\"]+)\" ]]; then
110+
current_repo="${BASH_REMATCH[1]}"
111+
elif [[ -n $current_repo && $line =~ ^[[:space:]]{4}tag:[[:space:]]*\"([^\"]*)\" ]]; then
112+
tag="${BASH_REMATCH[1]}"
113+
if [[ $current_repo == "docker.io/langchain/langgraph-operator" ]]; then
114+
tag="${OPERATOR_VERSION:-$tag}"
115+
elif [[ $current_repo == docker.io/langchain/* ]]; then
116+
tag="${VERSION:-${tag:-$CHART_APP_VERSION}}"
117+
fi
118+
119+
if [[ $image_key != "sandboxHostImage" ]] || $INCLUDE_SANDBOXES; then
120+
[[ -n $tag ]] || { echo "ERROR: no tag configured for ${image_key}" >&2; exit 1; }
121+
add_image "$current_repo" "$tag"
122+
fi
123+
image_key=""
124+
current_repo=""
125+
fi
126+
done < "$VALUES_FILE"
127+
128+
APP_VERSION="${VERSION:-$CHART_APP_VERSION}"
129+
if version_before "$APP_VERSION" "$CONSOLIDATED_VERSION"; then
130+
for legacy_repository in \
131+
docker.io/langchain/langsmith-go-backend \
132+
docker.io/langchain/langsmith-playground \
133+
docker.io/langchain/hosted-langserve-backend \
134+
docker.io/langchain/agent-builder-tool-server \
135+
docker.io/langchain/agent-builder-trigger-server; do
136+
add_image "$legacy_repository" "$APP_VERSION"
137+
done
94138
fi
95139

96-
echo "Using version: ${VERSION}"
140+
[[ ${#IMAGES[@]} -gt 0 ]] || { echo "ERROR: no images found in ${VALUES_FILE}" >&2; exit 1; }
141+
142+
echo "App version: ${APP_VERSION}"
97143
echo "Registry: ${REGISTRY}"
98144
[[ -n $DEST_REPO ]] && echo "Dest repo: ${DEST_REPO}"
99145
echo "Platform: ${PLATFORM}"
100146
echo "Include sandboxes: ${INCLUDE_SANDBOXES}"
101147
echo "Dry-run: ${DRY_RUN}"
148+
echo "Images (${#IMAGES[@]}):"
149+
printf ' %s\n' "${IMAGES[@]}"
102150
echo
103151

104-
###############################################################################
105-
# Helper to echo or execute a docker command
106-
###############################################################################
107152
run_cmd() {
108153
if $DRY_RUN; then
109154
printf '[DRY-RUN] %q' "$1"
@@ -115,20 +160,15 @@ run_cmd() {
115160
fi
116161
}
117162

118-
###############################################################################
119-
# Main loop
120-
###############################################################################
121163
for SRC in "${IMAGES[@]}"; do
122-
repo_tag=${SRC#*/} # strip first path element (docker.io/…)
123-
tag=${repo_tag##*:} # version tag
164+
repo_tag=${SRC#*/}
165+
tag=${repo_tag##*:}
124166

125167
if [[ -n $DEST_REPO ]]; then
126-
# Marketplace mode: all images → single repo, tag = <image-name>-<version>
127-
image_name=${repo_tag%%:*} # e.g. langchain/langsmith-backend
128-
image_name=${image_name##*/} # e.g. langsmith-backend
168+
image_name=${repo_tag%%:*}
169+
image_name=${image_name##*/}
129170
DEST="${REGISTRY}/${DEST_REPO}:${image_name}-${tag}"
130171
else
131-
# Default mode: preserve original repo structure
132172
repo=${repo_tag%%:*}
133173
DEST="${REGISTRY}/${repo}:${tag}"
134174
fi
@@ -140,4 +180,4 @@ for SRC in "${IMAGES[@]}"; do
140180
echo
141181
done
142182

143-
echo "All images processed."
183+
echo "All images processed."

0 commit comments

Comments
 (0)