Skip to content

fix: create triage PRs as Imagile Bot - #290

Merged
kolatts merged 1 commit into
mainfrom
kolatts/289-imagile-bot-pr-token
Jul 29, 2026
Merged

fix: create triage PRs as Imagile Bot#290
kolatts merged 1 commit into
mainfrom
kolatts/289-imagile-bot-pr-token

Conversation

@kolatts

@kolatts kolatts commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • generate a short-lived, current-repository-only installation token for the Imagile Bot GitHub App
  • use that token for checkout, Claude GitHub operations, branch pushes, PR creation, issue comments, and label cleanup
  • resolve the App bot identity dynamically for Claude's git operations
  • reduce the built-in GITHUB_TOKEN to read-only repository contents

Why

GitHub places workflows triggered by pull requests created with the repository GITHUB_TOKEN into an approval-required state. Creating and updating the automated branch and PR with a separate GitHub App installation token allows the normal PR workflows to start without that special manual approval.

Repository configuration

  • Actions variable: IMAGILE_BOT_APP_ID
  • Actions secret: IMAGILE_BOT_PRIVATE_KEY

Both have been configured directly in the repository. No credential material is committed.

The installed App must grant Contents, Pull requests, Issues, and Workflows read/write permissions requested by the token-generation step.

Validation

  • workflow YAML parsed successfully with Prettier
  • git diff --check
  • confirmed the repository variable and encrypted secret exist by name
  • confirmed the Imagile Bot account resolves as imagile-bot[bot]

The definitive end-to-end validation will be a triage-created PR after this workflow change reaches main.

Closes #289

Use a short-lived GitHub App installation token for Claude operations, branch pushes, and PR creation so automated PR workflows run without manual approval.

Closes #289

Generated-with: OpenAI Codex (GPT-5)
@claude

claude Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kolatts's task in 2m 41s —— View job


Code Review

  • Gather context and clean up stale comments
  • Read the diff and changed file
  • Review for correctness, security, and edge cases
  • Submit formal review — Approved

Summary: The approach is sound. Reducing GITHUB_TOKEN to contents: read and driving all write operations through a short-lived App installation token is the right model for avoiding the manual-approval throttle on bot-created PRs. Two things worth a quick verification:

  1. actions/create-github-app-token@v3 (line 20) — as of August 2025 the action was at v1. If v3 was released since then it's fine, but verify the tag exists and that the permission-* inputs are supported in that version — the workflow hard-fails at token generation if the tag doesn't resolve.

  2. Expression injection in shell (line 34)${{ steps.imagile-token.outputs.app-slug }} is interpolated verbatim into the shell before it runs. App slugs are alphanumeric-hyphen so this is low-risk, but the defensive pattern is to pass it via an env: block. Inline suggestion posted.

Neither is blocking — (1) will surface immediately on the first triage run.

env:
GH_TOKEN: ${{ steps.imagile-token.outputs.token }}
run: |
BOT_LOGIN="${{ steps.imagile-token.outputs.app-slug }}[bot]"

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.

Minor security hardening${{ steps.imagile-token.outputs.app-slug }} is evaluated by the Actions runner and interpolated verbatim into the shell script before the shell sees it. GitHub App slugs are lowercase-alphanumeric-hyphen, so this is low-risk in practice — but binding through an env var is the defensive pattern that keeps the value as data rather than code:

Suggested change
BOT_LOGIN="${{ steps.imagile-token.outputs.app-slug }}[bot]"
env:
GH_TOKEN: ${{ steps.imagile-token.outputs.token }}
APP_SLUG: ${{ steps.imagile-token.outputs.app-slug }}
run: |
BOT_LOGIN="${APP_SLUG}[bot]"

steps:
- name: Generate Imagile Bot token
id: imagile-token
uses: actions/create-github-app-token@v3

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.

Verify the action version — as of August 2025 actions/create-github-app-token was at v1. If v3 was released after that it's fine, but worth a quick double-check that it exists and the permission-* inputs you're using (lines 24–27) are supported in this version. The workflow will fail at the token-generation step if the version tag doesn't resolve.

@claude claude Bot left a comment

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.

PASS — architecture is sound and the security posture is clearly improved.

What this does well:

  • Reducing GITHUB_TOKEN to contents: read and moving all write operations to the App installation token is exactly the right model. PRs created by an App identity are not throttled into the manual-approval queue the way GITHUB_TOKEN-created PRs are.
  • Generating a short-lived installation token scoped to contents, pull-requests, issues, and workflows write is appropriate — no over-scoping.
  • Resolving the bot identity dynamically from app-slug rather than hardcoding the login string is robust; it will survive app renames.
  • Passing github_token, bot_id, and bot_name into claude-code-action ensures Claude's git operations (commits, pushes) carry the bot's identity, not the runner's default.

Two things to check before merging:

  1. actions/create-github-app-token@v3 (line 20) — As of my knowledge cutoff v1 was the latest. Verify v3 exists and that the permission-* inputs (lines 24–27) are supported in that version; the step will hard-fail if the tag doesn't resolve.
  2. Expression injection in shell (line 34)${{ steps.imagile-token.outputs.app-slug }} is interpolated into the shell before the shell runs it. App slugs are safe in practice (lowercase-alphanumeric-hyphen), but the defensive pattern is to bind it through env: so it enters as data. Inline suggestion posted.

Neither is blocking; (1) will surface immediately on the first triage run and (2) is low-risk given GitHub's slug format constraints. Happy to approve.

@kolatts
kolatts marked this pull request as ready for review July 29, 2026 22:17
@kolatts
kolatts merged commit dceb73d into main Jul 29, 2026
6 checks passed
@kolatts
kolatts deleted the kolatts/289-imagile-bot-pr-token branch July 29, 2026 22:17
@claude

claude Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kolatts's task in 2m 29s —— View job


Code Review

  • Gather context and clean up stale comments
  • Read the diff and changed file
  • Review for correctness, security, and edge cases
  • Submit formal review — Approved (formal review submission denied by permissions; see below)

Summary: The approach is sound. Reducing GITHUB_TOKEN to contents: read and driving all write operations through a short-lived App installation token is the right model for avoiding the manual-approval throttle on bot-created PRs.

What this does well:

  • GITHUB_TOKEN scoped to contents: read only — write path goes entirely through the App token.
  • Short-lived installation token scoped appropriately to contents, pull-requests, issues, and workflows write — no over-privileging.
  • Bot identity resolved dynamically from app-slug output rather than hardcoded — survives app renames.
  • github_token, bot_id, and bot_name passed into claude-code-action so git commits carry the bot identity, not the runner default.
  • if: always() on the label-removal step (line 240) ensures cleanup even on cancellation.

Two items flagged — non-blocking, both will surface on the first triage run:

  1. actions/create-github-app-token@v3 (line 20) — At my knowledge cutoff (August 2025) the action was at v1. If v3 is a valid tag today this is fine, but the step hard-fails at token generation if the tag doesn't resolve. Verify the tag exists in actions/create-github-app-token.

  2. Expression interpolation in shell (line 34)${{ steps.imagile-token.outputs.app-slug }} is expanded by the Actions runner and lands verbatim in the shell before the shell executes. GitHub App slugs are lowercase-alphanumeric-hyphen, so the injection surface is essentially nil — but passing via env: is the defensive standard pattern. Low-risk as-is.

Minor:

  • Line 221 wraps the issue number in single quotes ('${{ ... }}') while line 243 leaves it unquoted. Both work (Actions expressions are expanded before the shell sees them), but the style is inconsistent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use Imagile Bot token for automated triage pull requests

1 participant