Skip to content

feat(labels): label/tag system with Gitea-compatible scope semantics - #5

Merged
ranxianglei merged 6 commits into
masterfrom
feat/labels
Jul 28, 2026
Merged

feat(labels): label/tag system with Gitea-compatible scope semantics#5
ranxianglei merged 6 commits into
masterfrom
feat/labels

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Summary

Implements a full label/tag system for ework-web. The labels + issue_labels tables already existed (Gitea-aligned, per-project scope) but had zero UI, zero API, and the store functions were dead code. This PR brings them to life.

  • Schema: adds description, exclusive, is_archived columns (Gitea-compatible) to both SQLite + MySQL, with a SQLite boot-time ALTER migration for existing DBs
  • Store: full CRUD (create/update/archive/delete) with exclusive-scope support — Gitea's scope/name syntax where one issue holds at most one label per scope
  • API: form-POST management routes (/:o/:r/settings/labels/*) + JSON issue-label API (/api/:o/:r/issues/:n/labels)
  • Webhooks fix: outbound Gitea-shaped payloads now carry real label data (was hardcoded labels: [])
  • UI: project settings label management page (color palette, edit dialog, archive/delete) + label chips on issue detail with a picker dialog that reflects exclusive-scope mutual exclusion

Test plan

  • bun run check (tsc clean)
  • bun test (83 pass, 0 fail)
  • Manual: create/edit/archive/delete labels on a project
  • Manual: attach labels to an issue, verify exclusive-scope eviction
  • Manual: verify outbound webhook payload includes labels

Adds Gitea-compatible columns to the labels table for both SQLite and MySQL schemas. Includes a SQLite boot-time ALTER migration (migrateLabelsTable) so existing DBs gain the columns idempotently.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Rewrites the label store functions (previously dead code with zero callers) into a full CRUD: create/update/archive/delete + list/get. Adds exclusive-scope support (Gitea scope/name syntax) — attaching an exclusive label evicts sibling labels sharing the same scope so an issue holds at most one label per scope. setIssueLabels replaces the full label set of an issue. Includes input validation (name charset, #RRGGBB color).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Adds form-POST management routes (add/update/archive/delete) at /:o/:r/settings/labels/* mirroring the members/upstreams pattern, plus a JSON API at /api/:o/:r/issues/:n/labels (GET returns current+available, POST replaces the label set). Enforces admin role for management, writer role for issue-label edits.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
buildIssue previously hardcoded labels: [] in every emitted Gitea-shaped payload (issues + issue_comment events). Now fetches the issue's labels via listLabelsForIssue and maps them to the PayloadLabel shape, threaded through buildIssuePayload/buildCommentPayload. Fixes the latent bug where downstream consumers never received label data.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Adds a project settings tab (labels) with a full management page: create/edit/archive/delete labels with a color palette and exclusive-scope hint, plus an edit dialog. On the issue detail page, label chips render in the meta-status row next to the state badge, with a picker dialog (label-picker.js) that toggles labels via the JSON API and reflects exclusive-scope mutual exclusion in the UI.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…bulk replace

23 tests covering: labelScope parsing, createLabel validation (empty name, invalid color, illegal chars, scope/name syntax), partial/full updateLabel, archive visibility filtering, deleteLabel cascade, and the exclusive-scope mutual-exclusion semantics (same-scope eviction, different-scope coexistence, non-exclusive coexistence, detach, idempotent re-attach, bulk replace with dedup).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@ranxianglei
ranxianglei merged commit 8a88712 into master Jul 28, 2026
1 check passed
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.

2 participants