yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Harsh Aggarwal (NVIDIA)Bring back hooks for auto formatting and ensure build works (#7811)2d775b54d

master
13.6 KiB359 linesraw
1name: "Claude Code Runner"
2description: "Complete Claude Code execution with authentication, setup, execution, and results handling"
3inputs:
4  # Authentication inputs
5  llmgw-id:
6    description: "LLMGW ID for token generation"
7    required: true
8  llmgw-secret:
9    description: "LLMGW secret for token generation"
10    required: true
11  llmgw-token-url:
12    description: "LLMGW token URL for authentication"
13    required: true
14  github-token-fallback:
15    description: "Fallback GitHub token if App token fails"
16    required: false
17    default: ""
18
19  # Claude configuration
20  model:
21    description: "Anthropic model to use"
22    required: false
23    default: "claude-3-5-sonnet-20241022"
24  max-turns:
25    description: "Maximum number of turns for Claude"
26    required: false
27    default: "50000"
28  timeout-minutes:
29    description: "Timeout for Claude action in minutes"
30    required: false
31    default: "600"
32  trigger-phrase:
33    description: "Trigger phrase to activate Claude"
34    required: false
35    default: "@claude"
36  assignee-trigger:
37    description: "Assignee trigger name"
38    required: false
39    default: "claude"
40
41  # Environment and setup
42  custom-instructions:
43    description: "Custom instructions for Claude"
44    required: true
45  mcp-config:
46    description: "MCP server configuration JSON"
47    required: false
48    default: ""
49  allowed-tools:
50    description: "Comma-separated list of allowed tools"
51    required: false
52    default: "Bash,View,GlobTool,GrepTool,BatchTool,Write"
53  setup-commands:
54    description: "Setup commands to run before Claude (multiline string)"
55    required: false
56    default: ""
57  continue-on-setup-error:
58    description: "Continue if setup commands fail"
59    required: false
60    default: "false"
61
62  # AWS/Bedrock configuration
63  use-bedrock:
64    description: "Use AWS Bedrock for Claude"
65    required: false
66    default: "true"
67  aws-region:
68    description: "AWS region"
69    required: false
70    default: ""
71  bedrock-base-url:
72    description: "Anthropic Bedrock base URL"
73    required: false
74    default: ""
75  small-fast-model:
76    description: "Small fast model for Anthropic"
77    required: false
78    default: ""
79
80outputs:
81  auth-token:
82    description: "Generated authentication token"
83    value: ${{ steps.auth-token.outputs.token }}
84  github-token:
85    description: "Final GitHub token (App or fallback)"
86    value: ${{ steps.auth-config.outputs.github-token }}
87  token-expires:
88    description: "Token expiration time (if available)"
89    value: ${{ steps.auth-token.outputs.token-expires }}
90  github-app-token-outcome:
91    description: "Outcome of GitHub App token generation"
92    value: ${{ steps.github-app-token.outcome }}
93  claude-outcome:
94    description: "Outcome of Claude Code execution"
95    value: ${{ steps.claude-action.outcome }}
96
97runs:
98  using: "composite"
99  steps:
100    # Validate environment and inputs
101    - name: Validate Environment
102      shell: bash
103      run: |
104        set -euo pipefail
105
106        # Check required secrets
107        if [ -z "${{ inputs.llmgw-id }}" ] || [ -z "${{ inputs.llmgw-secret }}" ] || [ -z "${{ inputs.llmgw-token-url }}" ]; then
108          echo "::error::Missing required secrets: LLMGW_ID or LLMGW_SECRET or LLMGW_TOKEN_URL"
109          exit 1
110        fi
111
112        # Install required tools
113        command -v jq >/dev/null 2>&1 || { echo "::error::jq is required but not installed"; exit 1; }
114        command -v curl >/dev/null 2>&1 || { echo "::error::curl is required but not installed"; exit 1; }
115
116        echo "โœ… Environment validation passed"
117
118    # Generate custom auth token
119    - name: Generate Custom Auth Token
120      id: auth-token
121      shell: bash
122      run: |
123        set -euo pipefail
124
125        echo "๐Ÿ” Generating authentication token..."
126
127        # Set up error handling
128        cleanup() {
129          local exit_code=$?
130          echo "๐Ÿงน Cleaning up temporary files..."
131          rm -f /tmp/token_response.json 2>/dev/null || true
132          if [ $exit_code -ne 0 ]; then
133            echo "::error::Authentication failed - check your credentials and endpoint"
134          fi
135          exit $exit_code
136        }
137        trap cleanup EXIT
138
139        # Generate token with comprehensive error handling (using Basic auth like original)
140        HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/token_response.json --fail-with-body \
141          --max-time 30 \
142          --retry 3 \
143          --retry-delay 2 \
144          --location "${{ inputs.llmgw-token-url }}" \
145          --header 'Content-Type: application/x-www-form-urlencoded' \
146          --header "Authorization: Basic $(echo -n ${{ inputs.llmgw-id }}:${{ inputs.llmgw-secret }} | base64 -w0)" \
147          --data-urlencode 'grant_type=client_credentials' \
148          --data-urlencode 'scope=awsanthropic-readwrite azureopenai-readwrite' \
149          2>/dev/null)
150
151        # Check HTTP response code
152        if [ "$HTTP_CODE" -ne 200 ]; then
153          echo "::error::Authentication failed with HTTP code: $HTTP_CODE"
154          if [ -f /tmp/token_response.json ]; then
155            echo "::error::Response: $(cat /tmp/token_response.json | head -c 200)"
156          fi
157          exit 1
158        fi
159
160        # Extract and validate token
161        if [ ! -f /tmp/token_response.json ]; then
162          echo "::error::No response file generated"
163          exit 1
164        fi
165
166        ANTHROPIC_AUTH_TOKEN=$(jq -r '.access_token // empty' /tmp/token_response.json 2>/dev/null)
167
168        # Validate token format and length
169        if [ -z "$ANTHROPIC_AUTH_TOKEN" ] || [ "$ANTHROPIC_AUTH_TOKEN" = "null" ]; then
170          echo "::error::Failed to extract access token from response"
171          exit 1
172        fi
173
174        # Basic token validation
175        if [ ${#ANTHROPIC_AUTH_TOKEN} -lt 10 ]; then
176          echo "::error::Token appears to be too short (${#ANTHROPIC_AUTH_TOKEN} characters)"
177          exit 1
178        fi
179
180        # CRITICAL: Mask the token BEFORE any output
181        echo "::add-mask::$ANTHROPIC_AUTH_TOKEN"
182
183        # Set outputs
184        echo "token=$ANTHROPIC_AUTH_TOKEN" >> $GITHUB_OUTPUT
185
186        # Set token expiry if available
187        TOKEN_EXPIRES=$(jq -r '.expires_in // empty' /tmp/token_response.json 2>/dev/null)
188        if [ -n "$TOKEN_EXPIRES" ]; then
189          echo "::add-mask::$TOKEN_EXPIRES"
190          echo "token-expires=$TOKEN_EXPIRES" >> $GITHUB_OUTPUT
191        fi
192
193        echo "โœ… Authentication token generated and masked successfully"
194
195        # Clean up response file
196        rm -f /tmp/token_response.json
197
198    # Configure authentication
199    - name: Configure Authentication
200      id: auth-config
201      shell: bash
202      run: |
203        set -euo pipefail
204
205        # Use GitHub App token if available, otherwise use GITHUB_TOKEN
206        if [ -n "${{ steps.github-app-token.outputs.token }}" ]; then
207          echo "github-token=${{ steps.github-app-token.outputs.token }}" >> $GITHUB_OUTPUT
208          echo "โœ… Using GitHub App authentication"
209        else
210          echo "github-token=${{ inputs.github-token-fallback }}" >> $GITHUB_OUTPUT
211          echo "โš ๏ธ  Using fallback GITHUB_TOKEN authentication"
212        fi
213
214    # Run setup commands if provided
215    - name: Run setup commands
216      id: setup-commands
217      if: inputs.setup-commands != ''
218      shell: bash
219      continue-on-error: ${{ inputs.continue-on-setup-error == 'true' }}
220      run: ${{ inputs.setup-commands }}
221
222    # Security cleanup
223    - name: Security Cleanup
224      if: always()
225      shell: bash
226      run: |
227        set -euo pipefail
228
229        echo "๐Ÿงน Performing security cleanup..."
230
231        # Clear any temporary files that might contain sensitive data
232        find /tmp -name "*token*" -type f -delete 2>/dev/null || true
233        find /tmp -name "*auth*" -type f -delete 2>/dev/null || true
234        find /tmp -name "*response*" -type f -delete 2>/dev/null || true
235
236        # Clear environment variables (belt and suspenders approach)
237        unset ANTHROPIC_API_KEY 2>/dev/null || true
238        unset ANTHROPIC_AUTH_TOKEN 2>/dev/null || true
239
240        echo "โœ… Security cleanup completed"
241
242    # Workflow summary
243    - name: Generate Workflow Summary
244      if: always()
245      shell: bash
246      run: |
247        echo "## Claude Code Runner Summary" >> $GITHUB_STEP_SUMMARY
248        echo "" >> $GITHUB_STEP_SUMMARY
249        echo "### Authentication" >> $GITHUB_STEP_SUMMARY
250        echo "- **Auth Token**: โœ… Generated" >> $GITHUB_STEP_SUMMARY
251        echo "- **Token Expiry**: ${{ steps.auth-token.outputs.token-expires || 'Not provided' }}" >> $GITHUB_STEP_SUMMARY
252        echo "- **GitHub Token**: ${{ steps.github-app-token.outcome == 'success' && 'โœ… GitHub App' || 'โš ๏ธ Fallback' }}" >> $GITHUB_STEP_SUMMARY
253        echo "" >> $GITHUB_STEP_SUMMARY
254        echo "### Configuration" >> $GITHUB_STEP_SUMMARY
255        echo "- **Model**: ${{ inputs.model }}" >> $GITHUB_STEP_SUMMARY
256        echo "- **Max Turns**: ${{ inputs.max-turns }}" >> $GITHUB_STEP_SUMMARY
257        echo "- **Timeout**: ${{ inputs.timeout-minutes }} minutes" >> $GITHUB_STEP_SUMMARY
258        echo "- **Bedrock**: ${{ inputs.use-bedrock == 'true' && 'โœ… Enabled' || 'โŒ Disabled' }}" >> $GITHUB_STEP_SUMMARY
259        if [ "${{ inputs.use-bedrock }}" = "true" ]; then
260          echo "- **AWS Region**: ${{ inputs.aws-region || 'Default' }}" >> $GITHUB_STEP_SUMMARY
261        fi
262        echo "" >> $GITHUB_STEP_SUMMARY
263        echo "### Setup" >> $GITHUB_STEP_SUMMARY
264        echo "- **Setup Commands**: ${{ inputs.setup-commands != '' && 'โœ… Executed' || 'โญ๏ธ Skipped' }}" >> $GITHUB_STEP_SUMMARY
265        if [ "${{ inputs.setup-commands }}" != "" ]; then
266          echo "- **Setup Result**: ${{ steps.setup-commands.outcome || 'Unknown' }}" >> $GITHUB_STEP_SUMMARY
267        fi
268        echo "- **Security Cleanup**: โœ… Completed" >> $GITHUB_STEP_SUMMARY
269
270    # Execute Claude Code Action
271    - name: Execute Claude Code Action
272      id: claude-action
273      uses: anthropics/claude-code-action@beta
274      with:
275        custom_instructions: ${{ inputs.custom-instructions }}
276        mcp_config: ${{ inputs.mcp-config }}
277        allowed_tools: ${{ inputs.allowed-tools }}
278        trigger_phrase: ${{ inputs.trigger-phrase }}
279        assignee_trigger: ${{ inputs.assignee-trigger }}
280        timeout_minutes: ${{ inputs.timeout-minutes }}
281        github_token: ${{ steps.auth-config.outputs.github-token }}
282        use_bedrock: ${{ inputs.use-bedrock }}
283        model: ${{ inputs.model }}
284        max_turns: ${{ inputs.max-turns }}
285        # Use claude_env for custom environment variables
286        claude_env: |
287          ANTHROPIC_BEDROCK_BASE_URL: ${{ inputs.bedrock-base-url }}
288          ANTHROPIC_SMALL_FAST_MODEL: ${{ inputs.small-fast-model }}
289          AWS_REGION: ${{ inputs.aws-region }}
290          GITHUB_REPOSITORY: ${{ github.repository }}
291          GITHUB_EVENT_NAME: ${{ github.event_name }}
292          GITHUB_ACTOR: ${{ github.actor }}
293          ANTHROPIC_AUTH_TOKEN: ${{ steps.auth-token.outputs.token }}
294          DISABLE_TELEMETRY: 1
295      continue-on-error: true
296
297    # Handle Claude results
298    - name: Handle Claude Results
299      if: always()
300      shell: bash
301      run: |
302        set -euo pipefail
303
304        echo "๐Ÿ” Processing Claude action results..."
305
306        # Check if Claude action succeeded
307        if [ "${{ steps.claude-action.outcome }}" = "success" ]; then
308          echo "โœ… Claude Code action completed successfully"
309        elif [ "${{ steps.claude-action.outcome }}" = "failure" ]; then
310          echo "โŒ Claude Code action failed"
311
312          # Create error summary
313          echo "" >> $GITHUB_STEP_SUMMARY
314          echo "### โŒ Claude Execution Failed" >> $GITHUB_STEP_SUMMARY
315          echo "" >> $GITHUB_STEP_SUMMARY
316          echo "The Claude Code action encountered an error. Common causes:" >> $GITHUB_STEP_SUMMARY
317          echo "- Authentication issues" >> $GITHUB_STEP_SUMMARY
318          echo "- Network connectivity problems" >> $GITHUB_STEP_SUMMARY
319          echo "- Model availability issues" >> $GITHUB_STEP_SUMMARY
320          echo "- Rate limiting" >> $GITHUB_STEP_SUMMARY
321          echo "" >> $GITHUB_STEP_SUMMARY
322          echo "Please check the workflow logs for detailed error information." >> $GITHUB_STEP_SUMMARY
323        else
324          echo "โš ๏ธ  Claude Code action was cancelled or skipped"
325        fi
326
327    # Add execution summary
328    - name: Add Claude Execution Summary
329      if: always()
330      shell: bash
331      run: |
332        echo "" >> $GITHUB_STEP_SUMMARY
333        echo "### Claude Execution Details" >> $GITHUB_STEP_SUMMARY
334        echo "" >> $GITHUB_STEP_SUMMARY
335
336        # Event information
337        echo "#### Event Information" >> $GITHUB_STEP_SUMMARY
338        echo "- **Trigger**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
339        echo "- **Repository**: ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY
340        echo "- **Actor**: @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
341        echo "" >> $GITHUB_STEP_SUMMARY
342
343        # Execution status
344        echo "#### Execution Status" >> $GITHUB_STEP_SUMMARY
345        if [ "${{ steps.claude-action.outcome }}" = "success" ]; then
346          echo "- **Claude Action**: โœ… Success" >> $GITHUB_STEP_SUMMARY
347        elif [ "${{ steps.claude-action.outcome }}" = "failure" ]; then
348          echo "- **Claude Action**: โŒ Failed" >> $GITHUB_STEP_SUMMARY
349        else
350          echo "- **Claude Action**: โš ๏ธ ${{ steps.claude-action.outcome }}" >> $GITHUB_STEP_SUMMARY
351        fi
352        echo "- **Model Used**: ${{ inputs.model }}" >> $GITHUB_STEP_SUMMARY
353        echo "- **Max Turns**: ${{ inputs.max-turns }}" >> $GITHUB_STEP_SUMMARY
354        echo "- **Workflow Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
355
356        # Add timestamp
357        echo "" >> $GITHUB_STEP_SUMMARY
358        echo "#### Timestamp" >> $GITHUB_STEP_SUMMARY
359        echo "- **Completed at**: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY