Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
226 lines
7.6 KiB
Markdown
226 lines
7.6 KiB
Markdown
# todo-issue
|
|
|
|
Scans code for `TODO` comments and automatically creates, closes, updates, and references GitHub Issues.
|
|
|
|
Runs as a GitHub Actions workflow via [Bun](https://bun.sh/) with a single dependency (`parse-diff`).
|
|
|
|
## How it works
|
|
|
|
When code is pushed to `develop`, the script diffs the changes and:
|
|
|
|
- **Creates** a new issue for each new `TODO` comment
|
|
- **Closes** the issue when a `TODO` is removed
|
|
- **Updates** the issue title when a `TODO` is edited (detected via similarity matching)
|
|
- **References** an existing issue when a duplicate `TODO` is added (adds a comment instead of creating a duplicate)
|
|
|
|
Every issue created by the script receives the `todo` label, which is also used to efficiently query only relevant issues.
|
|
|
|
## TODO syntax
|
|
|
|
Any comment style works (`//`, `#`, `--`, `/* */`, etc.) as long as only symbols and whitespace appear before the `TODO` keyword. The keyword is case-insensitive.
|
|
|
|
### Examples
|
|
|
|
**Minimal -- title only:**
|
|
|
|
```ts
|
|
// TODO: Fix the race condition in token refresh
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| ------ | ----------------------------------------- |
|
|
| Title | `Fix the race condition in token refresh` |
|
|
| Body | _(none)_ |
|
|
| Labels | `todo` |
|
|
|
|
---
|
|
|
|
**With body -- continuation lines using the same comment prefix:**
|
|
|
|
```ts
|
|
// TODO: Refactor the auth flow
|
|
// The current token refresh logic has race conditions
|
|
// when multiple tabs are open simultaneously
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| ------ | ----------------------------------------------------------------------------------------------------- |
|
|
| Title | `Refactor the auth flow` |
|
|
| Body | `The current token refresh logic has race conditions`<br>`when multiple tabs are open simultaneously` |
|
|
| Labels | `todo` |
|
|
|
|
The body stops at the first line that doesn't share the same comment prefix or is empty.
|
|
|
|
---
|
|
|
|
**With custom labels:**
|
|
|
|
```ts
|
|
// TODO: Make this button red [frontend] [ui]
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| ------ | ------------------------ |
|
|
| Title | `Make this button red` |
|
|
| Body | _(none)_ |
|
|
| Labels | `todo`, `frontend`, `ui` |
|
|
|
|
Labels are extracted from `[square brackets]` at the end of the title. The `todo` label is always included.
|
|
|
|
---
|
|
|
|
**Full example -- body + labels in different languages:**
|
|
|
|
```python
|
|
# TODO: Add retry logic for S3 uploads [infra] [backend]
|
|
# Currently fails silently on timeout
|
|
# See https://github.com/org/repo/issues/42
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| ------ | ------------------------------------------------------------------------------------ |
|
|
| Title | `Add retry logic for S3 uploads` |
|
|
| Body | `Currently fails silently on timeout`<br>`See https://github.com/org/repo/issues/42` |
|
|
| Labels | `todo`, `infra`, `backend` |
|
|
|
|
---
|
|
|
|
**Block comments:**
|
|
|
|
```ts
|
|
/**
|
|
* TODO: Should we reinvent the wheel here?
|
|
* We already have a good one in @rocket.chat/core
|
|
*/
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| ------ | ------------------------------------------------- |
|
|
| Title | `Should we reinvent the wheel here?` |
|
|
| Body | `We already have a good one in @rocket.chat/core` |
|
|
| Labels | `todo` |
|
|
|
|
---
|
|
|
|
### Assignees
|
|
|
|
Mention GitHub usernames with `@` to automatically assign the issue:
|
|
|
|
```ts
|
|
// TODO: Fix flaky test @john-doe [testing]
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| --------- | ----------------- |
|
|
| Title | `Fix flaky test` |
|
|
| Body | _(none)_ |
|
|
| Labels | `todo`, `testing` |
|
|
| Assignees | `john-doe` |
|
|
|
|
Mentions in the title are removed from the issue title. Mentions in the body are also collected as assignees but kept in the body text:
|
|
|
|
```ts
|
|
// TODO: Migrate to new payments API
|
|
// @alice should review the Stripe integration
|
|
// @bob handles the webhook setup
|
|
```
|
|
|
|
Extracted data:
|
|
|
|
| Field | Value |
|
|
| --------- | --------------------------------------------------------------------------------- |
|
|
| Title | `Migrate to new payments API` |
|
|
| Body | `@alice should review the Stripe integration`<br>`@bob handles the webhook setup` |
|
|
| Labels | `todo` |
|
|
| Assignees | `alice`, `bob` |
|
|
|
|
---
|
|
|
|
### What is NOT captured
|
|
|
|
```ts
|
|
// This is not a TODO because the keyword is not at the start after the prefix
|
|
// See the TODO documentation for more info
|
|
|
|
const todo = 'strings containing TODO are ignored';
|
|
|
|
// TODONT -- partial keyword matches are ignored
|
|
```
|
|
|
|
## Trigger modes
|
|
|
|
The workflow supports four modes, configured via `workflow_dispatch` inputs or automatic push events.
|
|
|
|
### Push (automatic)
|
|
|
|
Triggers on every push to `develop`. Compares `BEFORE_SHA...GITHUB_SHA` to detect added/removed TODOs.
|
|
|
|
### SHA (manual)
|
|
|
|
Process a specific commit or range of commits.
|
|
|
|
| Input | Behavior |
|
|
| ------------------- | ------------------------------------------------------- |
|
|
| `a1b2c3d` | Diffs commit against its parent (`a1b2c3d~1...a1b2c3d`) |
|
|
| `a1b2c3d...f4e5d6a` | Diffs the full range |
|
|
|
|
### Path (manual)
|
|
|
|
Import all TODOs from a specific file or directory:
|
|
|
|
```
|
|
apps/meteor/client
|
|
packages/core-typings/src/IMessage.ts
|
|
```
|
|
|
|
Only creates issues (no close/update). Skips TODOs that already have a matching issue.
|
|
|
|
### Import all (manual)
|
|
|
|
Scans the entire codebase for TODOs. Only creates issues for TODOs that don't already have a matching issue. Use with caution on large codebases.
|
|
|
|
## Matching logic
|
|
|
|
The script compares found TODOs against existing issues using:
|
|
|
|
1. **Exact title match** -- identical titles are considered the same TODO
|
|
2. **Similarity match** -- titles within 80% Levenshtein similarity are considered the same TODO (catches typo fixes and small edits)
|
|
|
|
When a TODO is both added and deleted in the same diff:
|
|
|
|
- **Same title** -- treated as a move (no action)
|
|
- **Similar title** -- treated as an edit (updates the existing issue title)
|
|
|
|
When a new TODO matches an existing open issue, a reference comment is added to the issue instead of creating a duplicate.
|
|
|
|
## Rate limiting
|
|
|
|
The script reads `x-ratelimit-remaining` and `x-ratelimit-reset` from GitHub API response headers and automatically waits when approaching the limit.
|
|
|
|
## Project structure
|
|
|
|
```
|
|
scripts/todo-issue/
|
|
├── package.json
|
|
├── tsconfig.json
|
|
└── src/
|
|
├── index.ts # Entry point, config loading, diff resolution, orchestration
|
|
├── types.ts # Shared interfaces (Config, TodoItem, GitHubIssue, MatchResult)
|
|
├── diff.ts # Diff parsing (parse-diff), TODO extraction, body/label parsing
|
|
├── matcher.ts # Match found TODOs against existing issues
|
|
├── similarity.ts # Levenshtein distance and similarity check
|
|
└── github.ts # GitHub API (REST + GraphQL), rate limiting, issue CRUD
|
|
```
|