refactor: Enhance stETH management scripts #665
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: Run Forge Tests | |
| on: | |
| pull_request: | |
| branches: | |
| - staging-2.5 | |
| - master | |
| workflow_dispatch: | |
| jobs: | |
| check: | |
| name: Foundry project | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write # Required to comment on PRs | |
| steps: | |
| - uses: actions/checkout@v3 | |
| with: | |
| submodules: recursive | |
| - name: Install Foundry | |
| uses: foundry-rs/foundry-toolchain@v1 | |
| with: | |
| version: nightly | |
| - name: Run tests | |
| run: forge test -vvv | |
| env: | |
| MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} | |
| SCROLL_RPC_URL: ${{ secrets.SCROLL_RPC_URL }} | |
| HISTORICAL_PROOF_812_WITHDRAWAL_RPC_URL: ${{ secrets.HISTORICAL_PROOF_812_WITHDRAWAL_RPC_URL }} | |
| HISTORICAL_PROOF_RPC_URL: ${{ secrets.HISTORICAL_PROOF_RPC_URL }} | |
| - name: Generate coverage report | |
| if: always() | |
| shell: bash | |
| run: | | |
| # Capture full output; || true so the step always continues | |
| forge coverage --report summary \ | |
| --no-match-coverage '(script/|test/|src/helpers/|src/interfaces/|src/eigenlayer|src/libraries/|src/archive/)' \ | |
| --color never > full_output.txt 2>&1 || true | |
| # Extract coverage table lines | |
| grep -E '^\|' full_output.txt > coverage.txt || true | |
| if [ -s coverage.txt ]; then | |
| echo "" >> coverage.txt | |
| echo "---" >> coverage.txt | |
| grep -E "^(Ran|Suite result:|Test result:)" full_output.txt >> coverage.txt || true | |
| else | |
| echo "Coverage report could not be generated. Check workflow logs for details." > coverage.txt | |
| fi | |
| env: | |
| MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} | |
| SCROLL_RPC_URL: ${{ secrets.SCROLL_RPC_URL }} | |
| HISTORICAL_PROOF_812_WITHDRAWAL_RPC_URL: ${{ secrets.HISTORICAL_PROOF_812_WITHDRAWAL_RPC_URL }} | |
| HISTORICAL_PROOF_RPC_URL: ${{ secrets.HISTORICAL_PROOF_RPC_URL }} | |
| - name: Upload coverage artifact | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: forge-coverage | |
| path: coverage.txt | |
| - name: Post coverage comment on PR | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| // Hidden marker for reliable comment detection (emojis can have encoding issues) | |
| const COMMENT_MARKER = '<!-- forge-coverage-report -->'; | |
| // Get PR number - context.issue.number may be undefined on some event types | |
| const prNumber = context.payload.pull_request?.number || context.issue?.number; | |
| if (!prNumber) { | |
| console.log('Could not determine PR number, skipping comment'); | |
| return; | |
| } | |
| console.log(`PR number: ${prNumber}`); | |
| // Read coverage file | |
| let coverage; | |
| try { | |
| coverage = fs.readFileSync('coverage.txt', 'utf8'); | |
| console.log(`Coverage file read successfully (${coverage.length} chars)`); | |
| } catch (err) { | |
| console.log(`Failed to read coverage.txt: ${err.message}`); | |
| return; | |
| } | |
| // Build the Markdown with no leading indentation (YAML indentation would break fenced code blocks). | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const body = [ | |
| COMMENT_MARKER, | |
| '## 📊 Forge Coverage Report', | |
| '', | |
| '```', | |
| coverage.trimEnd(), | |
| '```', | |
| '', | |
| `<sub>Generated by workflow run [#${context.runNumber}](${runUrl})</sub>` | |
| ].join('\n'); | |
| try { | |
| // Find existing comment to update (avoids spam on multiple pushes). Fetch ALL comments with pagination | |
| const comments = []; | |
| let page = 1; | |
| let hasMore = true; | |
| while (hasMore) { | |
| const { data: pageComments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| per_page: 100, | |
| page: page | |
| }); | |
| comments.push(...pageComments); | |
| hasMore = pageComments.length === 100; | |
| page++; | |
| } | |
| // Search by hidden marker (more reliable than emoji-based search) | |
| const botComment = comments.find(c => | |
| c.body?.includes(COMMENT_MARKER) | |
| ); | |
| console.log(`Found ${comments.length} total comments`); | |
| if (botComment) { | |
| console.log(`Updating existing comment (id: ${botComment.id})`); | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: body | |
| }); | |
| console.log('Comment updated successfully'); | |
| } else { | |
| console.log('No existing comment found, creating new one'); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: body | |
| }); | |
| console.log('Comment created successfully'); | |
| } | |
| } catch (err) { | |
| console.error(`GitHub API error: ${err.message}`); | |
| throw err; // Re-throw to fail the step visibly | |
| } |