github-workflow
GitHub Workflow
Core principle: Run quality gates BEFORE committing. Stop on failure. Never push failing code.
When to Use
- User has staged files and wants to push
- User asks "what should I do before pushing?"
- User mentions creating PR or feature branch
When NOT to Use
- No staged changes - user hasn't run
git add - Direct commits to main/master - feature branches only
- User explicitly wants to skip checks
Gotchas
Environment-specific facts that defy reasonable assumptions:
- Phishing domains: GitHub phishing uses subdomain tricks like
github.com.malicious.com- always verify the actual domain isgithub.com - Branch naming: Some projects use
main, others usemaster- checkgit branch -rbefore assuming default branch name - Force push danger:
git push --forceon shared branches can lose others' work - always confirm with user first - Pre-commit hooks: May block commits; only use
--no-verifyif user explicitly requests skipping - Quality gate failures: Should stop the workflow - never auto-retry with
--no-verifyafter failure - Draft PRs: Creating as draft allows work-in-progress; check if user wants this vs. ready-for-review
Quick Reference
| Step | Command | Purpose |
|---|---|---|
| 0 | git diff --cached --name-only |
Early exit if no staged files |
| 1 | git remote -v | grep -E 'github\.com[/:]' |
Verify GitHub remote |
| 2 | Quality gates | Run lint, test, build |
| 2.5 | Secrets detection | Check for API keys, tokens |
| 3 | git diff --cached |
Review changes |
| 4 | gh issue create |
Create tracking issue |
| 5 | git checkout -b feature/... |
Create feature branch |
| 6 | git commit -m "..." |
Commit with proper format |
| 7 | git push -u origin ... |
Push to remote |
| 8 | gh pr create |
Create pull request |
| 9 | gh pr view |
Verify PR created |
Red Flags - STOP
- Skipping quality gates
- Committing directly to main/master
- Missing issue reference in commit
- Adding Co-Authored-By or AI attribution
- Pushing without tests passing
- Secrets detected in staged files
- Branch name contains special characters
- Suspicious or phishing remote domain detected
If any red flag triggered: Stop and fix before proceeding.
Step 0: Early Exit Check
git diff --cached --name-only
No staged files? Inform user to run git add first. Exit immediately.
Step 1: Verify GitHub Remote
git remote -v | grep -E '(^|[^.])github\.com[/:]'
which gh || echo "Install GitHub CLI: brew install gh"
Validate remote URL format:
- ✅
git@github.com:owner/repo.git - ✅
https://github.com/owner/repo.git - ❌
git@github.com.malicious.com:owner/repo.git(phishing domain)
Check for suspicious patterns:
# Extract domain and check for phishing indicators
REMOTE_DOMAIN=$(git remote -v | grep -oP '(?<=@|//)[^:/]+' | head -1)
if echo "$REMOTE_DOMAIN" | grep -qE '\.(com|org|io|net|co|app)\.'; then
echo "WARNING: Possible phishing domain detected: $REMOTE_DOMAIN"
# DO NOT proceed - ASK USER below
fi
If suspicious domain detected:
- STOP immediately
- Show warning with the detected domain
- ASK USER: "Suspicious remote domain detected:
<domain>. This looks like a phishing domain. Do you want to proceed anyway?" - Only proceed if user explicitly confirms
Example:
"WARNING: Your git remote is set to
github.com.malicious.comwhich appears to be a phishing domain (impersonating github.com).Do you want to proceed anyway? (y/N)"
Do NOT proceed without explicit user confirmation.
Multiple remotes? Ask user which remote to use.
Step 2: Run Quality Gates
Run checks. Stop immediately on failure (|| exit 1).
Language Projects
| Language | Commands |
|---|---|
| Python | ruff check . && mypy . && pytest || exit 1 |
| JS/TS | npm run lint && npm test || exit 1 |
| Go | go fmt ./... && go vet ./... && go test ./... || exit 1 |
| Java | mvn test || exit 1 or ./gradlew test || exit 1 |
| C/C++ | cmake --build build && ctest --test-dir build || exit 1 |
Skills
If changes include skills/*/SKILL.md:
Run each check in sequence. Stop on failure (|| exit 1).
# 1. YAML frontmatter validation
python3 -c "import yaml; yaml.safe_load(open('SKILL.md').read().split('---')[1])" || exit 1
# 2. Discoverability check (MUST run)
npx skills install . --list || exit 1
# 3. Evals verification
test -f evals.json && echo "evals.json exists" || echo "No evals.json"
# 4. Security checks
# Check for actual secret assignments (KEY='value' or KEY="value" patterns)
# Skip evals.json (test data) and documentation patterns
grep -lE "(API_KEY|SECRET|PASSWORD|TOKEN|PRIVATE_KEY|CONNECTION_STRING)\s*=\s*['\"][^'\"]{8,}['\"]" SKILL.md 2>/dev/null && echo "ERROR: Secrets detected" && exit 1 || true
| Check | Command | Purpose |
|---|---|---|
| YAML frontmatter | python3 -c "..." |
Valid syntax |
| Discoverable | npx skills install . --list |
REQUIRED - Can be found |
| Skills audit | npx skills audit . |
Compliance check |
| Skills check | npx skills-check . |
Quality validation |
| Evals verification | test -f evals.json |
Verify evals file |
| Security - secrets | grep -lE 'KEY.*=.*['\"][^'\"]{8,}' SKILL.md |
No hardcoded secrets (excludes docs/test data) |
| Security - shell injection | `grep -lE '$(.*) | ' + '.*${ |
| Security - unsafe exec | `grep -lE '(exec | eval |
Security Check Pattern Details:
The secrets check uses context-aware detection to reduce false positives:
| Pattern | Flags | Reason |
|---|---|---|
API_KEY='sk-12345678' |
✅ YES | Actual assignment with value |
API_KEY="secret123" |
✅ YES | Actual assignment with value |
Scan for API_KEY, PASSWORD |
❌ NO | Documentation (no assignment) |
"assertions": ["API_KEY"] |
❌ NO | Test assertion (in evals.json) |
API_KEY=<your-key> |
❌ NO | Placeholder (no actual value) |
Pattern explanation:
\s*=\s*- Requires assignment operator['\"][^'\"]{8,}['\"]- Requires quoted value of 8+ chars (real secrets are longer)
If ANY security check fails:
- STOP immediately - Do not proceed
- Fix the security issue (use env vars, input validation, safe APIs)
- Re-run all checks
- Only proceed when all security checks pass
Report:
Check Status
───────────────────────────────────────
Lint ✅/❌
Test ✅/❌
Build ✅/❌
Skills - YAML ✅/❌
Skills - Discoverable ✅/❌
Skills - Audit ✅/❌
Skills - Check ✅/❌
Skills - Evals file ✅/❌/N/A
Skills - Security ✅/❌
Security check failures are blocking. Fix before committing.
Step 2.5: Secrets Detection
CRITICAL: Check for secrets before committing.
# Check for actual secret assignments
# Excludes: evals.json (test data), documentation patterns
git diff --cached --name-only | grep -v 'evals\.json$' | xargs grep -l -E "(API_KEY|SECRET|PASSWORD|TOKEN|PRIVATE_KEY|CONNECTION_STRING)\s*=\s*['\"][^'\"]{8,}['\"]" 2>/dev/null || true
If secrets found:
- STOP immediately
- Remove secrets from files
- Use environment variables or secret management
- Add patterns to
.gitignore
Note: evals.json is excluded because it contains test data for security detection testing.
Common secret patterns:
.envfilesAPI_KEY=,SECRET=,TOKEN=- Private keys (
-----BEGIN PRIVATE KEY-----) - AWS credentials (
AKIA...)
Step 3: Review Changes
git diff --cached --stat
git diff --cached
Step 4: Create or Reference Issue
Ask: "Existing issue number, or create new?"
Create new:
gh issue create --title "<type>: <description>" --body "## Summary"
Types: feat, fix, docs, refactor, test, chore
Step 5: Feature Branch Decision
Check current branch first:
git branch --show-current
Decision logic:
| Current Branch | Action |
|---|---|
main or master |
Create new: git checkout -b feature/<name> |
feature/* or other |
ASK USER: "You're on branch <name>. Stay on this branch or create a new one?" |
IMPORTANT: If already on a feature branch, you MUST ask the user. Do not assume they want to stay or create new.
Example prompt to user:
"You're currently on branch
feature/add-login. Would you like to:
- Stay on this branch and commit here, or
- Create a new feature branch?"
Wait for user response before proceeding.
digraph branch_decision {
rankdir=TB
node [shape=box]
start [label="Check current branch" shape=diamond]
main [label="On main/master?"]
create [label="Create: git checkout -b feature/<name>"]
ask [label="ASK USER: Stay on current branch\nor create new?" shape=oval style=filled fillcolor=yellow]
done [label="Proceed to commit"]
start -> main
main -> create [label="yes"]
main -> ask [label="no (already on feature branch)"]
ask -> done [label="user chooses to stay"]
ask -> create [label="user chooses new"]
create -> done
}
Branch naming: feature/<type>-short-description
Check for unsafe characters before sanitizing:
if echo "$USER_INPUT" | grep -qE '[;&|$(\''"` ]'; then
echo "WARNING: Unsafe characters detected in branch name"
fi
Sanitize branch names:
BRANCH_NAME=$(echo "$USER_INPUT" | tr -cd 'a-zA-Z0-9/-' | tr '[:upper:]' '[:lower:]')
[ -z "$BRANCH_NAME" ] && echo "ERROR: Branch name is empty after sanitization" && exit 1
Allowed characters: letters, numbers, hyphens, forward slashes
Forbidden: ;, &, |, $, backticks, spaces, special chars
Step 6: Commit
git commit -m "<type>: <description>
<details>
Closes #<issue>"
CRITICAL: Never add Co-Authored-By or AI attribution.
Step 7: Push to GitHub
git push -u origin $(git branch --show-current)
Push rejected? Handle merge conflicts (see below).
Merge Conflict Handling
git pull --rebase origin $(git branch --show-current)
If conflicts:
- Edit conflicted files (look for
<<<<<<<markers) git add <resolved-files>git rebase --continue- Retry push
Step 8: Create Pull Request
Ask user about draft PR:
"Create as regular PR or draft PR?"
Wait for user response before proceeding.
# Regular PR
gh pr create --title "<type>: <description>" --body "Closes #<issue>"
# Draft PR (if user chose draft)
gh pr create --draft --title "<type>: <description>" --body "Closes #<issue>"
Step 9: Verify PR
gh pr view
Confirm:
- PR URL is accessible
- CI checks are running
- Base branch is correct
Common Mistakes
| Mistake | Fix |
|---|---|
| Skipping quality gates | Always run Step 2 |
| Committing to main | Create feature branch first |
| Missing issue reference | Include Closes #N |
| Adding Co-Authored-By | Never add AI attribution |
| Pushing without tests | Quality gates must pass |
| Ignoring merge conflicts | Resolve before push |
| Committing secrets | Run Step 2.5, use .gitignore |
| Skill security issues | Fix secrets/injection/unsafe-exec before commit |
| Unsafe branch names | Sanitize with tr -cd |
| Suspicious remote domain | Verify URL, reject phishing domains |
More from melodypapa/uncertainty
sync-req
Use when creating or maintaining ISO/IEC/IEEE 29148 requirements with bidirectional traceability between code and requirements. Handles extraction, generation, sync, deviation detection, and test design derivation using ISO 29119-4 techniques.
9req-traceability
Use when requirements need extraction from code, test cases need derivation from requirements, coverage gaps need analysis, or traceability between requirements, code, and tests is required. Triggers for UNCOVERED_REQ, STALE_TEST, TEST_DRIFT, requirements-code deviations, ISO 29148/29119-4 compliance, or user mentions 'requirements out of sync' or 'test coverage'.
8