Skip to content

feat(api): add REST API for repository project boards#36823

Closed
hanism01 wants to merge 11 commits intogo-gitea:mainfrom
hanism01:fix/project-board-api-review-feedback
Closed

feat(api): add REST API for repository project boards#36823
hanism01 wants to merge 11 commits intogo-gitea:mainfrom
hanism01:fix/project-board-api-review-feedback

Conversation

@hanism01
Copy link
Copy Markdown

@hanism01 hanism01 commented Mar 3, 2026

This PR picks up the work from #36008 by @SupenBysz, which added comprehensive REST API endpoints for Gitea repository project boards. That PR has been idle since December 2025 with review feedback unaddressed. Full credit for the original implementation goes to @SupenBysz.

What's included

All endpoints from the original PR are preserved:

  • GET/POST /repos/{owner}/{repo}/projects
  • GET/PATCH/DELETE /repos/{owner}/{repo}/projects/{id}
  • GET/POST /repos/{owner}/{repo}/projects/{id}/columns
  • PATCH/DELETE /repos/{owner}/{repo}/projects/columns/{id}
  • POST /repos/{owner}/{repo}/projects/columns/{id}/issues

Changes from #36008

Three issues raised by @lunny in review have been addressed:

1. Duplicate permission checks removed
The entire /projects route group is wrapped with reqRepoReader(unit.TypeProjects) in api.go (line 1605), and individual write routes carry reqRepoWriter. The inline CanRead/CanWrite checks at the top of all 10 handlers were unreachable dead code and are removed.

2. AddOrUpdateIssueToColumn replaced
The new function introduced in the original PR was missing:

  • A db.WithTx transaction wrapper (partial DB state on error)
  • CreateComment(CommentTypeProject) — the UI creates an audit entry on the issue timeline when assigning to a project; the API was silent
  • CanBeAccessedByOwnerRepo cross-repo ownership guard

AddIssueToProjectColumn now delegates to the existing issues_model.IssueAssignOrRemoveProject, which provides all three. The custom function is deleted entirely.

3. Pagination removed from ListProjectColumns
The original implementation fetched all columns from the DB then sliced in memory — adding complexity and a misleading Link header without practical benefit. Project boards have a structurally small, bounded number of columns. ListProjectColumns now returns all columns directly.

Testing

Built from source and tested against a local Gitea instance with SQLite:

go build -tags 'sqlite sqlite_unlock_notify' -o gitea-test .
go test -tags sqlite,sqlite_unlock_notify ./models/project/... ./services/convert/...

All 10 endpoints verified end-to-end:

Endpoint Result
POST /projects ✅ 201
GET /projects ✅ 200
GET /projects/{id} ✅ 200
PATCH /projects/{id} ✅ 200
DELETE /projects/{id} ✅ 204
POST /projects/{id}/columns ✅ 201
GET /projects/{id}/columns ✅ 200, all columns returned without pagination params
PATCH /projects/columns/{id} ✅ 200
DELETE /projects/columns/{id} ✅ 204
POST /projects/columns/{id}/issues ✅ 201, CommentTypeProject (type 30) audit record confirmed in DB

The integration tests from the original PR (tests/integration/api_repo_project_test.go) are retained unchanged.

AI disclosure

Developed with assistance from Claude Sonnet 4.5. All changes were reviewed and are understood by the submitter. Review feedback will be responded to directly.

SupenBysz and others added 9 commits December 19, 2025 00:37
This adds a complete REST API implementation for managing repository
project boards, including projects, columns, and adding issues to columns.

API Endpoints:
- GET    /repos/{owner}/{repo}/projects          - List projects
- POST   /repos/{owner}/{repo}/projects          - Create project
- GET    /repos/{owner}/{repo}/projects/{id}     - Get project
- PATCH  /repos/{owner}/{repo}/projects/{id}     - Update project
- DELETE /repos/{owner}/{repo}/projects/{id}     - Delete project
- GET    /repos/{owner}/{repo}/projects/{id}/columns    - List columns
- POST   /repos/{owner}/{repo}/projects/{id}/columns    - Create column
- PATCH  /repos/{owner}/{repo}/projects/columns/{id}    - Update column
- DELETE /repos/{owner}/{repo}/projects/columns/{id}    - Delete column
- POST   /repos/{owner}/{repo}/projects/columns/{id}/issues - Add issue

Features:
- Full Swagger/OpenAPI documentation
- Proper permission checks
- Pagination support for list endpoints
- State filtering (open/closed/all)
- Comprehensive error handling
- Token-based authentication with scope validation
- Archive repository protection

New Files:
- modules/structs/project.go: API data structures
- routers/api/v1/repo/project.go: API handlers
- routers/api/v1/swagger/project.go: Swagger responses
- services/convert/project.go: Model converters
- tests/integration/api_repo_project_test.go: Integration tests

Modified Files:
- models/project/issue.go: Added AddOrUpdateIssueToColumn function
- routers/api/v1/api.go: Registered project API routes
- routers/api/v1/swagger/options.go: Added project option types
- templates/swagger/v1_json.tmpl: Regenerated swagger spec
Route middleware reqRepoReader(unit.TypeProjects) wraps the entire
/projects route group, and reqRepoWriter(unit.TypeProjects) is applied
to each mutating route individually in api.go. These middleware run
before any handler fires and already gate access correctly.

The inline CanRead/CanWrite checks at the top of all 10 handlers were
therefore unreachable dead code — removed from ListProjects, GetProject,
CreateProject, EditProject, DeleteProject, ListProjectColumns,
CreateProjectColumn, EditProjectColumn, DeleteProjectColumn, and
AddIssueToProjectColumn.

The now-unused "code.gitea.io/gitea/models/unit" import is also removed.

Addresses review feedback on: go-gitea#36008

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
…oject

The custom AddOrUpdateIssueToColumn function introduced by this PR was
missing three things that the existing IssueAssignOrRemoveProject provides:

1. db.WithTx transaction wrapper — raw DB updates without a transaction
   can leave the database in a partial state on error.

2. CreateComment(CommentTypeProject) — assigning an issue to a project
   column via the UI creates a comment on the issue timeline. The API
   doing the same action silently was an inconsistency.

3. CanBeAccessedByOwnerRepo ownership check — IssueAssignOrRemoveProject
   validates that the issue is accessible within the repo/org context
   before mutating state.

AddOrUpdateIssueToColumn is removed entirely. AddIssueToProjectColumn
now delegates to issues_model.IssueAssignOrRemoveProject, which already
has the issue object loaded earlier in the handler.

Addresses review feedback on: go-gitea#36008

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Project columns are few in number by design (typically 3-8 per board).
The previous implementation fetched all columns from the DB then sliced
the result in memory — adding complexity and a misleading Link header
without any practical benefit.

ListProjectColumns now returns all columns directly. The page/limit
query parameters and associated swagger docs are removed.

Addresses review feedback on: go-gitea#36008

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Mar 3, 2026
@github-actions github-actions bot added modifies/api This PR adds API routes or modifies them modifies/go Pull requests that update Go code labels Mar 3, 2026
Ember and others added 2 commits March 3, 2026 17:29
…agination

Removes the page and limit parameters from the generated swagger spec
for the ListProjectColumns endpoint, matching the handler change that
dropped in-memory pagination.

Co-authored-by: Claude <noreply@anthropic.com>
ListProjectColumns no longer supports pagination — it returns all columns
directly. Remove the page/limit test case that expected 2 of 3 columns.

Co-authored-by: Claude <noreply@anthropic.com>
@hanism01
Copy link
Copy Markdown
Author

hanism01 commented Mar 4, 2026

Closing to address contribution guideline requirements before resubmitting. ListProjectColumns must support pagination and set X-Total-Count per the API requirements. Will reopen once properly implemented.

@hanism01 hanism01 closed this Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. modifies/api This PR adds API routes or modifies them modifies/go Pull requests that update Go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants