Skip to content

Commit 354b831

Browse files
committed
ood test
1 parent ccaf51b commit 354b831

8 files changed

Lines changed: 312 additions & 24 deletions

File tree

.github/workflows/runner.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ on:
3939
required: false
4040
type: string
4141
debug:
42-
description: "Enable debug output (set -x) in runner setup script"
42+
description: "Debug mode: false=off, true/trace=set -x only, number=set -x + sleep N minutes before shutdown"
4343
required: false
44-
type: boolean
44+
type: string
4545
default: false
4646
ec2_home_dir:
4747
description: "Home directory on the AWS instance (falls back to vars.EC2_HOME_DIR, then auto-detection)"
@@ -68,7 +68,7 @@ on:
6868
required: false
6969
type: string
7070
ec2_root_device_size:
71-
description: "Root device size in GB (0 = use AMI default)"
71+
description: "Root disk size in GB (0=AMI default, +N=AMI+N GB for testing, e.g. +2)"
7272
required: false
7373
type: string
7474
default: "0"
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: Test Disk Full
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
disk_size:
7+
description: 'Root disk size in GB (0=AMI default, +N=AMI+N GB, e.g. +2 for AMI+2GB)'
8+
required: false
9+
type: string
10+
default: '+2' # 2GB more than the AMI size
11+
fill_strategy:
12+
description: 'How to fill disk: gradual, immediate, or during-tests'
13+
required: false
14+
type: choice
15+
options:
16+
- gradual
17+
- immediate
18+
- during-tests
19+
default: gradual
20+
debug:
21+
description: 'Debug mode: false=off, true/trace=trace only, number=trace+sleep N minutes'
22+
required: false
23+
type: string
24+
default: 'true'
25+
instance_type:
26+
description: 'Instance type'
27+
required: false
28+
type: string
29+
default: 't3.medium'
30+
31+
permissions:
32+
id-token: write
33+
contents: read
34+
35+
jobs:
36+
launch:
37+
name: Launch runner
38+
uses: ./.github/workflows/runner.yml
39+
secrets:
40+
GH_SA_TOKEN: ${{ secrets.GH_SA_TOKEN }}
41+
with:
42+
ec2_image_id: ami-0ca5a2f40c2601df6 # Ubuntu 24.04 x86_64 in us-east-1
43+
ec2_instance_type: ${{ inputs.instance_type }}
44+
ec2_root_device_size: ${{ inputs.disk_size }}
45+
debug: ${{ inputs.debug }}
46+
max_instance_lifetime: "15" # 30 minutes max
47+
48+
test-disk-full:
49+
name: Fill disk (${{ inputs.fill_strategy }})
50+
needs: launch
51+
runs-on: ${{ needs.launch.outputs.id }}
52+
53+
steps:
54+
- name: Check initial disk usage
55+
run: |
56+
echo "=== Initial disk usage ==="
57+
df -h /
58+
echo ""
59+
echo "=== Largest directories ==="
60+
du -sh /* 2>/dev/null | sort -hr | head -10 || true
61+
62+
- name: Fill disk immediately
63+
if: inputs.fill_strategy == 'immediate'
64+
run: |
65+
echo "=== Filling disk immediately ==="
66+
# Create a large file that leaves only ~100MB free
67+
AVAILABLE=$(df / | awk 'NR==2 {print int($4/1024)-100}')
68+
if [ $AVAILABLE -gt 0 ]; then
69+
echo "Creating ${AVAILABLE}MB file to fill disk..."
70+
dd if=/dev/zero of=/tmp/disk_filler bs=1M count=$AVAILABLE 2>/dev/null || true
71+
fi
72+
echo "=== Disk usage after fill ==="
73+
df -h /
74+
75+
- name: Fill disk gradually
76+
if: inputs.fill_strategy == 'gradual'
77+
run: |
78+
echo "=== Filling disk gradually ==="
79+
COUNTER=0
80+
while true; do
81+
AVAILABLE=$(df / | awk 'NR==2 {print int($4/1024)}')
82+
if [ $AVAILABLE -lt 500 ]; then
83+
echo "Disk nearly full (${AVAILABLE}MB remaining), creating final files..."
84+
# Fill remaining space with smaller files
85+
for i in {1..10}; do
86+
dd if=/dev/zero of=/tmp/gradual_fill_${COUNTER}_${i} bs=1M count=50 2>/dev/null || break
87+
done
88+
break
89+
fi
90+
echo "Creating 500MB file (${AVAILABLE}MB currently available)..."
91+
dd if=/dev/zero of=/tmp/gradual_fill_${COUNTER} bs=1M count=500 2>/dev/null || break
92+
COUNTER=$((COUNTER + 1))
93+
df -h /
94+
sleep 2
95+
done
96+
echo "=== Final disk usage ==="
97+
df -h /
98+
99+
- name: Setup Python project for test
100+
if: inputs.fill_strategy == 'during-tests'
101+
run: |
102+
echo "=== Setting up Python project that will fill disk during tests ==="
103+
cat > setup.py << 'EOF'
104+
from setuptools import setup, find_packages
105+
106+
setup(
107+
name="disk-filler-test",
108+
version="0.1.0",
109+
packages=find_packages(),
110+
python_requires=">=3.8",
111+
install_requires=[
112+
"pytest>=7.0.0",
113+
"numpy>=1.20.0", # Large package
114+
"pandas>=1.3.0", # Large package
115+
"scipy>=1.7.0", # Large package
116+
"matplotlib>=3.4.0", # Large package
117+
"scikit-learn>=1.0.0", # Large package
118+
"torch>=2.0.0", # Very large package
119+
"transformers>=4.30.0", # Very large package
120+
],
121+
)
122+
EOF
123+
124+
mkdir -p tests
125+
cat > tests/test_disk_filler.py << 'EOF'
126+
import os
127+
import tempfile
128+
import pytest
129+
130+
def test_create_large_arrays():
131+
"""Create large arrays to consume memory and disk (via swap/tmp)"""
132+
import numpy as np
133+
arrays = []
134+
for i in range(10):
135+
# Create 100MB arrays
136+
arr = np.random.random((1024, 1024, 100))
137+
arrays.append(arr)
138+
# Also write to temp file
139+
with tempfile.NamedTemporaryFile(delete=False, dir='/tmp') as f:
140+
np.save(f, arr)
141+
print(f"Created array {i+1}/10")
142+
143+
def test_generate_files():
144+
"""Generate many temporary files"""
145+
for i in range(100):
146+
with tempfile.NamedTemporaryFile(delete=False, dir='/tmp',
147+
prefix=f'test_file_{i}_') as f:
148+
# Write 10MB to each file
149+
f.write(os.urandom(10 * 1024 * 1024))
150+
if i % 10 == 0:
151+
print(f"Generated {i+1}/100 files")
152+
153+
def test_disk_space_check():
154+
"""Check if we're out of disk space"""
155+
import shutil
156+
usage = shutil.disk_usage('/')
157+
percent_used = (usage.used / usage.total) * 100
158+
print(f"Disk usage: {percent_used:.1f}%")
159+
print(f"Free space: {usage.free / (1024**3):.2f} GB")
160+
# This test "passes" even when disk is full to see behavior
161+
assert percent_used > 0
162+
EOF
163+
164+
echo "=== Installing packages (this will consume disk space) ==="
165+
pip install -e . || true
166+
167+
echo "=== Running tests that fill disk ==="
168+
pytest tests/ -v || true
169+
170+
echo "=== Final disk usage ==="
171+
df -h /
172+
173+
- name: Try to write when disk is full
174+
if: always()
175+
run: |
176+
echo "=== Testing write operations with full disk ==="
177+
# Try various write operations to see what fails
178+
echo "Test" > /tmp/test_write.txt 2>&1 || echo "Failed to write to /tmp"
179+
echo "Test" > ~/test_write.txt 2>&1 || echo "Failed to write to home"
180+
touch /tmp/test_touch 2>&1 || echo "Failed to touch file"
181+
mkdir /tmp/test_mkdir 2>&1 || echo "Failed to create directory"
182+
183+
# Check if we can still run commands
184+
echo "=== Can we still run basic commands? ==="
185+
date || echo "date command failed"
186+
pwd || echo "pwd command failed"
187+
whoami || echo "whoami command failed"
188+
189+
- name: Monitor termination behavior
190+
if: always()
191+
run: |
192+
echo "=== Monitoring termination behavior ==="
193+
echo "This job will complete soon. Watch the runner logs to see if:"
194+
echo "1. The termination check detects disk full state"
195+
echo "2. The instance can successfully shut down"
196+
echo "3. The robust shutdown methods are triggered"
197+
echo ""
198+
echo "Current disk usage:"
199+
df -h /
200+
echo ""
201+
echo "Checking runner processes:"
202+
ps aux | grep -E '[R]unner|[c]heck-runner-termination' || true
203+
echo ""
204+
echo "Last entries in termination check log:"
205+
tail -20 /tmp/termination-check.log 2>/dev/null || echo "No termination check log found"

action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ inputs:
2121
description: "CloudWatch Logs group name for streaming runner logs (leave empty to disable)"
2222
required: false
2323
debug:
24-
description: "Enable debug output (set -x) in runner setup script"
24+
description: "Debug mode: false=off, true/trace=set -x only, number=set -x + sleep N minutes before shutdown"
2525
required: false
2626
ec2_home_dir:
2727
description: "Home directory on the AWS instance (falls back to vars.EC2_HOME_DIR, then auto-detection)"
@@ -39,7 +39,7 @@ inputs:
3939
description: "Name of an EC2 key pair to use for SSH access (falls back to vars.EC2_KEY_NAME)"
4040
required: false
4141
ec2_root_device_size:
42-
description: "Root device size in GB (0 = use AMI default)"
42+
description: "Root disk size in GB (0=AMI default, +N=AMI+N GB for testing, e.g. +2)"
4343
required: false
4444
ec2_security_group_id:
4545
description: "AWS security group ID (falls back to vars.EC2_SECURITY_GROUP_ID)"

src/ec2_gha/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def main():
3939
.update_state("INPUT_EC2_INSTANCE_PROFILE", "iam_instance_profile")
4040
.update_state("INPUT_EC2_INSTANCE_TYPE", "instance_type")
4141
.update_state("INPUT_EC2_KEY_NAME", "key_name")
42-
.update_state("INPUT_EC2_ROOT_DEVICE_SIZE", "root_device_size", type_hint=int)
42+
.update_state("INPUT_EC2_ROOT_DEVICE_SIZE", "root_device_size", type_hint=str)
4343
.update_state("INPUT_EC2_SECURITY_GROUP_ID", "security_group_id")
4444
.update_state("INPUT_EC2_USERDATA", "userdata")
4545
.update_state("INPUT_EXTRA_GH_LABELS", "labels")

src/ec2_gha/scripts/runner-setup.sh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ set -e
77
# Enable debug tracing to a file for troubleshooting
88
exec 2> >(tee -a /var/log/runner-debug.log >&2)
99

10-
# Conditionally enable debug mode
11-
[ "$debug" = "true" ] || [ "$debug" = "True" ] || [ "$debug" = "1" ] && set -x
10+
# Conditionally enable debug mode (set -x) for tracing
11+
# Debug can be: true/True/trace (trace only), or a number (trace + sleep minutes)
12+
if [ "$debug" = "true" ] || [ "$debug" = "True" ] || [ "$debug" = "trace" ] || [[ "$debug" =~ ^[0-9]+$ ]]; then
13+
set -x
14+
fi
1215

1316
# Determine home directory early since it's needed by shared functions
1417
if [ -z "$homedir" ] || [ "$homedir" = "AUTO" ]; then
@@ -47,8 +50,8 @@ B=/usr/local/bin
4750
V=/var/run/github-runner
4851
4952
# Fetch shared functions from GitHub
50-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fetching shared functions from GitHub" | tee -a /var/log/runner-setup.log
51-
FUNCTIONS_URL="https://raw.githubusercontent.com/Open-Athena/ec2-gha/${action_ref}/src/ec2_gha/templates/shared-functions.sh"
53+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fetching shared functions from GitHub (SHA: ${action_sha})" | tee -a /var/log/runner-setup.log
54+
FUNCTIONS_URL="https://raw.githubusercontent.com/Open-Athena/ec2-gha/${action_sha}/src/ec2_gha/templates/shared-functions.sh"
5255
if ! curl -sSL "$FUNCTIONS_URL" -o /tmp/shared-functions.sh && ! wget -q "$FUNCTIONS_URL" -O /tmp/shared-functions.sh; then
5356
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Failed to download shared functions" | tee -a /var/log/runner-setup.log
5457
shutdown -h now

0 commit comments

Comments
 (0)