Skip to content

Test

Test #3

Workflow file for this run

name: Validate and Update DNS
on:
pull_request:
paths: [domains/**]
types: [opened, synchronize, reopened]
push:
paths: [domains/**]
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
outputs:
is_valid: ${{ steps.validation.outputs.is_valid }}
changed_files: ${{ steps.get-changes.outputs.changed_files }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: get-changes
run: |
echo "πŸ” Detecting changed files..."
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "Mode: Pull Request"
git fetch origin ${{ github.base_ref }}
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }} ${{ github.sha }} -- domains/ | tr '\n' ' ' || true)
else
echo "Mode: Push to main"
if git log --oneline -2 > /dev/null 2>&1; then
CHANGED_FILES=$(git diff --name-only HEAD^ HEAD -- domains/ | tr '\n' ' ' || true)
else
CHANGED_FILES=$(find domains/ -name "*.json" | tr '\n' ' ')
fi
fi
echo "Changed files found: $CHANGED_FILES"
echo "changed_files=$CHANGED_FILES" >> $GITHUB_OUTPUT
- name: Validate JSON files
id: validation
run: |
echo "Starting validation..."
FILES="${{ steps.get-changes.outputs.changed_files }}"
if [ -z "$FILES" ]; then
echo "No files changed."
echo "is_valid=true" >> $GITHUB_OUTPUT
exit 0
fi
ALL_VALID=true
VALIDATION_LOG=""
read -r -a FILES_ARRAY <<< "$FILES"
for file_path in "${FILES_ARRAY[@]}"; do
if [[ -f "$file_path" ]] && [[ "$file_path" == *.json ]]; then
echo "=== Validating: $file_path ==="
if ! python3 -m json.tool "$file_path" > /dev/null 2>&1; then
VALIDATION_LOG+="❌ $file_path: Invalid JSON format\n"
ALL_VALID=false
continue
fi
# Extract Record Type
RECORD_TYPE=$(python3 -c "import json; f=open('$file_path'); d=json.load(f); print(d.get('record', {}).get('type', '').upper())")
if [[ "$RECORD_TYPE" != "CNAME" ]] && [[ "$RECORD_TYPE" != "A" ]]; then
VALIDATION_LOG+="❌ $file_path: Only CNAME/A allowed. Found: $RECORD_TYPE\n"
ALL_VALID=false
continue
fi
VALUE=$(python3 -c "import json; f=open('$file_path'); d=json.load(f); print(d.get('record', {}).get('value', ''))")
if [[ "$RECORD_TYPE" == "CNAME" ]]; then
if [[ ! "$VALUE" =~ ^[a-zA-Z0-9][a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
VALIDATION_LOG+="❌ $file_path: Invalid CNAME: $VALUE\n"
ALL_VALID=false
fi
elif [[ "$RECORD_TYPE" == "A" ]]; then
if [[ ! "$VALUE" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
VALIDATION_LOG+="❌ $file_path: Invalid IPv4: $VALUE\n"
ALL_VALID=false
fi
fi
fi
done
echo -e "$VALIDATION_LOG"
if [ "$ALL_VALID" = true ]; then
echo "is_valid=true" >> $GITHUB_OUTPUT
else
echo "is_valid=false" >> $GITHUB_OUTPUT
exit 1
fi
deploy:
needs: validate
if: github.event_name == 'push' && needs.validate.outputs.is_valid == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Update Cloudflare DNS
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
CHANGED_FILES: ${{ needs.validate.outputs.changed_files }}
run: |
python3 -m pip install requests
python3 << 'EOF'
import os, json, sys, requests
ZONE_ID = os.getenv('CLOUDFLARE_ZONE_ID')
API_TOKEN = os.getenv('CLOUDFLARE_API_TOKEN')
FILES = os.getenv('CHANGED_FILES', '').split()
BASE_URL = "https://api.cloudflare.com/client/v4"
HEADERS = {"Authorization": f"Bearer {API_TOKEN}", "Content-Type": "application/json"}
for file_path in FILES:
if not file_path.endswith('.json') or not os.path.exists(file_path): continue
with open(file_path) as f:
config = json.load(f)
sub = config.get('subdomain', '').strip()
record = config.get('record', {})
name = "codesigmax.com" if sub == "@" else f"{sub}.codesigmax.com"
print(f"Processing: {name}")
# Check existing
res = requests.get(f"{BASE_URL}/zones/{ZONE_ID}/dns_records", headers=HEADERS, params={"name": name, "type": record.get('type')})
existing = res.json().get('result', [])
payload = {
"type": record.get('type'),
"name": name,
"content": record.get('value'),
"ttl": record.get('ttl', 3600),
"proxied": record.get('proxied', record.get('type') == 'A')
}
if existing:
rid = existing[0]['id']
r = requests.put(f"{BASE_URL}/zones/{ZONE_ID}/dns_records/{rid}", headers=HEADERS, json=payload)
else:
r = requests.post(f"{BASE_URL}/zones/{ZONE_ID}/dns_records", headers=HEADERS, json=payload)
if r.status_code in [200, 201]:
print(f"βœ… Success for {name}")
else:
print(f"❌ Error for {name}: {r.text}")
EOF