Add GitHub Action to post Stainless docs preview link on PRs #11
Workflow file for this run
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: Docs Preview | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| concurrency: | |
| group: docs-preview-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| env: | |
| # Update this with your Stainless project name | |
| STAINLESS_PROJECT: tiger-data-docs | |
| jobs: | |
| post-preview-link: | |
| name: Post Preview Link | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| checks: read | |
| steps: | |
| - name: Generate preview URL | |
| id: preview-url | |
| run: | | |
| # Sanitize branch name for URL (replace special chars with hyphens) | |
| BRANCH_NAME="${{ github.head_ref }}" | |
| SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//' | tr '[:upper:]' '[:lower:]') | |
| # Stainless preview URL pattern - adjust if your pattern differs | |
| PREVIEW_URL="https://${STAINLESS_PROJECT}--${SANITIZED_BRANCH}.preview.stainless.dev" | |
| echo "preview_url=$PREVIEW_URL" >> $GITHUB_OUTPUT | |
| echo "branch=$SANITIZED_BRANCH" >> $GITHUB_OUTPUT | |
| - name: Wait for Stainless deployment | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const sha = context.payload.pull_request.head.sha; | |
| const maxAttempts = 60; // 10 minutes max (60 * 10 seconds) | |
| const delaySeconds = 10; | |
| for (let attempt = 1; attempt <= maxAttempts; attempt++) { | |
| console.log(`Checking for Stainless deployment (attempt ${attempt}/${maxAttempts})...`); | |
| const { data: checkRuns } = await github.rest.checks.listForRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: sha | |
| }); | |
| // Look for Stainless Docs Build check | |
| const stainlessCheck = checkRuns.check_runs.find(check => | |
| check.name === 'Stainless Docs Build' | |
| ); | |
| if (stainlessCheck) { | |
| console.log(`Found check: ${stainlessCheck.name} - Status: ${stainlessCheck.status}, Conclusion: ${stainlessCheck.conclusion}`); | |
| if (stainlessCheck.status === 'completed') { | |
| if (stainlessCheck.conclusion === 'success') { | |
| console.log('Stainless deployment completed successfully!'); | |
| return; | |
| } else { | |
| core.setFailed(`Stainless deployment failed with conclusion: ${stainlessCheck.conclusion}`); | |
| return; | |
| } | |
| } | |
| } else { | |
| console.log('No Stainless check found yet...'); | |
| } | |
| // Wait before next attempt | |
| await new Promise(resolve => setTimeout(resolve, delaySeconds * 1000)); | |
| } | |
| console.log('Timeout waiting for Stainless deployment, posting comment anyway'); | |
| - name: Comment preview link on PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prNumber = context.payload.pull_request.number; | |
| const previewUrl = '${{ steps.preview-url.outputs.preview_url }}'; | |
| const branch = '${{ steps.preview-url.outputs.branch }}'; | |
| const sha = context.payload.pull_request.head.sha.substring(0, 7); | |
| const commentMarker = '<!-- stainless-docs-preview -->'; | |
| const commentBody = `${commentMarker} | |
| ## 📚 Docs Preview | |
| | Status | Link | | |
| |--------|------| | |
| | ✅ Build successful | [Preview Deployment](${previewUrl}) | | |
| **Branch:** \`${branch}\` | |
| **Commit:** \`${sha}\` | |
| > 🕐 Preview deployments may take a few minutes to become available after the build completes. | |
| `; | |
| // Get existing comments | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber | |
| }); | |
| // Find existing bot comment | |
| const existingComment = comments.find(comment => | |
| comment.body && comment.body.includes(commentMarker) | |
| ); | |
| if (existingComment) { | |
| // Update existing comment | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existingComment.id, | |
| body: commentBody | |
| }); | |
| console.log('Updated existing preview comment'); | |
| } else { | |
| // Create new comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: commentBody | |
| }); | |
| console.log('Created new preview comment'); | |
| } |