Add regression test for #13358 #15860
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
| # https://help.github.com/en/categories/automating-your-workflow-with-github-actions | |
| name: "Issue bot" | |
| on: | |
| workflow_dispatch: | |
| pull_request: | |
| paths-ignore: | |
| - 'compiler/**' | |
| - 'apigen/**' | |
| - 'changelog-generator/**' | |
| push: | |
| branches: | |
| - "2.1.x" | |
| paths-ignore: | |
| - 'compiler/**' | |
| - 'apigen/**' | |
| - 'changelog-generator/**' | |
| concurrency: | |
| group: run-issue-bot-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches | |
| cancel-in-progress: true | |
| jobs: | |
| download: | |
| name: "Download data" | |
| runs-on: "ubuntu-latest" | |
| outputs: | |
| matrix: ${{ steps.shards.outputs.shards }} | |
| steps: | |
| - name: "Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Install PHP" | |
| uses: "shivammathur/setup-php@v2" | |
| with: | |
| coverage: "none" | |
| php-version: "8.5" | |
| - name: "Install issue-bot dependencies" | |
| uses: "ramsey/composer-install@v3" | |
| with: | |
| working-directory: "issue-bot" | |
| - name: "Cache downloads" | |
| uses: actions/cache@v4 | |
| with: | |
| path: ./issue-bot/tmp | |
| key: "issue-bot-download-v7-${{ github.run_id }}" | |
| restore-keys: | | |
| issue-bot-download-v7- | |
| - name: "Download data" | |
| working-directory: "issue-bot" | |
| env: | |
| GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} | |
| run: ./console.php download > matrix.json | |
| - name: "Output shards" | |
| id: shards | |
| working-directory: "issue-bot" | |
| run: | | |
| echo "shards=$(jq -c '{include: [range(length) | {shard: .}]}' matrix.json)" >> $GITHUB_OUTPUT | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: playground-cache | |
| path: issue-bot/tmp/playgroundCache.tmp | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: issue-cache | |
| path: issue-bot/tmp/issueCache.tmp | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: matrix | |
| path: issue-bot/matrix.json | |
| analyse: | |
| name: "Analyse" | |
| needs: download | |
| runs-on: "ubuntu-latest" | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.download.outputs.matrix) }} | |
| steps: | |
| - name: "Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Install PHP" | |
| uses: "shivammathur/setup-php@v2" | |
| with: | |
| coverage: "none" | |
| php-version: "8.5" | |
| - uses: "ramsey/composer-install@v3" | |
| with: | |
| composer-options: "--no-dev" | |
| - name: "Install issue-bot dependencies" | |
| uses: "ramsey/composer-install@v3" | |
| with: | |
| working-directory: "issue-bot" | |
| - uses: Wandalen/wretry.action@v3.8.0 | |
| with: | |
| action: actions/download-artifact@v4 | |
| with: | | |
| name: playground-cache | |
| path: issue-bot/tmp | |
| attempt_limit: 5 | |
| attempt_delay: 1000 | |
| - uses: Wandalen/wretry.action@v3.8.0 | |
| with: | |
| action: actions/download-artifact@v4 | |
| with: | | |
| name: matrix | |
| path: issue-bot | |
| attempt_limit: 5 | |
| attempt_delay: 1000 | |
| - name: "Extract shard" | |
| working-directory: "issue-bot" | |
| id: chunk | |
| run: | | |
| echo "phpVersion=$(jq -r '.[${{ matrix.shard }}].phpVersion' matrix.json)" >> "$GITHUB_OUTPUT" | |
| echo "playgroundExamples=$(jq -r '.[${{ matrix.shard }}].playgroundExamples' matrix.json)" >> "$GITHUB_OUTPUT" | |
| echo "chunkNumber=$(jq -r '.[${{ matrix.shard }}].chunkNumber' matrix.json)" >> "$GITHUB_OUTPUT" | |
| - name: "Run PHPStan" | |
| working-directory: "issue-bot" | |
| timeout-minutes: 5 | |
| run: ./console.php run ${{ steps.chunk.outputs.phpVersion }} ${{ steps.chunk.outputs.playgroundExamples }} | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: results-${{ steps.chunk.outputs.phpVersion }}-${{ steps.chunk.outputs.chunkNumber }} | |
| path: issue-bot/tmp/results-${{ steps.chunk.outputs.phpVersion }}-*.tmp | |
| evaluate: | |
| name: "Evaluate results" | |
| needs: analyse | |
| runs-on: "ubuntu-latest" | |
| steps: | |
| - name: "Checkout" | |
| uses: actions/checkout@v4 | |
| - name: "Install PHP" | |
| uses: "shivammathur/setup-php@v2" | |
| with: | |
| coverage: "none" | |
| php-version: "8.5" | |
| - name: "Install issue-bot dependencies" | |
| uses: "ramsey/composer-install@v3" | |
| with: | |
| working-directory: "issue-bot" | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: playground-cache | |
| path: issue-bot/tmp | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: issue-cache | |
| path: issue-bot/tmp | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: results-* | |
| merge-multiple: true | |
| path: issue-bot/tmp | |
| - name: "List tmp" | |
| run: "ls -lA issue-bot/tmp" | |
| - name: "Evaluate results - pull request" | |
| working-directory: "issue-bot" | |
| if: github.event_name == 'pull_request' | |
| env: | |
| GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set +e | |
| ./console.php evaluate > tmp/step-summary.md | |
| exit_code="$?" | |
| cat tmp/step-summary.md >> $GITHUB_STEP_SUMMARY | |
| if [[ "$exit_code" == "2" ]]; then | |
| echo "::notice file=.github/workflows/issue-bot.yml,line=3 ::Issue bot detected open issues which are affected by this pull request - see https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" | |
| exit 0 | |
| fi | |
| exit $exit_code | |
| - name: "Upload step summary" | |
| if: github.event_name == 'pull_request' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: step-summary | |
| path: issue-bot/tmp/step-summary.md | |
| - name: "Evaluate results - push" | |
| working-directory: "issue-bot" | |
| if: "github.repository_owner == 'phpstan' && github.ref == 'refs/heads/2.1.x'" | |
| env: | |
| GITHUB_PAT: ${{ secrets.PHPSTAN_BOT_TOKEN }} | |
| PHPSTAN_SRC_COMMIT_BEFORE: ${{ github.event.before }} | |
| PHPSTAN_SRC_COMMIT_AFTER: ${{ github.event.after }} | |
| run: | | |
| set +e | |
| ./console.php evaluate --post-comments >> $GITHUB_STEP_SUMMARY | |
| exit_code="$?" | |
| # its fine when issue-bot found affected issues | |
| if [[ "$exit_code" == "2" ]]; then | |
| exit 0 | |
| fi | |
| exit $exit_code | |
| regression-tests: | |
| name: "Generate regression tests" | |
| needs: evaluate | |
| if: github.event_name == 'pull_request' && github.event.pull_request.user.login == 'phpstan-bot' | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| timeout-minutes: 60 | |
| steps: | |
| - name: "Check for feedback loop" | |
| id: check | |
| env: | |
| GH_TOKEN: ${{ secrets.PHPSTAN_BOT_TOKEN }} | |
| run: | | |
| COMMIT_MSG=$(gh api "repos/${{ github.repository }}/commits/${{ github.event.pull_request.head.sha }}" --jq '.commit.message' 2>/dev/null || true) | |
| if [[ "$COMMIT_MSG" == "Add regression test for #"* ]]; then | |
| echo "Last commit was regression test addition, skipping" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: "Checkout" | |
| if: steps.check.outputs.skip != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.head_ref }} | |
| fetch-depth: 0 | |
| token: ${{ secrets.PHPSTAN_BOT_TOKEN }} | |
| - name: "Download step summary" | |
| if: steps.check.outputs.skip != 'true' | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: step-summary | |
| path: ./tmp | |
| - name: "Install PHP" | |
| if: steps.check.outputs.skip != 'true' | |
| uses: "shivammathur/setup-php@v2" | |
| with: | |
| coverage: "none" | |
| php-version: "8.4" | |
| ini-file: development | |
| extensions: mbstring | |
| - name: "Install dependencies" | |
| if: steps.check.outputs.skip != 'true' | |
| uses: "ramsey/composer-install@v3" | |
| - name: "Install Claude Code" | |
| if: steps.check.outputs.skip != 'true' | |
| run: npm install -g @anthropic-ai/claude-code | |
| - name: "Save HEAD before generation" | |
| if: steps.check.outputs.skip != 'true' | |
| id: before | |
| run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| - name: "Generate regression tests" | |
| if: steps.check.outputs.skip != 'true' | |
| env: | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| GH_TOKEN: ${{ secrets.PHPSTAN_BOT_TOKEN }} | |
| run: | | |
| git config user.name "phpstan-bot" | |
| git config user.email "ondrej+phpstanbot@mirtes.cz" | |
| claude -p \ | |
| --model claude-opus-4-6 \ | |
| --dangerously-skip-permissions \ | |
| "Read the file ./tmp/step-summary.md which contains the Issue Bot step summary from CI in Markdown format. Interpret this Markdown to figure out which GitHub issues need regression tests added. For each affected issue (where behavior changed), run /regression-test with the issue number. | |
| Also read the diff of this branch to see what has already been done. The primary fixed issue will already have a test committed. The Issue Bot step summary might mention other fixed issues, so please add regression tests for those. | |
| Do not create a branch or push - this will be handled automatically." | |
| - name: "Push" | |
| if: steps.check.outputs.skip != 'true' | |
| run: | | |
| if [ "$(git rev-parse HEAD)" = "$(git rev-parse @{u})" ]; then | |
| echo "No new commits to push" | |
| exit 0 | |
| fi | |
| git push | |
| - name: "Update PR description" | |
| if: steps.check.outputs.skip != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.PHPSTAN_BOT_TOKEN }} | |
| run: | | |
| BEFORE_SHA="${{ steps.before.outputs.sha }}" | |
| CURRENT_SHA="$(git rev-parse HEAD)" | |
| if [ "$BEFORE_SHA" = "$CURRENT_SHA" ]; then | |
| echo "No new commits, skipping PR description update" | |
| exit 0 | |
| fi | |
| # Extract issue numbers from new commit messages | |
| ISSUE_NUMBERS=$(git log --format='%s' "$BEFORE_SHA".."$CURRENT_SHA" | grep -oP '#\K[0-9]+' | sort -u) | |
| if [ -z "$ISSUE_NUMBERS" ]; then | |
| echo "No issue numbers found in new commits" | |
| exit 0 | |
| fi | |
| # Get current PR body via REST API (avoids GraphQL scope requirements) | |
| PR_API="repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" | |
| gh api "$PR_API" --jq '.body' > /tmp/pr-body.txt | |
| # Append closes lines for issues not already in the body | |
| ADDED=false | |
| for NUM in $ISSUE_NUMBERS; do | |
| ISSUE_URL="https://github.com/phpstan/phpstan/issues/$NUM" | |
| if ! grep -qF "$ISSUE_URL" /tmp/pr-body.txt; then | |
| if [ "$ADDED" = false ]; then | |
| echo "" >> /tmp/pr-body.txt | |
| fi | |
| echo "Closes $ISSUE_URL" >> /tmp/pr-body.txt | |
| ADDED=true | |
| fi | |
| done | |
| if [ "$ADDED" = false ]; then | |
| echo "All issues already referenced in PR description" | |
| exit 0 | |
| fi | |
| gh api "$PR_API" -X PATCH -f body="$(cat /tmp/pr-body.txt)" |