| name | using-redmine-as-developer |
| description | Use when a developer needs to handle Redmine issues or feedback through the Redmine UI/API, configure Redmine API access, split public comments from private engineering notes, list assigned issues, add comments or private notes, change statuses, search, attachments, calendar/gantt views, or ADX Project feedback workflow. |
Using Redmine as Developer
Overview
Use Redmine as the external feedback record: read the issue, leave clear comments, move the status, and keep engineering proof out of public notes. Do developer work in the codebase; use Redmine to record externally meaningful progress, requests, evidence, and confirmation. For substantial updates, always split the reply into public_note and private_note before writing.
Defaults
For the ADX deployment, default to:
export REDMINE_URL="${REDMINE_URL:-https://support.adxtek.com}"
export REDMINE_PROJECT="${REDMINE_PROJECT:-adx-project}"
Require REDMINE_API_KEY from the environment. Do not print, persist, commit, or echo API keys.
Configuration Bootstrap
Before any API read or write, make configuration explicit and verify the account:
: "${REDMINE_URL:=https://support.adxtek.com}"
: "${REDMINE_PROJECT:=adx-project}"
export REDMINE_URL REDMINE_PROJECT
if [ -z "${REDMINE_API_KEY:-}" ]; then
printf '%s\n' 'REDMINE_API_KEY is not set. Log in to https://support.adxtek.com, open /my/account from the top-right 我的账号 link, find the blue API访问键 block in the right sidebar, click 显示, then export REDMINE_API_KEY locally.'
exit 1
fi
If the user names an expected account, set and verify it:
EXPECTED_REDMINE_LOGIN="${EXPECTED_REDMINE_LOGIN:-ender}"
CURRENT_LOGIN=$(curl -fsS -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/users/current.json" | jq -r '.user.login')
test "$CURRENT_LOGIN" = "$EXPECTED_REDMINE_LOGIN" || {
printf 'Wrong Redmine API account: expected %s, got %s\n' \
"$EXPECTED_REDMINE_LOGIN" "$CURRENT_LOGIN"
exit 1
}
If jq is unavailable, inspect the raw JSON instead of guessing:
curl -fsS -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/users/current.json"
Confirm project and assigned-issue access before writing:
curl -fsS -G -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/issues.json" \
--data-urlencode "project_id=$REDMINE_PROJECT" \
--data-urlencode "assigned_to_id=me" \
--data-urlencode "status_id=*" \
--data-urlencode "limit=1" >/dev/null
Configuration is ready only when:
REDMINE_URL is set, defaulting to https://support.adxtek.com.
REDMINE_PROJECT is set, defaulting to adx-project.
REDMINE_API_KEY is present in the environment.
/users/current.json returns the intended developer account.
- The assigned-issue query returns HTTP success for the project.
If identity verification, project lookup, or permission checks return 401, 403, or 404, stop and report the smallest concrete configuration problem. Do not fall back to direct database access for ordinary developer workflow.
Verify identity before writes:
curl -sS -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/users/current.json" | jq '.user | {id, login, firstname, lastname}'
Quick Reference
| Task | API |
|---|
| My open issues | GET /issues.json?project_id=adx-project&assigned_to_id=me&status_id=open |
| Issue detail | GET /issues/:id.json?include=journals,attachments,relations,children |
| Add public note | PUT /issues/:id.json with {"issue":{"notes":"..."}} |
| Add private note | same, with private_notes:true |
| Draft split reply | prepare public_note for humans and private_note for engineering evidence |
| Change status | same, with status_id and notes |
| Search | GET /search.json?q=...&issues=1&scope=all |
| Upload file | POST /uploads.json, then attach token in issue update |
| Calendar/Gantt | UI pages under /projects/:project/issues/calendar and /issues/gantt |
Prefer curl -G --data-urlencode for query strings containing Chinese or brackets.
Read Before Acting
List assigned open issues:
curl -sS -G -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/issues.json" \
--data-urlencode "project_id=$REDMINE_PROJECT" \
--data-urlencode "assigned_to_id=me" \
--data-urlencode "status_id=open" \
--data-urlencode "sort=updated_on:desc" \
--data-urlencode "limit=100" |
jq '.issues[] | {id, subject, status: .status.name, priority: .priority.name, updated_on}'
Read full context before changing anything:
ISSUE_ID=14
curl -sS -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/issues/$ISSUE_ID.json?include=journals,attachments,relations,children" | jq
Search issues:
QUERY="提取管理"
curl -sS -G -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/search.json" \
--data-urlencode "q=$QUERY" \
--data-urlencode "issues=1" \
--data-urlencode "scope=all" | jq
Use search to detect duplicates, reopened failures, related reports, and repeated module complaints; do not only look at assigned_to_id=me.
Status Workflow
Current ADX status names are:
新提交, 已接收, 处理中, 需要补充, 待确认, 已解决, 已关闭, 暂不处理, 重新打开
Fetch status IDs instead of assuming them when portability matters:
curl -sS -H "X-Redmine-API-Key: $REDMINE_API_KEY" \
"$REDMINE_URL/issue_statuses.json" |
jq -r '.issue_statuses[] | "\(.id)\t\(.name)\tclosed=\(.is_closed)"'
Use statuses this way:
| Status | Use When | Developer Note |
|---|
新提交 | Newly submitted, not reviewed | Do not leave real work here |
已接收 | Developer has read and accepted queue ownership | Say what will be checked |
处理中 | Actual investigation/fix is active | Avoid leaving stuck issues here |
需要补充 | Missing facts block progress | Ask for precise fields, not "more info" |
待确认 | Developer result is ready for reporter/tester confirmation | Include verification steps |
已解决 | Confirmation or sufficient evidence says fixed | Summarize result |
已关闭 | No more action is needed | Avoid closing without confirmation |
暂不处理 | Valid but intentionally not handled now | Explain reason and reopening condition |
重新打开 | Prior result failed or new evidence invalidates it | Re-diagnose; do not resume blindly |
Typical flow:
新提交 -> 已接收 -> 处理中 -> 待确认 -> 已解决 -> 已关闭
\-> 需要补充 -> 已接收/处理中
待确认/已解决/已关闭 -> 重新打开 -> 已接收/处理中
新提交/已接收/处理中 -> 暂不处理
Public and Private Notes
Before any substantial writeback, prepare a local draft with this shape:
{
"public_note": "已完成处理,主要调整了列表显示和确认流程。请按原反馈场景确认是否符合预期;如果仍有问题,请补充页面、操作步骤和截图。",
"private_note": "内部验证记录:npm run build passed;web-vue foundation tests passed;release=...;sha256=...;ldd 确认依赖来源。",
"status": "待确认"
}
Write public_note as the normal Redmine note, meaning the public comment (公开评论). Write private_note separately with private_notes:true, meaning the private engineering note (内部备注). Do not merge them for convenience.
Public notes are for reporters, testers, and product readers. Include only:
- What changed in user-visible terms.
- What the reader should confirm next.
- What information to provide if the problem remains.
Private notes are for engineering evidence. Put these there by default:
- Test command names, test counts, build logs, stdout/stderr summaries.
- Release IDs, commit hashes, sha256 values, dependency versions,
ldd output.
- Server names, deployment topology, Nginx route checks, health-check details.
- Internal file paths, stack traces, database details, Agent/process notes.
Never use a public note to prove that work was done. If proof matters, write a short public result and a detailed private note.
Split before sending when a public note contains any of these red flags:
release, sha256, ldd, npm run, tests passed, build passed, health check,
stdout, stderr, backend hash, frontend hash, dependency version, internal path
Public notes should usually be short: one sentence for the result, 2-5 bullets for user-visible changes, and one confirmation request. If the note becomes an engineering report, split it.
Write Actions
Always include a useful note when changing status. Public notes should be readable by reporters; private notes are for internal details. For anything beyond a brief acknowledgement, draft public_note and private_note first.
Public progress note:
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d '{"issue":{"notes":"已接收,我会先确认复现路径和影响范围。"}}'
Change to 处理中:
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d '{"issue":{"status_id":2,"notes":"开始处理:先复现问题并定位原因。"}}'
Request precise missing information:
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d '{"issue":{"status_id":4,"notes":"需要补充以下信息后继续处理:1. 复现步骤;2. 实际结果截图;3. 期望结果;4. 发生时间和使用账号。"}}'
Move to confirmation:
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d '{"issue":{"status_id":8,"notes":"已完成处理并进入确认。请按原反馈场景确认是否符合预期;如果仍有问题,请补充具体页面、操作步骤和截图。"}}'
Private internal note:
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d '{"issue":{"notes":"内部记录:根因涉及服务端日志中的具体异常,已在本地留证。","private_notes":true}}'
Use private notes for stack traces, database records, private account data, security details, or internal Agent/process observations. Do not put secrets, tokens, credentials, or sensitive logs in public notes.
Engineering evidence note:
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d '{"issue":{"notes":"内部验证记录:测试命令、测试结果、release、sha256、ldd、部署节点和健康检查结果已记录。","private_notes":true}}'
Attachments
Download attachments from issue detail metadata only after checking whether the data is safe to handle. Treat screenshots and logs as potentially sensitive.
Upload evidence:
TOKEN=$(curl -sS -X POST \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary @result.png \
"$REDMINE_URL/uploads.json?filename=result.png" | jq -r '.upload.token')
curl -sS -X PUT \
-H "X-Redmine-API-Key: $REDMINE_API_KEY" \
-H "Content-Type: application/json" \
"$REDMINE_URL/issues/$ISSUE_ID.json" \
-d "{\"issue\":{\"uploads\":[{\"token\":\"$TOKEN\",\"filename\":\"result.png\",\"description\":\"验证截图\"}],\"notes\":\"已上传验证截图。\"}}"
Daily Developer Loop
- List assigned open issues and reopened issues.
- Read full details, latest journals, and attachments before responding.
- Search for duplicates or related reports.
- If actionable, move
新提交 to 已接收 or 处理中 with a short note.
- If blocked by missing external facts, move to
需要补充 with a precise checklist.
- Do code investigation/fix outside Redmine.
- Record the externally meaningful result in a public note and engineering evidence in a private note.
- Move to
待确认 when reporter/tester confirmation is needed.
- Move to
已解决 only after confirmation or strong evidence.
- Close only when no further follow-up is expected.
Use calendar/gantt to inspect due-date and schedule pressure, but do not invent dates or percent progress. In this setup, status is the progress signal; done_ratio, work hours, start date, due date, and estimated hours are not the primary developer workflow.
Boundaries
Do not:
- Use direct database writes for ordinary developer workflow.
- Change issues not assigned to the current developer unless explicitly asked.
- Delete issues as a developer.
- Replace reporter descriptions with developer summaries; add comments instead.
- Publicly expose code paths, secrets, private logs, internal Agent traces, or credentials.
- Mark
已解决 when the correct next state is 待确认.
- Leave issues in
处理中 when waiting for external facts.
- Treat Redmine as the full code repair log; it is the communication and evidence surface.
If an API write returns 403 or 422, do not bypass workflow rules. Read the current issue state, allowed transitions, and role permissions, then ask for the smallest necessary human/admin decision.
Common Mistakes
| Mistake | Fix |
|---|
| Hardcoding status IDs in reusable scripts | Fetch /issue_statuses.json or document deployment-specific IDs |
| Vague "please provide more info" comments | Ask for exact missing facts |
| Using public notes for internal debugging | Use private_notes:true or keep details outside Redmine |
Publishing release IDs, sha256, ldd, or test logs in public notes | Split into public_note plus private_note before writing |
| Treating a public reply as engineering proof | Keep proof in private notes; public notes ask for confirmation |
| Searching only assigned issues | Also search keywords for duplicates and related reports |
| Updating without reading journals | Read include=journals,attachments first |
Confusing 待确认 with 已解决 | Use 待确认 until external confirmation or sufficient evidence |