Repository navigation
✨ publish: Linear target (issue + sub-issues, blocks relations) - #118
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Two gaps need addressing before this fulfills #113:
-
Medium — dependency relations are never retried or added between existing children (
internal/publish/linear/linear.go:306).blockedByruns only when one endpoint appears inres.Created. After a relation fails, both issues still exist; the next--updatefinds them and skips the relation permanently. Adding a dependency between two existing children likewise updates the Markdown but creates no nativeblocksrelation. Hive can then schedule the dependant without its blocker. This contradicts the PR body's promise that relation failures are retried on--update. Reconcile missing relations for existing children too, with coverage for a failed first attempt and a newly added dependency. -
Medium — the required assignment option is absent (
internal/config/config.go:441,internal/publish/linear/linear.go:341). #113 explicitly requirespublish.linear.assigneeso children are visible when Hive usesassigned_only. The config has no assignee field and the create input never suppliesassigneeId, leaving children unassigned and invisible to that configuration. Implement the option and exercise it in the GraphQL fixture, or explicitly leave this part of #113 open rather than closing the entire issue.
Read the command's Find/Diff/Publish path, rendering, target implementation and fake. The build/test CI check is green; local test execution is disabled in this reviewer environment.
— hive: agent=reviewer backend=codex model=gpt-6.1-sol codex=0.167.0
|
@clubanderson some comments from claude when it was revieing Relations and parent are never repaired. blocks relations are created only for new issues (linear.go:301-308), and updateIssue (:373) never sets parentId for existing children (:262-272). “Retried on --update” in the description isn’t true. This is the same gap as in #117 and main’s GitHub target, so it’s best fixed once across all three. |
Add a Linear work-source target behind the publish Target interface. The RFC is filed as an issue in publish.linear.team and each child as a sub-issue of it (parentId), which hive already reads as a tracker; depends_on edges become blocks relations from the blocker, best effort. Labels (and the parent label on the RFC) are applied only when the team has them, new issues go to the team default state or publish.linear.state, and an unknown team or state is refused before anything is filed. Linear stores Markdown, so bodies round-trip verbatim and a re-publish finds its items by the marker in the description. Auth is LINEAR_API_KEY, sent bare as hive does; LINEAR_API_URL points tests at a fake. Includes an in-process fake GraphQL API (lineartest) and unit/command tests covering create, idempotent re-run, --update, relation failures as warnings, closed-state detection, refusals and dry-run making no network call. Signed-off-by: Andrew Anderson <andy@clubanderson.com>
…t, assignee, Todo default
- parent and blocks relations are read back (parent { id },
inverseRelations) and refiled when missing on every run, reported as
linked
- Find uses includeArchived: true and pages with pageInfo/after, so an
auto-archived completed RFC is found and refused as closed rather than
duplicated; team key compared with eqIgnoreCase
- a <!-- spek:digest --> line before the marker carries the digest of
the rendered body; Find reports BodyDigest and the comparison no longer
assumes Linear returns Markdown verbatim (the fake now normalises
whitespace on store)
- publish.linear.assignee resolved through users (email, display name or
name) to assigneeId on every filed issue
- default state is the team's Todo, else its first unstarted state, else
the team default; workspace labels count as existing
- team, state, label and user lookups happen only when something is
created, so a no-op run makes one issues query
- fake routes on the document's first field, asserts instead of
require on handler goroutines, Snapshot/Calls accessors, Archived and
NoTodo options
Signed-off-by: Andrew Anderson <andy@clubanderson.com>
d2b9781 to
0cf22c8
Compare
There was a problem hiding this comment.
Decision needed: @nicholasjackson should decide whether the Linear endpoint override must enforce the existing HTTPS credential-transport policy before landing.
Credential transport needs a maintainer decision before this lands.
Medium — API key can be sent over non-loopback HTTP. cmd/publish.go:445-446 accepts LINEAR_API_URL verbatim; internal/publish/linear/linear.go:630-641 then sends Authorization with the API key to that endpoint. An operator setting an HTTP proxy endpoint therefore exposes the credential in cleartext. Unlike jiraTarget, this path never calls the existing requireHTTPS guard. Please enforce HTTPS while retaining loopback HTTP for the fake server, and add a refusal test for non-loopback HTTP.
The current head repairs parents/relations and searches archived issues, addressing those earlier review concerns. Per #113 and the PR body, project-mode publishing is deliberately left open; that is not a scope defect. I read the adapter, fake, tests, command callers and base implementation. Reported Dagger build-and-test checks pass; local tests were blocked by hive policy. Real-workspace HTML-comment preservation remains unverified as the body acknowledges.
— hive: agent=reviewer backend=codex model=gpt-6.1-sol codex=0.167.0
|
Thanks — all addressed in 0cf22c8 (re-based on #117's a151ea7). Relations and parent never repaired. Fixed. Archived issues. Fixed. The Find query passes Description round-trip. Fixed structurally: the description now carries "Fixes #113" overclaims. Agreed; changed to "Part of #113". Of the three gaps: Smaller items, all fixed: workspace labels are found ( Green locally and in CI. |
|
/approve |
Part of #113 — what is still open there:
parent_as: project(RFC as a Linear project rather than a parent issue). Everything else in #113 is here.Stacked on #117 (Jira) because it shares
Filed.Key/SameAsFiled/ResultChild.Keyfrom that PR; once #117 merges this rebases to a single commit. Follows the GitHub target pattern exactly: sameTargetinterface, same ordering (RFC → children → relations → RFC checklist rewrite), same refusal codes withnext_action, dry-run with zero network calls, httptest GraphQL fake.What it does
publish.linear.team; each child → a sub-issue of it (parentId). Hive's Linear source already marks an issue with children (or a marker withouttask=) as a tracker, so the RFC is never claimed.depends_on→issueRelationCreate(issueId: blocker, relatedIssueId: dependant, type: blocks)(Linear's enum hasblocks, notblockedBy; the dependant'sinverseRelationsthen carries the blocker, which is whatlinearDependenciesin hive reads). Parent and relations are read back (parent { id },inverseRelations) and reconciled on every run; anything missing is refiled and reported aslinked. Failures are warnings.publish.linear.parent_label(defaultepic) applied only when the team or workspace has them; never created (GitHub semantics).publish.linear.stateoptional: unset → the team's Todo state, else its firstunstartedstate, else the team default (so children don't land in Backlog/Triage where a hive doesn't look).publish.linear.assignee(email / display name / name viausers) →assigneeIdon every issue. Unknown team, state or assignee is refused before any mutation; these lookups only run when something is created, so a no-op re-run makes a singleissuesquery.issues(filter: {team: {key: {eqIgnoreCase}}, description: {contains: "artifact_id=<id>"}}, includeArchived: true), paged viapageInfo, so an auto-archived completed RFC is still found and refused as closed.<!-- spek:digest <sha256> -->line before the marker carries the digest of the rendered body;FindreportsBodyDigest, so comparison does not depend on Linear returning Markdown byte-for-byte (the fake now normalises whitespace on store to prove it). Caveat, stated plainly: whether Linear preserves HTML comments in descriptions at all is something I have not verified against a real workspace (no key available here); the marker itself depends on it exactly as the GitHub target depends on GitHub keeping them. If it strips them, the fallback would be a visible footer line — flagging for whoever has a workspace.LINEAR_API_KEYsent bare inAuthorization(hive convention).LINEAR_API_URLoverrides the endpoint for tests.publish_target_unconfigured(no team / unknown target),publish_auth_missing.Crux
Checked
crux/proxy/linear_rules.go:issueCreate,issueUpdate,issueRelationCreateare allowed atModeIssuesOnlyand queries pass, so publishing from inside a hive needs no crux change. Recorded indocs/publish-hive-handshake.md.Tests
make lint && make testgreen locally (internal/publish/linear: reconciliation, archived + paging, digest vs normalised store, Todo/unstarted default, assignee, workspace labels + key case;lineartestfake routes on the document's first field, usesasserton handler goroutines,Snapshot(); cmd tests for dry-run with zero calls, refusals, file-then-update, assignee + archived RFC conflict).