From f9e1138e229a5aa25577d481d47ded3bffca8874 Mon Sep 17 00:00:00 2001 From: Matt Lydon <489306+Mpfk@users.noreply.github.com> Date: Wed, 13 May 2026 12:20:38 -0700 Subject: [PATCH] chore(template): remove residual tests and docs from Auto development Removes bats test files that validated Auto's own internal infrastructure and docs that were manual checklists from the development process. These are noise for template users; tests/ and docs/ are now clean placeholders. Closes #75 --- .../ADR-001-auto-detect-test-command.md | 71 ------ docs/orchestrator_init_detection.md | 70 ------ docs/readme_quickstart.md | 22 -- tests/agent_flow.bats | 34 --- tests/agent_instructions.bats | 202 ------------------ tests/detect_test_cmd.bats | 144 ------------- tests/label_sync_workflows.bats | 33 --- tests/pre_push_gate.bats | 118 ---------- tests/workflow_policy.bats | 137 ------------ 9 files changed, 831 deletions(-) delete mode 100644 docs/decisions/ADR-001-auto-detect-test-command.md delete mode 100644 docs/orchestrator_init_detection.md delete mode 100644 docs/readme_quickstart.md delete mode 100644 tests/agent_flow.bats delete mode 100644 tests/agent_instructions.bats delete mode 100644 tests/detect_test_cmd.bats delete mode 100644 tests/label_sync_workflows.bats delete mode 100644 tests/pre_push_gate.bats delete mode 100644 tests/workflow_policy.bats diff --git a/docs/decisions/ADR-001-auto-detect-test-command.md b/docs/decisions/ADR-001-auto-detect-test-command.md deleted file mode 100644 index 81a558a..0000000 --- a/docs/decisions/ADR-001-auto-detect-test-command.md +++ /dev/null @@ -1,71 +0,0 @@ -# ADR-001: Auto-detect test command - -## Status - -**Accepted** (2026-04-11) - -## Context - -The primary friction point in the multi-agent workflow template setup was requiring -users to manually edit `workflow.conf` before git hooks would work. Users would -clone a repository, attempt to push to an issue branch, and encounter cryptic -errors when the pre-push hook tried to run an empty `TEST_CMD`. - -This manual configuration step blocked adoption and created poor first-run experience. - -## Options Considered - -**Option A: Smarter defaults** -Set `TEST_CMD="echo 'No tests configured'"` in template to avoid empty command errors. - -**Option B: Auto-detect from project markers** -Scan for `package.json`, `pyproject.toml`, `go.mod`, etc. at hook runtime and -infer the appropriate test command. - -**Option C: Interactive setup script** -Provide a `setup.sh` script that prompts users for test command and writes -`workflow.conf`. - -**Option D: Agent-driven config** -Have orchestrator/issue agents automatically detect and configure test commands -during repository initialization. - -## Decision - -Implemented **Options A + B combined** with **Option D** as an enhancement: - -1. **Empty default signals auto-detect**: `TEST_CMD=""` in template triggers detection -2. **Runtime detection with write-back**: `.githooks/lib/detect.sh` scans project markers -3. **Agent integration**: Orchestrator Phase A also runs detection on repository init -4. **Option C rejected**: Interactive scripts add complexity and still require manual steps - -### Key Design Choices - -**Write-back vs runtime-only** -Chose write-back to `workflow.conf` for transparency and debuggability. Users can -see what was detected and manually override if needed. - -**Monorepo multiple-marker behavior** -When multiple markers found (e.g., `package.json` + `pyproject.toml`), warn and -skip rather than choosing first. Safety over convenience. - -**Shared library approach** -Created `.githooks/lib/detect.sh` sourced by both local hooks and CI to avoid -code duplication and ensure consistent behavior. - -## Consequences - -**Positive:** -- Fresh clones with standard project structures work immediately -- No manual configuration required for Node.js, Python, Go, Rust, Java projects -- Clear error messages guide users toward resolution -- Transparent auto-detection with manual override capability - -**Negative:** -- Monorepos and unusual project structures still require one manual configuration step -- Additional complexity in hook logic -- Edge cases (multiple test commands, custom runners) need documentation - -**Trade-offs:** -- Prioritized common case convenience over edge case flexibility -- Added detection logic increases maintenance surface but dramatically improves UX \ No newline at end of file diff --git a/docs/orchestrator_init_detection.md b/docs/orchestrator_init_detection.md deleted file mode 100644 index b609ce9..0000000 --- a/docs/orchestrator_init_detection.md +++ /dev/null @@ -1,70 +0,0 @@ -# Orchestrate Phase A Detection - Verification Checklist - -This checklist verifies that the Orchestrate agent correctly detects project types and writes `workflow.conf` during Phase A initialization. - -## Test Scenarios - -### ✓ Scenario 1: Fresh clone with package.json -- **Setup:** Clone with `package.json` and `workflow.conf` containing `TEST_CMD=""` -- **Expected:** Orchestrate Phase A detects Node.js project, sets `TEST_CMD="npm test"` in workflow.conf, commits change -- **Verification:** - - [ ] `workflow.conf` updated with `TEST_CMD="npm test"` - - [ ] Git commit made with message `chore(config): auto-detect test runner as npm test` - - [ ] Orchestrate agent reports what was detected to user -- **Status:** ✅ READY FOR TESTING - Feature implemented in Phase A step 4 - -### ✓ Scenario 2: Fresh clone with pyproject.toml -- **Setup:** Clone with `pyproject.toml` and `workflow.conf` containing `TEST_CMD=""` -- **Expected:** Orchestrate Phase A detects Python project, sets `TEST_CMD="pytest"` in workflow.conf -- **Verification:** - - [ ] `workflow.conf` updated with `TEST_CMD="pytest"` - - [ ] Git commit made with message `chore(config): auto-detect test runner as pytest` - - [ ] Orchestrate agent reports detection to user -- **Status:** ✅ READY FOR TESTING - Feature implemented in Phase A step 4 - -### ✓ Scenario 3: Fresh clone with multiple markers -- **Setup:** Clone with both `package.json` and `pyproject.toml`, `workflow.conf` has `TEST_CMD=""` -- **Expected:** Orchestrate agent warns user about multiple markers, does not write workflow.conf -- **Verification:** - - [ ] Warning message displayed about multiple project markers - - [ ] User asked to set `TEST_CMD` manually in workflow.conf - - [ ] No changes made to workflow.conf - - [ ] No git commits for config changes -- **Status:** ✅ READY FOR TESTING - Feature implemented in Phase A step 4 - -### ✓ Scenario 4: Fresh clone with no markers -- **Setup:** Clone with no project marker files, `workflow.conf` has `TEST_CMD=""` -- **Expected:** Orchestrate agent continues without error, notes config will be set later during scaffolding -- **Verification:** - - [ ] No error thrown - - [ ] Message noting workflow.conf will be configured during scaffolding - - [ ] workflow.conf remains unchanged - - [ ] Phase A continues to next step -- **Status:** ✅ READY FOR TESTING - Feature implemented in Phase A step 4 - -### ✓ Scenario 5: Clone where TEST_CMD already set -- **Setup:** Clone with `workflow.conf` containing `TEST_CMD="make test"` -- **Expected:** Orchestrate agent skips detection entirely, does not override manual configuration -- **Verification:** - - [ ] Detection step skipped - - [ ] workflow.conf remains unchanged - - [ ] No git commits for config changes - - [ ] Phase A continues normally -- **Status:** ✅ READY FOR TESTING - Feature implemented in Phase A step 4 - -## Implementation Requirements - -The Orchestrate agent must add this step to Phase A after branch creation: - -1. Check if `workflow.conf` has `TEST_CMD=""` (empty) -2. If empty, scan for project markers using same priority as `.githooks/lib/detect.sh` -3. Handle single marker: update workflow.conf and commit -4. Handle multiple markers: warn user, ask for manual config -5. Handle no markers: continue with note about later scaffolding -6. Handle existing config: skip detection entirely - -## Notes - -- This is a documentation/instruction change to `.github/agents/orchestrate.agent.md` -- Not executable code that can be unit tested -- Verification requires manual QA following this checklist \ No newline at end of file diff --git a/docs/readme_quickstart.md b/docs/readme_quickstart.md deleted file mode 100644 index 5ff0833..0000000 --- a/docs/readme_quickstart.md +++ /dev/null @@ -1,22 +0,0 @@ -# README Quick Start Verification Checklist - -Manual verification checklist for README.md Quick Start simplification (Issue #6). - -## Acceptance Criteria - -- [x] Quick Start has exactly 2 steps -- [x] Step 2 mentions `@orchestrate` -- [x] No mention of "Edit workflow.conf" in Quick Start or For a new project sections -- [x] `git config core.hooksPath .githooks` appears in developer setup note, not Quick Start -- [x] Configuration subsection explains auto-detection, not manual editing -- [x] No broken links - -## Current Status: PASSING ✅ - -The README.md now meets all acceptance criteria: -- ✅ Quick Start reduced from 4 steps to exactly 2 steps -- ✅ Step 2 mentions `@orchestrate` -- ✅ Removed "Edit `workflow.conf`" from guided path -- ✅ Moved `git config core.hooksPath .githooks` to developer setup note -- ✅ Configuration subsection explains auto-detection instead of manual editing -- ✅ All links verified and working \ No newline at end of file diff --git a/tests/agent_flow.bats b/tests/agent_flow.bats deleted file mode 100644 index d738e15..0000000 --- a/tests/agent_flow.bats +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bats -# Content verification tests for docs/auto/agent-flow.md (issue #48) - -AGENT_FLOW="docs/auto/agent-flow.md" - -@test "flowchart does not contain '+ branch' in the GitHub Issue node" { - run grep -n "create GitHub Issue + branch" "$AGENT_FLOW" - [ "$status" -ne 0 ] -} - -@test "Phase Coordination table Init row does not contain '+ branch'" { - run grep -n "Creates GitHub Issue + branch" "$AGENT_FLOW" - [ "$status" -ne 0 ] -} - -@test "Phase Coordination table Implement row contains 'Creates feature branch'" { - run grep -n "Creates feature branch" "$AGENT_FLOW" - [ "$status" -eq 0 ] -} - -@test "CI failure row contains 'prior retrospective'" { - run grep -n "prior retrospective" "$AGENT_FLOW" - [ "$status" -eq 0 ] -} - -@test "Transition Rules in-progress to review contains 'CI checks are green on the PR'" { - run grep -n "CI checks are green on the PR" "$AGENT_FLOW" - [ "$status" -eq 0 ] -} - -@test "Orchestrate agent description does not mention feature branch in status/draft context" { - run grep -n "status/draft.*feature branch\|feature branch.*status/draft\|and feature branch" "$AGENT_FLOW" - [ "$status" -ne 0 ] -} diff --git a/tests/agent_instructions.bats b/tests/agent_instructions.bats deleted file mode 100644 index 1ca0510..0000000 --- a/tests/agent_instructions.bats +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env bats -# Content verification tests for agent instruction files (issue #48) - -REPO_ROOT="/Users/matt/Documents/PounceTek/Developer/GitHub/mpfk/auto" -ORCHESTRATE="$REPO_ROOT/.github/agents/orchestrate.agent.md" -COPILOT_INSTRUCTIONS="$REPO_ROOT/.github/copilot-instructions.md" -DEVELOP="$REPO_ROOT/.github/agents/develop.agent.md" - -# Test 1: orchestrate.agent.md does NOT contain branch creation in Phase A -@test "orchestrate.agent.md: Phase A does not create a feature branch" { - # Phase A ends before Phase B; check that branch creation is not a numbered step in Phase A - # Extract Phase A content (between "## Phase A" and "## Phase B") - phase_a=$(awk '/^## Phase A/,/^## Phase B/' "$ORCHESTRATE") - run echo "$phase_a" - [[ "$output" != *"Create a feature branch"* ]] -} - -# Test 2: orchestrate.agent.md DOES contain Phase C implementation section -@test "orchestrate.agent.md: Phase C implementation section exists" { - grep -q "Phase C: Implementation Handoff" "$ORCHESTRATE" -} - -@test "orchestrate.agent.md: asks whether to assign Copilot develop agent" { - grep -q "Would you like me to assign the Copilot 'develop' Agent to begin work" "$ORCHESTRATE" -} - -# Test 3: copilot-instructions.md does NOT have "Create a feature branch" as step 3 -@test "copilot-instructions.md: branch creation is not step 3 in step-by-step" { - # Step 3 should NOT be "Create a feature branch" - run grep -n "^3\. \*\*Create a feature branch" "$COPILOT_INSTRUCTIONS" - [ "$status" -ne 0 ] -} - -# Test 4: copilot-instructions.md DOES contain retrospective reference for CI failure -@test "copilot-instructions.md: CI failure re-invocation mentions retrospective" { - grep -q "retrospective from the last develop agent run" "$COPILOT_INSTRUCTIONS" -} - -# Test 5: develop.agent.md DOES contain Retrospective Logging section -@test "develop.agent.md: Retrospective Logging section exists" { - grep -q "Retrospective Logging" "$DEVELOP" -} - -# Test 6: develop.agent.md DOES contain add_issue_comment instruction -@test "develop.agent.md: add_issue_comment is referenced in retrospective instructions" { - grep -q "add_issue_comment" "$DEVELOP" -} - -# Test 7: develop.agent.md DOES contain list_issue_comments instruction -@test "develop.agent.md: list_issue_comments is referenced in retrospective instructions" { - grep -q "list_issue_comments" "$DEVELOP" -} - -# Test 8: copilot-instructions.md Phase 1 does NOT mention branch creation -@test "copilot-instructions.md: Phase 1 Init does not mention feature branch" { - phase1=$(awk '/^### Phase 1: Init/,/^### Phase 2:/' "$COPILOT_INSTRUCTIONS") - run echo "$phase1" - [[ "$output" != *"feature branch"* ]] -} - -# Test 9: copilot-instructions.md GitHub-Native Triggers item 6 includes retrospective -@test "copilot-instructions.md: GitHub-Native Triggers CI failure item mentions prior retrospective" { - grep -q "prior retrospective as context" "$COPILOT_INSTRUCTIONS" -} - -# --- Issue #52: MCP tool name and fallback tests --- - -ISSUE_AGENT="$REPO_ROOT/.github/agents/issue.agent.md" -STATE_GUARD="$REPO_ROOT/.github/workflows/issue-state-guard.yml" -ISSUE_NATIVE="$REPO_ROOT/.github/workflows/issue-native-automation.yml" -PR_SYNC="$REPO_ROOT/.github/workflows/pr-issue-sync.yml" -CI_GATE="$REPO_ROOT/.github/workflows/ci-issue-gate.yml" - -# Test: issue.agent.md uses correct MCP tool names (no old names) -@test "issue.agent.md: no references to deprecated create_issue tool name" { - run grep -w "create_issue" "$ISSUE_AGENT" - [ "$status" -ne 0 ] -} - -@test "issue.agent.md: no references to deprecated update_issue tool name" { - run grep -w "update_issue" "$ISSUE_AGENT" - [ "$status" -ne 0 ] -} - -@test "issue.agent.md: no references to deprecated get_issue tool name" { - run grep -w "get_issue" "$ISSUE_AGENT" - [ "$status" -ne 0 ] -} - -@test "issue.agent.md: references issue_write tool" { - grep -q "issue_write" "$ISSUE_AGENT" -} - -@test "issue.agent.md: references issue_read tool" { - grep -q "issue_read" "$ISSUE_AGENT" -} - -# Test: issue.agent.md sets intermediate labels -@test "issue.agent.md: sets status/researching label" { - grep -q "status/researching" "$ISSUE_AGENT" -} - -@test "issue.agent.md: sets status/planning label" { - grep -q "status/planning" "$ISSUE_AGENT" -} - -# Test: issue.agent.md has fallback section -@test "issue.agent.md: has fallback section for update failure" { - grep -q "Fallback" "$ISSUE_AGENT" -} - -@test "issue.agent.md: ready handoff references Copilot develop agent" { - grep -q "Assign to Copilot 'develop' Agent to begin work" "$ISSUE_AGENT" -} - -# Test: orchestrate.agent.md uses correct MCP tool names (no old names) -@test "orchestrate.agent.md: no references to deprecated create_issue tool name" { - run grep -w "create_issue" "$ORCHESTRATE" - [ "$status" -ne 0 ] -} - -@test "orchestrate.agent.md: no references to deprecated update_issue tool name" { - run grep -w "update_issue" "$ORCHESTRATE" - [ "$status" -ne 0 ] -} - -@test "orchestrate.agent.md: no references to deprecated get_issue tool name" { - run grep -w "get_issue" "$ORCHESTRATE" - [ "$status" -ne 0 ] -} - -@test "orchestrate.agent.md: references issue_write tool" { - grep -q "issue_write" "$ORCHESTRATE" -} - -@test "orchestrate.agent.md: includes explicit Gate 1 decision wording" { - grep -q "Gate 1: Approve this plan to move the issue to status/ready" "$ORCHESTRATE" -} - -# Test: issue-state-guard.yml no longer auto-advances draft -> ready (3A) -@test "issue-state-guard.yml: does not auto-advance to status/ready" { - run grep -q "Auto-advanced to status/ready" "$STATE_GUARD" - [ "$status" -ne 0 ] -} - -# Test: assignment path no longer auto-promotes to status/ready -@test "issue-native-automation.yml: copilot assignment does not auto-promote status/ready" { - run grep -q "Plan is present but label wasn't updated — auto-promote" "$ISSUE_NATIVE" - [ "$status" -ne 0 ] -} - -# Test: /auto plan-approved is restricted to maintainers -@test "issue-native-automation.yml: plan approval checks maintainer association" { - grep -q "author_association" "$ISSUE_NATIVE" - grep -q "OWNER" "$ISSUE_NATIVE" - grep -q "MEMBER" "$ISSUE_NATIVE" -} - -# Test: /auto plan-approved validates source status -@test "issue-native-automation.yml: plan approval requires planning or researching status" { - grep -q "status/planning" "$ISSUE_NATIVE" - grep -q "status/researching" "$ISSUE_NATIVE" -} - -# Test: PR sync no longer promotes status/review from ready_for_review or review_requested -@test "pr-issue-sync.yml: does not reference ready_for_review transitions" { - run grep -q "ready_for_review" "$PR_SYNC" - [ "$status" -ne 0 ] -} - -@test "pr-issue-sync.yml: does not reference review_requested transitions" { - run grep -q "review_requested" "$PR_SYNC" - [ "$status" -ne 0 ] -} - -# Test: CI-driven workflow exists and targets status/review on green checks -@test "ci-issue-gate.yml: exists and sets status/review" { - grep -q "name: CI Issue Gate" "$CI_GATE" - grep -q "status/review" "$CI_GATE" -} - -@test "issue-native-automation.yml: ready comment mentions Copilot develop agent" { - grep -q "Assign to Copilot 'develop' Agent to begin work" "$ISSUE_NATIVE" -} - -@test "issue-native-automation.yml: plan approved comment includes next step" { - grep -q "Gate 1 approved" "$ISSUE_NATIVE" -} - -@test "ci-issue-gate.yml: review kickoff comment includes next-step instructions" { - grep -q "Review kickoff" "$CI_GATE" - grep -q "Invoke Copilot 'review' Agent" "$CI_GATE" -} - -@test "ci-issue-gate.yml: excludes own workflow run from check evaluation" { - grep -q "ownRunToken" "$CI_GATE" - grep -q "details.includes(ownRunToken)" "$CI_GATE" -} - -@test "pr-issue-sync.yml: merge completion comment includes gate closeout" { - grep -q "Gate 2 complete" "$PR_SYNC" -} diff --git a/tests/detect_test_cmd.bats b/tests/detect_test_cmd.bats deleted file mode 100644 index 6444a9d..0000000 --- a/tests/detect_test_cmd.bats +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env bats -# Tests for detect_test_cmd() function in .githooks/lib/detect.sh - -load '/Users/matt/Documents/PounceTek/Developer/GitHub/mpfk/auto/.githooks/lib/detect.sh' 2>/dev/null || { - echo "⚠️ .githooks/lib/detect.sh not found - this is expected during RED phase" >&2 - exit 1 -} - -setup() { - # Create a temporary directory for each test - TEST_DIR=$(mktemp -d) - cd "$TEST_DIR" - - # Create a mock workflow.conf - cat > workflow.conf << 'EOF' -# workflow.conf — Project-specific workflow configuration -TEST_CMD="npm test" -SRC_DIRS="src/ lib/" -TEST_DIRS="tests/ test/" -MAIN_BRANCH="main" -EOF - - # Unset TEST_CMD to start fresh - unset TEST_CMD -} - -teardown() { - # Clean up test directory - if [ -n "$TEST_DIR" ] && [ -d "$TEST_DIR" ]; then - cd / - rm -rf "$TEST_DIR" - fi -} - -@test "detect_test_cmd() with package.json sets npm test and writes back to workflow.conf" { - # Create package.json - echo '{"name":"test","scripts":{"test":"echo test"}}' > package.json - - # Reset workflow.conf to empty TEST_CMD - sed -i '' 's/TEST_CMD=.*/TEST_CMD=""/' workflow.conf - - # Run detection (direct call to persist exports) - detect_test_cmd - - [ "$TEST_CMD" = "npm test" ] - - # Check that workflow.conf was updated - grep -q 'TEST_CMD="npm test"' workflow.conf -} - -@test "detect_test_cmd() with pyproject.toml sets pytest and writes back" { - # Create pyproject.toml - echo '[project]' > pyproject.toml - echo 'name = "test"' >> pyproject.toml - - # Reset workflow.conf to empty TEST_CMD - sed -i '' 's/TEST_CMD=.*/TEST_CMD=""/' workflow.conf - - # Run detection (direct call to persist exports) - detect_test_cmd - - [ "$TEST_CMD" = "pytest" ] - - # Check that workflow.conf was updated - grep -q 'TEST_CMD="pytest"' workflow.conf -} - -@test "detect_test_cmd() with go.mod sets go test ./... and writes back" { - # Create go.mod - echo 'module test' > go.mod - echo 'go 1.19' >> go.mod - - # Reset workflow.conf to empty TEST_CMD - sed -i '' 's/TEST_CMD=.*/TEST_CMD=""/' workflow.conf - - # Run detection (direct call to persist exports) - detect_test_cmd - - [ "$TEST_CMD" = "go test ./..." ] - - # Check that workflow.conf was updated - grep -q 'TEST_CMD="go test ./..."' workflow.conf -} - -@test "detect_test_cmd() with multiple markers shows warning and does not set TEST_CMD" { - # Create multiple project markers - echo '{"name":"test"}' > package.json - echo '[project]' > pyproject.toml - - # Reset workflow.conf to empty TEST_CMD - sed -i '' 's/TEST_CMD=.*/TEST_CMD=""/' workflow.conf - - # Run detection - run detect_test_cmd - - [ "$status" -eq 0 ] - [ -z "$TEST_CMD" ] - - # Should contain warning about multiple markers - [[ "$stderr" == *"Multiple project markers found"* ]] - [[ "$stderr" == *"set TEST_CMD in workflow.conf"* ]] - - # workflow.conf should not be modified (still empty) - grep -q 'TEST_CMD=""' workflow.conf -} - -@test "detect_test_cmd() with no markers shows helpful message and does not set TEST_CMD" { - # No project markers created - - # Reset workflow.conf to empty TEST_CMD - sed -i '' 's/TEST_CMD=.*/TEST_CMD=""/' workflow.conf - - # Run detection - run detect_test_cmd - - [ "$status" -eq 0 ] - [ -z "$TEST_CMD" ] - - # Should contain helpful message - [[ "$stderr" == *"No project markers found"* ]] - - # workflow.conf should not be modified - grep -q 'TEST_CMD=""' workflow.conf -} - -@test "detect_test_cmd() with TEST_CMD already set does not override" { - # Create package.json - echo '{"name":"test"}' > package.json - - # Set TEST_CMD in environment - export TEST_CMD="custom test command" - - # Run detection - run detect_test_cmd - - [ "$status" -eq 0 ] - [ "$TEST_CMD" = "custom test command" ] - - # Should contain message about not overriding - [[ "$output" == *"TEST_CMD already set"* ]] - - # workflow.conf should not be modified - grep -q 'TEST_CMD="npm test"' workflow.conf -} \ No newline at end of file diff --git a/tests/label_sync_workflows.bats b/tests/label_sync_workflows.bats deleted file mode 100644 index ce6bb49..0000000 --- a/tests/label_sync_workflows.bats +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bats - -REPO_ROOT="/Users/matt/Documents/PounceTek/Developer/GitHub/mpfk/auto" -LABEL_SYNC="$REPO_ROOT/.github/workflows/labels-sync.yml" -REPO_SETUP="$REPO_ROOT/.github/workflows/repo-setup.yml" -PR_SYNC="$REPO_ROOT/.github/workflows/pr-issue-sync.yml" -CI_GATE="$REPO_ROOT/.github/workflows/ci-issue-gate.yml" - -@test "labels-sync.yml: manual-only trigger prevents bootstrap overlap" { - run grep -q '^ push:' "$LABEL_SYNC" - [ "$status" -ne 0 ] -} - -@test "labels-sync.yml: workflow_dispatch remains available for intentional reruns" { - grep -q '^ workflow_dispatch:' "$LABEL_SYNC" -} - -@test "repo-setup.yml: owns automatic setup on pushes to main" { - grep -q '^ push:' "$REPO_SETUP" - grep -q '^ branches: \[main\]' "$REPO_SETUP" -} - -@test "pr-issue-sync.yml: no direct status/review promotion on PR lifecycle" { - run grep -q "status/review" "$PR_SYNC" - [ "$status" -ne 0 ] -} - -@test "ci-issue-gate.yml: workflow_run trigger listens to CI workflows" { - grep -q '^ workflow_run:' "$CI_GATE" - grep -q 'Test Suite' "$CI_GATE" - grep -q 'Conventional Commits Check' "$CI_GATE" - grep -q 'Workflow Policy' "$CI_GATE" -} diff --git a/tests/pre_push_gate.bats b/tests/pre_push_gate.bats deleted file mode 100644 index 117766d..0000000 --- a/tests/pre_push_gate.bats +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env bats -# Tests for .githooks/pre-push.d/020-test-suite-gate.sh hook behavior - -setup() { - # Create a temporary directory for each test - TEST_DIR=$(mktemp -d) - cd "$TEST_DIR" - git init --quiet - git commit --allow-empty -m "initial" --quiet - - # Create a mock workflow.conf with empty TEST_CMD - cat > workflow.conf << 'EOF' -# workflow.conf — Project-specific workflow configuration -TEST_CMD="" -SRC_DIRS="src/ lib/" -TEST_DIRS="tests/ test/" -MAIN_BRANCH="main" -EOF - - # Create mock .githooks structure - mkdir -p .githooks/lib .githooks/pre-push.d - - # Copy the real detect.sh helper - cp /Users/matt/Documents/PounceTek/Developer/GitHub/mpfk/auto/.githooks/lib/detect.sh .githooks/lib/detect.sh - - # Create the updated pre-push hook that we want to implement - cat > .githooks/pre-push.d/020-test-suite-gate.sh << 'EOF' -#!/bin/bash -# Runs the full test suite before allowing a push. -REPO_ROOT="$(git rev-parse --show-toplevel)" -source "$REPO_ROOT/workflow.conf" - -# Source the shared detection helper -source "$REPO_ROOT/.githooks/lib/detect.sh" - -branch=$(git rev-parse --abbrev-ref HEAD) -if ! echo "$branch" | grep -qE '^issue/'; then - exit 0 -fi - -echo "Running test suite before push..." - -# Call detect_test_cmd to auto-detect or use existing TEST_CMD -detect_test_cmd - -# If no test command after detection, gracefully skip -if [ -z "${TEST_CMD:-}" ]; then - echo "⚠️ No test command configured or detected. Skipping test suite." - echo "Create package.json, pyproject.toml, go.mod, etc. or set TEST_CMD in workflow.conf" - exit 0 -fi - -# Run the test command -if ! eval "$TEST_CMD" 2>&1; then - echo "" - echo "ERROR: Test suite failed. Fix failing tests before pushing." - exit 1 -fi -EOF - chmod +x .githooks/pre-push.d/020-test-suite-gate.sh - - # Create a feature branch to trigger the hook - git checkout -b issue/123 --quiet -} - -teardown() { - # Clean up test directory - if [ -n "$TEST_DIR" ] && [ -d "$TEST_DIR" ]; then - cd / - rm -rf "$TEST_DIR" - fi -} - -@test "pre-push hook: TEST_CMD empty, no project markers → graceful skip, exit 0" { - # No project files, TEST_CMD empty - should skip gracefully - - run ./.githooks/pre-push.d/020-test-suite-gate.sh - - [ "$status" -eq 0 ] - [[ "$output" == *"Running test suite before push..."* ]] - [[ "$output" == *"No test command configured or detected. Skipping test suite."* ]] -} - -@test "pre-push hook: TEST_CMD empty, package.json present → test command runs" { - # Create package.json with a successful test command - echo '{"scripts":{"test":"echo \"All tests passed\""}}' > package.json - - run ./.githooks/pre-push.d/020-test-suite-gate.sh - - [ "$status" -eq 0 ] - [[ "$output" == *"Running test suite before push..."* ]] - [[ "$output" == *"Detected test command: npm test"* ]] - [[ "$output" == *"All tests passed"* ]] -} - -@test "pre-push hook: TEST_CMD set manually in workflow.conf → test command runs directly" { - # Set TEST_CMD manually in workflow.conf - sed -i '' 's/TEST_CMD=""/TEST_CMD="echo Manual test passed"/' workflow.conf - - run ./.githooks/pre-push.d/020-test-suite-gate.sh - - [ "$status" -eq 0 ] - [[ "$output" == *"Running test suite before push..."* ]] - [[ "$output" == *"TEST_CMD already set to: echo Manual test passed"* ]] - [[ "$output" == *"Manual test passed"* ]] -} - -@test "pre-push hook: test suite fails → hook exits 1" { - # Create package.json with a failing test command - echo '{"scripts":{"test":"echo \"Test failed\"; exit 1"}}' > package.json - - run ./.githooks/pre-push.d/020-test-suite-gate.sh - - [ "$status" -eq 1 ] - [[ "$output" == *"Running test suite before push..."* ]] - [[ "$output" == *"Test failed"* ]] - [[ "$output" == *"ERROR: Test suite failed. Fix failing tests before pushing."* ]] -} \ No newline at end of file diff --git a/tests/workflow_policy.bats b/tests/workflow_policy.bats deleted file mode 100644 index 55945b9..0000000 --- a/tests/workflow_policy.bats +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env bats - -REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)" -POLICY_WORKFLOW="$REPO_ROOT/.github/workflows/workflow-policy.yml" - -setup() { - command -v node >/dev/null || skip "Node.js is required for workflow policy tests" -} - -# The workflow script is a YAML block scalar under `script: |` with 12-space -# indentation. The first non-empty line indented to 6 spaces is outside that -# block and marks the end of the extracted script. -extract_script() { - awk ' - /script: \|/ { in_script = 1; next } - in_script { - if ($0 ~ /^ [^ ]/) exit - if ($0 ~ /^ /) { - sub(/^ /, "", $0) - print - } else { - print "" - } - } - ' "$POLICY_WORKFLOW" -} - -run_policy() { - local pr_json="$1" - local issue_json="$2" - local script - script="$(extract_script)" - - run env WORKFLOW_SCRIPT="$script" PR_JSON="$pr_json" ISSUE_JSON="$issue_json" node <<'NODE' -const script = process.env.WORKFLOW_SCRIPT; -const pr = JSON.parse(process.env.PR_JSON); -const issue = JSON.parse(process.env.ISSUE_JSON); - -const context = { - repo: { owner: 'Mpfk', repo: 'auto' }, - payload: { pull_request: pr }, -}; - -const github = { - rest: { - issues: { - get: async ({ issue_number }) => { - if (!issue || issue.number !== issue_number) { - throw new Error('Not Found'); - } - return { data: issue }; - }, - }, - }, -}; - -let failed = null; -let info = null; -const core = { - setFailed: (message) => { - failed = message; - }, - info: (message) => { - info = message; - }, -}; - -(async () => { - // This evaluates repository-controlled workflow code so tests can validate - // real policy behavior from the workflow file itself. - // Do not reuse this pattern with untrusted/external input. - const fn = new Function('context', 'github', 'core', `return (async () => {\n${script}\n})();`); - await fn(context, github, core); - process.stdout.write(JSON.stringify({ failed, info })); -})().catch((error) => { - console.error(error); - process.exit(1); -}); -NODE -} - -@test "workflow-policy: issue/{N} branch passes without explicit closing text" { - run_policy '{"head":{"ref":"issue/67"},"title":"feat: branch-linked PR","body":"","draft":true}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":null'* ]] - [[ "$output" == *'"info":"Workflow policy checks passed for issue #67 (branch: issue/67)."'* ]] -} - -@test "workflow-policy: non-issue branch passes with valid closing keyword reference" { - run_policy '{"head":{"ref":"copilot/add-policy-update"},"title":"fix: relax policy","body":"fIxEs #67","draft":true}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":null'* ]] -} - -@test "workflow-policy: non-issue branch passes with resolves keyword reference" { - run_policy '{"head":{"ref":"copilot/add-policy-update"},"title":"fix: relax policy","body":"Resolves #67","draft":true}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":null'* ]] -} - -@test "workflow-policy: non-issue branch without linkage fails with actionable guidance" { - run_policy '{"head":{"ref":"copilot/add-policy-update"},"title":"fix: relax policy","body":"No issue linkage","draft":true}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":"PR must either use an issue/{number} branch or include a valid issue-closing reference'* ]] -} - -@test "workflow-policy: ready-for-review PR still requires linked issue in status/review" { - run_policy '{"head":{"ref":"copilot/add-policy-update"},"title":"fix: relax policy","body":"Closes #67","draft":false}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":"PR cannot be ready-for-review unless linked issue #67 is status/review."'* ]] -} - -@test "workflow-policy: issue/{N} ready-for-review PR still requires status/review" { - run_policy '{"head":{"ref":"issue/67"},"title":"fix: relax policy","body":"","draft":false}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":"PR cannot be ready-for-review unless linked issue #67 is status/review."'* ]] -} - -@test "workflow-policy: PR from main branch fails even with closing reference" { - run_policy '{"head":{"ref":"main"},"title":"fix: something","body":"Closes #67","draft":true}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":"PR must not be opened directly from the main branch'* ]] -} - -@test "workflow-policy: any named feature branch with closing reference passes" { - run_policy '{"head":{"ref":"my-feature-branch"},"title":"fix: something","body":"Closes #67","draft":true}' '{"number":67,"labels":[]}' - - [ "$status" -eq 0 ] - [[ "$output" == *'"failed":null'* ]] -}