Skip to content

Introduce task container selector - #113

Open
vitolkachova wants to merge 2 commits into
mainfrom
support-task-selector
Open

Introduce task container selector#113
vitolkachova wants to merge 2 commits into
mainfrom
support-task-selector

Conversation

@vitolkachova

Copy link
Copy Markdown
Contributor

Add task container selector for commands ssh, scp and log. Proposes to choose from a task runs list if several are executed in parallel.

% upsun --task myagent -p 45rxrkidodaay -e main
Enter a number to choose which run of "myagent" to connect to:
  [0] 45tkoe3kh5w7w (started 2026-06-23T12:23:17.427775+00:00)
  [1] r4urjsfdqjfsa (started 2026-06-23T12:23:16.095779+00:00)

activity ID can be provided to specify exact task run:

upsun log --task myagent -p 45rxrkidodaay -e main --activity 45tkoe3kh5w7w

Copilot AI review requested due to automatic review settings June 23, 2026 12:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for targeting running task containers (ephemeral, activity-backed) via a new --task selector, enabling ssh, scp, and log to connect to a specific task run (optionally disambiguated via --activity).

Changes:

  • Introduces Selector::addTaskOption() and task-container resolution in Selector::selectRemoteContainer() based on in-progress/pending environment.task activities.
  • Adds a new RemoteContainer\Task implementation that derives an SSH URL for a task run.
  • Wires the new options into environment:ssh, environment:scp, and environment:logs commands (plus an example in ssh).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
legacy/src/Selector/Selector.php Adds --task/--activity options and implements selection logic for task-run containers.
legacy/src/Model/RemoteContainer/Task.php New remote container type for SSH access to an in-progress task run.
legacy/src/Command/Environment/EnvironmentSshCommand.php Exposes --task/--activity on ssh and adds a usage example.
legacy/src/Command/Environment/EnvironmentScpCommand.php Exposes --task/--activity on scp.
legacy/src/Command/Environment/EnvironmentLogCommand.php Exposes --task/--activity on log.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +963 to +979
private function matchTaskActivity(array $running, string $taskName, string $activityId): Activity
{
$matches = array_values(array_filter(
$running,
fn(Activity $activity): bool => $activity->id === $activityId,
));
if (count($matches) === 1) {
return $matches[0];
}
$ids = implode(', ', array_map(fn(Activity $activity): string => $activity->id, $running));
throw new InvalidArgumentException(sprintf(
'No running instance of the task "%s" matches the activity ID "%s". Running activity IDs: %s',
$taskName,
$activityId,
$ids,
));
}
Comment on lines +939 to +941
$choices[$activity->id] = $activity->created_at !== ''
? sprintf('%s (started %s)', $activity->id, $activity->created_at)
: $activity->id;

@pjcdawkins pjcdawkins left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. The structure fits the existing patterns well — Model\RemoteContainer\Task implementing RemoteContainerInterface, and correctly short-circuiting in the selector before the deployment loads. All four checks pass; the branch is behind main but not conflicted.

To be clear about scope: the container naming rule (<task>--task--<first 8 chars of activity ID>) and the parameters['task'] key are taken as correct here. Nothing else in legacy/src references environment.task parameters, so this review could not corroborate them from the repository — it is a coverage observation, not a claim that they are wrong. What follows is about robustness when the surrounding state is not the happy path.

Pending activities

Selector.php:902 queries [Activity::STATE_IN_PROGRESS, Activity::STATE_PENDING], which contradicts the invariant documented in this PR at Task.php:61-62 — that the container exists only while the activity is in progress. Running upsun ssh --task mytask immediately after task:run, while the activity is still pending, makes it the single match, so the fast path at :915-916 selects it and builds an SSH URL for a container that does not exist yet.

In practice SshDiagnostics::noServiceAccessMessage() does surface a usable message, so this degrades rather than failing raw — which is why it is worth fixing for wording rather than treating as urgent.

Worth noting the obvious fix is not the right one: simply dropping STATE_PENDING from the query routes the case to noRunningTaskMessage(), which would then report the queued run as "finished <created_at>" — worse than the current behavior. Better to keep pending in the query, reject a pending selection explicitly ("the task is queued, activity <id>; SSH is possible once it starts"), and include the state in the choice labels.

Other robustness items

  • Selector.php:963matchTaskActivity()'s docblock promises "exact, or a unique prefix", but the implementation compares full IDs only. The practical cost is that the 8-character prefix a user can read off the container name is rejected. Since activity IDs are unique, count($matches) > 1 is unreachable, so the shared error path only ever means "no match". Either implement the documented prefix matching or correct the docblock and message; prefix matching is the more useful of the two given the container suffix is exactly those 8 characters.
  • Selector.php:939 — the chooser labels created_at as "started" and omits the state. For a pending activity created_at is queue time, not start time. Model/Activity.php:20-28 and ActivityMonitor.php:677-680 establish the convention of preferring started_at with a fallback.
  • Selector.php:986noRunningTaskMessage() fetches only the 10 most recent environment.task activities and filters by name client-side, so on a busy environment it can report that a task has never run when it ran an hour ago. Also prints created_at prefixed with "finished" when completed_at is empty.
  • Selector.php:739--task silently overrides --app, --worker and --instance. upsun ssh --task mytask --app someapp returns early at :742 and ignores --app without a word, whereas the existing app/worker path deliberately errors on conflict at :745-752. --instance 1 --task x fails with a misleading "Instance not found: 1".

Tests

Task::constructTaskSshUrl()/referenceSshUrl() is pure and there is clear precedent for testing it — legacy/tests/Service/DrushServiceTest.php:40 and legacy/tests/Command/User/UserAddCommandTest.php:41 both build an Environment from a data array with _links. A few lines there would pin the naming rule in code, which is the most durable place for it given it is currently only stated in a comment.

Suggest reviewing after #112 merges, so the task surface is settled first.


Review by Claude Code.

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.

3 participants