Repository navigation
ci: track core releases, run E2E against published gateways, and tag lockstep releases - #6
Conversation
|
Setting up the App now, with a few changes from #2:
I'll post here once the secrets are in. |
Per the App setup on #6: the App is ai-openshell-go-sdk, its secrets are SDK_BOT_CLIENT_ID and SDK_BOT_PRIVATE_KEY (app-id is deprecated in create-github-app-token v3.3.0), and they live in the sdk-bot environment, which only main can deploy to. As repository secrets, any pushed branch could mint a bot token, push to a PR as the bot, and then approve it. core-watch, release-tag, and core-drift run from main and now use environment: sdk-bot. Signed-off-by: Roland Huß <rhuss@redhat.com>
|
Thanks, all four make sense. Done in |
conformance:check reads hack/conformance-fixtures.txt, so the core bump automation can refresh the same fixtures it checks. Signed-off-by: Roland Huß <rhuss@redhat.com>
core-tags.sh prints core release tags newer than the pin: every newer stable tag and the newest pre-release if it is ahead of them (--all for every tag). open-bump-pr.sh builds branch core/<tag> in a temporary worktree, moves the pin, regenerates the bindings, refreshes the vendored fixtures, and opens a PR labeled core-bump plus stable or prerelease with the proto diff between the two core tags. It skips tags that already have a branch or a merged proposal, closes older pre-release proposals, and closes proposals whose core tag was deleted. --dry-run changes nothing on GitHub. Signed-off-by: Roland Huß <rhuss@redhat.com>
tag-release.sh creates the SDK tag vX.Y.Z when a commit on main moves the pin to stable core vX.Y.Z, publishes the GitHub release with the merged proposal's body, and asks the Go module proxy for the version. Pre-release pins and commits that leave the pin alone create nothing, and an existing tag at another commit fails the run. Signed-off-by: Roland Huß <rhuss@redhat.com>
core-watch runs hourly and on dispatch, and opens a proposal per new core tag. release-tag runs on pushes to main and on dispatch for a given commit. Both use the ai-openshell-sdk-bot App token, scoped to the permissions they need, so their pushes and PRs trigger CI. Failures are reported through report-failure.sh, a job-summary stub until the drift issue exists. Adds the core:tags, core:bump, and release:tag tasks. Signed-off-by: Roland Huß <rhuss@redhat.com>
drift-check.sh runs buf breaking (FILE rules) from core main against the pinned tag for the proto files the SDK generates, regenerates the bindings from main in a temporary worktree and builds and vets against them, and lists RPCs the SDK does not call yet. It writes a markdown report with a 'Pin | Core main | Result' header and exits 1 on breaking changes or a failed build. Uncovered RPCs are informational. Signed-off-by: Roland Huß <rhuss@redhat.com>
update-drift-issue.sh writes the drift report into the single open 'Core main drift' issue (label core-drift), creating it on drift and closing it once the check passes and no failures are pending. report-failure.sh appends a dated line to the issue's 'Automation failures' section, which the report updates carry over. Both take --dry-run. Signed-off-by: Roland Huß <rhuss@redhat.com>
core-drift runs drift-check.sh and update-drift-issue.sh with an App token scoped to issues. A run that produces no report is recorded as an automation failure. Signed-off-by: Roland Huß <rhuss@redhat.com>
workflows:check also runs shellcheck over hack/automation and hack/migration. Fixes the one warning it found in port-pr.sh (an unquoted command substitution passed to git add). Signed-off-by: Roland Huß <rhuss@redhat.com>
Signed-off-by: Jiri Petrlik <jpetrlik@redhat.com>
The suite from NVIDIA/OpenShell#3338 predates the switch of Sandboxes().Create from a labels map to CreateOption values. Pass labels through v1.WithLabels and drop the nil maps. Signed-off-by: Roland Huß <rhuss@redhat.com>
start-gateway.sh fetches deploy/docker/docker-compose.yml and gateway.toml from core at the given tag, pins the supervisor and sandbox images to the same version, starts the gateway with the Docker driver, waits for /readyz, and registers it as gateway 'e2e' for the SDK. It first waits up to 15 minutes for the gateway image of a fresh tag. stop-gateway.sh saves the gateway log and removes the gateway and the sandbox containers it created. Signed-off-by: Roland Huß <rhuss@redhat.com>
e2e.yml starts the gateway for a core version (default the pin), runs mise run e2e, and uploads the gateway log on failure. ci.yml calls it for pull requests that change the pin, the bindings, the SDK code, the suite, or the gateway scripts. Signed-off-by: Roland Huß <rhuss@redhat.com>
Core's gateway.toml binds the health server to 127.0.0.1 inside the container, so the published port 8081 never answers and the readiness wait times out. Bind it to all container interfaces; the compose file publishes it on the host's loopback only. Signed-off-by: Roland Huß <rhuss@redhat.com>
Since NVIDIA/OpenShell#3383 the gateway ships no provider profiles, so creating a claude-code or nvidia provider fails until the profile is imported. TestMain now imports both into the default workspace, based on core's example profiles, replacing earlier copies so reruns start from the same definitions. Signed-off-by: Roland Huß <rhuss@redhat.com>
The gateway rejects an endpoint protocol without access or rules, and the SDK's NetworkEndpoint can't express those yet. The tests only need the credentials, so the fixtures use host and port only. Signed-off-by: Roland Huß <rhuss@redhat.com>
A credentialed L4 endpoint also needs allow_uninspected_credentials, which NetworkEndpoint can't express either. The tests only exercise credentials, so the fixtures declare no endpoints. Signed-off-by: Roland Huß <rhuss@redhat.com>
A provider without a profile workspace resolves its type against global profiles, so profiles imported into the default workspace were not found. Import and delete the fixtures in the global scope, as core's E2E harness does with --global. Signed-off-by: Roland Huß <rhuss@redhat.com>
The fixture profiles declare no endpoints, and the gateway withholds credentials of endpointless profiles unless the sandbox policy binds them to an endpoint. The credential tests now create their sandboxes with such a binding, as core's E2E does. Also drops the leftover nil CreateOption arguments. Signed-off-by: Roland Huß <rhuss@redhat.com>
A sandbox whose policy binds a provider's credentials can't detach it, so deleting the provider right after the sandbox fails with a conflict until the asynchronous sandbox deletion ends. Retry on conflict. Skip the attach/detach test, which needs a profile with endpoints that the SDK can't import yet. Signed-off-by: Roland Huß <rhuss@redhat.com>
Signed-off-by: Roland Huß <rhuss@redhat.com>
Per the App setup on #6: the App is ai-openshell-go-sdk, its secrets are SDK_BOT_CLIENT_ID and SDK_BOT_PRIVATE_KEY (app-id is deprecated in create-github-app-token v3.3.0), and they live in the sdk-bot environment, which only main can deploy to. As repository secrets, any pushed branch could mint a bot token, push to a PR as the bot, and then approve it. core-watch, release-tag, and core-drift run from main and now use environment: sdk-bot. Signed-off-by: Roland Huß <rhuss@redhat.com>
adapt.yml, adapt-context.sh, and the agent:adapt label are not part of this PR: a label trigger runs in PR context, which the sdk-bot environment restricted to main rules out, so the adaptation workflow gets its own design later. Signed-off-by: Roland Huß <rhuss@redhat.com>
| ) | ||
|
|
||
| var ( | ||
| sharedClient *v1.Client |
There was a problem hiding this comment.
I'm assuming that although tests are run in parallel, the TestMain is sequential meaning that this will be valid at the point where the tests start running?
There was a problem hiding this comment.
Yes. TestMain runs before any test starts, and tests (parallel ones included) only start inside m.Run(), so sharedClient and gatewayName are set by then and never written again.
There was a problem hiding this comment.
As a general question: What would it take to be able to run the same "conformance" tests using each of the SDKs? Is this something that we think we can strive towards?
There was a problem hiding this comment.
I think it's worth aiming for. Today the SDKs share only data: the JSON fixtures in core's sdk/conformance/, which sdk-go vendors and checks against the pinned tag. Sharing behavior would need scenarios in a language-neutral form (steps plus expected results) and a small runner per SDK, or one runner that drives each SDK through a thin CLI shim. Core's openshell-conformance crate already has driver-agnostic scenarios for the CLI, which might be a starting point. It's a cross-SDK design question, so I'd take it to an issue in NVIDIA/OpenShell rather than this PR.
elezar
left a comment
There was a problem hiding this comment.
The design is careful: SHA-pinned actions, bot secrets scoped to an environment that only main can use, and --dry-run modes on the scripts. I read the workflows and hack/automation scripts in full. I only skimmed the Go E2E code, and I haven't run anything.
Should fix
open-bump-pr.shreopens proposals that someone closed on purpose. It skips a tag only if the branch still exists onoriginor a PR from it was merged. If a maintainer closes a proposal and deletes the branch,core-watchrecreates it on the next hourly run. Add a--state closedcheck or a marker.- A transient API error looks like a deleted core tag.
if ! gh api repos/$core_repo/git/ref/tags/$tag --silent 2>/dev/nulltreats any failure (rate limit, 5xx) as "tag gone" and runsgh pr close --delete-branch. Only treat a 404 as gone. tag-release.shcan't recover from a half-finished release. It creates the tag, then the release. If the release step fails, a re-run sees "tag already points at $sha" and exits 0, so the release is never created. Check for the release separately.- Secret name mismatch. The description says
SDK_BOT_APP_ID, but all three bot workflows readsecrets.SDK_BOT_CLIENT_ID.
Worth considering
tag-release.shonly diffs$sha^..$sha. A rebase-merge, or several commits in one push, can miss a pin change that isn't the tip. Fine if squash-only is enforced; otherwise worth documenting.- The E2E path filter in
ci.ymlomits.github/workflows/e2e.yml,mise.tomlandgo.mod. start-gateway.sh/stop-gateway.shassume a throwaway CI host:- The header says stop "undoes everything", but it never removes
gateways/e2eoractive_gateway. - It
docker rm -fs every container labelledopenshell.sandbox_namespace=openshell. - Only the supervisor image pin is verified; the sandbox
sedhas no check. - The readiness wait only checks the gateway manifest, not the supervisor and sandbox images.
- The header says stop "undoes everything", but it never removes
report-failure.shandupdate-drift-issue.shread-modify-write the issue body from different concurrency groups, so a failure line can be lost. Low probability.- The uncovered-RPC grep (
\.${method}\() matches generic names such as.List(and.Delete(, so it under-reports. It's informational only. - Several open stable proposals branch from the same
main; merging an older one after a newer one moves the pin backwards. persist-credentials: trueincore-watchleaves the write-scoped App token in.git/configfor the rest of the job. Acceptable, but worth knowing.
Looks good
core-tags.sh version ordering, the port-pr.sh word-splitting fix, the shared fixture list in mise.toml, and inputs passed via env: rather than interpolated into run:.
|
@SDAChess #6 is ready for review. I rebased it onto CODEOWNERS sends After it merges, I'll do two one-off dispatches:
If both runs pass, I'll close #2. |
TestMain now delegates to run(m), so the shared client is closed by one deferred call instead of before every os.Exit. Signed-off-by: Roland Huß <rhuss@redhat.com>
The helper skips the test when no gateway is configured; it doesn't assert. The require prefix stays with the helpers that fail the test. Signed-off-by: Roland Huß <rhuss@redhat.com>
open-bump-pr.sh skipped a tag only when its branch existed or a PR from it was merged. A proposal closed by a maintainer, or closed as superseded by a newer pre-release (which deletes the branch), came back on the next hourly run. Skip the tag when any PR from the branch exists. The core tag lookup treated every failure as a deleted tag and closed the open proposal. Only a 404 means the tag is gone now; other errors fail the run, which reports to the drift issue. Signed-off-by: Roland Huß <rhuss@redhat.com>
tag-release.sh created the tag and then the release. When the release step failed, a re-run saw the tag at the commit and stopped, so the release was never created. Check the tag and the release separately and create whichever is missing; API errors other than 404 fail the run. It also decided by diffing only the pushed commit against its parent, so a push of several commits or a rebase merge could miss a pin change that was not the tip. The push workflow now passes the commit before the push as --since, and the script compares the pins at both commits. Signed-off-by: Roland Huß <rhuss@redhat.com>
The path filter now also matches .github/workflows/e2e.yml, mise.toml, go.mod, and go.sum. Signed-off-by: Roland Huß <rhuss@redhat.com>
start-gateway.sh verified only the supervisor image pin; it now checks the sandbox image pin too. stop-gateway.sh removes the "e2e" gateway registration and the active-gateway pointer when it still names it. The header no longer claims stop undoes everything and says the scripts are for throwaway CI hosts, since the sandbox cleanup matches core's default namespace label. Signed-off-by: Roland Huß <rhuss@redhat.com>
The App was registered as ai-openshell-sdk-go, following the repository naming convention. Signed-off-by: Roland Huß <rhuss@redhat.com>
|
@elezar thanks for the careful pass. Changes are in 0617220..de002ec. Should fix
Worth considering Separately, de002ec renames the App in the automation README to The fixes came from an agent-assisted pass. Checked locally: |
elezar
left a comment
There was a problem hiding this comment.
Checked the updates at de002ec against my earlier review: the four must-fix items (closed proposals reopening, non-404 errors treated as a deleted tag, half-finished releases, secret name) are fixed, and the optional items are fixed or reasonably declined. Thanks for the quick turnaround.
Summary
Release automation, the nightly drift check, and the E2E lane for sdk-go. Stacked on the governance PR; review after it is merged. Draft until the E2E lane is green here and the
ai-openshell-sdk-botApp exists (#2).Core releases and SDK releases
core-watch.yml(hourly, or dispatched with a tag):core-tags.shlists core tags newer than the pin, andopen-bump-pr.shopens one proposal per tag on branchcore/<tag>. Each proposal moves the pin inbuf.gen.yaml, regenerates the bindings, refreshes the vendored conformance fixtures, and shows the proto diff between the two core tags. Labels:core-bumpplusstableorprerelease. Only the newest pre-release of a train gets a proposal, a newer one closes older pre-release proposals, and stable proposals are never closed automatically.release-tag.yml(push tomain, or dispatched for a commit): when a commit moves the pin to stable corevX.Y.Z,tag-release.shtagsvX.Y.Z, publishes the GitHub release with the merged proposal's body, and asks the Go module proxy for the version. Pre-release pins and other commits create nothing; a tag at another commit fails the run.Drift
core-drift.yml(nightly):drift-check.shrunsbuf breakingfrom coremainagainst the pin for the files the SDK generates, regenerates frommainand builds, and lists RPCs the SDK doesn't call yet (informational).update-drift-issue.shkeeps oneCore main driftissue current and closes it when the check passes. Failed automation runs add a dated line to that issue throughreport-failure.sh.E2E
e2e/: the Go E2E suite from test: E2E tests for Go SDK NVIDIA/OpenShell#3338 by @jiripetrlik, with his commit, plus one commit adapting it toCreateOption.e2e.yml:start-gateway.shruns the published gateway with the Docker driver from core's owndeploy/docker/docker-compose.ymlandgateway.tomlat the core tag, with the supervisor and sandbox images pinned to that version.ci.ymlcalls it for pull requests that change the pin, the bindings, the SDK code, the suite, or the gateway scripts.The workflows that write to GitHub use the App token, scoped to the permissions each job needs, so their pushes and PRs trigger CI. They need the
SDK_BOT_CLIENT_IDandSDK_BOT_PRIVATE_KEYsecrets.workflows:checkalso runs shellcheck overhack/.Testing
mise run ciandmise run workflows:checkpass locally.core-tags.shagainst real core tags, and against a synthetic list for ordering (pre.10afterpre.2,v0.1.10afterv0.1.9).open-bump-pr.sh v0.1.7 --dry-runagainst a base pinned to v0.1.6: one commit, regenerated bindings, fixture report, and the proto diff in the body.tag-release.sh --dry-run: tags v0.1.7 at the pin commit; no-op for commits without a pin change and for pre-release pins.drift-check.shagainst coremain: pass. The breaking check reports a deliberately deleted field.gh: create, append a failure, keep pending failures across a passing report, close.start-gateway.shup to the compose call (image check, files at v0.1.7, image pinning). The E2E lane itself runs for the first time on this PR.Part of NVIDIA/OpenShell#5031.