Repository navigation
fix: bump tower-java-sdk to 1.230.0, support API 1.230 features and stop launch --wait duplicate runs [COMP-2645] - #692
Closed
cristianrcv wants to merge 16 commits into
Conversation
Platform API 1.230.0 is what the STABLE-27.1.x stage image (v27.1.0-cycle75_d932c88) serves and will reach prod next; prod runs 1.226.0. tw was built against 1.200.0, so it lacked enum values the server already returns (OrgRole.service_account, WspRole.project, Action.Source.pipeline_status, ...), which surface as "Connection error". Adaptations the new SDK requires: - DeleteCredentialsConflictResponseConflict was renamed to ConflictingResource, and the managed-credentials 409 body now has its own DeleteManagedCredentialsConflictResponse, so managed identities stop parsing it as the credentials one. - LogPage.entries is now typed List<String>, so runs view log and studios logs read it directly instead of converting an Object. - listDataLinks, describeDataLink and listWorkflowTasks gained optional query params (creationSource, includeVersioning, process); pass null to keep current behaviour. - resolveLineage gained the runName param (API 1.211). Pass null for now; lineage resolve exposes it in a later commit. - PLAT-6702 marked many response fields nullable, which the generator maps to JsonNullable. NON_NULL does not omit a JsonNullable holding an explicit server null, so -o json, the config views and CE export started printing null keys. prettyJson now drops null properties from the tree, restoring the previous output, and the views and export use it. - Regenerated reflect-config.json with runReflectionConfigGenerator on GraalVM 25. The GraalVM 25 agent writes the unified reachability-metadata.json and dropped the resource entries, so only the regenerated io.seqera.tower.model reflection entries were merged back into the legacy file; classes no longer in the SDK were removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…OMP-2645] tw launch --wait exited 1 after a successful submit when a single describeWorkflow poll failed: checkWorkflowStatus turned any ApiException into null, waitStatus mapped null past every target, and the loop ended as [ERROR]. An unknown status value threw ProcessingException, which escaped as "Connection error". Automation that retries on a non-zero exit then launched the pipeline again while the first run kept going, duplicating runs and compute spend. A single transient 400/5xx was enough, e.g. during the 2026-10-01 Cloud DB pool exhaustion. waitStatus now polls a Callable. A failed poll or an unrecognized status keeps polling with the existing backoff. It gives up only on 401/403/404 or after polls have kept failing for 10 minutes, and then throws StatusCheckFailedException, which exits with code 3 instead of 1. A run in UNKNOWN status is treated as a failed poll, since Platform lost contact but the run may still be running. Launch reports the run id and a tw runs view hint. Exit 1 is now only for runs that actually ended in another end state. The compute-env add/delete and studio waits share the same loop. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Service account update is the first PATCH call in tw. The SDK's ApiClient enables Jersey's SET_METHOD_WORKAROUND, which sets HttpURLConnection.method (and HttpsURLConnectionImpl.delegate for HTTPS) by reflection. On Java 25 that throws InaccessibleObjectException, which tw reported as a connection error. Open both packages to the test and run JVMs, and to java -jar tw.jar through the Add-Opens manifest attribute. The tracing-agent blocks now append to the JVM args instead of replacing them. The native image needs reflection entries for the same fields (next commit). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…COMP-2645] Native images enforce module encapsulation for setAccessible as well. Even with reflection entries for HttpURLConnection.method and HttpsURLConnectionImpl.delegate, the native binary failed with 'module java.base does not opens java.net'. Pass the same --add-opens to native-image, and register both fields in reflect-config.json: the tracing agent cannot record them, because its access filter only keeps io.seqera callers. Verified with the native binary: service-accounts update sends PATCH over HTTP (MockServer suite) and over HTTPS (local TLS server). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Platform API 1.230.0 (PLAT-6535) made the organization service account
endpoints generally available, but tw had no way to manage them.
Add 'tw service-accounts' with list, add, view, update and delete over
/orgs/{orgId}/service-accounts. 'list --workspace' uses
/orgs/{orgId}/workspaces/{workspaceId}/service-accounts to show the
accounts assigned to one workspace; that endpoint pages with an opaque
token, so every page is fetched and --offset/--max are applied locally.
Members of the new OrgRole.service_account now render as
SERVICE_ACCOUNT in 'tw members list' instead of the raw enum value.
Note: update uses PATCH, which Jersey's HttpURLConnection connector only
sends through a reflective workaround that needs
--add-opens java.base/java.net=ALL-UNNAMED on Java 16+.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Platform API 1.230.0 (PLAT-6639) added the pipeline_status action source: an action that launches its pipeline when a run of a watched Launchpad pipeline ends in a chosen state. tw had no way to create one. - 'actions add pipeline-status --watch-pipeline-id <id> --run-status <state>' sends CreateActionRequest.pipelineStatus. - 'actions update --watch-pipeline-id/--run-status' sends a partial UpdateActionRequest.pipelineStatus; the API keeps omitted fields. - Only SUCCEEDED, FAILED and CANCELLED can fire the action, as in the UI and the API's terminal-state check, so tw refuses other states before calling the API instead of hiding the 400 behind its generic error. - 'actions view' shows the watched pipeline and run state. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…' [COMP-2645]
Platform API 1.230.0 records every time an action fires, with how it
ended (launched, launch failed, or suppressed by the cycle or rate guard)
and the event that caused it. The UI shows it as the action's trigger
history; tw had no way to see why an action did or did not launch.
- 'actions triggers list -n|-i <action> [--outcome ...] [--max/--page/
--offset]' calls GET /actions/{id}/triggers, newest first.
- 'actions triggers view -n|-i <action> --trigger-id <id>' calls
GET /actions/{id}/triggers/{triggerId} and prints the event payload.
The event summary, outcome detail and payload come from outside
Platform (a GitHub commit message, an S3 notification), and the API
marks them as untrusted. The console output strips their control
characters through FormatHelper.formatUntrusted so they cannot inject
terminal escape sequences. JSON output keeps them as sent, escaped by
the JSON encoder.
The firedAfterOrEqual/firedBeforeOrEqual filters are not exposed yet.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
WorkflowLaunchRequest gained fusionVersion in API 1.230.0 (Component Compatibility Catalog, COMP-2121), but it could not be set from the CLI. It is the Fusion version to run the workflow with; it must exist in the Platform catalog and only applies when the compute environment enables Fusion v2. --fusion-version is JsonNullable on the request, so it joins NullableLaunchOptions and is applied only when given, in launch, pipelines add|update, actions add|update and runs relaunch; the guard test covers it automatically. A stored value is inherited by pipelines update and runs relaunch through ModelHelper's JSON copy; the tests now assert that. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…w info versions' [COMP-2645]
--fusion-version must name a version Platform knows, but 'tw info
versions' only listed the Nextflow versions configured in
GET /platform/versions (API 1.190.0). API 1.230.0 (COMP-2121) added
GET /catalog/components/{key}/versions: the catalog's non-yanked
versions of one component with its default, optionally constrained by
compatibility with other components. It only exists when the catalog is
enabled, which /platform/versions reports as catalogEnabled.
The command now mirrors the launch form: it reads /platform/versions,
and when the catalog is on it lists the requested component
(-c nextflow|fusion) from the catalog, constrained to this Platform
release (the form passes the same platform context). --nextflow/--fusion
narrow the list to versions compatible with the given ones, e.g. the
Fusion versions that work with a Nextflow pick. Without the catalog only
Nextflow versions exist, so asking for another component or a
compatibility filter fails instead of returning a list that silently
ignores the request.
The aggregated /catalog/versions is not used: across all components it
also returns platform, wave and sched, which have no launch option.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
API 1.230 added GET /credentials/federation-setup, which returns the values an administrator must configure in AWS or Google Cloud before creating workload identity credentials: the Platform public address, audience and the OIDC subject claims Platform mints for the workspace. tw added workload identity credentials in e6a8fb9 but users had no way to get these values from the CLI. Platform switches on 'aws' and 'google' exactly and returns no values for anything else, so a typo such as '-p AWS' would print 'No setup values', which reads as nothing to configure. The provider is an enum, so picocli rejects unknown values. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AzCloudConfig.keyVaultUrl (API 1.229.0) selects a per-CE Key Vault for pipeline secrets (COMP-2043). tw never set it, so Azure Cloud secrets fell back to an installation default that Cloud does not set. Only Intelligent Compute resolves these secrets, so the option documents that it is only used with --sched-enabled. keyVaultUrl is JsonNullable, so it is set only when given: setting null would send an explicit null. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…2645] API 1.230.0 added SchedConfig.billingExportTable: the BigQuery table holding the Cloud Billing export, which enables cost reporting for an Intelligent Compute CE. tw could not set it. Platform rejects it on other providers, so only google-cloud exposes the option, matching the tower-web form. billingExportTable is JsonNullable, so it is set only when given: setting null would send an explicit null. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ls [COMP-2645] API 1.230.0 lets an agent run as an organization service account and use GitHub App credentials to clone, commit and push, but tw could not set either. - 'agents add|update --service-account-id --github-app-credentials-id' send serviceAccountId and githubAppCredentialId; update keeps the stored values when the options are omitted. - 'agents view' shows the service account, the GitHub App credentials and who created the agent (createdByUserName, API 1.211.0). - 'agents runs list --filter' documents the serviceAccountId and serviceAccountName keywords. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pipeline [COMP-2645] API 1.211.0 made GET /lineage/resolve take runName with sessionId: a resumed run shares the session ID of its parent, so the session ID alone does not identify one run. 'lineage resolve --session-id' now requires --run-name and sends both; the SDK bump passed null until now. API 1.230.0 added the pipeline to lineage records (DisplayData pipelineName/pipelineId) and the pipeline/pipelineId search qualifiers. 'lineage view' shows a Pipeline row and 'lineage search --query' documents the new qualifiers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…645] Add the service accounts section and the 'Other additions' bullets for the API 1.230.0 items: --fusion-version, the pipeline-status action source and 'actions triggers', and 'credentials federation-setup'. The new 'tw info versions' wording covers Fusion as well as Nextflow. Usage examples are plain bash blocks (markdownlint MD014). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s [COMP-2645] The native binary instantiates picocli commands and serializes -o json responses by reflection, so every new tw class needs an entry. Copied from the full tracing-agent run of the catch-up branch: service accounts, pipeline-status actions, action triggers and credentials federation-setup. Response classes register all declared fields, since Jackson serializes every field for -o json, not only the ones a traced test read. Also adds the entries that run captured for existing classes: Tower.main and the AzBatchForgePlatform head/worker pool option constructors. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cristianrcv
added this pull request to stack #693
October 2, 2026 18:17
Contributor
Author
|
Superseded by #701 (API 1.230, COMP-2645). Pipeline-status actions and action triggers moved to #703 (actions), and the agent service-account options to #702 (agents). @jonmarti, your approval here doesn't carry over; #701 has the same SDK bump, the launch --wait fix and the build.gradle changes. The stack is now: #685 (1.101) → #686 (1.113) → #697 (1.145) → #698 (1.167) → #699 (1.190) → #700 (1.200) → #701 (1.230) → #702 (agents) → #703 (actions). The code at the top of the stack is identical to the old one; only the grouping changed. Agents and actions changes are grouped into one PR each instead of being spread across API versions. New branches were used instead of force-pushing. |
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.
Summary
This is the last PR of the API catch-up stack. It has three parts:
tower-java-sdk1.200.0 → 1.230.0. That is the API of the stage release (v27.1.0-cycle75_d932c88) that goes to prod next; prod runs 1.226.0. Published from seqeralabs/tower-sdk-gencode#111.tw launch --waitexited 1 after a successful submit when a single status poll failed (a transient 4xx/5xx, or a status the SDK doesn't know). Automation then retried and launched duplicate runs.build.gradlechanges they need.Changes
SDK bump (first commit)
DeleteCredentialsConflictResponseConflictis nowConflictingResource. New optional query params are passed asnull.LogPage.entriesis read as a list again, and managed-identity 409s are parsed with their own response class.JsonNullable.prettyJsondrops null properties, so-o json, views and CE export look the same as before.launch --waitfixtw runs viewhint.UNKNOWNis treated as a failed poll.Why
build.gradlechanges heretw service-accounts update(API 1.230) is the first PATCH call tw makes. Jersey'sSET_METHOD_WORKAROUNDreflects intoHttpURLConnection.methodandHttpsURLConnectionImpl.delegate, and Java 25 blocks that. The JVM reported a bogus "Connection error", and the native binary silently sent POST. Both packages are opened:tw.jarmanifest (Add-Opens);--add-opens.The two fields are also registered in
reflect-config.json.1.230 features
service-accounts(andOrgRole.service_accountshown inmembers).actions triggers list|view.--fusion-version, plus Fusion and catalog versions intw info versions.credentials federation-setup -p aws|google.azure-cloud --key-vault-url(COMP-2043),google-cloud --billing-export-table(COMP-2502).--service-account-idand--github-app-credentials-id.--run-name(required with--session-idsince API 1.211), and the Pipeline row.JIRA
COMP-2645 (related: COMP-2644)
Verification
./gradlew test: 989 tests, 0 failures.git diff 162c6d20(the feat: catch tw up with Platform API 1.230.0 and stop duplicate runs from launch --wait [COMP-2645] #684 head, which passed full CI including native suites on all OSes) differs only in:conf/reflect-config.json: response classes registerallDeclaredFields. Before, they had traced field lists, which could lose fields from native-o jsonoutput, e.g.RunLog.next.USAGE.mdbullet for aws-cloud--log-group/ google-cloud--project-id;ActionsList;java -jar tw.jar(in feat: catch tw up with Platform API 1.230.0 and stop duplicate runs from launch --wait [COMP-2645] #684).launch --waitwith polls returning 502 → PAUSED → SUCCEEDED gives exit 0; a 404 gives exit 3 with the hint.🤖 Generated with Claude Code