Skip to content

Merge branch 'main' into copilot/fix-github-actions-job-failure #87

Merge branch 'main' into copilot/fix-github-actions-job-failure

Merge branch 'main' into copilot/fix-github-actions-job-failure #87

name: "Autofix (Maintenance)"

Check failure on line 1 in .github/workflows/autofix-maintenance.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/autofix-maintenance.yml

Invalid workflow file

(Line: 265, Col: 9): Unexpected value 'permissions'
on:
push:
branches: ["main"]
paths:
- "**/*.py"
- "**/*.{js,jsx,ts,tsx,mjs,cjs,json,yml,yaml,md,css,scss,html}"
- "**/*.{c,cc,cpp,cxx,h,hh,hpp,hxx}"
- "package.json"
- "package-lock.json"
- "requirements*.txt"
- "pyproject.toml"
- ".ruff.toml"
- "ruff.toml"
- ".eslintrc*"
- "eslint.config.*"
- ".prettierrc*"
- ".prettierignore"
schedule:
- cron: "15 4 * * 2"
workflow_dispatch:
inputs:
allow_unsafe_fixes:
description: "Allow potentially unsafe fixes (ruff --unsafe-fixes) for manual/scheduled runs"
type: boolean
default: false
open_autofix_pr:
description: "Open PR for push/schedule/manual runs when fixes exist"
type: boolean
default: true
run_autofix:
description: "Run autofixers"
type: boolean
default: true
permissions:
contents: read
concurrency:
group: autofix-maintenance-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
autofix:
if: >-
github.event_name != 'workflow_dispatch' || inputs.run_autofix
name: Autofix maintenance
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Harden runner
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0
with:
disable-sudo: false
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
fetch-depth: 0
persist-credentials: true
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: "3.12"
cache: "pip"
- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: "20"
- name: Cache npm
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
with:
path: |
~/.npm
~/.cache
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- id: scope
name: Build maintenance file scope
shell: bash
run: |
set -euo pipefail
: > .changed_files.txt
: > .changed_py.txt
: > .changed_js_like.txt
: > .changed_c_like.txt
git ls-files > .changed_files.txt || true
grep -E '\.py$' .changed_files.txt > .changed_py.txt || true
grep -E '\.(js|jsx|ts|tsx|mjs|cjs|json|yml|yaml|md|css|scss|html)$' .changed_files.txt > .changed_js_like.txt || true
grep -E '\.(c|cc|cpp|cxx|h|hh|hpp|hxx)$' .changed_files.txt > .changed_c_like.txt || true
echo "all_count=$(wc -l < .changed_files.txt | tr -d ' ')" >> "$GITHUB_OUTPUT"
echo "py_count=$(wc -l < .changed_py.txt | tr -d ' ')" >> "$GITHUB_OUTPUT"
echo "js_count=$(wc -l < .changed_js_like.txt | tr -d ' ')" >> "$GITHUB_OUTPUT"
echo "c_count=$(wc -l < .changed_c_like.txt | tr -d ' ')" >> "$GITHUB_OUTPUT"
- name: Install autofix tooling
shell: bash
run: |
set -euo pipefail
python -m pip install --upgrade pip
pip install "ruff>=0.6,<1.0"
if [ -f package.json ]; then
if [ -f package-lock.json ]; then
npm ci --no-audit --no-fund || npm install --no-audit --no-fund
else
npm install --no-audit --no-fund
fi
npx --no-install prettier --version >/dev/null 2>&1 || npm install --no-audit --no-fund --no-save prettier@3
else
npm install --global --no-fund --no-audit prettier@3
fi
if [ "${{ steps.scope.outputs.c_count }}" != "0" ]; then
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends clang-format
fi
- name: Log tool versions
shell: bash
run: |
set -euo pipefail
python --version
node --version
npm --version
ruff --version
if [ -f package.json ]; then
npx --no-install prettier --version || true
npx --no-install eslint --version || true
else
prettier --version || true
fi
- name: Run ruff fixes
continue-on-error: true
shell: bash
run: |
set -euo pipefail
if [ "${{ steps.scope.outputs.py_count }}" = "0" ]; then
echo "No Python files; skipping ruff."
exit 0
fi
RUN_UNSAFE="false"
if [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "schedule" ]; then
if [ "${{ inputs.allow_unsafe_fixes || 'false' }}" = "true" ]; then
RUN_UNSAFE="true"
fi
fi
if [ "$RUN_UNSAFE" = "true" ]; then
xargs -r ruff check --fix --unsafe-fixes --exit-zero < .changed_py.txt
else
xargs -r ruff check --fix --exit-zero < .changed_py.txt
fi
xargs -r ruff format < .changed_py.txt
- name: Run eslint fixes (if configured)
continue-on-error: true
shell: bash
run: |
set -euo pipefail
if [ "${{ steps.scope.outputs.js_count }}" = "0" ]; then
echo "No JS/TS/etc files; skipping eslint."
exit 0
fi
if [ -f package.json ] && npx --no-install eslint --version >/dev/null 2>&1; then
xargs -r npx eslint --fix --ext .js,.jsx,.ts,.tsx < .changed_js_like.txt || true
else
echo "eslint not available; skipping."
fi
- name: Run prettier write
continue-on-error: true
shell: bash
run: |
set -euo pipefail
if [ "${{ steps.scope.outputs.all_count }}" = "0" ]; then
echo "No repository files found; skipping prettier."
exit 0
fi
if [ -f package.json ]; then
xargs -r npx --no-install prettier --write --ignore-unknown < .changed_files.txt || true
else
xargs -r prettier --write --ignore-unknown < .changed_files.txt || true
fi
- name: Run clang-format (C/C++)
continue-on-error: true
shell: bash
run: |
set -euo pipefail
if [ "${{ steps.scope.outputs.c_count }}" = "0" ]; then
echo "No C/C++ files; skipping clang-format."
exit 0
fi
if command -v clang-format >/dev/null 2>&1; then
mapfile -t files < .changed_c_like.txt
if [ "${#files[@]}" -gt 0 ]; then
clang-format -i --style=file --fallback-style=LLVM "${files[@]}" || true
fi
else
echo "clang-format not installed; skipping."
fi
- name: Revert workflow file changes
shell: bash
run: |
set -euo pipefail
git restore --staged --worktree -- .github/workflows || true
- name: Verify formatter/linter state
continue-on-error: true
shell: bash
run: |
set -euo pipefail
if [ "${{ steps.scope.outputs.py_count }}" != "0" ]; then
xargs -r ruff check < .changed_py.txt || true
xargs -r ruff format --check < .changed_py.txt || true
fi
if [ "${{ steps.scope.outputs.js_count }}" != "0" ]; then
if [ -f package.json ] && npx --no-install eslint --version >/dev/null 2>&1; then
xargs -r npx eslint --ext .js,.jsx,.ts,.tsx < .changed_js_like.txt || true
fi
if [ -f package.json ]; then
xargs -r npx --no-install prettier --check --ignore-unknown < .changed_files.txt || true
else
xargs -r prettier --check --ignore-unknown < .changed_files.txt || true
fi
fi
- id: diff
name: Detect changes
shell: bash
run: |
set -euo pipefail
if git diff --quiet --exit-code; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
git --no-pager diff --stat
fi
- name: Create follow-up PR for autofixes
if: >-
steps.diff.outputs.changed == 'true' &&
github.repository == 'Bryan-Roe/Aria' &&
(github.event_name == 'push' ||
github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && inputs.open_autofix_pr))
permissions:
contents: write
pull-requests: write
uses: step-security/create-pull-request@50c103da2b9ca12cd5bc013fc6931051a5aa872b # v8.1.1
with:
base: ${{ github.ref_name }}
branch: chore/autofix-${{ github.run_id }}
commit-message: "ci(style): apply automated autofixes"
title: "ci(style): automated lint/format autofixes"
body: |
Automated lint/format updates from workflow run #${{ github.run_id }}.
Applied tools:
- ruff check --fix (+ optional --unsafe-fixes on schedule/manual)
- ruff format
- eslint --fix (if configured)
- prettier --write
- clang-format (if C/C++ files exist)
labels: |
automated
autofix
chore
delete-branch: true
sign-commits: false
token: ${{ secrets.GITHUB_TOKEN }}