Skip to content

Update Test Rules #10699

Update Test Rules

Update Test Rules #10699

name: Update Test Rules
on:
schedule:
- cron: '*/10 * * * *'
workflow_dispatch: # Allow manual triggering
env:
PYTHON_VERSION: "3.13"
jobs:
update-test-rules:
runs-on: ubuntu-latest
permissions:
contents: write
checks: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: pip install requests
- name: Create and switch to test-rules branch
run: |
git fetch --all
if git show-ref --quiet refs/remotes/origin/test-rules; then
git checkout test-rules
git pull origin test-rules
else
git checkout -b test-rules
fi
- name: Get latest script from main branch
run: |
# Checkout the scripts directory from main branch without switching branches
git checkout origin/main -- scripts/
# Unstage the script changes - we only want to commit detection rule changes
git reset HEAD scripts/ || true
- name: Run the script
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SCRIPT_MODE: 'test-rules'
# Configure test-rules specific settings
FILTER_BY_ORG_MEMBERSHIP: 'true'
ORG_NAME: 'sublime-security'
INCLUDE_PRS_WITH_COMMENT: 'true'
COMMENT_TRIGGER: '/update-test-rules'
# SKIP_FILES pattern and labls are managed within the script
SKIP_FILES_WITH_TEXT: 'true'
# Skip PRs with too many rules
SKIP_BULK_PRS: 'true'
MAX_RULES_PER_PR: '10'
BULK_PR_LABEL: 'test-rules:excluded:bulk_rules'
# Disable adding tags that aren't useful
ADD_RULE_STATUS_TAG: 'false'
ADD_PR_REFERENCE: 'false'
INCLUDE_PR_IN_NAME: 'false'
ADD_AUTHOR_TAG: 'false'
CREATE_OPEN_PR_TAG: 'false'
ADD_TEST_RULES_LABEL: 'true'
IN_TEST_RULES_LABEL: 'in-test-rules'
AUTHOR_MEMBERSHIP_EXCLUSION_LABEL: 'test-rules:excluded:author_membership'
run: python scripts/sync_detection_rules.py
- name: Clean up script changes
run: |
# Revert any script changes back to test-rules branch version
# This keeps the working directory clean
# this shouldn't be required, but is a good thing to do anyway
git checkout HEAD -- scripts/ || true
- name: Commit changes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
# First check if there are any changes
if [[ -z $(git status --porcelain detection-rules) ]]; then
echo "No changes to detection rules"
exit 0
fi
# Get list of modified files
FILES=$(git status --porcelain detection-rules | awk '{print $2}')
# Track stats for the summary
ADDED_COUNT=0
MODIFIED_COUNT=0
DELETED_COUNT=0
UPDATED_PRS=()
# Process each file individually
for FILE in $FILES; do
echo "Processing $FILE"
# Skip non-rule files
if [[ ! "$FILE" =~ .*\.yml$ ]]; then
continue
fi
BASENAME=$(basename "$FILE")
# Extract PR number from filename (format: PR_NUMBER_filename.yml)
PR_NUMBER=$(echo "$BASENAME" | grep -o "^[0-9]*")
UPDATED_PRS+=("$PR_NUMBER")
echo "Processing $BASENAME from $PR_NUMBER for inclusion"
# Handle removed files
if [[ ! -f "$FILE" ]]; then
echo "$BASENAME was deleted, commiting deletion."
DELETED_COUNT=$((DELETED_COUNT+1))
git add "$FILE"
git commit -m "[PR #${PR_NUMBER}] Delete detection rule"
continue
fi
# Ensure that new files are tracked (otherwise they won't show up in diff)
git add -N "$FILE"
# Check if only testing_sha field changed
DIFF_OUTPUT=$(git diff HEAD -- "$FILE")
# Skip files with no changes at all
if [[ -z "$DIFF_OUTPUT" ]]; then
echo "\tSkipping $FILE: no changes"
continue
fi
# Check if the diff only contains testing_sha changes
# Look for lines that are only additions/deletions of testing_sha with hash values
# Handle files that may not have trailing newlines
# Filter out hunk headers & file paths so we just have +- lines of changed content.
LINES_CHANGES_ONLY=$(echo "$DIFF_OUTPUT" | grep -E '^[+-]' | grep -v -E '^[+-]{3}' | grep -v '^\\ No newline at end of file')
NON_TESTING_SHA_CHANGES=$(echo $LINES_CHANGES_ONLY | grep -v -E '^[+-]testing_sha: [0-9a-f]+' || true)
if [[ -z "$NON_TESTING_SHA_CHANGES" ]]; then
echo "\tSkipping $FILE: only testing_sha field changed. Lines changed:"
echo "$LINES_CHANGES_ONLY"
continue
fi
# Determine status directly from git
GIT_STATUS=$(git status --porcelain "$FILE" | cut -c1-2 | tr -d ' ')
if [[ "$GIT_STATUS" == "A" ]]; then
ADDED_COUNT=$((ADDED_COUNT+1))
STATUS="added"
elif [[ "$GIT_STATUS" == "M" ]]; then
MODIFIED_COUNT=$((MODIFIED_COUNT+1))
STATUS="modified"
else
MODIFIED_COUNT=$((MODIFIED_COUNT+1))
STATUS="changed"
fi
# Extract rule name and commit
RULE_NAME=$(grep -m 1 "name:" "$FILE" | sed 's/name: //' | sed 's/^"//' | sed 's/"$//' | sed "s/^'//" | sed "s/'$//")
# Build commit message
COMMIT_MSG="[PR #${PR_NUMBER}] ${STATUS} rule: ${RULE_NAME}"
# Add file and commit
git add "$FILE"
git commit -m "$COMMIT_MSG"
done
# Get unique PR count
UNIQUE_PRS=$(printf '%s\n' "${UPDATED_PRS[@]}" | sort -u | wc -l)
# Create summary
echo "Detection Rules Sync Summary ($(date '+%Y-%m-%d %H:%M:%S'))"
echo "- PRs processed: ${UNIQUE_PRS}"
echo "- Rules added: ${ADDED_COUNT}"
echo "- Rules modified: ${MODIFIED_COUNT}"
echo "- Rules deleted: ${DELETED_COUNT}"
# Push changes
git push