Skip to content

feat(ci): add LLM auto-assignment, rich Slack summaries, and Linear auto-linking to dependabot sync#4

Closed
justanothersynth wants to merge 17 commits intomainfrom
fix-integrations
Closed

feat(ci): add LLM auto-assignment, rich Slack summaries, and Linear auto-linking to dependabot sync#4
justanothersynth wants to merge 17 commits intomainfrom
fix-integrations

Conversation

@justanothersynth
Copy link
Copy Markdown
Member

@justanothersynth justanothersynth commented Apr 2, 2026

Resolves AMR-1896

Description

Overhauls the Slack, Linear, and GitHub PR integrations for the sync_dependabot_python.yml workflow so that sync tickets and PRs are automatically routed to the right person, cross-linked, and surfaced with rich context in Slack.

Slack integration

  • First-person summary with distinct sections for newly opened PRs and pending PRs still awaiting merge
  • Suppress posting when all repos are in sync and no PRs are outstanding
  • Inline PR numbers, Linear ticket links, and assignee full names directly in the message
  • Disable link/media unfurling to keep messages compact; add service label prefix and emoji

Linear integration

  • Fix printf for proper newline rendering in ticket descriptions
  • Create the Linear ticket before the PR so Resolves AMR-xxx auto-closes the ticket on merge
  • Assign, label (Amerabot), prioritize (Urgent), and place tickets in Todo instead of Triage

GitHub PR integration

  • Expanded PR descriptions with clear next steps, matching the Linear ticket tone
  • Push updated template commits to existing open PRs when the org config changes
  • Assign and request review from the resolved project lead

LLM-powered auto-assignment

  • Fetch project-mapping.md and person-reference.md from the .cursor repo at workflow start
  • Query Linear for project leads, then use Claude Haiku with structured JSON output to match each repo to its lead
  • Self-healing: retry assignment on subsequent runs for PRs that previously failed
  • Falls back to a default assignee when the LLM or API key is unavailable

Maintenance

  • Bump actions to Node.js 24 runtime (actions/checkout v5, actions/github-script v8, slackapi/slack-github-action v3)
  • Updated README with new variable names, secrets, and workflow behavior

Risk Level

  • Low — CI workflow changes only, no impact on production data or security

Rollback Plan

Revert this PR. The previous workflow behavior is fully captured in the commits on main.

PHI Impact

  • This change affects systems that create, receive, maintain, or transmit PHI — HIPAA impact reviewed

Testing

  • Tested in non-production environment

Why this change was needed:
The Linear ticket body created by the dependabot sync workflow was
rendering literal \n characters instead of actual line breaks, making
the ticket description unreadable.

What changed:
- Extracted the ticket description into a printf call that properly
  interprets \n escape sequences into real newlines
- Passed REPO and PR_URL as %s format args instead of inline shell
  interpolation

Problem solved:
Linear tickets created by the sync workflow now render with proper
Markdown formatting and line breaks.
Why this change was needed:
The previous Slack message was a flat, one-size-fits-all summary that
always posted — even when there was nothing actionable. Stale sync PRs
from previous runs were silently skipped with no visibility.

What changed:
- Track still-open PRs from previous runs in a `pending` array with
  their opened date as a gentle nudge for stale reviews
- Build a first-person Slack message with distinct sections for newly
  opened PRs and PRs still awaiting merge
- Suppress the Slack post entirely when all repos are in sync and no
  PRs are outstanding
- Move message construction into the script step for cleaner logic

Problem solved:
The team now gets actionable, context-rich Slack notifications that
surface stale PRs, and the channel stays quiet when there's nothing
to act on.
Why this change was needed:
The PR body opened by the dependabot sync workflow was a terse
one-liner that didn't give reviewers enough context about what
the PR is or what they should do with it.

What changed:
- Replaced the minimal PR description with a richer body that
  explains why the PR was opened and lists clear next steps
- Mirrors the tone and structure of the companion Linear ticket

Problem solved:
Reviewers now see actionable context directly in the PR without
needing to cross-reference the Linear ticket.
…fier

Why this change was needed:
The Linear ticket and PR were created independently with no
cross-reference. Reviewers had to manually find the corresponding
ticket, and merging the PR didn't update the ticket status.

What changed:
- Moved Linear ticket creation into the github-script step, called
  before the PR is created via fetch() to Linear's GraphQL API
- PR body now includes "Resolves AMR-<num>" so Linear auto-links the
  PR and auto-closes the ticket on merge
- Linear ticket description drops the explicit PR URL in favor of
  auto-linking, with a note explaining the link
- Both descriptions now mention "for Python repos" for clarity
- Removed the separate shell-based "Create Linear tickets" step

Problem solved:
Linear tickets and PRs are now bidirectionally linked. Merging a
sync PR automatically resolves its Linear ticket.
@justanothersynth justanothersynth self-assigned this Apr 2, 2026
…flow

Why this change was needed:
Tickets were landing in Triage with no assignee, label, or priority,
requiring manual triage before anyone would act on them.

What changed:
- Tickets are now assigned to Nauras, labeled "Amerabot", set to
  Urgent priority, and placed in Todo instead of Triage
- Renamed env vars to follow consistent double-underscore naming
  convention (LINEAR_TEAM_ID__AMERA, LINEAR_PROJECT_ID__SOC2_COMPLIANCE)

Problem solved:
Sync tickets are immediately actionable — assigned, prioritized, and
visible in the right board column without manual triage.
Why this change was needed:
GitHub Actions is deprecating Node.js 20 runners on June 2, 2026,
and the workflow was logging deprecation warnings on every run.

What changed:
- actions/checkout v4 → v5
- actions/github-script v7 → v8
- slackapi/slack-github-action v2 → v3

Problem solved:
Workflow runs cleanly without Node.js 20 deprecation warnings.
Why this change was needed:
When the org template changed, repos with an already-open sync PR
were silently skipped. The stale PR would stay open with outdated
content until manually closed and the workflow re-run.

What changed:
- When an open sync PR exists, compare its branch content against
  the current template before deciding to skip
- If the template has changed, push an updated commit directly to
  the PR branch so the existing PR reflects the latest config
- If the PR branch already matches, skip as before

Problem solved:
Template updates propagate to all repos automatically, even those
with open PRs from a previous run.
Why this change was needed:
The README referenced old variable names, was missing secrets, and
described the old Triage-based ticket flow rather than the current
Todo/assigned/labeled setup.

What changed:
- Added LINEAR_API_KEY and SLACK_BOT_TOKEN to the secrets table
- Updated variable names to new double-underscore convention
- Added LINEAR_PERSON_ID__NAURAS_J and LINEAR_LABEL_ID__AMERABOT vars
- Changed Triage references to Todo
- Replaced the numbered "How it works" list with a per-repo decision
  flowchart showing the template-update-to-existing-PR logic
- Added note about automatic propagation to open PRs

Problem solved:
README now accurately reflects the current workflow behavior and
configuration requirements.
Why this change was needed:
The Slack summary only showed repo names as links, requiring readers
to click through to find the PR or ticket. No ticket info was shown
for pending PRs at all.

What changed:
- createLinearTicket now returns { identifier, url } instead of just
  the identifier string
- Newly opened items store prNumber, ticketId, and ticketUrl
- Pending items parse the ticket ID from the PR body via regex and
  construct the Linear URL
- Slack lines now use the format: *repo* — PR #num · AMR-num with
  both the PR and ticket hyperlinked
- Extracted a shared formatRepoLine helper for consistent formatting

Problem solved:
Team members can jump directly to the PR or Linear ticket from the
Slack message without extra clicks.
Why this change was needed:
All dependabot sync tickets and PRs were assigned to a single person
by default, requiring manual reassignment to the actual project lead
for each repo.

What changed:
- Fetch project-mapping.md and person-reference.md from the .cursor
  repo at workflow start for team/project context
- Query Linear for all projects with their leads
- Added resolveAssignee() that calls Claude Haiku with structured
  output (output_config.format / json_schema) to match each repo
  to its project lead's Linear User ID and GitHub handle
- Linear tickets are created with the resolved assignee
- GitHub PRs are assigned and review-requested to the resolved user
- Falls back to LINEAR_PERSON_ID__NAURAS_J when LLM resolution fails
  or ANTHROPIC_API_KEY is not configured
- Updated README with ANTHROPIC_API_KEY secret and auto-assignment docs

Problem solved:
Tickets and PRs are automatically routed to the right project lead,
eliminating manual triage and assignment.
…R assignments

Why this change was needed:
The Slack summary posted by the dependabot config sync workflow only showed
repo, PR number, and Linear ticket — reviewers had to click through to see
who owned each PR. Additionally, PRs from earlier runs that failed GitHub
assignment (e.g. due to missing app permissions) were left permanently
unassigned.

What changed:
- Extended resolveAssignee to accept an optional GitHub handle hint and
  return fullName alongside linearUserId and githubHandle
- Added fullName to the LLM JSON schema and prompt instructions
- For pending PRs: read the existing assignee from the PR, pass as a hint
  to resolveAssignee, and retry assignment if the PR was unassigned
- Carry assigneeName through opened/pending entries to formatRepoLine
- Updated formatRepoLine to display the assignee's full name in Slack

Problem solved:
Team members can now see at a glance who owns each sync PR directly in
Slack, and previously-unassigned PRs self-heal on subsequent runs.
The Linear integration was auto-unfurling every ticket link into a
preview card, producing a wall of 11 attachments beneath the summary.
Disabling unfurl_links and unfurl_media keeps the message compact.
Makes it immediately clear which bot service posted the message when
scanning a busy Slack channel.
@justanothersynth justanothersynth deleted the fix-integrations branch April 6, 2026 15:22
@justanothersynth justanothersynth changed the title fix(ci): improve dependabot sync workflow integrations feat(ci): add LLM auto-assignment, rich Slack summaries, and Linear auto-linking to dependabot sync Apr 6, 2026
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