Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
pull_request_review:
types: [submitted]
issues:
types: [opened, assigned]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && (contains(github.event.comment.body, '@claude-code') || contains(github.event.comment.body, '@claude_code'))) ||
(github.event_name == 'pull_request_review_comment' && (contains(github.event.comment.body, '@claude-code') || contains(github.event.comment.body, '@claude_code'))) ||
(github.event_name == 'pull_request_review' && (contains(github.event.review.body, '@claude-code') || contains(github.event.review.body, '@claude_code'))) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude-code') || contains(github.event.issue.body, '@claude_code')))
Comment on lines +15 to +19

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For anthropics/claude-code-action v1, does the trigger_phraseinput support multiple trigger phrases or aliases, and what is the correct syntax to support both@claude-codeand@claude_code?

💡 Result:

For anthropics/claude-code-action v1, the trigger_phrase input does not natively support multiple trigger phrases or aliases as a list [1][2]. The input accepts a single string value to define the trigger phrase that the action will monitor [3][2]. To support both @claude-code and @claude_code as trigger phrases, you must handle the logic at the workflow level rather than relying on the trigger_phrase input alone [4]. Because the action's execution is often gated by a conditional if statement in your GitHub Actions workflow file, you should update that condition to check for both strings [4]. For example: if: contains(github.event.comment.body, '@claude-code') || contains(github.event.comment.body, '@claude_code') Additionally, if you set the trigger_phrase input in your workflow configuration to one of your desired phrases (e.g., @claude-code), you may also need to ensure that the logic within the action's environment is aligned or that you have accounted for both patterns in your workflow's job-level triggers [4]. It is a known limitation that simply changing the input without updating the workflow's conditional logic may result in the action failing to trigger as expected [4].

Citations:


Update the trigger_phrase input to handle both aliases or verify action behavior for @claude_code.

The job-level if condition correctly permits execution for both @claude-code and @claude_code, but the anthropics/claude-code-action input trigger_phrase accepts only a single string and performs its own internal check.

If the action is configured with trigger_phrase: "@claude-code", it will likely ignore the trigger for @claude_code comments, causing the job to run but the action to exit without responding.

Fix:

  1. Verify if the specific action version supports multiple triggers via a specific syntax (docs suggest it does not).
  2. If not, update the trigger_phrase input to match the preferred alias, or ensure the workflow logic aligns with the action's internal expectations.
  3. Alternatively, if the action allows, configure it to accept the underscore variant if that is the primary usage, or split the workflow logic.

Since the action's internal filter is the bottleneck, simply having the workflow if condition is insufficient if the action itself ignores the mismatched trigger.

Please check the anthropics/claude-code-action documentation or source for supported syntax for multiple trigger phrases or confirm if a workaround (like using a generic trigger phrase) is intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude.yml around lines 15 - 19, The workflow trigger
currently allows both `@claude-code` and `@claude_code`, but the
anthropics/claude-code-action input trigger_phrase only does its own
single-phrase check, so the job can start and the action still ignore the
underscore alias. Update the claude job configuration in claude.yml so the
trigger_phrase setting matches the alias you intend to support, or confirm and
use the action’s documented syntax if it supports multiple phrases; otherwise
align the workflow’s if condition with the action’s internal trigger handling.
Refer to the claude-code-action invocation and its trigger_phrase input when
making the change.

runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
id-token: write
steps:
- name: Check actor has write access
env:
GH_TOKEN: ${{ github.token }}
run: |
PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission')
if [ "$PERMISSION" != "admin" ] && [ "$PERMISSION" != "write" ] && [ "$PERMISSION" != "maintain" ]; then
echo "::error::Actor ${{ github.actor }} does not have write permission (has: $PERMISSION)"
exit 1
fi

- name: Acknowledge with eyes emoji
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ github.event_name }}" = "issue_comment" ]; then
gh api repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions -f content=eyes
elif [ "${{ github.event_name }}" = "pull_request_review_comment" ]; then
gh api repos/${{ github.repository }}/pulls/comments/${{ github.event.comment.id }}/reactions -f content=eyes
elif [ "${{ github.event_name }}" = "pull_request_review" ]; then
gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/reactions -f content=eyes
elif [ "${{ github.event_name }}" = "issues" ]; then
gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/reactions -f content=eyes
fi

- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0

- name: Add fork remote for cross-repo PRs
if: github.event.issue.pull_request
env:
GH_TOKEN: ${{ github.token }}
run: |
PR_NUMBER=${{ github.event.issue.number }}
FORK_REPO=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.head.repo.full_name')
if [ "$FORK_REPO" != "${{ github.repository }}" ]; then
git remote set-url --add origin "https://github.com/${FORK_REPO}.git"
fi
Comment on lines +56 to +65

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/claude.yml

Repository: Red-Hat-AI-Innovation-Team/its_hub

Length of output: 5370


🌐 Web query:

github actions event structure issue_comment vs pull_request_review event.json.github.event

💡 Result:

In GitHub Actions, the github.event object contains the webhook payload for the event that triggered the workflow, and its structure varies significantly between event types [1]. The issue_comment and pull_request_review events serve different purposes and provide distinct data structures [2][3]. issue_comment The issue_comment event triggers when a comment is created, edited, or deleted on an issue or a pull request [2]. Because it covers both, the payload includes both issue and pull_request objects, though the pull_request object is only present if the comment was made on a pull request [2]. Key payload paths include: - Comment content: github.event.comment.body [4] - Comment ID: github.event.comment.id [4] - Associated Issue/PR number: github.event.issue.number (note that PRs are treated as issues in the issue_comment payload) [4] - Identification: You can distinguish between an issue or a pull request by checking if github.event.issue.pull_request exists [2]. pull_request_review The pull_request_review event triggers when a pull request review is submitted, edited, or dismissed [2]. This event is specifically for the review action (e.g., approving, requesting changes, or providing a summary comment) rather than individual line comments on a diff [2][3]. Key payload paths include: - Review body: github.event.review.body [4] - Review ID: github.event.review.id [4] - Associated Pull Request number: github.event.pull_request.number [4] - Review State: github.event.review.state (e.g., approved, changes_requested) [2] Key Differences - Context: issue_comment is for general comments on an issue or PR; pull_request_review is specifically for the formal review process [2]. - Data Access: Accessing comment body text is done via github.event.comment.body for issue_comment, whereas pull_request_review uses github.event.review.body [4]. - Hierarchy: In the issue_comment payload, the comment is a top-level object under the event; in pull_request_review, the review information is a distinct object (github.event.review) separate from the pull request details (github.event.pull_request) [4]. For technical implementation, it is best practice to refer to the specific GitHub Webhook documentation for each event type, as these payloads follow the standard REST API webhook structures [2][3].

Citations:


Step skips fork remote setup for pull_request_review and pull_request_review_comment events on cross-repo PRs.

The condition if: github.event.issue.pull_request only matches issue_comment events on PRs. For pull_request_review and pull_request_review_comment triggers, github.event.issue doesn't contain the pull_request field, so the fork remote step is skipped.

Use an event-based check that works across all three PR event types:

Proposed fix

      - name: Add fork remote for cross-repo PRs
-        if: github.event.issue.pull_request
+        if: github.event_name == 'issue_comment' && github.event.issue.pull_request || github.event_name == 'pull_request_review_comment' && github.event.issue.pull_request || github.event_name == 'pull_request_review' && github.event.pull_request.number
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
-          PR_NUMBER=${{ github.event.issue.number }}
+          if [ "${{ github.event_name }}" = "pull_request_review" ]; then
+            PR_NUMBER=${{ github.event.pull_request.number }}
+          else
+            PR_NUMBER=${{ github.event.issue.number }}
+          fi
          FORK_REPO=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.head.repo.full_name')

Alternatively, consolidate the condition by checking the actor context or extracting PR number from a unified helper step.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude.yml around lines 56 - 65, The fork remote setup
step is gated by an `issue.pull_request` check that only works for
`issue_comment`, so it skips `pull_request_review` and
`pull_request_review_comment` on cross-repo PRs. Update the conditional in the
`Add fork remote for cross-repo PRs` step to use a PR-event-safe check that
covers all three PR-triggered event types, and keep the existing `gh api`/`git
remote set-url --add origin` logic unchanged. If needed, centralize PR detection
in a shared helper expression so the step runs whenever the workflow is handling
a PR review/comment from a fork.


- name: Load shared skills
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
repository: Red-Hat-AI-Innovation-Team/claude-skills
path: .claude
Comment on lines +67 to +71

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For anthropics/claude-code-action v1 plugins, can plugin_marketplaces or individual plugin entries be pinned to an immutable commit SHA or release?

💡 Result:

For the anthropics/claude-code-action v1 GitHub Action, there is currently no native support for pinning the plugin_marketplaces input directly to an immutable commit SHA via a URL fragment or a structured configuration block [1]. The plugin_marketplaces input expects a newline-separated list of Git repository URLs [2], and it typically clones the HEAD of the default branch [1]. However, you can achieve version pinning for marketplaces through the following workarounds: 1. Local Path Checkouts: Because claude-code-action supports local filesystem paths for plugin_marketplaces [3], you can check out your desired marketplace repository at a specific commit SHA using the official actions/checkout@v4 action in a prior workflow step [3]. You can then pass the local path of that checked-out directory to the plugin_marketplaces input [3]. 2. Individual Plugin Pinning: While the marketplace itself may be dynamic, individual plugins within that marketplace can be pinned to an immutable commit SHA [4][5]. Within the marketplace.json file, plugin sources that use the github type support both ref (branch/tag) and sha fields [6][4]. When both are specified, the sha acts as the effective, immutable pin [6][4]. This ensures that even if the marketplace definition changes, the specific plugin versions installed by Claude Code remain locked to the defined commit [4][7]. Official documentation confirms that for plugins, providing a full commit SHA in the sha field is the supported method for ensuring reproducible installations [6][4]. Organizations often manage this by updating these SHAs in their marketplace.json alongside version bumps to maintain controlled release cycles [7].

Citations:


🏁 Script executed:

sed -n '84,91p' .github/workflows/claude.yml

Repository: Red-Hat-AI-Innovation-Team/its_hub

Length of output: 551


Pin mutable inputs for shared skills and plugin marketplaces before executing Claude code.

The workflow pins Actions by SHA but loads unversioned inputs (skills repo ref and plugin marketplace URL) into a high-privilege run. Fix:

  • Add a pinned ref and set persist-credentials: false for the shared skills checkout.
  • For the plugin marketplace, switch from the remote URL to a local path by checking out the marketplace repo at a specific commit SHA in a prior step, then pass that local path to plugin_marketplaces.
Apply these hardening steps
-          repository: Red-Hat-AI-Innovation-Team/claude-skills
+          repository: Red-Hat-AI-Innovation-Team/claude-skills
+          ref: <pinned-commit-sha-or-reviewed-tag>
+          persist-credentials: false
           path: .claude

Replace the marketplace URL with a local path (example):

  - name: Checkout pinned plugin marketplace
-    uses: actions/checkout@v4
+    uses: actions/checkout@v4
    with:
-      repository: anthropics/claude-plugins-official
-      path: plugin-marketplace
+      repository: anthropics/claude-plugins-official
+      ref: <pinned-commit-sha-or-reviewed-tag>
+      path: plugin-marketplace
+      persist-credentials: false

  - name: Run Claude action
    uses: anthropics/claude-code-action@v1
    with:
-      plugin_marketplaces: |
-        https://github.com/anthropics/claude-plugins-official.git
+      plugin_marketplaces: |
+        ./plugin-marketplace

Additionally, ensure marketplace.json in the pinned checkout uses the sha field for each plugin source (when present) to lock plugin versions immutably.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 67-71: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude.yml around lines 67 - 71, The workflow is still
pulling mutable inputs into the Claude execution path, so harden the shared
skills and plugin marketplace setup in the workflow job. In the Load shared
skills checkout step, add a pinned ref for the claude-skills repository and
disable credential persistence with persist-credentials false; then update the
marketplace setup so plugin_marketplaces points to a locally checked-out
marketplace directory instead of a remote URL, with that repo fetched earlier at
a specific commit SHA. Also make sure the marketplace.json used by the pinned
checkout locks each plugin source with sha when available so the plugin set
stays immutable.

Source: Linters/SAST tools


- name: Authenticate to GCP
uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}

Comment on lines +73 to +77

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/claude.yml

Repository: Red-Hat-AI-Innovation-Team/its_hub

Length of output: 5370


🏁 Script executed:

ls -la .github/workflows/

Repository: Red-Hat-AI-Innovation-Team/its_hub

Length of output: 716


🏁 Script executed:

grep -n "workload_identity_provider\|GCP_WORKLOAD_IDENTITY_PROVIDER" .github/workflows/*.yaml

Repository: Red-Hat-AI-Innovation-Team/its_hub

Length of output: 172


Prefer Workload Identity Federation and remove unused OIDC permissions.

The job grants id-token: write (line 25) but authenticates with a static credentials_json secret (lines 75-76). The OIDC permission is currently unused and exposes a long-lived static key unnecessarily.

  1. Immediate fix: Remove id-token: write from the permissions block if you intend to keep using the static key short-term.
  2. Recommended: Migrate to Workload Identity Federation (WIF). This requires setting up a Workload Identity Provider in your GCP Console and binding it to a Service Account. Once configured, you can remove the GCP_SA_KEY secret and credentials_json input.

Current authentication relies on long-lived credentials; WIF would provide short-lived, automatically rotated tokens.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude.yml around lines 73 - 77, The workflow’s GCP auth
setup is mixing an unused OIDC permission with a static service account key. In
the job permissions block, remove id-token: write if you are keeping the current
credentials_json-based approach, or better, update the Authenticate to GCP step
to use Workload Identity Federation instead of GCP_SA_KEY. Use the auth step and
the surrounding job configuration to locate the change, and ensure the final
setup matches the chosen auth method without leaving unused OIDC permissions
enabled.

- name: Run Claude Code
uses: anthropics/claude-code-action@1c8b699d43e9bfed42b48ef15da85d89bab70960 # v1
with:
use_vertex: true
trigger_phrase: "@claude-code"
claude_args: "--model claude-opus-4-6[1m] --effort max --dangerously-skip-permissions"
plugins: |
code-review@claude-plugins-official
commit-commands@claude-plugins-official
feature-dev@claude-plugins-official
huggingface-skills@claude-plugins-official
frontend-design@claude-plugins-official
plugin_marketplaces: |
https://github.com/anthropics/claude-plugins-official.git
env:
ANTHROPIC_VERTEX_PROJECT_ID: ${{ secrets.GCP_PROJECT }}
CLOUD_ML_REGION: ${{ secrets.GCP_REGION }}
CLAUDE_CODE_SUBAGENT_MODEL: "claude-opus-4-6[1m]"
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: "1"
ANTHROPIC_DEFAULT_OPUS_MODEL: "claude-opus-4-6[1m]"
CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING: "1"
MAX_THINKING_TOKENS: "128000"
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,14 @@ Try it in your browser: [https://red.ht/its-hub-demo](https://red.ht/its-hub-dem

To run the demo yourself, see the [demo setup instructions](https://github.com/lukeinglis/its_hub_demo/blob/main/demo_ui/README.md).

## Demo

See the library in action with a walkthrough of inference-time scaling algorithms:

[![Demo walkthrough](https://img.youtube.com/vi/qaXyvmR-YBU/maxresdefault.jpg)](https://www.youtube.com/watch?v=qaXyvmR-YBU)

Try it in your browser: [https://red.ht/its-hub-demo](https://red.ht/its-hub-demo)

To run the demo yourself, see the [demo setup instructions](https://github.com/lukeinglis/its_hub_demo/blob/main/demo_ui/README.md).

Comment on lines +221 to +230

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove duplicate ## Demo section.

This inserted section duplicates the identical ## Demo section at lines 211-219, causing a markdownlint warning (MD024/no-duplicate-heading) and redundant content. Remove lines 221-230.

🛠️ Proposed fix
-## Demo
-
-See the library in action with a walkthrough of inference-time scaling algorithms:
-
-[![Demo walkthrough](https://img.youtube.com/vi/qaXyvmR-YBU/maxresdefault.jpg)](https://www.youtube.com/watch?v=qaXyvmR-YBU)
-
-Try it in your browser: [https://red.ht/its-hub-demo](https://red.ht/its-hub-demo)
-
-To run the demo yourself, see the [demo setup instructions](https://github.com/lukeinglis/its_hub_demo/blob/main/demo_ui/README.md).
-
 For detailed documentation, visit: [https://ai-innovation.team/its_hub](https://ai-innovation.team/its_hub)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Demo
See the library in action with a walkthrough of inference-time scaling algorithms:
[![Demo walkthrough](https://img.youtube.com/vi/qaXyvmR-YBU/maxresdefault.jpg)](https://www.youtube.com/watch?v=qaXyvmR-YBU)
Try it in your browser: [https://red.ht/its-hub-demo](https://red.ht/its-hub-demo)
To run the demo yourself, see the [demo setup instructions](https://github.com/lukeinglis/its_hub_demo/blob/main/demo_ui/README.md).
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 221-221: Multiple headings with the same content

(MD024, no-duplicate-heading)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 221 - 230, The README has a duplicated Demo heading
and content, triggering a markdownlint duplicate-heading warning. Remove the
second `## Demo` block so only one demo section remains, and keep the existing
demo content under the original `## Demo` heading.

Source: Linters/SAST tools

For detailed documentation, visit: [https://ai-innovation.team/its_hub](https://ai-innovation.team/its_hub)
Loading