Skip to content

chore(deps): update pytest requirement from >=7.4.0 to >=9.1.1 #7

chore(deps): update pytest requirement from >=7.4.0 to >=9.1.1

chore(deps): update pytest requirement from >=7.4.0 to >=9.1.1 #7

Workflow file for this run

# CTO Watchdog — Real-time Event Watcher v1.1.0

Check failure on line 1 in .github/workflows/cto-watch.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/cto-watch.yml

Invalid workflow file

(Line: 338, Col: 13): Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.CTO_WATCHDOG_SMTP_SERVER
# Triggers on push, PR, branch, and release events
# Downloads scripts from central cto-watchdog repo
# Part of: cto-watchdog — Dhaher Labs
# Author: Mulky Malikul Dhaher
name: CTO Watch — Event Monitor
on:
push:
branches: ['*']
pull_request:
types: [opened, synchronize, reopened, closed]
create:
delete:
release:
types: [published, edited, deleted]
workflow_dispatch:
inputs:
audit_type:
description: 'Audit type'
required: false
default: 'event'
type: choice
options:
- event
- full
- branding-only
- security-only
permissions:
contents: write
issues: write
pull-requests: write
env:
CTO_WATCHDOG_VERSION: '1.1.0'
CTO_WATCHDOG_REPO: 'dhaher-labs/cto-watchdog'
jobs:
download-scripts:
name: Download CTO Watchdog Scripts
runs-on: ubuntu-latest
outputs:
scripts_ready: ${{ steps.download.outputs.ready }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download scripts from central repo
id: download
run: |
mkdir -p cto-watchdog/scripts
# Download each script from the central cto-watchdog repo
SCRIPTS="event-classifier.py cto-auditor.py safe-fix.py report-generator.py email-notifier.py branch-analyzer.py repo-registry.py"
for script in $SCRIPTS; do
echo "Downloading $script..."
status=$(curl -s -o "cto-watchdog/scripts/$script" \
-w "%{http_code}" \
-H "Authorization: token ${{ secrets.CTO_WATCHDOG_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3.raw" \
"https://api.github.com/repos/${{ env.CTO_WATCHDOG_REPO }}/contents/scripts/$script")
if [ "$status" = "200" ]; then
chmod +x "cto-watchdog/scripts/$script"
echo " ✅ Downloaded: $script"
else
echo " ❌ Failed to download: $script (HTTP $status)"
# Create a minimal fallback
echo "#!/usr/bin/env python3" > "cto-watchdog/scripts/$script"
echo "# Fallback — $script not available" >> "cto-watchdog/scripts/$script"
echo "import json, sys; print(json.dumps({'error': 'script unavailable'})); sys.exit(1)" >> "cto-watchdog/scripts/$script"
chmod +x "cto-watchdog/scripts/$script"
fi
done
# Download repo-registry.json
mkdir -p cto-watchdog/config
curl -s -o "cto-watchdog/config/repo-registry.json" \
-H "Authorization: token ${{ secrets.CTO_WATCHDOG_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3.raw" \
"https://api.github.com/repos/${{ env.CTO_WATCHDOG_REPO }}/contents/config/repo-registry.json" 2>/dev/null || true
echo "ready=true" >> $GITHUB_OUTPUT
echo "📊 Scripts downloaded successfully"
- name: Upload scripts artifact
uses: actions/upload-artifact@v4
with:
name: cto-watchdog-scripts
path: cto-watchdog/
retention-days: 1
classify-event:
name: Classify Event
needs: download-scripts
runs-on: ubuntu-latest
outputs:
category: ${{ steps.classify.outputs.category }}
risk_level: ${{ steps.classify.outputs.risk_level }}
auto_fixable: ${{ steps.classify.outputs.auto_fixable }}
requires_review: ${{ steps.classify.outputs.requires_review }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Download scripts artifact
uses: actions/download-artifact@v4
with:
name: cto-watchdog-scripts
path: cto-watchdog/
- name: Install dependencies
run: pip install --quiet pyyaml
- name: Classify event
id: classify
run: |
# Build event payload from GitHub context
cat > /tmp/event.json << 'EVENT_EOF'
${{ toJson(github) }}
EVENT_EOF
# Run classifier
python3 cto-watchdog/scripts/event-classifier.py /tmp/event.json > /tmp/classification.json 2>/dev/null || {
echo "⚠️ Classifier failed, using defaults"
echo '{"category":"unknown","risk_level":"medium","is_auto_fixable":false,"requires_review":true}' > /tmp/classification.json
}
# Parse results safely
CATEGORY=$(python3 -c "import json; d=json.load(open('/tmp/classification.json')); print(d.get('category','unknown'))" 2>/dev/null || echo "unknown")
RISK=$(python3 -c "import json; d=json.load(open('/tmp/classification.json')); print(d.get('risk_level','medium'))" 2>/dev/null || echo "medium")
AUTO_FIX=$(python3 -c "import json; d=json.load(open('/tmp/classification.json')); print(str(d.get('is_auto_fixable',False)).lower())" 2>/dev/null || echo "false")
REVIEW=$(python3 -c "import json; d=json.load(open('/tmp/classification.json')); print(str(d.get('requires_review',True)).lower())" 2>/dev/null || echo "true")
echo "category=$CATEGORY" >> $GITHUB_OUTPUT
echo "risk_level=$RISK" >> $GITHUB_OUTPUT
echo "auto_fixable=$AUTO_FIX" >> $GITHUB_OUTPUT
echo "requires_review=$REVIEW" >> $GITHUB_OUTPUT
echo "📊 Event Classification:"
echo " Category: $CATEGORY"
echo " Risk Level: $RISK"
echo " Auto-fixable: $AUTO_FIX"
echo " Requires Review: $REVIEW"
audit:
name: CTO Audit
needs: [download-scripts, classify-event]
runs-on: ubuntu-latest
if: always()
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Download scripts artifact
uses: actions/download-artifact@v4
with:
name: cto-watchdog-scripts
path: cto-watchdog/
- name: Install dependencies
run: pip install --quiet pyyaml
- name: Run CTO Auditor
id: audit
run: |
OWNER="${{ github.repository_owner }}"
REPO="${{ github.repository }}"
python3 cto-watchdog/scripts/cto-auditor.py . \
--owner "$OWNER" \
--json > /tmp/audit-report.json 2>/tmp/audit-stderr.txt
if [ $? -ne 0 ]; then
echo "⚠️ CTO Auditor encountered errors:"
cat /tmp/audit-stderr.txt 2>/dev/null || true
# Generate fallback report
python3 -c "
import json, os
issues = []
for f in ['README.md', 'LICENSE', '.gitignore']:
if not os.path.exists(f):
issues.append({'severity': 'MEDIUM', 'title': f'Missing {f}', 'file': f, 'category': 'docs', 'description': f'{f} not found', 'recommendation': f'Add {f}', 'auto_fixable': False})
report = {
'repository': '$REPO',
'summary': {'total_issues': len(issues), 'critical': 0, 'high': 0, 'medium': len(issues), 'low': 0, 'info': 0, 'auto_fixable': 0, 'requires_review': len(issues)},
'issues': issues,
'scores': {'code_quality': 80, 'documentation': 70, 'branding_consistency': 85, 'security': 95, 'branch_health': 75, 'seo': 70, 'overall': 79},
'next_steps': []
}
json.dump(report, open('/tmp/audit-report.json', 'w'), indent=2)
"
fi
# Display summary
python3 -c "
import json
try:
r = json.load(open('/tmp/audit-report.json'))
s = r.get('summary', {})
sc = r.get('scores', {})
print(f'📊 Audit Summary for {r.get(\"repository\", \"unknown\")}')
print(f' Issues: {s.get(\"total_issues\", 0)} (C:{s.get(\"critical\",0)} H:{s.get(\"high\",0)} M:{s.get(\"medium\",0)} L:{s.get(\"low\",0)})')
print(f' Overall Score: {sc.get(\"overall\", 0)}/100')
print(f' Auto-fixable: {s.get(\"auto_fixable\", 0)}')
except Exception as e:
print(f'Error reading report: {e}')
" 2>/dev/null || true
- name: Upload audit report
uses: actions/upload-artifact@v4
with:
name: audit-report
path: /tmp/audit-report.json
retention-days: 30
safe-fix:
name: Apply Safe Fixes
needs: [download-scripts, classify-event, audit]
runs-on: ubuntu-latest
if: needs.classify-event.outputs.auto_fixable == 'true'
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.CTO_WATCHDOG_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Download scripts artifact
uses: actions/download-artifact@v4
with:
name: cto-watchdog-scripts
path: cto-watchdog/
- name: Run Safe Fix Engine (dry-run first)
run: |
echo "🔍 Preview of safe fixes..."
python3 cto-watchdog/scripts/safe-fix.py . --dry-run 2>/dev/null || echo "Preview not available"
- name: Run Safe Fix Engine (apply)
run: |
python3 cto-watchdog/scripts/safe-fix.py . --json > /tmp/fixes.json 2>/dev/null || echo "[]" > /tmp/fixes.json
# Show what was fixed
python3 -c "
import json
try:
fixes = json.load(open('/tmp/fixes.json'))
print(f'🔧 Applied {len(fixes)} safe fixes:')
for f in fixes:
print(f' ✅ [{f.get(\"risk\",\"LOW\")}] {f.get(\"file_path\",\"\")}: {f.get(\"description\",\"\")}')
except:
print('No fixes applied')
" 2>/dev/null || true
- name: Commit and push fixes
run: |
if [ -n "$(git status --porcelain)" ]; then
git config user.name "CTO Watchdog"
git config user.email "dhaher-labs@email.com"
git add -A
FIXES_COUNT=$(python3 -c "import json; print(len(json.load(open('/tmp/fixes.json'))))" 2>/dev/null || echo "several")
git commit -m "[cto-watchdog] safe-fix: branding and formatting fixes (${FIXES_COUNT} fixes)
Auto-fixed by CTO Watchdog v${{ env.CTO_WATCHDOG_VERSION }}
Risk level: LOW
Classification: ${{ needs.classify-event.outputs.category }}
Trigger: ${{ github.event_name }}"
git push
echo "✅ Safe fixes committed and pushed"
else
echo "ℹ️ No changes to commit"
fi
- name: Upload fixes report
uses: actions/upload-artifact@v4
with:
name: safe-fixes
path: /tmp/fixes.json
retention-days: 30
notify:
name: Send Notification
needs: [download-scripts, classify-event, audit]
runs-on: ubuntu-latest
if: always()
steps:
- name: Download audit report
uses: actions/download-artifact@v4
with:
name: audit-report
path: /tmp/
- name: Determine recipient
id: recipient
run: |
OWNER="${{ github.repository_owner }}"
if [ "$OWNER" = "mulkymalikuldhaher" ]; then
echo "email=mulkymalikuldhr@mail.com" >> $GITHUB_OUTPUT
else
echo "email=dhaher-labs@email.com" >> $GITHUB_OUTPUT
fi
- name: Send email notification
if: ${{ secrets.CTO_WATCHDOG_SMTP_SERVER }}
uses: dawidd6/action-send-mail@v3
with:
server_address: ${{ secrets.CTO_WATCHDOG_SMTP_SERVER }}
server_port: ${{ secrets.CTO_WATCHDOG_SMTP_PORT }}
username: ${{ secrets.CTO_WATCHDOG_SMTP_USER }}
password: ${{ secrets.CTO_WATCHDOG_SMTP_PASS }}
from: ${{ secrets.CTO_WATCHDOG_SMTP_FROM }}
to: ${{ steps.recipient.outputs.email }}
subject: "[CTO-Watchdog] [${{ needs.classify-event.outputs.risk_level }}] ${{ github.repository }}: ${{ github.event_name }}"
body: |
CTO Watchdog Audit Report
Repository: ${{ github.repository }}
Event: ${{ github.event_name }}
Risk Level: ${{ needs.classify-event.outputs.risk_level }}
Category: ${{ needs.classify-event.outputs.category }}
Auto-fixable: ${{ needs.classify-event.outputs.auto_fixable }}
See the full audit report in the GitHub Actions artifacts.
Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
---
CTO Watchdog v${{ env.CTO_WATCHDOG_VERSION }} — Dhaher Labs
env:
CTO_WATCHDOG_SMTP_SERVER: ${{ secrets.CTO_WATCHDOG_SMTP_SERVER }}
- name: Create issue for high/critical findings
if: needs.classify-event.outputs.risk_level == 'high' || needs.classify-event.outputs.risk_level == 'critical'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
let report;
try {
report = JSON.parse(fs.readFileSync('/tmp/audit-report.json', 'utf8'));
} catch (e) {
report = { summary: { critical: 0, high: 0 }, issues: [] };
}
const critical = report.summary.critical || 0;
const high = report.summary.high || 0;
if (critical > 0 || high > 0) {
const riskLabel = critical > 0 ? 'CRITICAL' : 'HIGH';
const title = `[CTO-Watchdog] ${riskLabel}: ${critical + high} issue(s) found`;
const body = `## CTO Watchdog Finding\n\n` +
`**Risk Level**: ${riskLabel}\n` +
`**Issues Found**: ${critical} critical, ${high} high\n\n` +
report.issues
.filter(i => i.severity === 'CRITICAL' || i.severity === 'HIGH')
.map(i => `### [${i.severity}] ${i.title}\n- File: \`${i.file}\`\n- ${i.description || ''}\n- Recommendation: ${i.recommendation || 'Review manually'}`)
.join('\n\n') +
`\n\n---\n*Detected by CTO Watchdog v${process.env.CTO_WATCHDOG_VERSION}*`;
try {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body,
labels: ['cto-watchdog', 'automated']
});
} catch (labelErr) {
// Label might not exist, create without labels
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: body
});
}
}
- name: Log notification
run: |
echo "📧 Notification sent to: ${{ steps.recipient.outputs.email }}"
echo "📋 Risk Level: ${{ needs.classify-event.outputs.risk_level }}"
echo "📊 Category: ${{ needs.classify-event.outputs.category }}"
echo "🔧 Auto-fixable: ${{ needs.classify-event.outputs.auto_fixable }}"