From cd16d063a9dc18291560439ad4be06fe4d7bb0b9 Mon Sep 17 00:00:00 2001 From: Panagiotis Siatras Date: Wed, 6 May 2026 13:12:07 +0300 Subject: [PATCH] gh: fixed go-generate cleanup to match recursively and tolerate empty grep --- .github/workflows/goLint.yml | 98 ++++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/.github/workflows/goLint.yml b/.github/workflows/goLint.yml index b08fcb2..82f64f0 100644 --- a/.github/workflows/goLint.yml +++ b/.github/workflows/goLint.yml @@ -40,8 +40,7 @@ jobs: env: GOPRIVATE: ${{ inputs.goprivate }} steps: - - - name: Install Dependencies # Some dependencies require this package + - name: Install Dependencies # Some dependencies require this package if: ${{ inputs.os-dependencies != '' }} shell: bash env: @@ -66,22 +65,22 @@ jobs: exit 1 ;; esac - - - name: Checkout + + - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: submodules: true ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} - - - name: Setup Go + + - name: Setup Go uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 with: go-version-file: go.mod check-latest: true cache: true cache-dependency-path: '**/go.sum' - - - name: Setup SSH key for private dependencies + + - name: Setup SSH key for private dependencies uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0 env: SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} @@ -89,43 +88,88 @@ jobs: with: ssh-private-key: | ${{ secrets.SSH_PRIVATE_KEY }} - - - name: Configure Linter - if: ${{ hashFiles('.golangci.yml', '.golangci.yaml', '.golangci.toml', '.golangci.json') == '' }} + + - name: Configure Linter + id: configure-linter + if: ${{ hashFiles('.golangci.yml', '.golangci.yaml', '.golangci.toml', '.golangci.json') == '' }} shell: bash run: | - curl -O https://raw.githubusercontent.com/smallstep/workflows/main/.golangci.yml - - - name: Reconfigure Git for private repos + # GH Actions runs `bash --noprofile --norc -eo pipefail`; `-u` is added on top + # so a typo in a variable name fails loudly instead of expanding to empty. + set -euo pipefail + + CONFIG="${RUNNER_TEMP}/golangci-lint-fallback.yml" + curl -fsSL --output "${CONFIG}" https://raw.githubusercontent.com/smallstep/workflows/main/.golangci.yml + echo "extra-args=--config=${CONFIG}" >> "${GITHUB_OUTPUT}" + + - name: Reconfigure Git for private repos env: PAT: ${{ secrets.PAT }} if: ${{ env.PAT != '' }} run: | git config --global url.https://${{ secrets.PAT }}@github.com/.insteadOf git+ssh://git@github.com git config --global url.git@github.com:.insteadOf https://github.com/ - - - name: Check that go.mod is tidied + + - name: Check that go.mod is tidied if: inputs.skip-go-mod-tidy == false run: go mod tidy -diff - - - name: Run Linter + + - name: Run Linter uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 if: success() || failure() # run this step even if the previous one failed with: version: ${{ inputs.golangci-lint-version }} - args: '${{ inputs.golangci-lint-args }}' + args: '${{ steps.configure-linter.outputs.extra-args }} ${{ inputs.golangci-lint-args }}' verify: true - - - name: Run go generate + + - name: Run go generate if: ( success() || failure() ) && !inputs.skip-go-generate shell: bash run: | - # delete all go-generated files (that adhere to the comment convention); protobuf code is excluded, because its output is (currently) not fully controlled by tools.go - git grep -l "^// Code generated .* DO NOT EDIT\.$" -- '*.go' ':!*.pb.go' | xargs rm -f + # GH Actions runs `bash --noprofile --norc -eo pipefail`; `-u` is added on top + # so a typo in a variable name fails loudly instead of expanding to empty. + set -euo pipefail + + # delete all go-generated files (that adhere to the comment convention); protobuf code is + # excluded, because its output is (currently) not fully controlled by tools.go + { + git grep -lz "^// Code generated .* DO NOT EDIT\.$" \ + -- ':(glob)**/*.go' ':(exclude,glob)**/*.pb.go' \ + || [ $? -eq 1 ] + } | while IFS= read -r -d '' file; do + rm -f "$file" + done + # now generate everything go generate ./... - # check if any files were changed - git diff --exit-code || ( - echo "Generated files are not up to date. Please run 'go generate ./...' and commit the changes." + + # check that no files were modified or left untracked + status="$(git status --porcelain)" + if [ -n "$status" ]; then + # intent-to-add lets git diff include new untracked files as full additions + git add -N . + + DIFF=$(mktemp "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/go-generate-diff.XXXXXX") + trap 'rm -f "${DIFF}"' EXIT + git --no-pager diff > "${DIFF}" + + { + echo "### ❌ Generated files are not up to date" + echo + echo "One or more files generated by \`go generate ./...\` differ from what's committed." + echo "Please run \`go generate ./...\` locally and commit the result." + echo + echo "Here's the diff:" + echo + echo "\`\`\`diff" + cat "${DIFF}" + echo "\`\`\`" + } >> "${GITHUB_STEP_SUMMARY}" + + echo "::error title=Generate check failed::Generated files are not up to date. Run 'go generate ./...' to fix." + echo "::group::View Generate Diff" + cat "${DIFF}" + echo "::endgroup::" + exit 1 - ) + fi