sql_query_analyzer 0.5.2

Static analysis tool for SQL queries with 20 built-in rules for performance, security, and style
Documentation
name: 'SQL Query Analyzer'
description: 'Static analysis for SQL queries. Detects performance issues, security vulnerabilities, and style violations.'
author: 'RAprogramm'

branding:
  icon: 'database'
  color: 'blue'

inputs:
  schema:
    description: 'Path to SQL schema file'
    required: true
  queries:
    description: 'Path to SQL queries file (use - for stdin)'
    required: true
  dialect:
    description: 'SQL dialect (generic, mysql, postgresql, sqlite)'
    required: false
    default: 'generic'
  format:
    description: 'Output format (text, json, yaml, sarif)'
    required: false
    default: 'text'
  fail-on-warning:
    description: 'Fail if warnings are found'
    required: false
    default: 'false'
  fail-on-error:
    description: 'Fail if errors are found'
    required: false
    default: 'true'
  disabled-rules:
    description: 'Comma-separated list of rule IDs to disable'
    required: false
    default: ''
  post-comment:
    description: 'Post analysis as PR comment'
    required: false
    default: 'false'
  update-comment:
    description: 'Update existing comment instead of creating new'
    required: false
    default: 'true'
  upload-sarif:
    description: 'Upload SARIF results to GitHub Security tab'
    required: false
    default: 'false'

outputs:
  analysis:
    description: 'Analysis result'
    value: ${{ steps.analyze.outputs.analysis }}
  error-count:
    description: 'Number of errors found'
    value: ${{ steps.analyze.outputs.error_count }}
  warning-count:
    description: 'Number of warnings found'
    value: ${{ steps.analyze.outputs.warning_count }}
  exit-code:
    description: 'Exit code (0=ok, 1=warnings, 2=errors)'
    value: ${{ steps.analyze.outputs.exit_code }}

runs:
  using: 'composite'
  steps:
    - name: Download sql-query-analyzer
      shell: bash
      run: |
        VERSION="v0.1.0"
        ARCH="x86_64-unknown-linux-gnu"
        URL="https://github.com/RAprogramm/sql-query-analyzer/releases/download/${VERSION}/sql-query-analyzer-${ARCH}.tar.gz"

        curl -sL "$URL" | tar xz -C /tmp
        chmod +x /tmp/sql_query_analyzer
        echo "/tmp" >> $GITHUB_PATH

    - name: Run analysis
      id: analyze
      shell: bash
      run: |
        ARGS="analyze -s ${{ inputs.schema }} -q ${{ inputs.queries }}"
        ARGS="$ARGS --dialect ${{ inputs.dialect }}"
        ARGS="$ARGS -f ${{ inputs.format }}"
        ARGS="$ARGS --no-color"

        OUTPUT=$(sql_query_analyzer $ARGS 2>&1) || EXIT_CODE=$?
        EXIT_CODE=${EXIT_CODE:-0}

        echo "$OUTPUT"

        ERROR_COUNT=$(echo "$OUTPUT" | grep -oP '\d+(?= error)' | head -1 || echo "0")
        WARNING_COUNT=$(echo "$OUTPUT" | grep -oP '\d+(?= warning)' | head -1 || echo "0")

        echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
        echo "error_count=${ERROR_COUNT:-0}" >> $GITHUB_OUTPUT
        echo "warning_count=${WARNING_COUNT:-0}" >> $GITHUB_OUTPUT

        {
          echo "analysis<<EOF"
          echo "$OUTPUT"
          echo "EOF"
        } >> $GITHUB_OUTPUT

    - name: Generate SARIF
      id: sarif
      if: inputs.upload-sarif == 'true'
      shell: bash
      run: |
        sql_query_analyzer analyze \
          -s ${{ inputs.schema }} \
          -q ${{ inputs.queries }} \
          --dialect ${{ inputs.dialect }} \
          -f sarif > results.sarif || true

    - name: Upload SARIF
      if: inputs.upload-sarif == 'true'
      uses: github/codeql-action/upload-sarif@v4
      with:
        sarif_file: results.sarif
        category: sql-query-analyzer

    - name: Post PR comment
      if: inputs.post-comment == 'true' && github.event_name == 'pull_request'
      shell: bash
      env:
        GH_TOKEN: ${{ github.token }}
      run: |
        MARKER="<!-- sql-query-analyzer -->"
        PR_NUMBER=${{ github.event.pull_request.number }}

        ERROR_COUNT=${{ steps.analyze.outputs.error_count }}
        WARNING_COUNT=${{ steps.analyze.outputs.warning_count }}
        EXIT_CODE=${{ steps.analyze.outputs.exit_code }}

        # Build verdict section
        if [ "$EXIT_CODE" = "0" ]; then
          VERDICT="> [!TIP]
        > **All SQL checks passed.** No issues found in your queries!"
        elif [ "$EXIT_CODE" = "1" ]; then
          VERDICT="> [!WARNING]
        > **Found ${WARNING_COUNT} warning(s).** Consider reviewing before merging."
        else
          VERDICT="> [!CAUTION]
        > **Found ${ERROR_COUNT} error(s) and ${WARNING_COUNT} warning(s).** Please fix before merging.
        >
        > - Run \`sql_query_analyzer analyze\` locally for detailed output"
        fi

        # Status icons
        if [ "${ERROR_COUNT:-0}" -eq 0 ]; then ERROR_STATUS="✅"; else ERROR_STATUS="❌"; fi
        if [ "${WARNING_COUNT:-0}" -eq 0 ]; then WARNING_STATUS="✅"; else WARNING_STATUS="⚠️"; fi

        # Build comment
        COMMENT="${MARKER}
        ## SQL Query Analysis

        ${VERDICT}

        <details>
        <summary><strong>Results</strong> — analysis summary</summary>

        > *Static analysis checks for performance issues, security vulnerabilities, and style violations.*

        | Category | Count | Status |
        |:---------|------:|:------:|
        | Errors | ${ERROR_COUNT:-0} | ${ERROR_STATUS} |
        | Warnings | ${WARNING_COUNT:-0} | ${WARNING_STATUS} |

        </details>

        <details>
        <summary><strong>Analysis Details</strong> — full output</summary>

        \`\`\`
        ${{ steps.analyze.outputs.analysis }}
        \`\`\`

        </details>

        <details>
        <summary><strong>Configuration</strong> — analysis settings used</summary>

        > *These settings were used for this analysis run.*

        | Setting | Value |
        |:--------|:------|
        | Dialect | \`${{ inputs.dialect }}\` |
        | Schema | \`${{ inputs.schema }}\` |
        | Queries | \`${{ inputs.queries }}\` |

        </details>

        ---
        <sub>[SQL Query Analyzer](https://github.com/RAprogramm/sql-query-analyzer)</sub>"

        if [ "${{ inputs.update-comment }}" = "true" ]; then
          EXISTING=$(gh api repos/${{ github.repository }}/issues/${PR_NUMBER}/comments \
            --jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | head -1)

          if [ -n "$EXISTING" ]; then
            gh api repos/${{ github.repository }}/issues/comments/${EXISTING} \
              -X PATCH -f body="$COMMENT"
          else
            gh pr comment $PR_NUMBER --body "$COMMENT"
          fi
        else
          gh pr comment $PR_NUMBER --body "$COMMENT"
        fi

    - name: Check result
      shell: bash
      run: |
        EXIT_CODE=${{ steps.analyze.outputs.exit_code }}

        if [ "$EXIT_CODE" = "2" ] && [ "${{ inputs.fail-on-error }}" = "true" ]; then
          echo "::error::SQL analysis found errors"
          exit 1
        fi

        if [ "$EXIT_CODE" = "1" ] && [ "${{ inputs.fail-on-warning }}" = "true" ]; then
          echo "::warning::SQL analysis found warnings"
          exit 1
        fi