Skip to content

Commit bfd16c4

Browse files
author
ide-coder
committed
fix: optimize CI test job with single container mode
- Replace 22+ docker run calls with single background container - Add timeout protection at job (15min) and step (1-5min) levels - Add 10s timeout per tool test command - Add cleanup step with 'if: always()' to ensure container removal - Expected: test time reduced from 5+ minutes to 30-60 seconds
1 parent e5e1c5e commit bfd16c4

1 file changed

Lines changed: 66 additions & 41 deletions

File tree

.github/workflows/build-and-push.yml

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ jobs:
150150
name: Test Image
151151
runs-on: ${{ matrix.runs-on }}
152152
needs: merge
153+
timeout-minutes: 15
153154
permissions:
154155
contents: read
155156
packages: read
@@ -180,59 +181,76 @@ jobs:
180181
- name: Pull image
181182
run: docker pull ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }}
182183

184+
- name: Start test container
185+
run: docker run -d --name test-container ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} sleep 600
186+
183187
- name: Test default user is coder
188+
timeout-minutes: 1
184189
run: |
185190
echo "Testing default user is 'coder'..."
186-
USER=$(docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} whoami)
191+
USER=$(docker exec test-container whoami)
187192
if [ "$USER" != "coder" ]; then
188193
echo "::error::Default user is '$USER', expected 'coder'"
189194
exit 1
190195
fi
191196
echo "✓ Default user is 'coder'"
192197
193198
- name: Test installed tools accessibility
199+
timeout-minutes: 5
194200
run: |
195201
echo "Testing installed tools accessibility for coder user..."
196202
197-
# Define tools to test with their version commands
198-
declare -A TOOLS=(
199-
["go"]="go version"
200-
["gopls"]="gopls version"
201-
["dlv"]="dlv version"
202-
["golangci-lint"]="golangci-lint --version"
203-
["python3"]="python3 --version"
204-
["pip"]="pip --version"
205-
["uv"]="uv --version"
206-
["conda"]="conda --version"
207-
["node"]="node --version"
208-
["npm"]="npm --version"
209-
["pnpm"]="pnpm --version"
210-
["yarn"]="yarn --version"
211-
["java"]="java -version"
212-
["mvn"]="mvn --version"
213-
["ruby"]="ruby --version"
214-
["gem"]="gem --version"
215-
["rails"]="rails --version"
216-
["git"]="git --version"
217-
["curl"]="curl --version"
218-
["wget"]="wget --version"
219-
["vim"]="vim --version | head -1"
220-
["kubectl"]="kubectl version --client"
221-
["yq"]="yq --version"
222-
)
223-
224-
FAILED_TOOLS=""
225-
226-
for tool in "${!TOOLS[@]}"; do
227-
cmd="${TOOLS[$tool]}"
228-
echo "Testing $tool..."
229-
if docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} bash -c "$cmd" > /dev/null 2>&1; then
203+
# Test function with timeout
204+
test_tool() {
205+
local tool=$1
206+
local cmd=$2
207+
local timeout_secs=10
208+
209+
if timeout $timeout_secs docker exec test-container bash -c "$cmd" > /dev/null 2>&1; then
230210
echo " ✓ $tool is accessible"
211+
return 0
231212
else
232213
echo " ✗ $tool is NOT accessible"
233-
FAILED_TOOLS="$FAILED_TOOLS $tool"
214+
return 1
234215
fi
235-
done
216+
}
217+
218+
FAILED_TOOLS=""
219+
220+
# Go tools
221+
test_tool "go" "go version" || FAILED_TOOLS="$FAILED_TOOLS go"
222+
test_tool "gopls" "gopls version" || FAILED_TOOLS="$FAILED_TOOLS gopls"
223+
test_tool "dlv" "dlv version" || FAILED_TOOLS="$FAILED_TOOLS dlv"
224+
test_tool "golangci-lint" "golangci-lint --version" || FAILED_TOOLS="$FAILED_TOOLS golangci-lint"
225+
226+
# Python tools
227+
test_tool "python3" "python3 --version" || FAILED_TOOLS="$FAILED_TOOLS python3"
228+
test_tool "pip" "pip --version" || FAILED_TOOLS="$FAILED_TOOLS pip"
229+
test_tool "uv" "uv --version" || FAILED_TOOLS="$FAILED_TOOLS uv"
230+
test_tool "conda" "conda --version" || FAILED_TOOLS="$FAILED_TOOLS conda"
231+
232+
# Node.js tools
233+
test_tool "node" "node --version" || FAILED_TOOLS="$FAILED_TOOLS node"
234+
test_tool "npm" "npm --version" || FAILED_TOOLS="$FAILED_TOOLS npm"
235+
test_tool "pnpm" "pnpm --version" || FAILED_TOOLS="$FAILED_TOOLS pnpm"
236+
test_tool "yarn" "yarn --version" || FAILED_TOOLS="$FAILED_TOOLS yarn"
237+
238+
# Java tools
239+
test_tool "java" "java -version" || FAILED_TOOLS="$FAILED_TOOLS java"
240+
test_tool "mvn" "mvn --version" || FAILED_TOOLS="$FAILED_TOOLS mvn"
241+
242+
# Ruby tools
243+
test_tool "ruby" "ruby --version" || FAILED_TOOLS="$FAILED_TOOLS ruby"
244+
test_tool "gem" "gem --version" || FAILED_TOOLS="$FAILED_TOOLS gem"
245+
test_tool "rails" "rails --version" || FAILED_TOOLS="$FAILED_TOOLS rails"
246+
247+
# System tools
248+
test_tool "git" "git --version" || FAILED_TOOLS="$FAILED_TOOLS git"
249+
test_tool "curl" "curl --version" || FAILED_TOOLS="$FAILED_TOOLS curl"
250+
test_tool "wget" "wget --version" || FAILED_TOOLS="$FAILED_TOOLS wget"
251+
test_tool "vim" "vim --version | head -1" || FAILED_TOOLS="$FAILED_TOOLS vim"
252+
test_tool "kubectl" "kubectl version --client --output=json" || FAILED_TOOLS="$FAILED_TOOLS kubectl"
253+
test_tool "yq" "yq --version" || FAILED_TOOLS="$FAILED_TOOLS yq"
236254
237255
if [ -n "$FAILED_TOOLS" ]; then
238256
echo "::error::The following tools are not accessible:$FAILED_TOOLS"
@@ -242,30 +260,37 @@ jobs:
242260
echo "✓ All tools are accessible for coder user"
243261
244262
- name: Test sudo without password
263+
timeout-minutes: 1
245264
run: |
246265
echo "Testing sudo works without password..."
247-
docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} bash -c "sudo whoami" | grep -q "root" && echo "✓ sudo works without password" || { echo "::error::sudo requires password"; exit 1; }
266+
docker exec test-container bash -c "sudo whoami" | grep -q "root" && echo "✓ sudo works without password" || { echo "::error::sudo requires password"; exit 1; }
248267
249268
- name: Test su command is blocked
269+
timeout-minutes: 1
250270
run: |
251271
echo "Testing su command is blocked..."
252-
if docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} bash -c "sudo su - root" 2>&1 | grep -q "sudo: su: command not found\|Sorry, user coder is not allowed to execute"; then
272+
if docker exec test-container bash -c "sudo su - root" 2>&1 | grep -q "sudo: su: command not found\|Sorry, user coder is not allowed to execute"; then
253273
echo "✓ su command is properly blocked"
254274
else
255275
echo "::warning::su command might not be properly blocked"
256276
fi
257277
258278
- name: Test mirror configurations
279+
timeout-minutes: 2
259280
run: |
260281
echo "Testing mirror configurations..."
261282
262283
# Test Go proxy
263-
docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} bash -c 'echo $GOPROXY | grep -q "goproxy.cn"' && echo " ✓ Go proxy configured" || echo " ⚠ Go proxy not using goproxy.cn"
284+
docker exec test-container bash -c 'echo $GOPROXY | grep -q "goproxy.cn"' && echo " ✓ Go proxy configured" || echo " ⚠ Go proxy not using goproxy.cn"
264285
265286
# Test npm registry
266-
docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} bash -c 'npm config get registry | grep -q "npmmirror"' && echo " ✓ npm registry configured" || echo " ⚠ npm registry not using npmmirror"
287+
docker exec test-container bash -c 'npm config get registry | grep -q "npmmirror"' && echo " ✓ npm registry configured" || echo " ⚠ npm registry not using npmmirror"
267288
268289
# Test gem sources
269-
docker run --rm ${{ env.IMAGE_NAME }}:${{ env.DATE_TAG }} bash -c 'gem sources | grep -q "ruby-china"' && echo " ✓ gem sources configured" || echo " ⚠ gem sources not using ruby-china"
290+
docker exec test-container bash -c 'gem sources | grep -q "ruby-china"' && echo " ✓ gem sources configured" || echo " ⚠ gem sources not using ruby-china"
270291
271292
echo "✓ Mirror configurations verified"
293+
294+
- name: Cleanup test container
295+
if: always()
296+
run: docker rm -f test-container 2>/dev/null || true

0 commit comments

Comments
 (0)