Skip to content

feat(jira): add worklogs to tickets - #158

Merged
Bakhomious merged 1 commit into
mainfrom
step/jira-add-worklog
Oct 29, 2026
Merged

Bakhomious merged 1 commit into
mainfrom
step/jira-add-worklog

Conversation

@Bakhomious

Copy link
Copy Markdown
Contributor

Brief

Goal. The shared Jira client adds a worklog to a ticket. time will then take one at POST /time/worklogs (step worklog-add), and the Time page will fill a missing day (fill-day). This is the 13th of time-tracking's sixteen steps.

Why three steps. The plan's worklog-add touched three packages: the Jira client, the shared poller (so time polls again right after a write, as decision 180 says) and time itself. AGENTS.md wants one package a step, so it splits in three (decision 189): jira-add-worklog, poll-now and worklog-add.

Scope.

  • jira.IsKey(s) reports whether s is a Jira key, by decision 125's rule. The rule moves from todos' todo package, which now calls it.
  • (*jira.Client).AddWorklog(ctx, key, worklog) posts to rest/api/3/issue/{key}/worklog.
    • The body has started in Jira's layout (2006-01-02T15:04:05.000-0700, with the start's own offset) and timeSpentSeconds in whole seconds.
    • There's no query, so Jira's defaults hold, as decision 180 chose: the ticket's watchers get an email, and the remaining estimate drops by the time spent.
    • It takes a 201 only, and doesn't read Jira's answer.
    • A key that isn't a Jira key is refused before any request, so . or .. can't move the path.
  • do takes the status it wants, and reads no answer when it's given none. A shared newPost builds the JSON POSTs of Fetch and AddWorklog.
  • Docs: plan §0 row, §8.2 (sixteen steps) and decision 189.

Out of scope.

  • The poller's poll on request (poll-now).
  • time's POST /time/worklogs, its checks and its zone (worklog-add).
  • The page (fill-day).
  • A comment on the worklog, and Jira's error messages in a refusal: only Jira's status is reported.
  • Updating or deleting worklogs.
  • Whether the token has write:jira-work (decision 103 planned it): a question for the user's end review.

Acceptance criteria.

  1. For 90 minutes from 09:00 in Budapest, AddWorklog sends one POST to <API>/rest/api/3/issue/WEB-9/worklog. It has Basic auth, JSON Content-Type and Accept, no query, and the body {"started":"2026-10-26T09:00:00.000+0100","timeSpentSeconds":5400}. It returns nil on Jira's 201.
  2. started keeps the start's offset and milliseconds: +0000 in UTC, -0230 in Newfoundland in summer, .250 for a quarter of a second.
  3. Any other answer fails as add a Jira worklog: <status>: 200, 204, 400, 401, 403, 404, 413 and 500.
  4. A key that isn't a Jira key fails before any request: "", ., .., web-9, WEB-0, WEB-9/x, WEB-9, WEB-9\n.
  5. IsKey takes decision 125's keys and nothing else. Todos behave as before: their tests pass unchanged.
  6. Without Jira, and with a context that has ended, the call fails, and the context's error is wrapped.
  7. Fetch behaves as before: its tests pass unchanged.
  8. mise run check is green.

QA

  • Every acceptance criterion passes. AC1 to AC4 and AC6 have a test each in addworklog_test.go and addworklogfail_test.go; IsKey's tests sit in key_test.go. For AC5 and AC7, the diff changes none of todos' tests or Fetch's.
  • Mutations: 47 of 47 caught (a script kept out of the repo). They cover:
    • the key check and the refusal's text;
    • the 201, and the answer left unread;
    • the whole seconds, truncated;
    • the start's layout, offset and milliseconds;
    • the path, API v3, and the API rather than the site;
    • the members' names and the wrapped errors;
    • do's wanted status and nil answer, and the 200 of get and fetch;
    • newPost's method, body and Content-Type, plus Accept and Basic auth;
    • every part of the key rule: the anchors, (?m), case, one-letter projects, ticket 0 and non-ASCII digits;
    • todos' two callers, run with todos' database tests.
  • QA added TestAddWorklogFailsOnAnAddressItCantAsk. A request that can't be built was the one line of AddWorklog no test reached. AddWorklog and newPost are now fully covered: internal/jira went from 98.1% to 99.4%. The failure tests moved to addworklogfail_test.go, as Fetch's live in fetchfail_test.go, so both files stay well under 200 lines.
  • Checked against Atlassian's OpenAPI spec (swagger-v3):
    • POST /rest/api/3/issue/{issueIdOrKey}/worklog is operation addWorklog;
    • it needs scope write:jira-work (or a set of granular beta scopes);
    • it answers 201;
    • notifyUsers defaults to true and adjustEstimate to auto;
    • the spec's own example sends "started": "2021-01-17T12:34:00.000+0000" with timeSpentSeconds.
  • No live probe. Nothing calls AddWorklog until worklog-add, and the tests already talk to a real HTTP server on loopback. The work Jira wasn't touched.
  • mise run check is green:
    • Go lint: 0 issues;
    • Go coverage: 96.1% (internal/jira 99.4%);
    • web unit tests: 1,108;
    • E2E: 339 passed, 7 skipped.

Review

No blocking findings.

  • Fixed: startedLayout's comment said the layout was only for Jira's answers. It now names new worklogs too.
  • Non-blocking:
    • AddWorklog sends whatever time it's given. Less than a second becomes 0, which Jira refuses with a 400. worklog-add will check for 1 to 1,440 minutes first.
    • Todos' todo store now imports the Jira client's package for the key rule. A package of its own for one regexp would be a speculative split, and a key is a Jira concept.
    • get's request-building error is still unreached. That's older than this step.

Merged under the user's standing OK (2026-10-26): merge once CI's check is green, and review everything at the end.

The time service will take worklogs and add them to Jira, so the shared
client gains AddWorklog: it posts the start, with its own offset, and the
time spent in whole seconds, keeping Jira's defaults. A key that isn't a
Jira key fails before anything is sent, since it's a segment of the path;
decision 125's rule moves from todos to the client as jira.IsKey.

worklog-add splits in three (decision 189): this client step, poll-now
and worklog-add.
@Bakhomious
Bakhomious merged commit f4ebad1 into main Oct 29, 2026
2 checks passed
@Bakhomious
Bakhomious deleted the step/jira-add-worklog branch October 29, 2026 18:11
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.

1 participant