name: Validate script formatting

on:
  push:
    branches:
      - main
  pull_request_target:
    paths:
      - "**/*.sh"
      - "**/*.func"

jobs:
  shfmt:
    name: Check changed files
    runs-on: ubuntu-latest
    permissions:
					 
      pull-requests: write

    steps:
      - name: Get pull request information
        if: github.event_name == 'pull_request_target'
        uses: actions/github-script@v7
        id: pr
        with:
          script: |
            const { data: pullRequest } = await github.rest.pulls.get({
              ...context.repo,
              pull_number: context.payload.pull_request.number,
            });
            return pullRequest;

      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Ensure the full history is fetched for accurate diffing
          ref: ${{ github.event_name == 'pull_request_target' && fromJSON(steps.pr.outputs.result).merge_commit_sha || '' }}

      - name: Get changed files
        id: changed-files
        run: |
          if ${{ github.event_name == 'pull_request_target' }}; then
              echo "files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ steps.pr.outputs.result && fromJSON(steps.pr.outputs.result).merge_commit_sha }} | grep -E '\.(sh|func)$' | xargs)" >> $GITHUB_OUTPUT
          else
              echo "files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | grep -E '\.(sh|func)$' | xargs)" >> $GITHUB_OUTPUT
          fi

      - name: Set up Go
        if: steps.changed-files.outputs.files != ''
        uses: actions/setup-go@v5

      - name: Install shfmt
        if: steps.changed-files.outputs.files != ''
        run: |
          go install mvdan.cc/sh/v3/cmd/shfmt@latest
          echo "$GOPATH/bin" >> $GITHUB_PATH

      - name: Run shfmt
        if: steps.changed-files.outputs.files != ''
        id: shfmt
        run: |
          set +e

									 
          shfmt_output=$(shfmt -d ${{ steps.changed-files.outputs.files }})
          if [[ $? -eq 0 ]]; then
            exit 0
          else
            echo "diff=\"$(echo -n "$shfmt_output" | base64 -w 0)\"" >> $GITHUB_OUTPUT
            printf "%s" "$shfmt_output"
            exit 1
          fi

      - name: Post comment with results
        if: always() && steps.changed-files.outputs.files != '' && github.event_name == 'pull_request_target'
        uses: actions/github-script@v7
        with:
          script: |
            const result = "${{ job.status }}" === "success" ? "success" : "failure";
            const diff = Buffer.from(
              ${{ steps.shfmt.outputs.diff }},
              "base64",
            ).toString();
            const issueNumber = context.payload.pull_request
              ? context.payload.pull_request.number
              : null;
            const commentIdentifier = "validate-formatting";
            let newCommentBody = `<!-- ${commentIdentifier}-start -->\n### Script formatting\n\n`;

            if (result === "failure") {
              newCommentBody +=
                `:x: We found issues in the formatting of the following changed files:\n\n\`\`\`diff\n${diff}\n\`\`\`\n`;
            } else {
              newCommentBody += `:rocket: All changed shell scripts are formatted correctly!\n`;
            }

            newCommentBody += `\n\n<!-- ${commentIdentifier}-end -->`;

            if (issueNumber) {
              const { data: comments } = await github.rest.issues.listComments({
                ...context.repo,
                issue_number: issueNumber,
              });

              const existingComment = comments.find(
                (comment) => comment.user.login === "github-actions[bot]",
																	 
              );

              if (existingComment) {
                if (existingComment.body.includes(commentIdentifier)) {
                  const re = new RegExp(
                    String.raw`<!-- ${commentIdentifier}-start -->[\s\S]*?<!-- ${commentIdentifier}-end -->`,
                    "",
                  );
                  newCommentBody = existingComment.body.replace(re, newCommentBody);
                } else {
                  newCommentBody = existingComment.body + "\n\n---\n\n" + newCommentBody;
                }

                await github.rest.issues.updateComment({
                  ...context.repo,
                  comment_id: existingComment.id,
                  body: newCommentBody,
                });
              } else {
                await github.rest.issues.createComment({
                  ...context.repo,
                  issue_number: issueNumber,
                  body: newCommentBody,
                });
              }
            }