Skip to content

fix(xtest): remove standalone otdfctl source path; route go through platform monorepo#458

Open
dmihalcik-virtru wants to merge 4 commits into
mainfrom
DSPX-3086-fix-failing-proto-update-lookups
Open

fix(xtest): remove standalone otdfctl source path; route go through platform monorepo#458
dmihalcik-virtru wants to merge 4 commits into
mainfrom
DSPX-3086-fix-failing-proto-update-lookups

Conversation

@dmihalcik-virtru
Copy link
Copy Markdown
Member

@dmihalcik-virtru dmihalcik-virtru commented May 20, 2026

The archived opentdf/otdfctl repo is no longer source-cloned. otdfctl is now sourced exclusively from opentdf/platform, with pre-v0.31.0 releases falling back to the Go module proxy for artifact install.

What changed

Resolution

  • resolve() for go always queries opentdf/platform first (using the otdfctl/ tag infix). Only if the tag isn't there does it fall back once to the archived opentdf/otdfctl repo.
  • Bare semver inputs like v0.24.0 are looked up as otdfctl/v0.24.0 in platform; the otdfctl/ prefix is optional.
  • Branch refs (refs/heads/...), SHAs, PR refs (refs/pull/N), main, and latest always resolve against platform.

Artifact install (go install)

  • Module path is picked by tag semver in one place — config.go_module_for_tag():
    • Pre-v0.31.0 → github.com/opentdf/otdfctl@<tag> (archived module proxy, still served by proxy.golang.org).
    • v0.31.0+ → github.com/opentdf/platform/otdfctl@<tag>.
  • cli.sh / otdfctl.sh read .version and go run <module>@<tag> at runtime — no pre-built binary needed for releases.

Source builds (head, branches, PRs)

  • otdfctl head builds source-checkout opentdf/platform and symlink platform-src/<ref>/otdfctlsrc/<ref>.
  • The Makefile auto-detects GOWORK by looking for a go.work file alongside the resolved src/<tag> symlink target. With GOWORK in scope, protocol/go, sdk, and lib/* resolve to the platform checkout's local sources instead of the otdfctl go.mod's pinned releases. This fixes the failing-PR scenario where one platform PR adds proto symbols and consumes them from otdfctl/.
  • Pre-v0.31.0 source builds are not supported — the otdfctl/ subdir doesn't exist at those commits. These versions are artifact-install-only.

Version listing

  • otdf-sdk-mgr versions list go now only queries the platform repo's otdfctl/* tags (one network call, not two). The install_method field uses go_module_for_tag() so pre-v0.31.0 entries correctly point at the archived module.

CI workflow & action

  • The otdfctl-source workflow input is removed entirely (it was auto/platform/standalone before; routing is now invariant and inferred).
  • setup-cli-tool/action.yaml no longer threads a --source flag through install artifact, and the "platform vs standalone" branch in the source-checkout step is gone — for go, source builds always target opentdf/platform.
  • The replace otdfctl go.mod packages step that used go mod edit -replace to splice platform modules is removed; GOWORK handles it.

Net impact

Compared to main: +331 / −437 = −106 lines net. Removing support for the archived repo is now a net deletion, not a net addition.

Test plan

  • cd otdf-sdk-mgr && uv run pytest -v — 54/54 pass
  • otdf-sdk-mgr versions list go — only platform tags listed; pre-v0.31.0 entries show the archived module path in install_method
  • otdf-sdk-mgr install artifact --sdk go --version v0.24.0 --dist-name v0.24.0 — installs via Go module proxy (archive)
  • otdf-sdk-mgr install artifact --sdk go --version otdfctl/v0.31.0 --dist-name v0.31.0 — installs via Go module proxy (platform)
  • CI run on this PR — verify go heads, tagged go releases (pre- and post-v0.31.0), and Java/JS unaffected

Summary by CodeRabbit

  • Documentation

    • Clarified Go artifact install behavior: v0.31.0+ resolves from the platform monorepo; older versions fall back to archived standalone repo. Updated action/CLI docs to explain conditional platform checkout and deprecate the legacy source input.
  • Refactor

    • Simplified release/install flows to always prefer the platform monorepo for Go, removed per-version source plumbing, and adjusted CI to emit platform checkout metadata for reuse.
  • Tests

    • Added/updated tests verifying Go resolution and platform-vs-standalone fallback behavior.

Review Change Stack

…latform monorepo

The archived opentdf/otdfctl repo is no longer source-cloned. All Go heads
and post-v0.31.0 release tags resolve against opentdf/platform with the
otdfctl/ tag infix; bare semver inputs auto-prepend otdfctl/. Pre-v0.31.0
tags fall back to the Go module proxy for artifact install only.

Builds of the platform-embedded otdfctl now run with GOWORK pointing at
the platform checkout's go.work (auto-detected by the Makefile from each
src/{tag} symlink target), so protocol/go, sdk, and lib/* resolve to the
local platform sources instead of the otdfctl go.mod's pinned releases.
This fixes the failing platform PR scenario where a single PR adds proto
symbols and consumes them from otdfctl/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@dmihalcik-virtru dmihalcik-virtru requested review from a team as code owners May 20, 2026 18:33
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Warning

Rate limit exceeded

@dmihalcik-virtru has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 35 minutes and 2 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78370465-bb03-407c-8126-5ed06d0fd827

📥 Commits

Reviewing files that changed from the base of the PR and between f89b1c8 and e6ac04c.

📒 Files selected for processing (3)
  • otdf-sdk-mgr/src/otdf_sdk_mgr/config.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/registry.py
📝 Walkthrough

Walkthrough

Switches Go resolution and installs to use the opentdf/platform monorepo (otdfctl subtree) for modern tags, adds platform worktree/symlink checkout support, removes per-version source plumbing, simplifies resolve return payloads, updates installers/CLI signatures, and rewires CI/workflow to conditionally reuse platform-embedded otdfctl.

Changes

Go SDK Platform Migration

Layer / File(s) Summary
Docs: release install behavior
otdf-sdk-mgr/README.md
Clarifies that Go v0.31.0+ resolves against opentdf/platform/otdfctl, older tags fallback to archived standalone, and bare semver tags are auto-prefixed for platform resolution.
Config: module path and registry changes
otdf-sdk-mgr/src/otdf_sdk_mgr/config.py, otdf-sdk-mgr/src/otdf_sdk_mgr/registry.py
Adds go_module_for_tag(tag) and platform vs standalone module constants; removes standalone "go" bare-repo entry and Go-resolution helpers; registry now returns platform-only otdfctl/... tags using go_module_for_tag in install_method.
Resolve: remove go_source, simplify returns
otdf-sdk-mgr/src/otdf_sdk_mgr/resolve.py
resolve() no longer accepts go_source; Go resolution is platform-first with standalone fallback; ResolveSuccess no longer contains source; _resolve_against returns concrete payloads directly.
Tests: update and add resolve tests
otdf-sdk-mgr/tests/test_resolve.py
Updates Go latest expectations to platform tags and adds TestResolveGo verifying main, prefixed-tag, and fallback behaviors.
Checkout: platform worktree and symlink for Go
otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py
Adds checkout_go_from_platform(ref) to fetch platform bare repo, manage worktrees for refs, validate otdfctl/ presence, and create/update go_dir/src/<ref> symlink; checkout_sdk_branch now rejects Go and recommends the new function.
Installers & CLI: remove source args, set GOWORK for tip
otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py, otdf-sdk-mgr/src/otdf_sdk_mgr/cli_install.py, otdf-sdk-mgr/src/otdf_sdk_mgr/cli_versions.py
Removes source propagation and extra kwargs from installer/CLI signatures, uses go_module_for_tag for Go install paths, simplifies latest_stable_version return, and sets GOWORK for Go tip builds via checkout_go_from_platform.
Build: Makefile GOWORK integration
xtest/sdk/go/Makefile
Per-version build loop computes absolute src path, detects parent go.work, sets GOWORK (or preserves existing), and runs go build from resolved path.
Workflow & composite action wiring for platform otdfctl
.github/workflows/xtest.yml, xtest/setup-cli-tool/action.yaml
Replaces detect-otdfctl with conditional capture step that emits platform-otdfctl dir/sha only if otdfctl/go.mod exists; rewires Go CLI setup to consume those outputs, removes explicit Go head resolution and go.mod replace/tidy loop, and updates action checkout logic/comments to force platform behavior for Go source builds.

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs:

  • opentdf/tests#434: Earlier changes that added otdfctl-source/OTDFCTL_SOURCE plumbing and source annotation which this PR removes/replaces with platform-first logic.
  • opentdf/tests#445: Related updates to xtest/setup-cli-tool/action.yaml Go checkout/reuse behavior for platform-embedded otdfctl.

Suggested reviewers:

  • sujankota
  • sievdokymov-virtru
  • alkalescent

Poem:

"A rabbit hopped through branches wide,
Found worktrees nested, symlinks tied.
Tags now point to platform roots,
No more stray source-route pursuits.
Build hops, test hops—GOWORK smiles inside."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: removing standalone otdfctl routing and centralizing Go sourcing through the platform monorepo, which is the core refactoring across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DSPX-3086-fix-failing-proto-update-lookups

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py`:
- Around line 122-124: The current logic that removes and recreates src_link
uses src_link.unlink() which raises IsADirectoryError when src_link is a real
directory; update the removal logic (around the
src_link.is_symlink()/src_link.exists() block) to: if src_link.is_symlink():
call src_link.unlink(); elif src_link.exists(): if src_link.is_dir(): call
shutil.rmtree(str(src_link)) else: call src_link.unlink(); then recreate the
symlink with src_link.symlink_to(...). Also add an import for shutil at the top
and ensure removal calls are safe (wrap with minimal error handling if needed).
- Around line 98-100: The current update path uses "git pull origin <ref>" which
fails for tags or detached HEADs; replace that single pull with a ref-safe
sequence: run a fetch that includes tags (e.g., _run(["git", "-C",
str(worktree_path), "fetch", "origin", "--tags"]) or equivalent), then attempt
to update the worktree by checking out the supplied ref in a way that supports
tags and commits (use "git checkout --detach <ref>" for non-branch refs) and
fall back to checking out the branch or resetting to origin/<ref> when the ref
is a branch; update the code around worktree_path, ref, and _run to perform
fetch + checkout/reset instead of the single git pull.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bb5f6af1-3c9c-4bd2-a8bc-131b3ccab915

📥 Commits

Reviewing files that changed from the base of the PR and between 410379e and adab06d.

📒 Files selected for processing (11)
  • .github/workflows/xtest.yml
  • otdf-sdk-mgr/README.md
  • otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/cli_versions.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/config.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/registry.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/resolve.py
  • otdf-sdk-mgr/tests/test_resolve.py
  • xtest/sdk/go/Makefile
  • xtest/setup-cli-tool/action.yaml

Comment thread otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py Outdated
Comment thread otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py Outdated
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request migrates the otdfctl Go tool management from a standalone repository to the opentdf/platform monorepo. Key changes include updating the version resolution logic to automatically distinguish between archived standalone releases (pre-v0.31.0) and newer monorepo-based releases (v0.31.0+). The SDK manager now handles source builds by cloning the platform monorepo, symlinking the otdfctl subdirectory, and configuring the GOWORK environment variable to ensure local dependencies resolve correctly. Additionally, documentation and GitHub Action workflows were updated to reflect this architectural shift. I have no feedback to provide as there were no review comments to assess.

…heckout

- Remove existing src/<ref> path safely when it's a real directory (not just
  a symlink), so upgrades from prior layouts don't hard-fail.
- Update existing worktrees via fetch + checkout FETCH_HEAD so tags and
  detached refs work, not just branches.
- Accept deprecated otdfctl-source workflow input and emit a warning so
  callers passing it don't break.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py (1)

101-102: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fetch in the linked worktree before checking out FETCH_HEAD.

Line 101 writes FETCH_HEAD via the bare repo, but Line 102 resolves FETCH_HEAD from the linked worktree. In Git worktrees that pseudo-ref is worktree-scoped, so reruns against an existing checkout can still fail or pick up stale state.

Suggested fix
-        _run(["git", f"--git-dir={bare_repo_path}", "fetch", "origin", ref, "--tags"])
+        _run(["git", "-C", str(worktree_path), "fetch", "origin", ref, "--tags"])
         _run(["git", "-C", str(worktree_path), "checkout", "--force", "FETCH_HEAD"])
#!/bin/bash
set -euo pipefail

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
cd "$tmp"

git init --bare remote.git
git clone remote.git seed >/dev/null
cd seed
git config user.email test@example.com
git config user.name test
echo one > a.txt
git add a.txt
git commit -m "init" >/dev/null
git branch -M main
git push origin main >/dev/null
git tag otdfctl/v0.31.0
git push origin --tags >/dev/null
echo two > a.txt
git commit -am "second" >/dev/null
git push origin main >/dev/null
cd "$tmp"

git clone --bare remote.git bare.git >/dev/null
git --git-dir=bare.git worktree add wt main >/dev/null

echo "bare git-path FETCH_HEAD: $(git --git-dir=bare.git rev-parse --git-path FETCH_HEAD)"
echo "worktree git-path FETCH_HEAD: $(git -C wt rev-parse --git-path FETCH_HEAD)"

echo
echo "Fetch through bare repo, then checkout FETCH_HEAD in worktree:"
git --git-dir=bare.git fetch origin otdfctl/v0.31.0 --tags >/dev/null
set +e
git -C wt checkout --force FETCH_HEAD
rc_bare=$?
set -e
echo "checkout exit code after bare fetch: $rc_bare"

echo
echo "Fetch through worktree, then checkout FETCH_HEAD in worktree:"
git -C wt fetch origin otdfctl/v0.31.0 --tags >/dev/null
git -C wt checkout --force FETCH_HEAD >/dev/null
echo "checked out: $(git -C wt rev-parse --short HEAD)"

Expected result: the two FETCH_HEAD paths differ, and the bare-repo fetch path is the one to watch on the runner image; the worktree-local fetch should consistently make the subsequent checkout succeed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py` around lines 101 - 102, The code
fetches into the bare repo but then checks out FETCH_HEAD from the linked
worktree, which can be stale; update the logic in checkout.py so the worktree
itself is fetched before checking out: either replace the bare-repo fetch call
with a worktree-scoped fetch using _run(["git", "-C", str(worktree_path),
"fetch", "origin", ref, "--tags"]) or add an additional _run(["git", "-C",
str(worktree_path), "fetch", "origin", ref, "--tags"]) immediately before the
existing _run(["git", "-C", str(worktree_path), "checkout", "--force",
"FETCH_HEAD"]) to ensure FETCH_HEAD is resolved in the worktree context
(referencing _run, bare_repo_path, worktree_path, and FETCH_HEAD).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py`:
- Around line 101-102: The code fetches into the bare repo but then checks out
FETCH_HEAD from the linked worktree, which can be stale; update the logic in
checkout.py so the worktree itself is fetched before checking out: either
replace the bare-repo fetch call with a worktree-scoped fetch using _run(["git",
"-C", str(worktree_path), "fetch", "origin", ref, "--tags"]) or add an
additional _run(["git", "-C", str(worktree_path), "fetch", "origin", ref,
"--tags"]) immediately before the existing _run(["git", "-C",
str(worktree_path), "checkout", "--force", "FETCH_HEAD"]) to ensure FETCH_HEAD
is resolved in the worktree context (referencing _run, bare_repo_path,
worktree_path, and FETCH_HEAD).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 71598493-040f-44d3-803b-79f614d14964

📥 Commits

Reviewing files that changed from the base of the PR and between adab06d and b66994a.

📒 Files selected for processing (2)
  • .github/workflows/xtest.yml
  • otdf-sdk-mgr/src/otdf_sdk_mgr/checkout.py

Encode the otdfctl module-path policy in one place (config.go_module_for_tag)
and drop the `source` field that was being threaded through resolve →
version-info JSON → action.yaml. Pre-v0.31.0 tags use the archived
github.com/opentdf/otdfctl module path; everything else uses
github.com/opentdf/platform/otdfctl. Resolve always tries the platform
monorepo first and falls back once to the archive repo. The CI workflow
drops the now-meaningless `otdfctl-source` input and its warning step.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py (1)

1-240: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Run ruff format to fix formatting.

The pipeline indicates this file needs reformatting. Run uv run ruff format . from the otdf-sdk-mgr directory to resolve.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py` around lines 1 - 240, This file
(installers.py) is misformatted; run the project's formatter (ruff format) over
the repository and commit the changes so the file conforms to style checks;
specifically reformat installers.py (affecting functions like
install_go_release, install_js_release, install_java_release and related
top-level definitions such as INSTALLERS, install_release,
latest_stable_version) by running the ruff format command used in CI and then
add/commit the updated file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py`:
- Around line 1-240: This file (installers.py) is misformatted; run the
project's formatter (ruff format) over the repository and commit the changes so
the file conforms to style checks; specifically reformat installers.py
(affecting functions like install_go_release, install_js_release,
install_java_release and related top-level definitions such as INSTALLERS,
install_release, latest_stable_version) by running the ruff format command used
in CI and then add/commit the updated file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 68a19464-4e63-4003-8f76-ed1dcf6cf449

📥 Commits

Reviewing files that changed from the base of the PR and between b66994a and f89b1c8.

📒 Files selected for processing (8)
  • .github/workflows/xtest.yml
  • otdf-sdk-mgr/src/otdf_sdk_mgr/cli_install.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/config.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/installers.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/registry.py
  • otdf-sdk-mgr/src/otdf_sdk_mgr/resolve.py
  • otdf-sdk-mgr/tests/test_resolve.py
  • xtest/setup-cli-tool/action.yaml
💤 Files with no reviewable changes (1)
  • .github/workflows/xtest.yml

@sonarqubecloud
Copy link
Copy Markdown

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.

1 participant