cp_cli lives in agent-runtimes; previously every planner call ran 'python3 -m lib.cp_cli' from the current repo with no --context, so the script only worked inside agent-runtimes. The context now resolves from ~/.cpconfig by matching project_id to the repo directory name. Verified live from hatchmate (item + parent + documents fetched via the hatchmate context). Claude-Session: https://claude.ai/code/session_01JgJbWzVJioVznVTFyQFEfx
5.2 KiB
5.2 KiB
wait-for-version
Purpose
Poll a Gitea repository's Actions runs until the CI workflow for HEAD of the main branch completes successfully, then print the latest release tag. Solves the race condition where a dependency's main branch has been updated but CI has not yet produced a release.
Usage
wait-for-version [OPTIONS] REPO
Arguments
| Argument | Description |
|---|---|
REPO |
Gitea repo in owner/name form (e.g. skynet/hugo-accelerator). |
Flags
| Flag | Description |
|---|---|
-t, --token TOKEN |
Gitea access token. Fallback order: $GITEA_TOKEN, $GITHUB_TOKEN. |
--workflow NAME |
Name of the CI workflow to wait for (default: version). Matched against the name field of each workflow run. |
--timeout SECONDS |
Max total wait time (default: 300). 0 means poll once then give up. |
--interval SECONDS |
Polling interval (default: 15; min: 1). |
--server URL |
Gitea base URL. Fallback order: $GITHUB_SERVER_URL, https://gitea.oreillyit.nz. |
-v, --verbose |
Emit polling progress to stderr. |
-n, --dryrun |
Print resolved configuration and exit; make no API calls. |
-h, --help |
Show usage. |
Behaviour
- Validate inputs: REPO must be
owner/name;--timeoutis a non-negative integer;--intervalis an integer ≥ 1. - Compute
API_BASE = <server>/api/v1/repos/<owner>/<name>. - Compute
DEADLINE = now + timeout. - Resolve HEAD SHA:
GET <API_BASE>/branches/main. Extract.commit.id. On HTTP 401/403 exit 3; on HTTP 404 exit 3; on any other failure exit 3. - Emit
Waiting for '<workflow>' CI on <repo> @ <sha[0:8]>...to stderr. - Loop:
GET <API_BASE>/actions/runs?head_sha=<SHA>&limit=50. AddAuthorization: token <TOKEN>when a token is available.- From the JSON response, filter
.workflow_runs[]where.name == <workflow>. Take the first (index 0) result. - If no matching run: treat as
pending, continue polling. - If
status == "completed"andconclusion == "success": fetchGET <API_BASE>/releases/latest, extract.tag_name, print to stdout, exit 0. - If
status == "completed"andconclusion != "success": print error to stderr (include conclusion value), exit 1. - Otherwise (queued / in_progress / waiting / etc.): continue polling.
- On HTTP 401 or 403: print auth error to stderr, exit 3.
- On HTTP 404: print not-found error to stderr, exit 3.
- On any other HTTP code or network error: keep retrying (log to stderr when
--verbose).
- Between polls, sleep for
--intervalseconds, capped so sleep never overshoots the deadline. - When the deadline passes without success, print timeout error to stderr, exit 1.
Dryrun Behaviour
When --dryrun is passed, no HTTP requests are made. Output (to stdout):
[dryrun] Server: https://gitea.oreillyit.nz
[dryrun] Repo: skynet/hugo-accelerator
[dryrun] Workflow: version
[dryrun] Timeout: 300s
[dryrun] Interval: 15s
[dryrun] Auth: yes
[dryrun] Actions API: https://gitea.oreillyit.nz/api/v1/repos/skynet/hugo-accelerator/actions/runs
Auth: yes when a token was supplied or present in the environment; otherwise Auth: no.
Exit Codes
| Code | Meaning |
|---|---|
| 0 | CI succeeded; latest release tag printed to stdout. |
| 1 | Timeout elapsed, CI concluded with a non-success result, or no release tag found. |
| 2 | Usage error (missing / invalid arguments). |
| 3 | Terminal API error (401, 403, 404, or failure resolving HEAD SHA). |
Edge Cases
| Case | Handling |
|---|---|
| REPO missing the slash | Error, exit 2. |
| No matching workflow run found | Treated as pending; continue polling until timeout. |
| CI run fails (non-success conclusion) | Print error including conclusion value, exit 1. |
Latest release has no tag_name |
Error to stderr, exit 1. |
| No token for a private repo | API returns 401/403 → exit 3. |
| Invalid token | HTTP 401 → exit 3. |
| Repo doesn't exist | HTTP 404 → exit 3. |
| Transient 5xx or network error | Retry each --interval seconds until timeout. |
--timeout 0 |
Resolve SHA, poll once, exit 1 if not yet complete. |
--interval 0 |
Error, exit 2. |
Examples
# Wait for the version CI workflow to complete on HEAD of main
wait-for-version skynet/hugo-accelerator
# Capture version and update a consumer project
VERSION=$(wait-for-version skynet/hugo-accelerator)
sed -i "s/hugo-accelerator: .*/hugo-accelerator: $VERSION/" config.yaml
# With explicit token for a private repo
wait-for-version -t "$MY_TOKEN" skynet/private-lib
# Longer timeout for slow CI (10 minutes)
wait-for-version --timeout 600 skynet/hugo-accelerator
# Verbose polling progress
wait-for-version -v skynet/hugo-accelerator
# Custom workflow name
wait-for-version --workflow release skynet/hugo-accelerator
# Dryrun preview
wait-for-version --dryrun skynet/hugo-accelerator
In a Claude Code session
Invoke via the Bash tool with run_in_background=true. The session is notified when the script exits. On success stdout holds the new version tag.
VERSION=$(wait-for-version skynet/hugo-accelerator) || exit 1
echo "Dependency released as $VERSION"