Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 22 additions & 112 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,29 @@ jobs:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
- name: Check for path changes
id: changes
with:
filters: |
functions:
- 'functions/**'
ui:
- 'ui/**'
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
# For PRs, compare PR head against base
git fetch origin ${{ github.event.pull_request.base.ref }}
CHANGED_FILES=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD)
else
# For push events, compare against default branch
CHANGED_FILES=$(git diff --name-only origin/${{ github.event.repository.default_branch }}...HEAD)
fi

if echo "$CHANGED_FILES" | grep -q '^functions/'; then
echo "functions=true" >> $GITHUB_OUTPUT
else
echo "functions=false" >> $GITHUB_OUTPUT
fi

if echo "$CHANGED_FILES" | grep -q '^ui/'; then
echo "ui=true" >> $GITHUB_OUTPUT
else
echo "ui=false" >> $GITHUB_OUTPUT
fi

test-functions:
needs: check-changes
Expand All @@ -44,9 +59,6 @@ jobs:
- name: Install Python dependencies
run: pip install -r requirements.txt
working-directory: ${{ matrix.function }}
- name: Install HTTPie for API testing
run: pip install httpie
if: matrix.function == 'functions/csv-import'
- name: Run tests if test_main.py exists
run: |
if [ -f "test_main.py" ]; then
Expand All @@ -56,108 +68,6 @@ jobs:
echo "No test_main.py found, skipping tests"
fi
working-directory: ${{ matrix.function }}
- name: Run Python function and verify output
env:
FALCON_CLIENT_ID: ${{ secrets.FALCON_CLIENT_ID }}
FALCON_CLIENT_SECRET: ${{ secrets.FALCON_CLIENT_SECRET }}
FALCON_BASE_URL: ${{ secrets.FALCON_BASE_URL }}
APP_ID: ${{ secrets.APP_ID }}
run: |
# Start the function
python main.py > output.log 2>&1 &
PID=$!
timeout=30
elapsed=0
while [ $elapsed -lt $timeout ]; do
if grep -q "running at port 8081" output.log; then
echo "✅ Application started successfully"
break
fi
sleep 1
elapsed=$((elapsed+1))
done

if [ $elapsed -ge $timeout ]; then
echo "❌ Application failed to start within $timeout seconds"
cat output.log
kill $PID 2>/dev/null || true
exit 1
fi

TEST_FAILURES=0

# Run CSV import tests
if [[ "${{ matrix.function }}" == "functions/csv-import" ]]; then
echo "Running CSV import tests..."
sleep 2

# Create sample CSV if needed
if [ ! -f "security_events.csv" ]; then
echo "timestamp,event_type,severity,description,source_ip,destination_ip,user" > security_events.csv
echo "2025-07-11T14:14:08Z,login_failure,medium,Failed login from IP 192.168.1.100,192.168.1.100,192.168.1.1,test.user" >> security_events.csv
echo "2025-07-11T14:15:22Z,malware_detected,high,Malware detected on workstation,192.168.1.101,192.168.1.1,admin.user" >> security_events.csv
fi

# Test 1: Import CSV with file path
echo "=== Test 1: Import file path ==="
set +e
http --ignore-stdin POST :8081 method=POST url=/import-csv "body[csv_file_path]=security_events.csv" > import_file_output.log 2>&1
IMPORT_FILE_EXIT_CODE=$?
set -e

if [ $IMPORT_FILE_EXIT_CODE -eq 0 ] && grep -q '"success": true' import_file_output.log; then
echo "✅ Import file path test passed"
else
echo "❌ Import file path test failed"
cat import_file_output.log
TEST_FAILURES=$((TEST_FAILURES + 1))
fi

# Test 2: Import CSV with inline data
echo "=== Test 2: Import inline data ==="
CSV_DATA=$(cat security_events.csv)
set +e
http --ignore-stdin POST :8081 method=POST url=/import-csv "body[csv_data]=$CSV_DATA" > import_data_output.log 2>&1
IMPORT_DATA_EXIT_CODE=$?
set -e

if [ $IMPORT_DATA_EXIT_CODE -eq 0 ] && grep -q '"success": true' import_data_output.log; then
echo "✅ Import inline data test passed"
else
echo "❌ Import inline data test failed"
cat import_data_output.log
TEST_FAILURES=$((TEST_FAILURES + 1))
fi

# Test 3: Execute import.py script
if [ -f "import.py" ]; then
echo "=== Test 3: Import script ==="
set +e
python import.py > import_script_output.log 2>&1
IMPORT_SCRIPT_EXIT_CODE=$?
set -e

if [ $IMPORT_SCRIPT_EXIT_CODE -eq 0 ] && grep -q '"success": true' import_script_output.log; then
echo "✅ Import script test passed"
else
echo "❌ Import script test failed"
cat import_script_output.log
TEST_FAILURES=$((TEST_FAILURES + 1))
fi
fi
fi

# Cleanup
kill $PID 2>/dev/null || true

# Final result
if [ $TEST_FAILURES -gt 0 ]; then
echo "❌ $TEST_FAILURES test(s) failed"
exit 1
else
echo "✅ All tests passed"
fi
working-directory: ${{ matrix.function }}

test-ui:
needs: check-changes
Expand Down
155 changes: 155 additions & 0 deletions functions/csv-import/test-integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/bin/bash
#
# Integration test script for the CSV import function.
# This script starts the function server and tests the import endpoints.
#
# Prerequisites:
# - Python 3.x
# - Collections Toolkit app deployed (install from Foundry > Templates, or run `foundry apps deploy`)
#
# Usage:
# ./test-integration.sh
#
# Environment variables (will prompt if not set):
# FALCON_CLIENT_ID - API client ID (requires Custom Storage Read and Write scopes)
# FALCON_CLIENT_SECRET - API client secret
# APP_ID - Your Foundry app ID

set -e

# Detect Python command
if command -v python3 &> /dev/null; then
PYTHON_CMD="python3"
elif command -v python &> /dev/null; then
PYTHON_CMD="python"
else
echo "Error: Python not found. Please install Python 3.x"
exit 1
fi

# Create and activate virtual environment
if [ ! -d ".venv" ]; then
echo "Creating virtual environment..."
$PYTHON_CMD -m venv .venv
fi

echo "Activating virtual environment..."
source .venv/bin/activate

# Install dependencies
echo "Installing dependencies..."
pip install -q --upgrade pip -r requirements.txt
pip install -q httpie

# Prompt for credentials if not set
if [ -z "$FALCON_CLIENT_ID" ]; then
read -p "Enter FALCON_CLIENT_ID: " FALCON_CLIENT_ID
export FALCON_CLIENT_ID
fi

if [ -z "$FALCON_CLIENT_SECRET" ]; then
read -s -p "Enter FALCON_CLIENT_SECRET: " FALCON_CLIENT_SECRET
echo
export FALCON_CLIENT_SECRET
fi

if [ -z "$APP_ID" ]; then
read -p "Enter APP_ID: " APP_ID
export APP_ID
fi

echo "Starting integration tests..."

# Start the function
$PYTHON_CMD main.py > output.log 2>&1 &
PID=$!

# Wait for server to start
timeout=30
elapsed=0
while [ $elapsed -lt $timeout ]; do
if grep -q "running at port 8081" output.log; then
echo "Application started successfully"
break
fi
sleep 1
elapsed=$((elapsed+1))
done

if [ $elapsed -ge $timeout ]; then
echo "Application failed to start within $timeout seconds"
cat output.log
kill $PID 2>/dev/null || true
exit 1
fi

TEST_FAILURES=0

echo "Running CSV import tests..."
sleep 2

# Create sample CSV if needed
if [ ! -f "security_events.csv" ]; then
echo "timestamp,event_type,severity,description,source_ip,destination_ip,user" > security_events.csv
echo "2025-07-11T14:14:08Z,login_failure,medium,Failed login from IP 192.168.1.100,192.168.1.100,192.168.1.1,test.user" >> security_events.csv
echo "2025-07-11T14:15:22Z,malware_detected,high,Malware detected on workstation,192.168.1.101,192.168.1.1,admin.user" >> security_events.csv
fi

# Test 1: Import CSV with file path
echo "=== Test 1: Import file path ==="
set +e
http --ignore-stdin POST :8081 method=POST url=/import-csv "body[csv_file_path]=security_events.csv" > import_file_output.log 2>&1
IMPORT_FILE_EXIT_CODE=$?
set -e

if [ $IMPORT_FILE_EXIT_CODE -eq 0 ] && grep -q '"success": true' import_file_output.log; then
echo "Import file path test passed"
else
echo "Import file path test failed"
cat import_file_output.log
TEST_FAILURES=$((TEST_FAILURES + 1))
fi

# Test 2: Import CSV with inline data
echo "=== Test 2: Import inline data ==="
CSV_DATA=$(cat security_events.csv)
set +e
http --ignore-stdin POST :8081 method=POST url=/import-csv "body[csv_data]=$CSV_DATA" > import_data_output.log 2>&1
IMPORT_DATA_EXIT_CODE=$?
set -e

if [ $IMPORT_DATA_EXIT_CODE -eq 0 ] && grep -q '"success": true' import_data_output.log; then
echo "Import inline data test passed"
else
echo "Import inline data test failed"
cat import_data_output.log
TEST_FAILURES=$((TEST_FAILURES + 1))
fi

# Test 3: Execute import.py script
if [ -f "import.py" ]; then
echo "=== Test 3: Import script ==="
set +e
$PYTHON_CMD import.py > import_script_output.log 2>&1
IMPORT_SCRIPT_EXIT_CODE=$?
set -e

if [ $IMPORT_SCRIPT_EXIT_CODE -eq 0 ] && grep -q '"success": true' import_script_output.log; then
echo "Import script test passed"
else
echo "Import script test failed"
cat import_script_output.log
TEST_FAILURES=$((TEST_FAILURES + 1))
fi
fi

# Cleanup
kill $PID 2>/dev/null || true

# Final result
if [ $TEST_FAILURES -gt 0 ]; then
echo "$TEST_FAILURES test(s) failed"
exit 1
else
echo "All tests passed"
fi