Repository navigation
feat: support Platform API 1.101 features (catch-up backlog) - #685
Conversation
|
@educalleja @t0randr @swampie @jonmarti Rob Syme reported a bug on CLI that some missing features were returning a 400. Within that context I reviewed all the SDK bumps against the features supported by the CLI and opened a bunch of pull requests. While the other ones can be targgeted per SDK bump, this targets all the old features that the CLI does not support. Before doing the effort of splitting this into PRs, do you know if supporting these features is needed in the CLI? Are the users on your use cases missing or complaining about these missing features? |
Staging test report — full stack,
|
| tested as | now | notes |
|---|---|---|
| #685 | #685 | unchanged |
| #686 | #686 | unchanged |
| #687 | #697 | bucket actions moved to #703 |
| #688 | #703 | cron actions folded into the actions PR |
| #689 | #698 | |
| #690 | #699 + #702 | agents extracted to #702 |
| #691 | #700 + #702 | agents extracted to #702 |
| #692 | #701 + #702 + #703 |
PR health at a glance
| PR | Area | Verdict |
|---|---|---|
| #685 | API 1.101 catch-up | ed484abe) |
| #686 | 1.113 — SSH keys | ✅ healthy — no defects found |
| #697 | 1.145 — roles, folder mounts, linked datasets | ✅ healthy (1 cosmetic nit, m4) |
| #698 | 1.167 — audit logs, IdP/SCIM, Intelligent Compute | 🛑 blocker — B2 |
| #699 | 1.190 — studio stars, Nextflow versions | 🛑 blocker — B4 (fixed by ed484abe, not yet in this line) |
| #700 | 1.200 — lineage, studio logs, IC limits | 🛑 blocker — B3 |
| #701 | 1.230 — SDK bump, service accounts, federation | |
| #702 | agents command group | ✅ healthy — and it resolves M1 |
| #703 | actions: bucket/cron/pipeline-status + triggers |
Healthy: #686, #697, #702. Everything else has at least one open issue.
⚠️ Read first: the auth fix is not in the rest of the stack
ed484abe (the B1/B4 fix, merged into feat/NOTASK-api-1.101-catch-up) is not an ancestor of any other branch in the stack, including #686's head — they all fork from 72a45266, which predates the merge.
ed484abe present in: feat/NOTASK-api-1.101-catch-up only
absent in: #686, #697, #698, #699, #700, #701, #702, #703
So tw runs star, tw runs unstar and tw info versions are still broken everywhere downstream until #686 is rebased onto the updated #685 and the rebase propagates. Nothing is wrong with the fix — this is purely propagation.
🛑 Blocking defects
B2 — tw audit-logs list / view cannot parse a successful response — #698
The request succeeds (HTTP 200, valid JSON). The CLI then fails to deserialize it:
JsonMappingException: AuditLogTargetStateNewState cannot be null
ListAuditLogV2Response["auditLogs"]→[0]→["target"]→["state"]→AuditLogTargetState["previousState"]
The server returns "state":{"previousState":null,"newState":null,…}. AuditLogTargetStateNewState is a generated oneOf wrapper (34 variants) whose deserializer has:
public AuditLogTargetStateNewState getNullValue(DeserializationContext ctx) throws JsonMappingException {
throw new JsonMappingException(ctx.getParser(), "AuditLogTargetStateNewState cannot be null");
}— unconditional, the generator's pattern for a oneOf not marked nullable: true.
- Frequency: 41 of 41 sampled logs have
previousState: null. This is the normal case, not an edge case. - Not fixed by the SDK bump — reproduced identically against SDK 1.230.0 via a direct Jackson probe.
audit-logs exportis unaffected (CSV is rendered server-side) — usable workaround today.- Not a permissions issue: the export CSV shows
actorIsRoot: true. - User-facing symptom is misleading: it reports
Connection error. Check the connection using 'tw info'when the network is fine.
Fix options: mark those two fields nullable: true in the spec (fixes all SDK consumers); or override the null handling CLI-side — there is precedent in AbstractApiCmd, which already registers TaskExitMixin for a structurally identical SDK mismatch.
B3 — tw lineage view returns 404 for every record — #700
Against the same encoded lid, same workspace, same token:
| endpoint | status |
|---|---|
/lineage/{lid} ← used by the default view |
404 |
/lineage/{lid}/summary |
200 |
/lineage/{lid}/upstream |
200 |
/lineage/{lid}/downstream |
200 |
Reproduced for FileOutput, TaskRun and WorkflowRun. The record is demonstrably present — three sibling routes resolve the identical identifier.
- Workaround:
tw lineage view --summaryworks. - Ruled out — path encoding. The CLI emits a double-encoded segment (
%253A,%252F), which looked like the obvious culprit. It isn't: single-encoded, double-encoded and literal-slash forms all 404, and the siblings succeed with the identical double-encoded segment. - Ruled out — response shape as a diagnostic. Every 404 on this API is empty-bodied, including known-good routes with bogus ids, so it can't distinguish a missing route from a missing record.
- Undetermined from the client: whether
/lineage/{lid}is undeployed at 1.231.0, or deployed but unable to materialise the record. The--summaryhelp text hints at a mechanism — summary comes from the lineage index, while the full record'srecordUriis an S3 object (s3://seqera-lineage-…/.data.json). Needs someone with server/bucket visibility. - Caveat: all 1000 lineage records on staging live in one workspace (
64430228002560), so a workspace-specific condition can't be excluded.
B4 — tw info versions sends no Authorization header — #699
Same root cause as B1: NextflowApi.nextflowVersions passes null authNames, and ApiClient.invokeAPI skips authentication entirely when that array is null rather than falling back.
Confirmed by curl: GET /platform/versions → 401 without auth, 200 with auth.
Already fixed by ed484abe — but see the propagation note above. This was the third command hit by this root cause, which is why that fix defaults auth generally instead of special-casing the star endpoints.
⚠️ Major
M2 — the documented service-account workflow does not work — #701
#701's own USAGE.md says: "Add one to a workspace with tw participants add -t MEMBER -n <name>." That command fails:
ERROR: Service accounts cannot be added as workspace collaborators
AddCmd's MEMBER branch calls findOrganizationMemberByName, falling back to userNameOrEmail on MemberNotFoundException. Service accounts are not returned by /orgs/{id}/members (?search=… → {"members":[],"totalSize":0}), so the lookup always throws and the fallback sends a shape the server rejects for service accounts.
The API supports it — PUT …/participants/add with {"memberId":227302255131700} → 200, userType: SERVICE_ACCOUNT. That member id is already surfaced by tw service-accounts view ("Member ID").
This blocks the service-account → agent flow end to end; I had to add the participant via raw API to test agents at all. participants update -t MEMBER is unaffected (it resolves against existing participants).
M3 — tw actions add pipeline-status fails server-side — #703
HTTP 400 {"message":"Unexpected error while processing request - Error ID: …"}
Reproduced via raw curl, identically, for three different watched-pipeline ids including a bogus one — so the CLI's request is well-formed and this is a platform failure, not a CLI defect. The body sent looks correct:
{"launch":{…},"name":"…","pipelineStatus":{"pipelineId":196256443154544,"runStatus":"FAILED"},"source":"pipeline_status"}Error IDs for the platform team: 3iars46Gfj1Y1MD4Px6wvt, 7TirUNr5EOFtlC7mpzENm9, 1w0X4z3ZTcx9VCrNQG9ZWp, 2EYZrnbdzxBCg6m7VKskJk.
Consequence: actions add pipeline-status is unverified, and actions triggers list|view could only be exercised against an action with no triggers.
M1 — agents add was unusable before the agents split — resolved in #702
The server requires serviceAccountId; SDK 1.200.0's CreateAgentRequest has no such field, so it was unsettable in the old #690/#691. SDK 1.230.0 adds it and #702 adds the matching --service-account-id. Verified working: agent created, agents view shows Service account | cli-test-sa. Recorded only because it meant the old 1.190/1.200 PRs could not be validated standalone — the split into #702 resolves that.
Minor
| id | issue | where |
|---|---|---|
| m1 | AbstractAddCmd.java:107 does catch (Exception e) and throws "Unable to add action for workspace '<ws>'", discarding the server body — e is never used. For a bad cron the server actually says {"message":"Cron expression contains 3 parts but we expect one of [5]"}. Pre-existing on master; cron makes it far more visible. |
#703 |
| m2 | Empty-body errors render as ERROR: error (seen on 403s from seqera-compute add, rename-checkpoint, bulk run delete; 404s from lineage). The response carries X-Request-Id, which could be surfaced. |
pre-existing |
| m3 | actions list -w <ws> always prints Actions for <user> user: regardless of -w (ActionsList.java:54). |
pre-existing |
| m4 | tw roles view -n nope → Role nope doesn't exist (double space). |
#697 |
| m5 | teams delete accepts only -i, while #685 added -n to teams view/update/workspaces. |
#685 |
| m6 | Latent: SDK AuditEventType lacks action_triggered, which the server emits (12 of 100 sampled logs). Currently masked by B2 — likely to surface as the next failure once B2 is fixed. Worth folding into the same spec pass. |
#698 |
What passed
Substantial parts of the stack are solid. Highlights verified end-to-end against staging:
- feat: support Platform API 1.113 features (SSH keys) #686 — SSH keys: full lifecycle, both ref forms, both output formats, 4 distinct error paths, and keys round-trip byte-identical through
-k <file>and-k -. - feat: support Platform API 1.145 features (roles, folder mounts, linked datasets) #697 — roles: full custom-role lifecycle;
-pcorrectly replaces permissions; deletion refused while assigned ("assigned to 0 participants and 1 teams");participants update --roleaccepts a custom role. Linked datasets (--url) and studios folder mounts (mountDataV2: {dataLinkId, path}) both correct, including trailing-slash normalisation. - feat(actions): add bucket, cron and pipeline-status sources and trigger history #703 — cron: next-execution arithmetic correct in both directions (02:00
Europe/London→ 01:00 GMT; Mon 06:30America/New_York→ 10:30 GMT), UTC defaulting, and the--marker-file/--eventssource guard. - feat: support Platform API 1.167 features (audit logs, IdP groups, SCIM, Intelligent Compute) #698 — Intelligent Compute: all options map correctly on AWS/Google/Azure (
pool.{enabled,desiredWarm,scaleToZeroSecs}etc.), and every out-of-range value is rejected with no CE created. - fix(launch): stop launch --wait duplicate runs and support API 1.230 options [COMP-2645] #701 — PATCH on Java 25 works in the native image (
service-accounts update→ PATCH → 200, change applied). This was the riskiest item in that PR. Service accounts,federation-setup(both providers, correctly rejecting azure),--fusion-version,--billing-export-table,--key-vault-url, and lineage resolve-by-run all pass. - feat: support Platform API 1.101 features (catch-up backlog) #685 fixes:
pipelines updatenow preserves labels (verified:aws,gcpsurvive a description-only update), and team-lookup-by-name resolves exact matches over prefix siblings.
Behaviour-changing fixes in #685 were regression-tested specifically, since those carry the most risk for existing users.
Not covered — stated explicitly rather than implied
- IdP groups / SCIM (feat: support Platform API 1.167 features (audit logs, IdP groups, SCIM, Intelligent Compute) #698) —
IdP claims mapping is not enabledon the org; skipped by agreement. agents launchhappy path (feat: add the agents and service-accounts command groups #702) — org is out of Seqera credits. The command reaches the server and errors cleanly.studios logswith real content —aws-cloudCE creation began returningHTTP 400 {"message":"Malformed JSON"}for any body partway through the session. A previously-built binary fails identically, so this is staging-side, not a PR regression. Only the empty-log path was verified.launch --waitthrough failed polls (fix(launch): stop launch --wait duplicate runs and support API 1.230 options [COMP-2645] #701) — needs a transient API failure to exercise; code-reviewed only (the PR adds 80 lines of unit tests for it).- Compute-env options requiring real cloud resources (DRAGEN, log groups, project ids, warm pools) — verified at the wire level by asserting the serialized request body; the server-side effect is unverified.
Housekeeping: all test artifacts were removed and the engineering team was restored to its original admin role. One exception — an azure-cloud CE cli-kv (7g8TjHbBFHSZe3R4neH2rY) in seqerakit/megatest13 is stuck in CREATING and refuses deletion (Unable to delete a compute environment in CREATING state); it needs manual cleanup.
Suggested order of attack
- Propagate
ed484abe— rebase feat: support Platform API 1.113 features (SSH keys) #686 so B1/B4 clear across the whole stack. Cheapest, unblocks three commands. - B2 — spec
nullablefix, or the CLI-side mixin workaround if you'd rather not wait. - B3 and M3 — both need Platform-side investigation; Error IDs are above.
- M2 — resolve service accounts by member id in
participants add.
🤖 Generated with Claude Code
|
@cristianrcv the commit claude references above is the small correction I did to the tip of the stack but the actual fix would be the one you did in the platform api. So feel free to ignore |
…S Batch The Platform API (at least since 1.101.0) accepts AwsBatchConfig.logGroup and the ForgeConfig DRAGEN fields (dragenEnabled, dragenAmiId, dragenInstanceType), and the web UI exposes them, but tw never set them. - --log-group for 'aws-batch forge' and 'aws-batch manual' - --dragen, --dragen-ami-id, --dragen-instance-type for 'aws-batch forge' DRAGEN settings are checked client-side because the AMI and instance type are only validated during asynchronous forge creation, so a missing value would otherwise surface later as an errored compute environment. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Slurm, LSF, Univa Grid Engine, Altair PBS and Moab configs have accepted propagateHeadJobOptions since at least API 1.101.0, and the web UI shows it as 'Apply head job submit options to compute jobs'. tw never set it, so CLI-created HPC environments could not pass the head job submit options to the Nextflow compute jobs (process.clusterOptions). The option requires --head-job-options: Platform reads the head job options unguarded when propagation is on, so the combination is rejected up front. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SeqeraComputeConfig.defaultDataRetentionPolicy (API 1.101.0 or earlier) asks Seqera Compute to put a lifecycle policy on the bucket it creates, deleting intermediate files after 28 days. The web UI shows it as 'Automatic Data Retention Policy' and turns it on by default; tw never sent it, so CLI-created environments always got a bucket without the policy. The flag is opt-in, which keeps the current tw behaviour when it is not given. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Two cloud config fields accepted by the Platform API (at least since 1.101.0) were never set by tw: - aws-cloud --log-group (AwsCloudConfig.logGroup): CloudWatch Logs group for the CE; Platform defaults it to /seqera/platform. - google-cloud --project-id (GoogleCloudConfig.projectId): written as google.project and used to qualify short network/subnetwork names. Platform does not fill it from the credentials for Google Cloud. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
POST/DELETE /workflow/{workflowId}/star have been in the API since at
least 1.101.0, but runs could only be starred from the web UI. Starring
is per user, so a starred run surfaces in that user's run list in the UI.
Unstarring a run that is not starred is a 404 on Platform; it is
reported like any other API error rather than reinterpreted.
The starred state is not added to 'tw runs view': it would cost an extra
request, and the SDK types GET /workflow/{id}/star as
CreateWorkflowStarResponse (workflowId only) although Platform returns
DescribeWorkflowStarResponse with a 'starred' flag, so the flag cannot be
read through the SDK.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
POST /workflow/delete (deleteWorkflowMany, in the API since at least
1.101.0) deletes a list of runs and reports the ones it could not delete,
but tw only took one id, so cleaning up runs meant one invocation per
run.
'-i' now accepts several ids, repeated or comma-separated. A single id
keeps calling DELETE /workflow/{id}, so its output and errors are
unchanged. Several ids go through the bulk endpoint with --force passed
on; each run is reported as deleted or not, and the command exits 1 when
any could not be deleted so scripts notice partial failures. Platform
caps the list size and rejects longer ones with a 400.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
'tw runs view download' and 'tw runs dump' fetch log files through
/workflow/{id}/download, which serves the files the run leaves in its
work directory. GET /workflow/{id}/log and /log/{taskId} (in the API
since at least 1.101.0) are what the UI's Execution log tab uses: Platform
reads the compute platform's live log stream when the provider has one
and only falls back to the output file otherwise, so they also show the
output of a run that is still going. tw had no way to reach them.
'tw runs view -i <id> log' prints the Nextflow head job output and
'-t <taskId>' the task output. Platform's own notice (for example why the
log could not be read) is shown after the entries, and a truncated page
says so and points to 'download' for the complete file.
Only the first page is fetched. Following the cursor would turn the
command into a 'tail -f', and how the cursor behaves differs per compute
platform, so that is left for when someone needs it.
Up to SDK 1.200.0 the spec types LogPage.entries as an Iterator object,
so the SDK exposes it as Object; Platform sends a JSON array of strings,
which LogCmd reads back as a list.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Live log streams such as CloudWatch return one page per call (up to 10k events or 1 MB) without
flagging truncation. So 'runs view log' printed the first page of a long log as if it were all of
it. Print the forward cursor and accept it with --next (the 'next' query parameter of
GET /workflow/{id}/log, in the API since at least 1.101.0). An empty page ends the hint, because
CloudWatch keeps returning a cursor at the end of the stream.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The update sent no labelIds and no icon. Platform's update replaces the
pipeline's labels with labelIds; the API docs for both PUT
/pipelines/{id} and POST /pipelines/{id}/versions/{versionId} say a null
or omitted labelIds removes existing labels. It also sets the icon to
the request value and, when that is null, recomputes it from the
repository, so an uploaded icon was replaced. The web form sends back
the current labels and icon; tw now does the same, reading the labels
through describePipeline's 'labels' attribute.
Found while checking whether moving to updatePipeline (PUT
/pipelines/{id}) would gain anything. It would not: both endpoints call
the same PipelineService.updatePipeline, and PUT is the versionId=null
case, which only adds auto-promoting a new draft version to default.
tw already handles that, with --allow-draft on top.
The label loss is inferred from the Platform source and API docs, not
reproduced against a live Platform: LabelRefServiceImpl.applyLabelsToEntities
evaluates labelIds.contains(...) for each existing label.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eter schema
GET /pipelines/{pipelineId}/schema (describePipelineSchema, in the API
since at least 1.101.0) returns the schema Platform uses to render a
pipeline's launch form: the custom schema attached to the launch
configuration if there is one, otherwise the repository's
nextflow_schema.json. tw could attach a custom schema
('tw pipeline-schemas add', 'tw pipelines add --pipeline-schema-id') but
never read one back, and had no way to see which parameters a pipeline
takes before writing a --params-file.
'tw pipelines schema -n <name>' prints the schema; '--params' prints the
parameter values the pipeline launches with instead (pipeline defaults
merged with the stored launch parameters). --version-id/--version-name
select a version, as in 'tw pipelines view'. Platform answers 204 when it
cannot resolve a schema; that is reported as an error rather than empty
output.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Platform API (at least since 1.101.0) exposes studio operations that tw
never wired up: lifespan extension (POST /studios/{sessionId}/lifespan)
and checkpoint renaming (PUT /studios/{sessionId}/checkpoints/{checkpointId}).
This adds 'tw studios extend|rename-checkpoint' so CLI users can do what
the UI already does.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DataStudioProgressStep.warnings (in the API since at least 1.101.0; e.g. cross-region data, failed checkpoint mounts) were never shown. They are now printed once each while waiting on a studio with '--wait'. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Two data-explorer operations available since API 1.101.0 had no tw
command:
- 'tw data-links delete-content' calls DELETE /data-links/{id}/content
to delete files (--file) and folders with their contents (--dir)
while keeping the data link. The platform supports it for Seqera
Compute data links only, and answers a partial deletion with 500 plus
the failed items, which tw reports per item instead of a bare error.
- 'tw data-links download-script' calls GET
/data-links/{id}/script/download and prints the cloud CLI commands
(aws s3 cp, gcloud storage cp, ...) the UI offers for downloading.
GET /data-links/{id}/download/{filePath} is not added: it streams the
same file through the platform, with a size limit, that
'tw data-links download' already fetches through a signed URL.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DELETE /data-links/{id}/content takes a request body. The SDK disables Jersey's HTTP compliance check,
so the body is sent, but Jersey still logs 'Entity must be null for http method DELETE' to stderr
through JUL on every call. In-process JVM tests don't capture System.err, so only the native binary
tests caught it. Raise that logger to SEVERE.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
POST /datasets/{id}/versions/{version}/disable (API 1.101.0 or earlier)
had no tw command, so a dataset version could only be disabled from the
UI.
- 'tw datasets disable-version --dataset-version <n>' disables it; the
version can no longer be used for runs.
- 'datasets view ... versions' gains a Disabled column
(DatasetVersionDto.disabled), so the result is visible.
DatasetsCmdTest now resets MockServer before each test, as the other
suites do, so request verifications are not affected by earlier tests.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The API has long had describeOrganizationTeam, updateOrganizationTeam and listWorkspacesByTeam (at least since 1.101.0), but tw could only list, add and delete teams. Add 'teams view', 'teams update' and 'teams workspaces', addressing a team by --id or --name. The update endpoint replaces name, description and avatar, so 'teams update' reads the team first and keeps unset fields. The team response only carries the avatar download URL, so the avatar ID is taken from its last path segment to avoid clearing the avatar. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
listOrganizationTeams pages by 50 by default, so looking a team up by name missed any team after the first page. That affects the new teams view/update/workspaces commands and the existing participants commands. Pass the name as the search filter and keep the exact-name match. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
describeOrganizationQuotas (/orgs/{orgId}/quotas, in the API since at
least 1.101.0) had no tw command.
Add 'tw organizations quotas' to show the organization limits.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The /tokens endpoints (API 1.101) let users manage their personal access tokens, but tw could only consume one. 'tw access-tokens' now lists, creates and deletes them by id or name. 'add' prints the token value once, since Platform never returns it again. 'list' drops the deprecated basicAuth field, which is a usable credential for legacy tokens. DELETE /tokens/delete-all is not exposed: tw has no confirmation pattern for bulk destructive operations, and it would also revoke the token tw itself is running with. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tials Managed identities (/identities, API 1.101) are organization-level HPC cluster connections (Altair PBS, LSF, Moab, Slurm, UGE): an owner registers the login host and port once, and each member attaches their own SSH key and Linux username as managed credentials. tw could not manage either. 'tw managed-identities' adds list/add/view/update/delete, and 'tw managed-identities credentials' lists members' credentials and adds, replaces or deletes them, for yourself or (as owner) for another member. Deletions honour Platform's running-jobs check unless --force. Two SDK gaps are worked around: the describe endpoint is modelled with the wrong response shape, so identities are looked up in the list; and the managed credentials metadata model lacks the required SSH userName, so tw sends it through a small subclass. SDK 1.200.0 generates a separate conflict type for each 409 response, so the managed credentials 409 body is parsed as the credentials one (same shape) to reuse CredentialsInUseException. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The endpoint returns one row per organization member, 50 by default. The list silently stopped at 50 members. Page through all rows, 100 at a time, in the helper that the list and the member lookups share. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
execBinary read the binary's stdout line by line and re-printed each line with println. On Windows that turned every line feed inside printed content into CRLF. The new commands print server content verbatim (e.g. data-link download scripts), so their binary tests failed only on the Windows native job even though tw's output was right. Copy the raw streams instead, which matches how in-process tests capture output. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sections for teams and organization quotas, access tokens and managed identities, plus a summary of the new options on existing commands. Examples are plain commands in bash blocks (markdownlint MD014). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both commands failed with "Unauthorized" against a live Platform, even though the caller's token was valid and the same request made by hand succeeded. The workflow star endpoints are missing their security requirement in the Platform OpenAPI spec, so the generated SDK passes no auth names for them. ApiClient.invokeAPI skips authentication entirely when the auth name array is null, rather than falling back to the configured scheme, so the request went out with no Authorization header at all. Default the auth names to BearerAuth when an operation declares none. This routes through the SDK's own authentication, reusing the token already set with setBearerToken. In SDK 1.200.0 eleven operations declare no security: the three *WorkflowStar ones, six GA4GH ones, ServiceInfoApi.info and NextflowApi.nextflowVersions. The last two are genuinely public and the GA4GH ones target the same host, so sending the token is harmless; a token is always present by the time the client is built. The existing star tests matched on method and path only, so an unauthenticated request satisfied them. Assert the Authorization header instead. The mock server is shared across the test class without a reset, so the verification allows for the star requests other tests record. This is a workaround, not the cure: the spec is still missing the security block in SDK 1.230.0. Once that is fixed the override becomes a no-op. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…onflicts These commands were written against SDK 1.200.0, where LogPage.entries was typed Object and managed credentials had no conflict response of their own. SDK 1.233.0 types the entries as List<String> and adds DeleteManagedCredentialsConflictResponse, so drop both workarounds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Entries for the new commands, option groups and responses, plus classes master already lacked (e.g. computeenvs.ValidateCmd, RunView), taken from a full test run under the GraalVM tracing agent. Response classes register allDeclaredFields, since Jackson serializes every field for -o json. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ed484ab to
4148f96
Compare
|
@swampie I have rebased this PR and the next 2 to master so that they can be merged independently. Major issues are addressed and I will address the minor issues as a follow-up once all is merged (it is easier to track and fix). |
Resolves conflicts with the API 1.101 catch-up (#685): the SSH keys section moves under 'Personal access' next to access tokens, and conf/reflect-config.json is master's file plus the ssh-keys entries, regenerated. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Summary
Exposes API features that were already in Platform API 1.101.0 or earlier (1.101.0 is the oldest spec in tower-sdk-gencode's history), which tw never surfaced.
This is one PR in a stack that catches tw up with Platform API 1.230.0, one PR per API version that introduced the features, then one PR per topic for agents and actions. Each PR adds the items whose API elements all exist in that version.
master; the next one is feat: support Platform API 1.113 features (SSH keys) #686.tower-java-sdk1.200.0, which already contains every API element used here. The last PR in the stack bumps it to 1.230.0.Changes
Notes for review
pipelines updatenow sends back the existing labels and icon. Platform's update replaces both, so they were silently dropped before.teamsandparticipants.data-links delete-contentis a DELETE with a body. Jersey logsEntity must be null for http method DELETEto stderr through JUL, so that logger is raised to SEVERE.BaseCmdTest.execBinarynow copies the native binary's output verbatim. Re-joining lines withprintlnturned line feeds inside printed content into CRLF on Windows.conf/reflect-config.json:masterwas already missing for 17 existing classes (e.g.computeenvs.ValidateCmd,RunView);allDeclaredFieldsfor the new responses, so-o jsondoesn't lose fields in the native binary.LogPage.entriesasObject(the spec saysIterator_String_). Managed-identity 409 bodies are parsed asDeleteCredentialsConflictResponse.Verification
./gradlew test: 819 tests, 0 failures. Every new command and option has MockServer tests that assert the request (method, path, query, body) and the output.tower-sdk-gencodehistory) to confirm where it first appears.TOWER_CLI=build/native/nativeCompile/tw ./gradlew cleanTest test).🤖 Generated with Claude Code