name: JSON Data Validation on: pull_request_target: types: [opened, synchronize, reopened, edited] branches: - main paths: - 'repo/pathing/**/*.json' workflow_dispatch: inputs: path: description: '要验证的路径' required: true default: 'repo/pathing' type: string auto_fix: description: '是否自动修复问题' required: false default: true type: boolean pr_number: description: '关联的 PR 号' required: false type: string jobs: validate-json: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha || github.sha }} token: ${{ secrets.GITHUB_TOKEN }} repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies run: | pip install packaging semver - name: Debug file structure run: | echo "Current directory: $(pwd)" echo "List files in root:" ls -la echo "List files in build directory (if exists):" if [ -d "build" ]; then ls -la build/ else echo "build directory does not exist" mkdir -p build fi - name: Setup Git and repositories run: | git config --global user.name "GitHub Actions Bot" git config --global user.email "actions@github.com" # 确保远程仓库设置正确 echo "当前远程仓库配置:" git remote -v # 设置上游仓库(upstream)和origin UPSTREAM_REPO="https://github.com/${{ github.repository }}.git" ORIGIN_REPO="https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}.git" echo "设置upstream指向主仓库: $UPSTREAM_REPO" git remote remove upstream 2>/dev/null || true git remote add upstream $UPSTREAM_REPO echo "确保origin指向正确的仓库: $ORIGIN_REPO" git remote set-url origin $ORIGIN_REPO 2>/dev/null || git remote add origin $ORIGIN_REPO # 获取最新的主仓库和分支 echo "获取远程分支信息" git fetch upstream git fetch origin # 显示远程仓库配置 echo "更新后的远程仓库配置:" git remote -v # 检查是否处于PR环境 if [ -n "${{ github.event.pull_request.head.ref }}" ]; then echo "检测到PR,切换到PR分支: ${{ github.event.pull_request.head.ref }}" git checkout "${{ github.event.pull_request.head.ref }}" elif [ -n "${{ github.ref_name }}" ]; then echo "切换到分支: ${{ github.ref_name }}" git checkout "${{ github.ref_name }}" else echo "创建临时分支" git checkout -b temp-validation-branch fi - name: Prepare validation script run: | git show upstream/main:build/validate.py > build/validate.py 2>/dev/null # 检查文件是否成功获取并且非空 if [ ! -s "build/validate.py" ]; then echo "无法从上游仓库获取validate.py文件,终止流程" exit 1 else echo "成功获取validate.py" fi - name: Get PR information if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number != '' }} id: pr_info uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | try { const pr = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: parseInt(${{ github.event.inputs.pr_number }}) }); core.setOutput('head_sha', pr.data.head.sha); core.setOutput('head_ref', pr.data.head.ref); core.setOutput('head_repo', pr.data.head.repo.full_name); core.setOutput('found', 'true'); console.log(`找到 PR #${{ github.event.inputs.pr_number }}`); console.log(`Head SHA: ${pr.data.head.sha}`); console.log(`Head Ref: ${pr.data.head.ref}`); console.log(`Head Repo: ${pr.data.head.repo.full_name}`); // 如果找到PR,切换到PR分支 const exec = require('child_process').execSync; if (pr.data.head.ref) { console.log(`切换到PR分支: ${pr.data.head.ref}`); exec(`git checkout ${pr.data.head.ref}`); } } catch (error) { console.log(`获取 PR #${{ github.event.inputs.pr_number }} 信息失败: ${error.message}`); core.setOutput('found', 'false'); } - name: Get changed files id: changed_files if: github.event_name == 'pull_request_target' run: | # 使用upstream/main作为比较基准 CHANGED_FILES=$(git diff --name-only upstream/main HEAD | grep -E '^repo/pathing/.*\.json$' || true) echo "Changed JSON files in repo/pathing compared to upstream/main:" echo "$CHANGED_FILES" echo "changed_files=$CHANGED_FILES" >> $GITHUB_OUTPUT if [ -z "$CHANGED_FILES" ]; then echo "No JSON files changed in repo/pathing directory" fi - name: Run validation and correction env: GITHUB_ACTOR: ${{ github.actor }} PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HEAD_REF: ${{ github.event.pull_request.head.ref || steps.pr_info.outputs.head_ref || '' }} PR_REPO: ${{ github.event.pull_request.head.repo.full_name || steps.pr_info.outputs.head_repo || github.repository }} VALIDATE_PATH: ${{ github.event.inputs.path || 'repo/pathing' }} AUTO_FIX: ${{ github.event.inputs.auto_fix || 'true' }} CHANGED_FILES: ${{ steps.changed_files.outputs.changed_files }} run: | # 根据触发方式决定验证路径和是否自动修复 if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then echo "手动触发模式,验证路径: ${VALIDATE_PATH}" python build/validate.py ${VALIDATE_PATH} $([[ "${AUTO_FIX}" == "true" ]] && echo "--fix") else echo "PR 触发模式,仅验证修改的 JSON 文件" if [ -z "$CHANGED_FILES" ]; then echo "没有找到修改的 JSON 文件,跳过验证" exit 0 fi # 单独验证每个修改的文件 for file in $CHANGED_FILES; do echo "验证文件: $file" python build/validate.py "$file" --fix done fi # 检查是否有文件被修改 if [ -n "$(git status --porcelain)" ]; then echo "发现修改,提交更改" git add . git commit -m "自动修复 JSON 格式和版本号 [ci skip]" # 确定当前分支 CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) echo "当前分支: ${CURRENT_BRANCH}" if [ "$CURRENT_BRANCH" = "HEAD" ]; then # 如果在detached HEAD状态,使用正确的方式推送 if [ -n "${HEAD_REF}" ]; then echo "在detached HEAD状态,使用HEAD_REF推送: ${HEAD_REF}" git push origin HEAD:${HEAD_REF} else echo "无法确定目标分支,跳过推送" fi else # 常规推送 echo "推送到分支: ${CURRENT_BRANCH}" git push origin ${CURRENT_BRANCH} fi else echo "没有文件被修改,无需提交" fi - name: Add PR comment if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number != '' && steps.pr_info.outputs.found == 'true') }} continue-on-error: true uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const fs = require('fs'); const pr_number = ${{ github.event.pull_request.number || github.event.inputs.pr_number }}; if (fs.existsSync('validation_notes.md')) { const message = fs.readFileSync('validation_notes.md', 'utf8'); await github.rest.issues.createComment({ issue_number: pr_number, owner: context.repo.owner, repo: context.repo.repo, body: message }); } else { console.log("没有发现 validation_notes.md 文件"); // 检查是否有文件被修改并提交 const { execSync } = require('child_process'); let commitMessage = ''; try { const lastCommit = execSync('git log -1 --pretty=%B').toString().trim(); if (lastCommit.includes('自动修复')) { commitMessage = '✅ 校验完成并自动修复了一些问题。修改已提交到PR中。'; } else { commitMessage = '✅ 校验完成,没有发现需要修复的问题'; } } catch (error) { commitMessage = '✅ 校验完成,没有发现需要修复的问题'; } await github.rest.issues.createComment({ issue_number: pr_number, owner: context.repo.owner, repo: context.repo.repo, body: commitMessage }); }