From 3e274b1e96ad7332c829a0aa8dca369e00684ff6 Mon Sep 17 00:00:00 2001 From: Holger Schmermbeck Date: Sun, 9 Nov 2025 17:44:01 +0100 Subject: [PATCH 1/3] feat: add Git conflict marker detection - Add check-conflict-markers.sh script (95 lines) - Integrate CI workflow for automated checks - Document usage and troubleshooting - Scans for <<<<<<, =======, >>>>>>>, ||||||| markers - Prevents commits with unresolved merge conflicts - Update CHANGELOG.md --- .github/workflows/check-conflict-markers.yml | 27 +++ CHANGELOG.md | 7 + docs/scripts/CHECK_CONFLICT_MARKERS.md | 196 +++++++++++++++++++ scripts/check-conflict-markers.sh | 89 +++++++++ 4 files changed, 319 insertions(+) create mode 100644 .github/workflows/check-conflict-markers.yml create mode 100644 docs/scripts/CHECK_CONFLICT_MARKERS.md create mode 100755 scripts/check-conflict-markers.sh diff --git a/.github/workflows/check-conflict-markers.yml b/.github/workflows/check-conflict-markers.yml new file mode 100644 index 0000000..655b3e7 --- /dev/null +++ b/.github/workflows/check-conflict-markers.yml @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2025 SecPal Contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +name: Check for Merge Conflict Markers + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + contents: read + +jobs: + check-conflicts: + name: Check for Git Conflict Markers + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run conflict marker check + run: | + chmod +x scripts/check-conflict-markers.sh + ./scripts/check-conflict-markers.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index fc409e8..b9a9022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **Git Conflict Marker Detection** - Automated check for unresolved merge conflicts + - `scripts/check-conflict-markers.sh` - Scans all tracked files for conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`, `|||||||`) + - `.github/workflows/check-conflict-markers.yml` - CI integration (runs on all PRs and pushes to main) + - `docs/scripts/CHECK_CONFLICT_MARKERS.md` - Complete usage guide with examples and troubleshooting + - Exit codes: 0 = clean, 1 = conflicts detected + - Prevents accidental commits of broken code from merge conflicts + - Colored output shows exact file locations and line numbers - **RBAC Phase 3: API Endpoints & Authorization** - Role management REST API (#107) - `POST /api/v1/users/{id}/roles` - Assign role with temporal parameters (valid_from, valid_until, auto_revoke) - `GET /api/v1/users/{id}/roles` - List user roles with expiry info (is_active, is_expired status) diff --git a/docs/scripts/CHECK_CONFLICT_MARKERS.md b/docs/scripts/CHECK_CONFLICT_MARKERS.md new file mode 100644 index 0000000..7fc1f39 --- /dev/null +++ b/docs/scripts/CHECK_CONFLICT_MARKERS.md @@ -0,0 +1,196 @@ + + +# Git Conflict Marker Detection + +The `check-conflict-markers.sh` script detects unresolved Git merge conflict markers in tracked files to prevent accidental commits of broken code. + +## Problem + +When resolving merge conflicts, developers sometimes forget to remove conflict markers: + +```bash +<<<<<<< HEAD +code from current branch +======= +code from incoming branch +>>>>>>> feature-branch +``` + +These markers cause: + +- **Syntax errors** in source code +- **Runtime failures** in scripts and configuration files +- **Broken builds** in CI/CD pipelines +- **Production incidents** if deployed + +## Solution + +This script automatically detects conflict markers in all tracked text files before they reach the repository. + +## Usage + +### Manual Check + +```bash +# Check all tracked files +./scripts/check-conflict-markers.sh +``` + +### CI/CD Integration + +The script runs automatically in CI via GitHub Actions on every PR and push to `main`. + +### Pre-commit Hook + +Add to `.git/hooks/pre-commit`: + +```bash +#!/bin/bash +# Run conflict marker check +if [ -f scripts/check-conflict-markers.sh ]; then + ./scripts/check-conflict-markers.sh || exit 1 +fi +``` + +## Detected Patterns + +The script detects these conflict markers: + +| Marker | Meaning | +| ---------------- | ------------------------------- | +| `<<<<<<<` | Start of conflict (from HEAD) | +| `=======` | Separator between changes | +| `>>>>>>>` | End of conflict (from incoming) | +| `\|\|\|\|\|\|\|` | Optional: diff3 style marker | + +## Exit Codes + +- `0` - No conflict markers found ✅ +- `1` - Conflict markers detected ❌ + +## Example Output + +### Success (No Conflicts) + +```bash +═══════════════════════════════════════════════════════════════ +Git Conflict Marker Detection +═══════════════════════════════════════════════════════════════ + +───────────────────────────────────────────────────── +Checked files: 111 +✓ No conflict markers found +═══════════════════════════════════════════════════════════════ +``` + +### Failure (Conflicts Found) + +```bash +═══════════════════════════════════════════════════════════════ +Git Conflict Marker Detection +═══════════════════════════════════════════════════════════════ + +✗ Conflict markers detected: + +File: .git/hooks/pre-push + Line 73: <<<<<<< Updated upstream... + +File: src/main.py + Line 42: =======... + +───────────────────────────────────────────────────── +Checked files: 111 +✗ Found conflict markers in files + +Action required: +1. Open the affected files +2. Search for conflict markers: <<<<<<<, =======, >>>>>>> +3. Manually resolve the conflicts +4. Remove all conflict markers +5. Test your changes +6. Commit again + +═══════════════════════════════════════════════════════════════ +``` + +## How to Resolve Conflicts + +1. **Locate the markers** - The script shows file names and line numbers +2. **Review both changes** - Understand code from both branches +3. **Choose or merge** - Keep one version, the other, or combine both +4. **Remove markers** - Delete all `<<<<<<<`, `=======`, `>>>>>>>` lines +5. **Test** - Verify the code works correctly +6. **Commit** - Try committing again + +## Common Scenarios + +### False Positives + +The script only checks lines **starting with** conflict markers, reducing false positives. If you legitimately need these patterns in your code (e.g., documentation), indent them: + +```markdown + + + <<<<<<< This won't trigger (indented) +``` + +### Binary Files + +Binary files are automatically skipped - only text files are checked. + +### .git Directory + +The `.git` directory itself is excluded from checks (uses `git ls-files`). + +## Integration with Other Tools + +### Pre-commit Framework + +```yaml +# .pre-commit-config.yaml +repos: + - repo: local + hooks: + - id: check-conflict-markers + name: Check for conflict markers + entry: ./scripts/check-conflict-markers.sh + language: script + pass_filenames: false +``` + +### CI/CD Pipelines + +```yaml +# GitHub Actions (already included) +- name: Check conflict markers + run: ./scripts/check-conflict-markers.sh +``` + +## Troubleshooting + +### "Permission denied" + +```bash +chmod +x scripts/check-conflict-markers.sh +``` + +### "file: command not found" + +Install the `file` utility: + +```bash +# Ubuntu/Debian +sudo apt install file + +# macOS +brew install file +``` + +## See Also + +- [Preflight Scripts](../scripts/preflight.sh) - Quality Gate Checks +- [System Requirements Check](CHECK_SYSTEM_REQUIREMENTS.md) - Development Prerequisites +- [Git Merge Conflicts](https://git-scm.com/docs/git-merge#_how_conflicts_are_presented) - Official Git Documentation diff --git a/scripts/check-conflict-markers.sh b/scripts/check-conflict-markers.sh new file mode 100755 index 0000000..15d88a9 --- /dev/null +++ b/scripts/check-conflict-markers.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2025 SecPal Contributors +# SPDX-License-Identifier: MIT + +# ============================================================================ +# Git Conflict Marker Detection +# ============================================================================ +# Detects unresolved Git merge conflict markers in tracked files to prevent +# accidental commits of broken code. +# +# Exit codes: +# 0 - No conflict markers found +# 1 - Conflict markers detected +# ============================================================================ + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Conflict marker patterns +MARKERS=( + "<<<<<<< " # Start of conflict (from HEAD) + "=======" # Separator between changes + ">>>>>>> " # End of conflict (from incoming) + "||||||" # Optional: diff3 style marker +) + +CONFLICTS_FOUND=0 +CHECKED_FILES=0 + +echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" +echo -e "${BLUE}Git Conflict Marker Detection${NC}" +echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" +echo "" + +# Get list of tracked files (excluding .git directory) +while IFS= read -r -d '' file; do + # Skip binary files and non-text files + if file "$file" | grep -q "text"; then + CHECKED_FILES=$((CHECKED_FILES + 1)) + + # Check each conflict marker pattern + for marker in "${MARKERS[@]}"; do + if grep -n "^${marker}" "$file" > /dev/null 2>&1; then + if [ $CONFLICTS_FOUND -eq 0 ]; then + echo -e "${RED}✗ Conflict markers detected:${NC}" + echo "" + fi + + CONFLICTS_FOUND=$((CONFLICTS_FOUND + 1)) + echo -e "${YELLOW}File:${NC} $file" + + # Show lines with conflict markers + grep -n "^${marker}" "$file" | while IFS=: read -r line_num line_content; do + echo -e " ${RED}Line $line_num:${NC} ${line_content:0:60}..." + done + echo "" + break # Only report once per file + fi + done + fi +done < <(git ls-files -z) + +echo -e "${BLUE}─────────────────────────────────────────────────────${NC}" +echo -e "Checked files: ${CHECKED_FILES}" + +if [ $CONFLICTS_FOUND -eq 0 ]; then + echo -e "${GREEN}✓ No conflict markers found${NC}" + echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" + exit 0 +else + echo -e "${RED}✗ Found conflict markers in files${NC}" + echo "" + echo -e "${YELLOW}Action required:${NC}" + echo "1. Open the affected files" + echo "2. Search for conflict markers: <<<<<<<, =======, >>>>>>>" + echo "3. Manually resolve the conflicts" + echo "4. Remove all conflict markers" + echo "5. Test your changes" + echo "6. Commit again" + echo "" + echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" + exit 1 +fi From 97bffc2e5dc54340db7521d76fb53d5056c6827b Mon Sep 17 00:00:00 2001 From: Holger Schmermbeck Date: Sun, 9 Nov 2025 18:15:35 +0100 Subject: [PATCH 2/3] fix: resolve Copilot review comments in PR #124 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix diff3 marker pattern: Change '||||||' to '||||||| ' (6→7 pipes + space) - Update CHANGELOG: Correct conflict marker pattern to '||||||| ' - Update docs table: Fix diff3 marker pattern with trailing space - Fix docs link: Change '../scripts/preflight.sh' to 'PREFLIGHT.md' Resolves 4 Copilot review comments. Nitpick #4 (copyright format) is correct as-is. --- CHANGELOG.md | 2 +- docs/scripts/CHECK_CONFLICT_MARKERS.md | 14 +++++++------- scripts/check-conflict-markers.sh | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9a9022..df5a40b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **Git Conflict Marker Detection** - Automated check for unresolved merge conflicts - - `scripts/check-conflict-markers.sh` - Scans all tracked files for conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`, `|||||||`) + - `scripts/check-conflict-markers.sh` - Scans all tracked files for conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`, `|||||||` with space) - `.github/workflows/check-conflict-markers.yml` - CI integration (runs on all PRs and pushes to main) - `docs/scripts/CHECK_CONFLICT_MARKERS.md` - Complete usage guide with examples and troubleshooting - Exit codes: 0 = clean, 1 = conflicts detected diff --git a/docs/scripts/CHECK_CONFLICT_MARKERS.md b/docs/scripts/CHECK_CONFLICT_MARKERS.md index 7fc1f39..2c49139 100644 --- a/docs/scripts/CHECK_CONFLICT_MARKERS.md +++ b/docs/scripts/CHECK_CONFLICT_MARKERS.md @@ -59,12 +59,12 @@ fi The script detects these conflict markers: -| Marker | Meaning | -| ---------------- | ------------------------------- | -| `<<<<<<<` | Start of conflict (from HEAD) | -| `=======` | Separator between changes | -| `>>>>>>>` | End of conflict (from incoming) | -| `\|\|\|\|\|\|\|` | Optional: diff3 style marker | +| Marker | Meaning | +| ----------------------- | ------------------------------- | +| `<<<<<<<` | Start of conflict (from HEAD) | +| `=======` | Separator between changes | +| `>>>>>>>` | End of conflict (from incoming) | +| `\|\|\|\|\|\|\|` (+ space) | Optional: diff3 style marker | ## Exit Codes @@ -191,6 +191,6 @@ brew install file ## See Also -- [Preflight Scripts](../scripts/preflight.sh) - Quality Gate Checks +- [Preflight Script Documentation](PREFLIGHT.md) - Quality Gate Checks - [System Requirements Check](CHECK_SYSTEM_REQUIREMENTS.md) - Development Prerequisites - [Git Merge Conflicts](https://git-scm.com/docs/git-merge#_how_conflicts_are_presented) - Official Git Documentation diff --git a/scripts/check-conflict-markers.sh b/scripts/check-conflict-markers.sh index 15d88a9..b35b87b 100755 --- a/scripts/check-conflict-markers.sh +++ b/scripts/check-conflict-markers.sh @@ -27,7 +27,7 @@ MARKERS=( "<<<<<<< " # Start of conflict (from HEAD) "=======" # Separator between changes ">>>>>>> " # End of conflict (from incoming) - "||||||" # Optional: diff3 style marker + "||||||| " # Optional: diff3 style marker ) CONFLICTS_FOUND=0 From bd256b93e054dda128e2a2e144a5d14a8b761980 Mon Sep 17 00:00:00 2001 From: Holger Schmermbeck Date: Sun, 9 Nov 2025 18:55:44 +0100 Subject: [PATCH 3/3] docs: indent conflict marker examples in CHECK_CONFLICT_MARKERS.md Prevents false positives in conflict marker detection script by indenting the example markers in documentation. --- docs/scripts/CHECK_CONFLICT_MARKERS.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/scripts/CHECK_CONFLICT_MARKERS.md b/docs/scripts/CHECK_CONFLICT_MARKERS.md index 2c49139..081eb55 100644 --- a/docs/scripts/CHECK_CONFLICT_MARKERS.md +++ b/docs/scripts/CHECK_CONFLICT_MARKERS.md @@ -12,11 +12,11 @@ The `check-conflict-markers.sh` script detects unresolved Git merge conflict mar When resolving merge conflicts, developers sometimes forget to remove conflict markers: ```bash -<<<<<<< HEAD -code from current branch -======= -code from incoming branch ->>>>>>> feature-branch + <<<<<<< HEAD + code from current branch + ======= + code from incoming branch + >>>>>>> feature-branch ``` These markers cause: @@ -59,11 +59,11 @@ fi The script detects these conflict markers: -| Marker | Meaning | -| ----------------------- | ------------------------------- | -| `<<<<<<<` | Start of conflict (from HEAD) | -| `=======` | Separator between changes | -| `>>>>>>>` | End of conflict (from incoming) | +| Marker | Meaning | +| -------------------------- | ------------------------------- | +| `<<<<<<<` | Start of conflict (from HEAD) | +| `=======` | Separator between changes | +| `>>>>>>>` | End of conflict (from incoming) | | `\|\|\|\|\|\|\|` (+ space) | Optional: diff3 style marker | ## Exit Codes