Repository navigation
chore: add Claude Code GitHub Actions workflows - #10
lukeocodes wants to merge 1 commit into
Conversation
- auto-close-duplicates.yml - backfill-duplicate-comments.yml - claude.yml - claude-dedupe-issues.yml - claude-issue-triage.yml - issue-lifecycle-comment.yml - lock-closed-issues.yml - non-write-users-check.yml - remove-autoclose-label.yml - sweep.yml
|
This PR adds or modifies If this is a new flow, please make sure you actually need See existing workflows in this repo for safe usage examples, or contact the AppSec team. |
There was a problem hiding this comment.
Pull request overview
Adds a set of GitHub Actions workflows (ported from deepgram/claude-code) intended to automate issue deduplication/triage, lifecycle management, and integrate Claude Code on repo activity.
Changes:
- Introduces multiple issue-management workflows (sweep, lifecycle comments, duplicate auto-close, stale locking).
- Adds Claude Code-driven workflows for issue triage and dedupe, plus an on-demand
@claudetrigger workflow. - Adds a PR guard workflow to detect
allowed_non_write_usersusage in workflow changes.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/sweep.yml | Scheduled issue sweep invoking a Bun/TS script |
| .github/workflows/remove-autoclose-label.yml | Removes autoclose label when new issue comments arrive |
| .github/workflows/non-write-users-check.yml | PR check to warn on allowed_non_write_users additions |
| .github/workflows/lock-closed-issues.yml | Scheduled locking of stale closed issues via github-script |
| .github/workflows/issue-lifecycle-comment.yml | Posts lifecycle comments on labeling via Bun/TS script |
| .github/workflows/claude.yml | Runs Claude Code on @claude mentions across issues/PR reviews |
| .github/workflows/claude-issue-triage.yml | Runs Claude-driven triage on issue open/comment events |
| .github/workflows/claude-dedupe-issues.yml | Runs Claude dedupe on issue open / workflow_dispatch (+ optional Statsig logging) |
| .github/workflows/backfill-duplicate-comments.yml | Manual backfill job invoking a Bun/TS script |
| .github/workflows/auto-close-duplicates.yml | Scheduled duplicate auto-close invoking a Bun/TS script |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,83 @@ | |||
| name: Claude Issue Dedupe | |||
| description: Automatically dedupe GitHub issues using Claude Code | |||
There was a problem hiding this comment.
description: is not a valid top-level key in GitHub Actions workflow YAML and can cause the workflow to be treated as invalid. Remove it (or replace with a YAML comment).
| description: Automatically dedupe GitHub issues using Claude Code | |
| # description: Automatically dedupe GitHub issues using Claude Code |
|
|
||
| on: | ||
| schedule: | ||
| # 8am Pacific = 1pm UTC (2pm UTC during DST) |
There was a problem hiding this comment.
The schedule comment doesn't match the cron expression. 0 14 * * * is 14:00 UTC (which is not 8am Pacific in either PST or PDT). Update the comment or adjust the cron to the intended time so future maintainers don't get misled.
| # 8am Pacific = 1pm UTC (2pm UTC during DST) | |
| # Runs daily at 14:00 UTC (6am Pacific Standard Time / 7am Pacific Daylight Time) |
| - name: Setup Bun | ||
| uses: oven-sh/setup-bun@v2 | ||
| with: | ||
| bun-version: latest | ||
|
|
||
| - name: Post lifecycle comment | ||
| run: bun run scripts/lifecycle-comment.ts | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| LABEL: ${{ github.event.label.name }} | ||
| ISSUE_NUMBER: ${{ github.event.issue.number }} |
There was a problem hiding this comment.
bun run scripts/lifecycle-comment.ts references scripts/lifecycle-comment.ts, but that file does not exist in the repo. Add the script (and any required dependencies) or update the workflow to run an existing implementation.
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Post lifecycle comment | |
| run: bun run scripts/lifecycle-comment.ts | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| LABEL: ${{ github.event.label.name }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| - name: Post lifecycle comment | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const label = context.payload.label?.name; | |
| const issueNumber = context.payload.issue?.number; | |
| if (!label || !issueNumber) { | |
| core.info('No label or issue number found; skipping lifecycle comment.'); | |
| return; | |
| } | |
| const body = `Lifecycle label **${label}** was added to this issue.`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| body, | |
| }); |
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| allowed_non_write_users: "*" | ||
| prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}" | ||
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| claude_args: "--model claude-sonnet-4-5-20250929" | ||
|
|
There was a problem hiding this comment.
Setting allowed_non_write_users: "*" allows any GitHub user (including non-collaborators) to trigger this workflow on issue events, while the job has issues: write and receives ANTHROPIC_API_KEY. This is a significant security/cost risk; restrict to an explicit allowlist (or remove this setting) and/or add an actor permission check before invoking the action.
| GH_REPO: ${{ github.repository }} | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| allowed_non_write_users: "*" |
There was a problem hiding this comment.
Setting allowed_non_write_users: "*" allows any non-collaborator to trigger Claude runs on issue opens/comments while the workflow has issues: write and uses ANTHROPIC_API_KEY. This is a high-risk configuration; use a restricted allowlist and/or gate execution on actor association/permissions before calling the action.
| allowed_non_write_users: "*" | |
| allowed_non_write_users: "" |
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} | ||
| GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }} |
There was a problem hiding this comment.
This workflow runs on schedule, where github.event.repository is typically absent; github.event.repository.name may resolve to an empty string. Consider using ${{ github.repository }} (and parsing it) instead of relying on github.event.repository.name so scheduled runs have consistent env values.
| GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }} | |
| GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name || github.repository }} |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} | ||
| GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }} | ||
| STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }} |
There was a problem hiding this comment.
PR description lists only ANTHROPIC_API_KEY as required, but these workflows also reference STATSIG_API_KEY (here and in claude-dedupe-issues.yml). If Statsig logging is optional, it would help to note that in the PR description/README; if it's required for correct operation, it should be included in the required secrets list.
| @@ -0,0 +1,31 @@ | |||
| name: Auto-close duplicate issues | |||
| description: Auto-closes issues that are duplicates of existing issues | |||
There was a problem hiding this comment.
description: is not a valid top-level key in GitHub Actions workflow YAML and can cause the workflow to be rejected as invalid. Remove it or convert it to a comment/documentation elsewhere.
| description: Auto-closes issues that are duplicates of existing issues | |
| # Auto-closes issues that are duplicates of existing issues |
| @@ -0,0 +1,44 @@ | |||
| name: Backfill Duplicate Comments | |||
| description: Triggers duplicate detection for old issues that don't have duplicate comments | |||
There was a problem hiding this comment.
description: is not a valid top-level key in GitHub Actions workflow YAML and can make the workflow invalid. Remove this key (keep it as a comment if needed).
| description: Triggers duplicate detection for old issues that don't have duplicate comments | |
| # description: Triggers duplicate detection for old issues that don't have duplicate comments |
| - name: Backfill duplicate comments | ||
| run: bun run scripts/backfill-duplicate-comments.ts | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| DAYS_BACK: ${{ inputs.days_back }} | ||
| DRY_RUN: ${{ inputs.dry_run }} No newline at end of file |
There was a problem hiding this comment.
bun run scripts/backfill-duplicate-comments.ts references scripts/backfill-duplicate-comments.ts, but that file does not exist in the repository. Add the script or update the workflow to run an existing implementation.
## Summary After the release workflow opens the "Bump deepctl to X" PR on deepgram/homebrew-tap, it now merges that PR in the same step, using the same `CLI_TAP_SYNC_PAT` that pushed the branch. The step is also made safe to re-run and safe against two releases racing on the tap. ## Why The tap has no branch protection, no checks and no reviewers, so an open bump PR only delays Homebrew users. The 0.3.1, 0.3.2 and 0.3.3 bumps (homebrew-tap #9, #10, #11) all sat unmerged while the tap's formula stayed at 0.2.26. #11 was merged by hand; this keeps that from happening again. The formula is generated from PyPI metadata by `scripts/bump_brew_formula.py`, so there is nothing for a reviewer to judge in the tap PR itself. The merged PR stays as the audit trail, and a broken formula is fixed by editing the template, as the generated PR body already says. ## What changed (`bump-brew-formula` job only) - **Serialized.** The job gets `concurrency: {group: homebrew-tap-bump, cancel-in-progress: false}`, so two root releases in quick succession bump the tap one after the other instead of both reading the same starting formula. - **Version guard.** Before touching git, the step reads the version the tap currently serves from `git show HEAD:Formula/deepgram.rb` (the regenerate step has already overwritten the working tree, so HEAD is the tap's state) and the regenerated version from the working tree. - It fails the job if the tag, the current formula or the regenerated formula is not a plain `X.Y.Z` version, or if the regenerated formula does not point at the tagged version. - It exits 0 with a warning unless the new version is strictly greater than what the tap serves. Re-running an older release can no longer downgrade the tap, and re-running a release that already landed is a no-op. - **Formula syntax check.** `ruby -c Formula/deepgram.rb` runs before the commit. This is a Ruby syntax check only: it catches a broken template or a mangled resource block, not a wrong sha256 or a failing `brew install`. - **Re-runnable push and PR.** The branch is pushed with `--force`, so a re-run replaces a branch left behind by an earlier failed attempt. If an open PR for that branch already exists, it is reused instead of `gh pr create` failing on the duplicate. - The existing-PR lookup only accepts same-repo PRs (`isCrossRepository == false`) authored by the PAT's own login. The tap is public, so anyone can open a fork PR whose head branch is named `bump-deepctl-X`; an unfiltered lookup could have merged it with the PAT. - The resulting PR URL must match `https://github.com/deepgram/homebrew-tap/pull/N` or the job fails. - **Merge with retry.** GitHub computes mergeability after a PR is created and gh does not wait for it, so `gh pr merge <url> --merge --delete-branch` is tried up to five times with a short backoff. If a merge attempt fails but the PR's state is `MERGED` (merged by hand mid-loop, or merged and then the branch delete failed), that counts as success. After five failed attempts the job fails with an error annotation. - **Stale bump cleanup.** After a successful merge, open `bump-deepctl-*` PRs that are same-repo, authored by the PAT owner, and for a strictly older plain `X.Y.Z` version are closed with their branch deleted and a comment linking the superseding PR. This is best effort: listing or closing failures emit a warning and never fail the job. ## Checked - The workflow YAML parses, and `bash -n` passes on the extracted step script. - actionlint 1.7.12 with shellcheck 0.11.0 reports 0 findings on `.github/workflows/release.yml`. The one intentional single-quoted jq `$login` carries a `shellcheck disable=SC2016` with a comment. - No job other than `bump-brew-formula` is modified. - Typed `ci:` so release-please adds no changelog line and bumps no version for CI plumbing (precedent: #66, #70). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add Claude Code Workflows
This PR adds GitHub Actions workflows from deepgram/claude-code.
Workflows added
auto-close-duplicates.yml— Auto-close duplicate issuesbackfill-duplicate-comments.yml— Backfill Duplicate Commentsclaude.yml— Claude Codeclaude-dedupe-issues.yml— Claude Issue Dedupeclaude-issue-triage.yml— Claude Issue Triageissue-lifecycle-comment.yml— Issue Lifecycle Commentlock-closed-issues.yml— Lock Stale Issuesnon-write-users-check.yml— Non-write Users Checkremove-autoclose-label.yml— Remove Autoclose Label on Activitysweep.yml— Issue SweepRequired secrets
ANTHROPIC_API_KEY— your Anthropic API keySet it with:
gh secret set ANTHROPIC_API_KEY --repo deepgram/cliInstalled via
dxi claudify