name: 'Ruling Update and Notify' description: 'Consumes ruling artifacts from test jobs, updates expectations, and notifies via PR comments' author: 'SonarSource' inputs: ruling-failed: description: 'Whether the ruling test failed (true/false)' required: true outputs: has-differences: description: 'Whether there are ruling differences (true/false)' value: ${{ steps.check-diff.outputs.has-differences }} fix-pr-url: description: 'URL of the fix PR if created' value: ${{ steps.create-fix-pr.outputs.fix-pr-url }} runs: using: 'composite' steps: - name: Install uv if: inputs.ruling-failed == 'true' uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 with: enable-cache: true - name: Find ruling directory id: ruling-paths if: inputs.ruling-failed == 'true' shell: bash run: python3 "${{ github.action_path }}/find_ruling_directory.py" - name: Setup environment variables id: setup-env shell: bash env: RULING_FAILED: ${{ inputs.ruling-failed }} GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} run: | if [[ "$RULING_FAILED" != true && "$RULING_FAILED" != false ]]; then echo "::error::ruling-failed must be true or false" exit 1 fi if [ -n "$GITHUB_PR_NUMBER" ]; then IS_PR=true PR_NUMBER="$GITHUB_PR_NUMBER" else IS_PR=false PR_NUMBER="" fi TARGET_REF="${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" if ! [[ "$TARGET_REF" =~ ^[a-zA-Z0-9][a-zA-Z0-9/_.-]*$ ]]; then echo "::error::Invalid target ref: $TARGET_REF" exit 1 fi echo "is-pr=$IS_PR" >> "$GITHUB_OUTPUT" echo "pr-number=$PR_NUMBER" >> "$GITHUB_OUTPUT" echo "target-ref=$TARGET_REF" >> "$GITHUB_OUTPUT" - name: Check for auto-update loop if: inputs.ruling-failed == 'true' shell: bash run: | LAST_COMMIT_MSG=$(git log -1 --format=%B) if echo "$LAST_COMMIT_MSG" | grep -q "🤖 Generated with GitHub Actions"; then echo "::warning::Last commit was an auto-update, skipping to prevent infinite loop" echo "skip-update=true" >> "$GITHUB_ENV" else echo "skip-update=false" >> "$GITHUB_ENV" fi - name: Download ruling artifacts id: download-artifacts if: inputs.ruling-failed == 'true' && env.skip-update == 'false' continue-on-error: true uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: actual_* path: ruling-artifacts-temp # merge-multiple must be true: with download-artifact v8, when a single # artifact matches the pattern, merge-multiple: false places the artifact # contents directly in the path directory (not in a named subdirectory). # This broke the sync step which expected actual_* subdirectories. # Using merge-multiple: true gives consistent behavior regardless of # the number of matching artifacts. merge-multiple: true - name: Sync ruling artifacts if: inputs.ruling-failed == 'true' && env.skip-update == 'false' shell: bash env: RULING_ROOT: ${{ steps.ruling-paths.outputs.ruling-root }} DOWNLOAD_OUTCOME: ${{ steps.download-artifacts.outcome }} run: python3 "${{ github.action_path }}/sync_ruling_artifacts.py" - name: Check for differences id: check-diff shell: bash env: RULING_ROOT: ${{ steps.ruling-paths.outputs.ruling-root }} RULING_FAILED: ${{ inputs.ruling-failed }} run: | if [ "$RULING_FAILED" != true ]; then echo "has-differences=false" >> "$GITHUB_OUTPUT" exit 0 fi # Check if there are uncommitted changes in the ruling directory # produced by artifact sync. if [ -n "$(git status --porcelain -- "$RULING_ROOT/")" ]; then echo "has-differences=true" >> "$GITHUB_OUTPUT" else echo "has-differences=false" >> "$GITHUB_OUTPUT" fi - name: Create fix PR id: create-fix-pr if: | inputs.ruling-failed == 'true' && env.skip-update == 'false' && steps.check-diff.outputs.has-differences == 'true' shell: bash env: GH_TOKEN: ${{ github.token }} TARGET_REF: ${{ steps.setup-env.outputs.target-ref }} PR_NUMBER: ${{ steps.setup-env.outputs.pr-number }} RULING_ROOT: ${{ steps.ruling-paths.outputs.ruling-root }} run: python3 "${{ github.action_path }}/create_fix_pr.py" - name: Post ruling diff comment if: steps.setup-env.outputs.is-pr == 'true' && steps.create-fix-pr.outputs.fix-pr-url != '' uses: SonarSource/core-languages-tooling-public/ruling-diff-comment@master with: pr-number: ${{ steps.setup-env.outputs.pr-number }} repository: ${{ github.repository }} base-sha: ${{ steps.create-fix-pr.outputs.fix-base-sha }} head-sha: ${{ steps.create-fix-pr.outputs.fix-sha }} sources-root: ${{ steps.ruling-paths.outputs.sources-root }} env: GH_TOKEN: ${{ github.token }} - name: Cleanup stale fix PR if: | env.skip-update != 'true' && (inputs.ruling-failed != 'true' || steps.check-diff.outputs.has-differences != 'true') shell: bash env: GH_TOKEN: ${{ github.token }} TARGET_REF: ${{ steps.setup-env.outputs.target-ref }} run: python3 "${{ github.action_path }}/cleanup_fix_pr.py"