Files
argocd-apps/.claude/commands/solve-issue.md
T
unkinben 0b7819bda3 chore: bump almalinux9 image tags (#188)
Bump almalinux9 image tags to 20260606

Reviewed-on: #188
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-06-07 00:35:12 +10:00

8.4 KiB
Raw Blame History

description
description
Pull master, read open issues, pick one, branch, implement, test, commit, PR, and comment.

Solve a Gitea Issue

Current repo state

git status --short
echo "Current branch: $(git branch --show-current)"
echo "Remote: $(git remote get-url origin 2>/dev/null || echo 'none')"

Open issues (with full body)

echo "Fetching open issues..."
issue_ids=$(tea issues list --output simple 2>/dev/null | awk 'NF && $1 ~ /^[0-9]+$/ {print $1}')
if [ -z "$issue_ids" ]; then
  echo "No open issues found (or tea is not logged in)."
else
  for id in $issue_ids; do
    echo ""
    echo "══════════════════════════════════════"
    tea issues view "$id" --fields index,title,body 2>/dev/null \
      || tea issue "$id" 2>/dev/null \
      || echo "  (could not read issue #$id)"
    echo "══════════════════════════════════════"
  done
fi

Your task

Follow these steps in order. Do not skip steps.

1 — Choose an issue

Present the issues above to the user as a numbered list (index, one-line title). Ask which one to work on. Wait for the answer before continuing.

2 — Sync master

git checkout master
git pull

Confirm you are on master and up to date.

3 — Create a branch

Name the branch benvin/issue-<N>-<short-slug> where <short-slug> is 24 kebab-case words from the issue title.

git checkout -b benvin/issue-<N>-<slug>

4 — Read the issue in full

Re-read the full issue body shown above. If any part is ambiguous, state your interpretation before coding.

If you discover other problems while working: do NOT solve them inline. Create a new Gitea issue with tea issues create --title "..." --description "..." and stay focused on the assigned issue.

5 — Implement the solution

Make the code changes needed to resolve the issue. Follow the conventions already in the repo:

  • main.py route handlers each contain a single function call; logic lives in submodules.
  • No comments unless the WHY is non-obvious.
  • No new files unless the issue or architecture requires it.
  • Security: no command injection, XSS, SQL injection, or secrets in code.
  • For performance improvements: implement at the most generic call site possible so the fix applies to all current and future implementations, not just the one being tested.

6 — Update tests

Add or update tests that cover the new behaviour. Tests live in tests/. Check existing test structure before writing new ones — mirror the style and fixture patterns already in use.

7 — Update README

If the feature introduces new config keys, endpoints, or user-facing behaviour, document it in README.md. Keep additions concise — follow the existing section style.

8 — Run the full test suite

make test

All tests must pass. If any fail, fix them before proceeding. Do not skip or suppress failing tests.

9 — Live Docker test (new package type only)

Skip this step if the issue does not add a new remote package type.

If the issue adds a new package type (e.g. deb, conda, cargo, rubygems, or any type not already in remotes.yaml), do the following before committing.

9a — Add a real test remote to remotes.yaml

Append a valid, publicly accessible remote of the new type to remotes.yaml. Use a real upstream URL and patterns that cover both an immutable file (versioned artifact) and a mutable file (index/metadata). Add a comment explaining which URLs to use for manual testing.

9b — Start the stack

make docker-up

Wait until curl -s http://localhost:8000/health returns {"status":"healthy"}.

9c — Test a mutable file (first fetch — cache miss)

Download the index or metadata file for the new remote. Confirm:

  • HTTP 200
  • X-Artifact-Source: remote header (or equivalent log line confirming a cache miss)
  • Content looks correct (not empty, not an error page)
curl -sv "http://localhost:8000/api/v1/remote/<new-remote>/<mutable-path>" 2>&1 | grep -E "< HTTP|X-Artifact"

9d — Test a mutable file (second fetch — cache hit)

Repeat the exact same request. Confirm:

  • HTTP 200
  • X-Artifact-Source: cache
curl -sv "http://localhost:8000/api/v1/remote/<new-remote>/<mutable-path>" 2>&1 | grep -E "< HTTP|X-Artifact"

9e — Test an immutable file (first fetch — cache miss)

Download a versioned/immutable artifact. Confirm HTTP 200 and a cache-miss log line.

curl -sv "http://localhost:8000/api/v1/remote/<new-remote>/<immutable-path>" 2>&1 | grep -E "< HTTP|X-Artifact"

9f — Test an immutable file (second fetch — cache hit)

Repeat. Confirm X-Artifact-Source: cache.

9g — Check container logs

make docker-logs

Scan for:

  • Cache MISS on first fetches, Cache HIT on second fetches
  • Cache ADD SUCCESS with correct sizes
  • No unhandled exceptions or ERROR lines

9h — Exercise package-type tooling against the proxy

Use the native tooling for this package type to verify end-to-end behaviour. Examples:

Package type Command
pypi uv run --index-url http://localhost:8000/api/v1/remote/<remote>/simple <tool>
npm npm install --registry http://localhost:8000/api/v1/remote/<remote>/ <pkg>
helm helm repo add test http://localhost:8000/api/v1/remote/<remote> && helm search repo test && helm template test/<chart>
alpine apk fetch --repository http://localhost:8000/api/v1/remote/<remote>/<branch>/<arch> <pkg>
rpm dnf install --repofrompath ... <pkg> or repoquery
generic curl / wget as appropriate

Confirm the tool resolves and downloads correctly through the proxy.

9i — Tear down

make docker-down

Fix any failures found during 9b9h before moving on.

9.5 — Performance issues: measure before/after and gate the PR

Skip this step if the issue is not a performance improvement.

For performance issues, a PR is only warranted if there is a measurable gain. Use the Docker stack to compare before and after.

9.5a — Baseline measurement (before)

Start the stack with the unmodified code (temporarily revert your change):

make docker-up

Warm or clear the cache as appropriate, then measure the relevant metric — e.g. concurrent request latency during a slow operation, response time for a specific endpoint, or throughput. Record the numbers.

9.5b — Apply your change and rebuild

make docker-up   # rebuilds the image

Repeat exactly the same measurement. Record the numbers.

9.5c — Decide

If the improvement is not clearly measurable, do not open a PR. Instead:

  1. Update the issue with your findings.
  2. Note any conditions under which the improvement would be observable.
  3. Skip steps 1114.

If the improvement is clear, proceed with the commit and PR. Include the before/after numbers in the PR description and the issue comment.

9.5d — Tear down

make docker-down

10 — Build the wheel (smoke check)

uv build --wheel

Confirm the build succeeds.

11 — Stage and commit

Stage only the files you changed. Do not use git add -A or git add . — list files explicitly. Run:

git add <file1> <file2> ...
git commit

The commit message must:

  • Start with a conventional-commit prefix (feat:, fix:, refactor:, chore:, etc.)
  • Summarise the change in ≤ 72 characters on the first line
  • Optionally include a short body explaining why (not what)

If the pre-commit hook auto-fixes files, re-stage the fixed files and commit again.

12 — Push the branch

git push origin <branch-name>

13 — Open a pull request

tea pulls create \
  --base master \
  --head <branch-name> \
  --title "<same as commit subject>" \
  --description "Closes #<N>\n\n## Summary\n<bullet points>\n\n## Test plan\n<what was verified>"

14 — Comment on the issue

tea comment <N> "<resolution comment>"

The comment must cover:

  • How it was resolved — what changed and why
  • Issues encountered — any non-obvious problems hit during implementation
  • Potential future improvements — what could be done next

15 — Return to master

git checkout master

Report the PR URL and a one-sentence summary to the user.