Repository navigation
Expand file tree
/
Copy pathsetup-build-server.sh
More file actions
executable file
·276 lines (237 loc) · 10.2 KB
/
Copy pathsetup-build-server.sh
File metadata and controls
executable file
·276 lines (237 loc) · 10.2 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#!/bin/bash
# Setup build server for DDA development
# Installs dependencies and configures the build environment
set -e
VERBOSE="${VERBOSE:-0}"
LOG_FILE="/tmp/setup-build-$(date +%s).log"
ERRORS=()
WARNINGS=()
# Helper function to run commands with logging
run_cmd() {
local cmd="$@"
if [ "$VERBOSE" = "1" ]; then
echo "[RUN] $cmd"
eval "$cmd" | tee -a "$LOG_FILE"
else
echo "[RUN] $cmd"
if ! eval "$cmd" >> "$LOG_FILE" 2>&1; then
ERRORS+=("Failed: $cmd")
return 1
fi
fi
}
# Helper to add errors
add_error() {
ERRORS+=("$1")
echo "❌ $1" | tee -a "$LOG_FILE"
}
# Helper to add warnings
add_warning() {
WARNINGS+=("$1")
echo "⚠️ $1" | tee -a "$LOG_FILE"
}
# Trap errors and show summary
trap 'show_summary' EXIT
show_summary() {
echo ""
echo "=========================================="
if [ ${#ERRORS[@]} -eq 0 ] && [ ${#WARNINGS[@]} -eq 0 ]; then
echo "✅ Build server setup complete!"
elif [ ${#ERRORS[@]} -eq 0 ]; then
echo "✅ Build server setup complete (with warnings)"
else
echo "❌ Setup completed with ERRORS"
fi
echo "=========================================="
if [ ${#ERRORS[@]} -gt 0 ]; then
echo ""
echo "ERRORS ENCOUNTERED:"
printf '%s\n' "${ERRORS[@]}"
fi
if [ ${#WARNINGS[@]} -gt 0 ]; then
echo ""
echo "WARNINGS:"
printf '%s\n' "${WARNINGS[@]}"
fi
echo ""
echo "📋 Full log: $LOG_FILE"
if [ "$VERBOSE" != "1" ] && [ ${#ERRORS[@]} -gt 0 ]; then
echo "Run with VERBOSE=1 to see detailed output:"
echo " VERBOSE=1 $0"
fi
if [ ${#ERRORS[@]} -eq 0 ] && [ ${#WARNINGS[@]} -eq 0 ]; then
echo ""
echo "Next steps:"
echo " 1. Verify Docker access: docker ps"
echo " 2. Build component: ./gdk-component-build-and-publish.sh"
fi
echo ""
if [ ${#ERRORS[@]} -gt 0 ]; then
return 1
fi
}
echo "Setting up build server..."
echo "Log file: $LOG_FILE"
echo ""
echo "▶ Detecting host Ubuntu release..."
# Detect the host release once: /etc/os-release first, with the
# lsb_release fallback the Python 3.11 block below already uses.
OS_RELEASE=$(. /etc/os-release 2>/dev/null && echo "$VERSION_ID") || OS_RELEASE=""
if [ -z "$OS_RELEASE" ] && command -v lsb_release >/dev/null 2>&1; then
OS_RELEASE=$(lsb_release -rs 2>/dev/null) || OS_RELEASE=""
fi
echo "✓ Detected Ubuntu release: ${OS_RELEASE:-unknown}"
# Ubuntu 24.04 (noble) marks the system Python as externally managed
# (PEP 668), so pip installs need --break-system-packages there. Jammy's
# pip rejects that option as unknown, so the flag is release-keyed: it
# expands to nothing on 22.04 and earlier.
PIP_BREAK_FLAG=''
if [ "$OS_RELEASE" = "24.04" ]; then
PIP_BREAK_FLAG='--break-system-packages'
fi
echo "▶ Hardening apt against IPv6-only regional mirrors..."
# Fresh EC2 instances get sources pointing at the regional mirror
# (e.g. us-east-1.ec2.ports.ubuntu.com / us-east-1.ec2.archive.ubuntu.com).
# Those hostnames can resolve to IPv6 addresses only; on a subnet without
# IPv6 egress apt-get update then hangs indefinitely and the whole
# bootstrap stalls before any tool is installed (observed on arm64/JP6
# build servers). Repoint to the canonical hosts and force IPv4 so apt
# can never block on an unreachable AAAA record.
echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99dda-force-ipv4 >/dev/null
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources; do
[ -f "$f" ] || continue
sudo sed -i -E 's@[a-z0-9-]+\.ec2\.(ports|archive)\.ubuntu\.com@\1.ubuntu.com@g' "$f"
done
echo "✓ apt sources repointed to canonical mirrors, IPv4 forced"
echo "▶ Updating package manager..."
# Every apt-get carries DPkg::Lock::Timeout=600: on a fresh instance an
# SSM patch run can hold the dpkg lock, and install/remove then wait up
# to 600 s for it instead of failing at once. (apt does not apply the
# option to the lists lock `apt-get update` takes; that failure stays
# tolerated, as before.)
run_cmd "sudo apt-get -o DPkg::Lock::Timeout=600 update" || true
echo "▶ Installing system dependencies..."
run_cmd "sudo apt-get -o DPkg::Lock::Timeout=600 install -y python3 python3-pip nodejs npm git curl snapd zip" || add_warning "Some system packages failed to install"
echo "▶ Removing old Docker packages from apt..."
run_cmd "sudo apt-get -o DPkg::Lock::Timeout=600 remove -y docker.io docker-compose" || true
echo "▶ Installing Docker via snap..."
if ! command -v docker >/dev/null 2>&1; then
run_cmd "sudo snap install docker" || add_error "Failed to install Docker via snap"
echo "✓ Docker installed via snap"
else
echo "✓ Docker already installed"
fi
echo "▶ Installing docker-compose..."
if ! command -v docker-compose >/dev/null 2>&1; then
if [ "$OS_RELEASE" = "24.04" ]; then
# Noble ships only the `docker compose` plugin; write a
# docker-compose shim delegating to it instead of the snap.
if run_cmd "printf '#!/bin/sh\nexec docker compose \"\$@\"\n' | sudo tee /usr/local/bin/docker-compose > /dev/null" \
&& run_cmd "sudo chmod +x /usr/local/bin/docker-compose"; then
echo "✓ docker-compose shim installed (delegates to the docker compose plugin)"
else
add_error "Failed to install docker-compose shim"
fi
else
run_cmd "sudo snap install docker-compose" || add_error "Failed to install docker-compose via snap"
echo "✓ docker-compose installed via snap"
fi
else
echo "✓ docker-compose already installed"
fi
echo "▶ Starting Docker daemon..."
if run_cmd "sudo systemctl start snap.docker.dockerd.service"; then
echo "✓ Docker daemon started"
else
add_error "Failed to start Docker daemon"
fi
echo "▶ Configuring Docker permissions..."
# Create docker group if it doesn't exist
if ! getent group docker > /dev/null; then
if run_cmd "sudo groupadd docker"; then
echo "✓ Created docker group"
else
add_error "Failed to create docker group"
fi
else
echo "✓ Docker group already exists"
fi
# Add user to docker group
if run_cmd "sudo usermod -aG docker $USER"; then
echo "✓ Added $USER to docker group"
else
add_error "Failed to add user to docker group"
fi
# Fix Docker socket permissions
if run_cmd "sudo chmod 666 /var/run/docker.sock"; then
echo "✓ Fixed Docker socket permissions"
else
add_warning "Could not fix Docker socket permissions"
fi
# Reload systemd daemon
if run_cmd "sudo systemctl daemon-reload"; then
echo "✓ Reloaded systemd daemon"
else
add_warning "Could not reload systemd daemon"
fi
echo "▶ Verifying Docker installation..."
if sudo docker ps > /dev/null 2>&1; then
echo "✓ Docker is accessible"
else
add_warning "Docker may not be fully accessible (may need to restart or log in again)"
fi
echo "▶ Installing Python 3.11..."
if ! command -v python3.11 >/dev/null 2>&1; then
UBUNTU_VERSION=$(lsb_release -rs)
if [ "$UBUNTU_VERSION" = "18.04" ]; then
echo " Building Python 3.11 from source (Ubuntu 18.04)..."
run_cmd "sudo apt-get -o DPkg::Lock::Timeout=600 install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget" || add_warning "Failed to install build dependencies"
if [ ! -d /tmp/Python-3.11.9 ]; then
run_cmd "cd /tmp && wget --tries=5 --waitretry=30 --retry-on-http-error=429,500,502,503 https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tgz" || add_error "Failed to download Python 3.11"
run_cmd "cd /tmp && tar -xf Python-3.11.9.tgz" || add_error "Failed to extract Python 3.11"
fi
run_cmd "cd /tmp/Python-3.11.9 && ./configure --enable-optimizations" || add_error "Failed to configure Python 3.11"
run_cmd "cd /tmp/Python-3.11.9 && make -j 8" || add_error "Failed to build Python 3.11"
run_cmd "cd /tmp/Python-3.11.9 && sudo make altinstall" || add_error "Failed to install Python 3.11"
else
echo " Installing Python 3.11 from PPA..."
run_cmd "sudo add-apt-repository ppa:deadsnakes/ppa -y" || add_warning "Failed to add deadsnakes PPA"
run_cmd "sudo apt-get -o DPkg::Lock::Timeout=600 update" || add_warning "Failed to update package manager"
run_cmd "sudo apt-get -o DPkg::Lock::Timeout=600 install -y python3.11 python3.11-venv python3.11-dev" || add_error "Failed to install Python 3.11"
fi
# Set as default
run_cmd "sudo update-alternatives --install /usr/local/bin/python3 python3 /usr/local/bin/python3.11 1" || add_warning "Failed to set Python 3.11 as default"
echo "✓ Python 3.11 installed"
else
echo "✓ Python 3.11 already installed"
fi
echo "▶ Configuring PATH..."
if ! grep -q 'export PATH="$HOME/.local/bin:$PATH"' ~/.bashrc; then
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
echo "✓ Added ~/.local/bin to PATH"
else
echo "✓ PATH already configured"
fi
export PATH="$HOME/.local/bin:$PATH"
echo "▶ Installing AWS CLI..."
if ! command -v aws >/dev/null 2>&1; then
run_cmd "sudo pip3 install $PIP_BREAK_FLAG awscli" || add_warning "Failed to install AWS CLI"
else
echo "✓ AWS CLI already installed"
fi
echo "▶ Installing botocore[crt] (required by GDK publish for credential resolution)..."
run_cmd "sudo pip3 install $PIP_BREAK_FLAG --no-compile 'botocore[crt]'" || add_warning "Failed to install botocore[crt] - 'gdk component publish' may fail to resolve credentials"
echo "▶ Installing AWS CDK (optional for build server)..."
if ! command -v cdk >/dev/null 2>&1; then
run_cmd "sudo npm install -g aws-cdk" || add_warning "Failed to install AWS CDK (optional - not required for component builds)"
else
echo "✓ AWS CDK already installed"
fi
echo "▶ Installing AWS Greengrass Development Kit (GDK)..."
if ! command -v gdk >/dev/null 2>&1; then
run_cmd "pip3 install --user $PIP_BREAK_FLAG git+https://github.com/aws-greengrass/aws-greengrass-gdk-cli.git@v1.6.2" || add_warning "Failed to install GDK CLI from GitHub"
else
echo "✓ GDK CLI already installed"
fi
echo ""
echo "✓ Build server setup complete!"