-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup
More file actions
executable file
·117 lines (102 loc) · 4.47 KB
/
Copy pathsetup
File metadata and controls
executable file
·117 lines (102 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env bash
# Selects the dev environment's stacks, rewrites the manifest, and builds
# the image. Runs on the host (not inside the container) — it's what builds
# the image, so it can't depend on anything from inside it.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# .code-server is always a submodule directly under the consuming repo's
# root (see docs/OVERVIEW.md) — REPO_ROOT is that root, one level up.
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
STACKS_DIR="$SCRIPT_DIR/stacks"
COMPOSE="$SCRIPT_DIR/core/compose-dockerfile.sh"
# Lives in the consuming repo's own root (tracked by its own history), not
# inside .code-server/: .code-server is a shared submodule pointing at this
# template, and per-project stack selection has to survive `git submodule`
# updates instead of being local, uncommittable state inside vendored code.
MANIFEST="$REPO_ROOT/.code-server.stack.json"
DOCKERFILE_OUT="$SCRIPT_DIR/Dockerfile"
IMAGE_NAME="${IMAGE_NAME:-$(basename "$REPO_ROOT")-dev}"
for bin in jq whiptail docker; do
command -v "$bin" >/dev/null 2>&1 || {
echo "setup: '$bin' must be installed on the host." >&2
exit 1
}
done
if [ ! -d "$STACKS_DIR" ] || [ -z "$(ls -A "$STACKS_DIR" 2>/dev/null)" ]; then
echo "setup: no stacks found in $STACKS_DIR." >&2
exit 1
fi
if [ -f "$MANIFEST" ]; then
CURRENT="$(cat "$MANIFEST")"
else
CURRENT='{}'
fi
# Builds the checklist from the folders in stacks/, pre-checking whatever
# is already in the current manifest.
CHECKLIST_ARGS=()
for stack_dir in "$STACKS_DIR"/*/; do
name="$(basename "$stack_dir")"
if jq -e --arg s "$name" 'has($s)' <<<"$CURRENT" >/dev/null; then
status=on
else
status=off
fi
CHECKLIST_ARGS+=("$name" "" "$status")
done
if ! SELECTED_RAW=$(whiptail --title "setup" --checklist \
"Select the monorepo's stacks (space to toggle, enter to confirm)" \
20 70 10 "${CHECKLIST_ARGS[@]}" 3>&1 1>&2 2>&3); then
echo "setup: cancelled." >&2
exit 1
fi
SELECTED_STACKS=()
if [ -n "$SELECTED_RAW" ]; then
mapfile -t SELECTED_STACKS < <(xargs -n1 <<<"$SELECTED_RAW")
fi
# Validates inter-stack dependencies: a stack may declare an optional
# requires.json (array of stack names) that must also be selected. Kept
# generic rather than special-cased, since android/java won't stay the only
# pair — fails loudly instead of silently changing the user's selection.
for name in "${SELECTED_STACKS[@]}"; do
requires_file="$STACKS_DIR/$name/requires.json"
[ -f "$requires_file" ] || continue
while IFS= read -r dep; do
if ! printf '%s\n' "${SELECTED_STACKS[@]}" | grep -qx "$dep"; then
echo "setup: stack '$name' requires '$dep' — select it too." >&2
exit 1
fi
done < <(jq -r '.[]' "$requires_file")
done
# For each selected stack, asks for the version (using the manifest's
# current version, if any, as the default) and builds the new manifest from
# scratch — unchecked stacks simply don't get included, no uninstall logic.
NEW_MANIFEST='{}'
for name in "${SELECTED_STACKS[@]}"; do
versions_file="$STACKS_DIR/$name/versions.json"
VERSION_MENU_ARGS=()
while IFS= read -r v; do
VERSION_MENU_ARGS+=("$v" "")
done < <(jq -r '.[]' "$versions_file")
CURRENT_VERSION="$(jq -r --arg s "$name" '.[$s] // empty' <<<"$CURRENT")"
DEFAULT_ARGS=()
if [ -n "$CURRENT_VERSION" ]; then
DEFAULT_ARGS=(--default-item "$CURRENT_VERSION")
fi
if ! VERSION=$(whiptail --title "setup" "${DEFAULT_ARGS[@]}" --menu \
"Version of $name" 15 50 6 "${VERSION_MENU_ARGS[@]}" 3>&1 1>&2 2>&3); then
echo "setup: cancelled." >&2
exit 1
fi
NEW_MANIFEST=$(jq --arg s "$name" --arg v "$VERSION" '. + {($s): $v}' <<<"$NEW_MANIFEST")
done
echo "$NEW_MANIFEST" | jq '.' > "$MANIFEST"
# Composes the Dockerfile: core + each selected stack (dependencies first),
# with {{VERSION}} substituted with the chosen version. Always from scratch —
# never hand-edited. The composition itself lives in core/compose-dockerfile.sh
# so CI builds stacks exactly the way this does; STACK_MANIFEST is what makes
# it use the versions just chosen above instead of its lowest-listed default.
STACK_MANIFEST="$MANIFEST" "$COMPOSE" "${SELECTED_STACKS[@]}" > "$DOCKERFILE_OUT"
echo "setup: Dockerfile generated at $DOCKERFILE_OUT"
echo "setup: building image '$IMAGE_NAME'..."
docker build -f "$DOCKERFILE_OUT" -t "$IMAGE_NAME" "$SCRIPT_DIR"
echo "setup: image '$IMAGE_NAME' ready."