Repository navigation
remote: incode remote run — run a task on GitHub Actions (refs #23) - #49
Merged
Merged
Conversation
…ult (refs #23) incode could only run a task on the machine it was started on. A long task held that machine and its session for as long as it ran, and nothing could hand it to a runner and collect the outcome later. `incode remote run "<task>"` dispatches the repository's incode-remote.yml workflow (workflow_dispatch: task, model, id), finds the run by the id the workflow titles it with, polls it every 10 s for up to --timeout minutes (60 by default; a wait that runs out says the run is still going and cancels nothing), and prints result.json from the run's incode-result artifact: the `-t --output-format json` result plus `branch`, the incode/remote-<id> branch the run pushed its changes to. It exits non-zero when the run did not succeed, the task reported is_error, or the wait ran out. `list` and `logs <run-id>` show past runs and a run's result. The token (GH_TOKEN, else GITHUB_TOKEN) travels only in a header, only to the API's own origin, and only over https or to this machine (key_may_travel_to). Redirects are followed one hop at a time, so the artifact download's redirect to blob storage is fetched without it. The repository is -R or the github.com repository origin names; both are held to GitHub's name characters so neither can reshape an API path. The workflow ships as a template (.github/workflows/incode-remote.yml.example, inert in this repository) that installs and configures incode as the GitHub Action does, passes every input through environment variables, and writes the result outside the checkout so it is never committed. A test holds the template to the names remote.rs relies on and refuses an input spliced into a script. Setup is in docs/remote-runs.md. Tests run each path against a loopback fake GitHub API: dispatch body and headers, discovery by id, polling, the artifact zip, the token kept off the redirect target, timeout, failed conclusion, remote parsing, missing token.
…d poll (refs #23) The workflow ran the agent and pushed its branch in one job. A hosted runner gives the agent's commands sudo, and actions/checkout left the job's contents:write GITHUB_TOKEN in .git/config, so a prompt-injected task could push anywhere in the repository, or rewrite git so the later push step did. The template now has two jobs: `task` runs incode with contents:read and persist-credentials:false and uploads its result and a patch of everything it changed (against $GITHUB_SHA, so its own commits count) as data; `publish`, on a fresh runner with contents:write, applies the patch and pushes incode/remote-<id>. A patch that fails to apply, or that holds the model key as written, is not pushed, and the result says so (is_error, publish_error) instead of reporting branch null as if nothing changed. `incode remote run` ended an hour-long wait on the first failed read of the run: the `?` on get_run turned one GitHub 502, rate limit or dropped connection into a failure. Up to POLL_MISSES_TOLERATED (5) failed reads in a row are now reported and asked again. `incode remote logs` exited 0 for a run that failed, so a script that dispatched with --no-wait could not tell failure from success; it now exits non-zero when a completed run did not succeed or its task reported an error, as `run` does. Tests: the template test holds the split (incode only in `task`, no contents:write there, no persisted credentials); a fake that answers 502 to the first polls; logs' exit for failed and is_error runs. Each was checked against a deliberately broken control.
The Windows CI checkout has core.autocrlf on, so the workflow template that include_str! reads there has CRLF line endings and the template test split it on "\n publish:\n", which never matched: "the template has a publish job" failed on windows-latest only. The test now finds the job by its line and checks the template both as LF and as CRLF, so a run on an LF checkout reproduces the Windows case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
incode remote run | list | logs(#23): run a task withincode -ton GitHub Actions instead of this machine, wait for it, and print its result.How it works
rundispatches the repository'sincode-remote.yml(workflow_dispatch:task,model,id), finds the run by the id in its title, polls every 10 s for up to--timeoutminutes (60 by default; a wait that runs out cancels nothing), then printsresult.jsonfrom theincode-resultartifact plusbranch.is_error, or the wait ran out.logs <run-id>exits the same way for a completed run.Token safety
The workflow (
.github/workflows/incode-remote.yml.example, inert here; setup indocs/remote-runs.md)taskruns the agent withcontents: readandpersist-credentials: false, and uploads its result and a patch of its changes as data.publish, on a fresh runner withcontents: write, applies the patch and pushesincode/remote-<id>. The agent's commands get sudo on a hosted runner, so nothing in its own job can be trusted to push.Verified locally
cargo fmt --checkandcargo clippy --all-targets -D warningsare clean;cargo testpasses (lib 2243, bin 59).bash -n.$(...)stayed literal;Not verified: the workflow has not run on GitHub Actions yet; the
jqparts were not run locally (nojqon this machine; Ubuntu runners have it). GitHub Enterprise is not supported.