Skip to content

Extract id and status in a single jq pass to avoid cross-entry inconsistency #157

Open

Description

@github-actions

What

In entrypoint.sh, the reclaim_orphaned_name() function extracts the runner id and status via two independent jq invocations over the same /actions/runners listing. Replace them with a single jq pass that emits both fields from the same matched entry.

Why

The two separate jq runs are a latent cross-entry inconsistency: if the listing ever contains two entries with the same name (the API has been known to lag), id and status could be read from different entries. That would let the function delete a runner whose status was read from a different (offline) entry than the id it deletes — i.e. delete a live runner, which is exactly the outcome the no---replace stance is meant to prevent. Extracting both fields in one pass makes the id/status pair atomic with respect to the matched entry.

How

Replace the two jq calls with a single invocation that emits both fields, then split the result:

read -r id status < <(
  jq -r --arg n "$RUNNER_NAME" \
    '.runners[]? | select(.name==$n) | "\(.id) \(.status)"' <<<"${listing}"
)

Then keep the existing guards ([[ -n "${id}" ]] || return 0, status == "offline" check) unchanged. Note the head -n1 on the current output is a no-op given the select; it can be dropped as part of this change.

This is a mechanical refactor of the extraction only — do not change the delete logic, the api_method DELETE call, or the surrounding control flow.

Files Affected

  • entrypoint.sh

Constraints

  • Must not change behaviour for the single-match case: offline → delete, online → refuse to start.
  • Must not introduce a new dependency or change the jq invocation's argument handling (--arg stays, to preserve the injection safety noted in the review).
  • Out of scope: the command -v jq guard, the swallowed stderr on the listing call, Retry-After handling, the unconditional rm -f .runner fix, and test coverage — these are separate follow-ups from the same review.

LLM tier

Haiku — mechanical single-file refactor of two jq calls into one, with no design judgment required.

Success looks like

  • reclaim_orphaned_name() performs exactly one jq invocation over the listing.
  • id and status are read from the same matched entry.
  • The offline → delete and online → refuse branches behave identically to before for a single-match listing.
  • No other lines in entrypoint.sh change.

Failure looks like

  • The two jq calls remain, or are merged in a way that still allows id and status to come from different entries.
  • The delete/refuse control flow is altered, or the --arg interpolation is replaced with string interpolation into the filter.
  • New dependencies, guards, or unrelated cleanups are bundled in.

Follow-up from AI review of PR #154.

Activity

  1. added
    ai-suggestedSuggested by AI code review
    haikuSuitable for Claude Haiku (simple/mechanical task)
    on Sep 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ai-suggestedSuggested by AI code reviewhaikuSuitable for Claude Haiku (simple/mechanical task)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions