Go linters check and fix using AI #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Go linters check and fix using AI | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| FILE: | |
| description: 'File name for check' | |
| required: true | |
| default: 'main.go' | |
| LINES: | |
| description: 'Range of lines for context' | |
| required: false | |
| default: '20' | |
| PR: | |
| description: 'Creat Pull Request' | |
| default: false | |
| type: boolean | |
| jobs: | |
| lint: | |
| name: Linters check and fix using AI | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| models: read | |
| env: | |
| APP_VERSION: 'latest' | |
| RESULTS: '' | |
| ISSUES_COUNT: '' | |
| ISSUE_LINT: '' | |
| ISSUE_TEXT: '' | |
| ISSUE_CODE: '' | |
| ISSUE_LINE: '' | |
| START_LINE: '' | |
| END_LINE: '' | |
| CONTEXT: '' | |
| FIXED: 'false' | |
| steps: | |
| - name: Checkout repository (main branch and 1 last commits) | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 1 | |
| ref: main | |
| - name: Install Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: 1.25 | |
| - name: Install dependencies | |
| run: | | |
| go fmt ./... | |
| go vet ./... | |
| go get ./... | |
| go mod tidy | |
| go mod verify | |
| go build -v ./... | |
| - name: Get app version in env | |
| run: | | |
| APP_VERSION=$(go run main.go -v) | |
| echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV | |
| - name: Install golangci | |
| run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.8.0 | |
| - name: Getting linter check results in json format before fixing | |
| run: | | |
| results=$(golangci-lint run --output.json.path stdout --show-stats=false --issues-exit-code 0 ${{ github.event.inputs.file }} 2>/dev/null | jq -c .) | |
| echo "RESULTS=$results" >> $GITHUB_ENV | |
| count=$(echo "$results" | jq ".Issues | length") | |
| echo "ISSUES_COUNT=$count" >> $GITHUB_ENV | |
| - name: Extract context for fix | |
| run: | | |
| lint=$(echo $RESULTS | jq -r .Issues[0].FromLinter) | |
| text=$(echo $RESULTS | jq -r .Issues[0].Text) | |
| code=$(echo $RESULTS | jq -r .Issues[0].SourceLines[0]) | |
| line=$(echo $RESULTS | jq -r .Issues[0].Pos.Line) | |
| line=$(echo "$line" | tr -d '\r') | |
| lines_offset=$(echo "${{ github.event.inputs.LINES }}" | tr -d '\r') | |
| start=$((line - lines_offset)) | |
| [ $start -le 0 ] && start=1 # Защита от отрицательных строк | |
| end=$((line + lines_offset)) | |
| echo "ISSUE_LINT=$lint" >> $GITHUB_ENV | |
| echo "ISSUE_TEXT=$text" >> $GITHUB_ENV | |
| echo "ISSUE_CODE=$code" >> $GITHUB_ENV | |
| echo "ISSUE_LINE=$line" >> $GITHUB_ENV | |
| echo "START_LINE=$start" >> $GITHUB_ENV | |
| echo "END_LINE=$end" >> $GITHUB_ENV | |
| echo "CONTEXT<<EOF" >> $GITHUB_ENV | |
| sed -n "${start},${end}p" "${{ github.event.inputs.FILE }}" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| - name: Fix issue using AI | |
| id: ai_query | |
| uses: actions/ai-inference@v2 | |
| with: | |
| model: gpt-4.1 | |
| max-tokens: 2048 | |
| system-prompt: | | |
| You are an issues analyzer from the golangci linters for the Go language. | |
| Your task is never to answer questions, but only to correct the given piece of code. | |
| You will be provided with the linter name, error text, and code context. | |
| Never change the logic of the source code or add analysis text to the response. | |
| Output ONLY raw code. Do NOT use markdown code blocks. | |
| Your answer should always include the same number of lines of code as was provided to you (excluding corrections). | |
| prompt: | | |
| Linter: ${{ env.ISSUE_LINT }} | |
| Issue text: ${{ env.ISSUE_TEXT }} | |
| Line of code with an error: ${{ env.ISSUE_CODE }} | |
| Context: | |
| ${{ env.CONTEXT }} | |
| - name: Update file | |
| run: | | |
| GO_FILE=${{ github.event.inputs.FILE }} | |
| TMP_FILE=$(echo $(echo "$GO_FILE" | sed "s/.go//")-fix.go) | |
| head -n $((START_LINE - 1)) "$GO_FILE" > "$TMP_FILE" | |
| cat <<'EOF' >> "$TMP_FILE" | |
| ${{ steps.ai_query.outputs.response }} | |
| EOF | |
| tail -n +$((END_LINE + 1)) "$GO_FILE" >> "$TMP_FILE" | |
| mv "$TMP_FILE" "$GO_FILE" | |
| go fmt "$GO_FILE" | |
| - name: Getting linter check results in json format after fixing | |
| run: | | |
| results=$(golangci-lint run --output.json.path stdout --show-stats=false --issues-exit-code 0 ${{ github.event.inputs.file }}) | |
| count=$(echo "$results" | jq ".Issues | length") | |
| if [ "$count" -lt "$ISSUES_COUNT" ]; then | |
| echo "FIXED=true" >> $GITHUB_ENV | |
| fi | |
| - name: Create Pull Request for fix lint | |
| if: ${{ github.event.inputs.PR == 'true' && env.FIXED == 'true' }} | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| commit-message: "fix linters using ai" | |
| branch: "fix/${{ env.APP_VERSION }}-lint" | |
| title: "Fixed linters" | |
| body: "Fixing linters with AI from GitHub Actions." | |
| add-paths: | | |
| ${{ github.event.inputs.file }} |