name: Code Style Check on: push: pull_request: workflow_dispatch: permissions: contents: write pull-requests: write jobs: clang-format: runs-on: ubuntu-latest env: STYLE_FIX_BRANCH: codex/style-autofix-${{ github.run_id }}-${{ github.run_attempt }} steps: - name: Checkout uses: actions/checkout@v4 - name: Install clang-format run: | sudo apt-get update sudo apt-get install -y clang-format - name: Resolve base ref id: base shell: bash run: | set -euo pipefail if [[ "${{ github.event_name }}" == "pull_request" ]]; then echo "base_ref=${{ github.event.pull_request.head.ref }}" >> "$GITHUB_OUTPUT" else echo "base_ref=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" fi - name: Detect auto-fix capability id: capability shell: bash run: | set -euo pipefail can_fix=false if [[ "${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then can_fix=true elif [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]]; then can_fix=true fi echo "can_fix=$can_fix" >> "$GITHUB_OUTPUT" - name: Run clang-format and detect drift id: format shell: bash run: | set -euo pipefail mapfile -t files < <( git ls-files \ '*.c' '*.h' '*.cc' '*.cpp' '*.cxx' '*.hpp' '*.hxx' \ | grep -Ev '^(limine/|third_party/|build/|build-cmake/)' || true ) if [[ ${#files[@]} -eq 0 ]]; then echo "No C/C++ files to check." echo "changed=false" >> "$GITHUB_OUTPUT" exit 0 fi for f in "${files[@]}"; do clang-format -i "$f" done if git diff --quiet -- "${files[@]}"; then echo "changed=false" >> "$GITHUB_OUTPUT" echo "Code style check passed." exit 0 fi echo "changed=true" >> "$GITHUB_OUTPUT" echo "Style drift detected. Auto-fix patch:" echo "" git diff -- "${files[@]}" - name: Create auto-fix PR id: cpr if: steps.format.outputs.changed == 'true' && steps.capability.outputs.can_fix == 'true' continue-on-error: true uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.STYLE_PR_TOKEN != '' && secrets.STYLE_PR_TOKEN || secrets.GITHUB_TOKEN }} commit-message: "style: auto-format C/C++ sources with clang-format" title: "style: auto-format C/C++ sources" body: | This PR was generated automatically by CI style check. - Trigger: `${{ github.event_name }}` - Base branch: `${{ steps.base.outputs.base_ref }}` - Formatter: `clang-format` branch: ${{ env.STYLE_FIX_BRANCH }} base: ${{ steps.base.outputs.base_ref }} delete-branch: true labels: | automated style - name: Report auto-fix PR result if: steps.format.outputs.changed == 'true' && steps.capability.outputs.can_fix == 'true' shell: bash run: | if [[ "${{ steps.cpr.outcome }}" == "success" ]]; then echo "Auto-fix PR created: ${{ steps.cpr.outputs.pull-request-url }}" exit 0 fi echo "::warning::Auto-fix branch was pushed, but PR creation is blocked by repository policy." echo "::warning::Enable 'Allow GitHub Actions to create and approve pull requests' OR set secret STYLE_PR_TOKEN (PAT with repo scope)." echo "Manual PR URL:" echo "https://github.com/${{ github.repository }}/compare/${{ steps.base.outputs.base_ref }}...${{ env.STYLE_FIX_BRANCH }}?expand=1" exit 0 - name: Fail when style drift cannot be auto-fixed if: steps.format.outputs.changed == 'true' && steps.capability.outputs.can_fix != 'true' shell: bash run: | echo "Style drift found, but this event does not have permission to auto-create a fix PR." echo "Please run clang-format locally and push the result." exit 1