Home
Softono
github-issue-due-dates-action

github-issue-due-dates-action

Open source MIT TypeScript
87
Stars
21
Forks
3
Issues
2
Watchers
1 week
Last Commit

About github-issue-due-dates-action

:calendar: GitHub Issue Due Dates Action

Platforms

Web Self-hosted

Languages

TypeScript

Links

:calendar: GitHub Issue Due Dates Action

Give GitHub Issues a real due date. This action reads a date from each issue's YAML frontmatter and keeps labels (and optionally comments) in sync.

CI GitHub Marketplace Release License: MIT


Why?

GitHub Issues don't have a native "due date" concept — only milestones, which are one-per-issue and don't map cleanly to personal task lists or roadmaps. This action lets you drop a one-line date into any issue body and get automatic, queryable labels for free:

  • Want a Kanban column for stuff due this week? Filter by the Due in 1 week label.
  • Want to triage what slipped? Filter by Overdue.
  • Want to @-mention yourself a week out? Turn on reminder comments.

No bots to install, no external service — just one scheduled workflow.

Table of Contents


Quick start

1. Annotate issues. Add YAML frontmatter to the top of any issue body:

---
due: 2026-09-19
---

The actual description of the issue goes here.

2. Add a scheduled workflow at .github/workflows/due-dates.yml:

name: Issue due-date labels
on:
  schedule:
    - cron: '0 * * * *'   # hourly
  workflow_dispatch:       # or run it manually

jobs:
  label:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      contents: read
    steps:
      - uses: alexleventer/github-issue-due-dates-action@v2
        with:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

That's it. The built-in GITHUB_TOKEN has enough permission — no personal access token required.

How it works

On every run the action:

  1. Fetches all open issues (pull requests are skipped).
  2. Parses YAML frontmatter from each issue body and looks for a due: key.
  3. Computes the number of whole days between today (UTC) and the due date.
  4. Reconciles the issue's labels against your configured buckets:
    • daysUntil <= 0Overdue label.
    • Otherwise, the smallest-matching upcoming bucket (default: Due in 1 week).
    • Any managed label that no longer applies is removed. Unrelated labels are left alone.
  5. Optionally posts one comment per (issue, due date, kind) — changing the due date bumps the dedup key.

All logic is idempotent: running it a hundred times in a row produces the same state as running it once.

Inputs

Name Required Default Description
GH_TOKEN Token used to read issues and write labels/comments. ${{ secrets.GITHUB_TOKEN }} is usually enough.
overdue-label Overdue Label applied when an issue is past its due date.
upcoming-labels see below YAML list of { days, label } buckets. Smallest-matching bucket wins.
comment-on-overdue (disabled) Template posted once when an issue becomes overdue. Supports {{daysUntil}}, {{dueDate}}, {{issueNumber}}.
comment-on-upcoming (disabled) Template posted once when an issue enters an upcoming-due bucket. Same template variables.
dry-run false Log planned changes instead of calling the GitHub API — handy for first-time setup.

Default upcoming-labels:

- days: 7
  label: 'Due in 1 week'

Outputs

Name Description
issues-processed Total number of open issues fetched.
issues-changed Number of issues whose labels or comments were updated.

Examples

Multiple upcoming-due buckets

- uses: alexleventer/github-issue-due-dates-action@v2
  with:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    upcoming-labels: |
      - days: 3
        label: 'Due in 3 days'
      - days: 14
        label: 'Due in 2 weeks'
      - days: 30
        label: 'Due in a month'

An issue due in 10 days will get Due in 2 weeks. In 5 days, Due in 3 days. In 31 days, no label.

Reminder comments

- uses: alexleventer/github-issue-due-dates-action@v2
  with:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    comment-on-overdue: |
      :rotating_light: This issue is **overdue** (was due on `{{dueDate}}`, {{daysUntil}} day(s) ago).
    comment-on-upcoming: |
      :hourglass_flowing_sand: Heads up — this issue is due on `{{dueDate}}` ({{daysUntil}} day(s) away).

Comments are deduplicated per due date. Bumping the due date allows exactly one new comment; repeated runs against the same date do nothing.

Custom label names (e.g. emoji)

- uses: alexleventer/github-issue-due-dates-action@v2
  with:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    overdue-label: '🔥 overdue'
    upcoming-labels: |
      - days: 7
        label: '⏰ due soon'

Dry run (no writes)

- uses: alexleventer/github-issue-due-dates-action@v2
  with:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    dry-run: true

Permissions

When using GITHUB_TOKEN, the job needs:

permissions:
  issues: write     # to add/remove labels and post comments
  contents: read    # to check out nothing, really — just kept for future extensibility

If your repo defaults to a restricted GITHUB_TOKEN, set these explicitly at the workflow or job level. A PAT with the repo scope works too but is rarely necessary.

Versioning

Pin using one of:

  • @v2 — floating major, recommended. Gets bug fixes and backwards-compatible features automatically.
  • @v2.0.0 — exact version, reproducible.
  • @master — bleeding edge, not recommended.

See releases for the changelog.

FAQ

Can I use this on private repos?

Yes. The built-in GITHUB_TOKEN works fine; no PAT required.

Will it touch labels I don't manage?

No. The action only adds/removes its own configured overdue-label and upcoming-labels. Hand-applied labels (e.g. bug, enhancement, triage labels) are left alone.

What date formats are supported?

Any YYYY-MM-DD string or a native YAML date. The comparison is done in UTC at day granularity, so there's no time zone foot-gun.

Why doesn't my label appear immediately?

Scheduled workflows run on cron — they aren't instant. For an immediate test, trigger the workflow manually via workflow_dispatch (see the quick-start example).

What if I change the due date?

On the next run the action recomputes: it will remove any stale label it previously applied and add the correct one. If reminder comments are enabled, the new due date will trigger one new comment; the old one stays for history.

Does it handle pull requests?

No — PRs are filtered out. The GitHub REST API treats PRs as issues, but this action only labels real issues.

Development

npm ci
npm run lint       # tsc --noEmit
npm test           # Jest unit tests (no network)
npm run build      # bundles to dist/index.js with @vercel/ncc
npm run all        # lint + test + build

CI enforces that dist/ is checked in and up to date. Run npm run build and commit the result before pushing.

Project layout:

src/
  app.ts                # entry point (reads inputs, loops over issues)
  processor.ts          # pure reconciliation logic (fully unit-tested)
  integrations/Octokit.ts
  utils/{dateUtils,frontmatter,labels}.ts
__tests__/              # Jest tests, all mocked — no live API calls
dist/                   # ncc bundle, committed

Contributing

Issues and PRs welcome. If you're adding a new label mode or comment behavior, please include a test in __tests__/processor.test.ts — that's where all the business logic lives and where regressions get caught.

License

MIT — © 2020-2026 Alex Leventer